A qmail-style Maildir mailbox.
| 272 | |
| 273 | |
| 274 | class Maildir(Mailbox): |
| 275 | """A qmail-style Maildir mailbox.""" |
| 276 | |
| 277 | colon = ':' |
| 278 | |
| 279 | def __init__(self, dirname, factory=None, create=True): |
| 280 | """Initialize a Maildir instance.""" |
| 281 | Mailbox.__init__(self, dirname, factory, create) |
| 282 | self._paths = { |
| 283 | 'tmp': os.path.join(self._path, 'tmp'), |
| 284 | 'new': os.path.join(self._path, 'new'), |
| 285 | 'cur': os.path.join(self._path, 'cur'), |
| 286 | } |
| 287 | if not os.path.exists(self._path): |
| 288 | if create: |
| 289 | os.mkdir(self._path, 0o700) |
| 290 | for path in self._paths.values(): |
| 291 | os.mkdir(path, 0o700) |
| 292 | else: |
| 293 | raise NoSuchMailboxError(self._path) |
| 294 | self._toc = {} |
| 295 | self._toc_mtimes = {'cur': 0, 'new': 0} |
| 296 | self._last_read = 0 # Records last time we read cur/new |
| 297 | self._skewfactor = 0.1 # Adjust if os/fs clocks are skewing |
| 298 | |
| 299 | def add(self, message): |
| 300 | """Add message and return assigned key.""" |
| 301 | tmp_file = self._create_tmp() |
| 302 | try: |
| 303 | self._dump_message(message, tmp_file) |
| 304 | except BaseException: |
| 305 | tmp_file.close() |
| 306 | os.remove(tmp_file.name) |
| 307 | raise |
| 308 | _sync_close(tmp_file) |
| 309 | if isinstance(message, MaildirMessage): |
| 310 | subdir = message.get_subdir() |
| 311 | suffix = self.colon + message.get_info() |
| 312 | if suffix == self.colon: |
| 313 | suffix = '' |
| 314 | else: |
| 315 | subdir = 'new' |
| 316 | suffix = '' |
| 317 | uniq = os.path.basename(tmp_file.name).split(self.colon)[0] |
| 318 | dest = os.path.join(self._path, subdir, uniq + suffix) |
| 319 | if isinstance(message, MaildirMessage): |
| 320 | os.utime(tmp_file.name, |
| 321 | (os.path.getatime(tmp_file.name), message.get_date())) |
| 322 | # No file modification should be done after the file is moved to its |
| 323 | # final position in order to prevent race conditions with changes |
| 324 | # from other programs |
| 325 | try: |
| 326 | try: |
| 327 | os.link(tmp_file.name, dest) |
| 328 | except (AttributeError, PermissionError): |
| 329 | os.rename(tmp_file.name, dest) |
| 330 | else: |
| 331 | os.remove(tmp_file.name) |
no outgoing calls
no test coverage detected
searching dependent graphs…