diff options
Diffstat (limited to 'Lib/mailbox.py')
| -rw-r--r-- | Lib/mailbox.py | 42 |
1 files changed, 27 insertions, 15 deletions
diff --git a/Lib/mailbox.py b/Lib/mailbox.py index c73fb95..3b64c2e 100644 --- a/Lib/mailbox.py +++ b/Lib/mailbox.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python3 - """Read/write support for Maildir, mbox, MH, Babyl, and MMDF mailboxes.""" # Notes for authors of new mailbox subclasses: @@ -311,6 +309,12 @@ class Maildir(Mailbox): suffix = '' uniq = os.path.basename(tmp_file.name).split(self.colon)[0] dest = os.path.join(self._path, subdir, uniq + suffix) + if isinstance(message, MaildirMessage): + os.utime(tmp_file.name, + (os.path.getatime(tmp_file.name), message.get_date())) + # No file modification should be done after the file is moved to its + # final position in order to prevent race conditions with changes + # from other programs try: if hasattr(os, 'link'): os.link(tmp_file.name, dest) @@ -324,8 +328,6 @@ class Maildir(Mailbox): % dest) else: raise - if isinstance(message, MaildirMessage): - os.utime(dest, (os.path.getatime(dest), message.get_date())) return uniq def remove(self, key): @@ -360,11 +362,15 @@ class Maildir(Mailbox): else: suffix = '' self.discard(key) + tmp_path = os.path.join(self._path, temp_subpath) new_path = os.path.join(self._path, subdir, key + suffix) - os.rename(os.path.join(self._path, temp_subpath), new_path) if isinstance(message, MaildirMessage): - os.utime(new_path, (os.path.getatime(new_path), - message.get_date())) + os.utime(tmp_path, + (os.path.getatime(tmp_path), message.get_date())) + # No file modification should be done after the file is moved to its + # final position in order to prevent race conditions with changes + # from other programs + os.rename(tmp_path, new_path) def get_message(self, key): """Return a Message representation or raise a KeyError.""" @@ -1157,8 +1163,7 @@ class MH(Mailbox): def get_sequences(self): """Return a name-to-key-list dictionary to define each sequence.""" results = {} - f = open(os.path.join(self._path, '.mh_sequences'), 'r') - try: + with open(os.path.join(self._path, '.mh_sequences'), 'r', encoding='ASCII') as f: all_keys = set(self.keys()) for line in f: try: @@ -1177,13 +1182,11 @@ class MH(Mailbox): except ValueError: raise FormatError('Invalid sequence specification: %s' % line.rstrip()) - finally: - f.close() return results def set_sequences(self, sequences): """Set sequences using the given name-to-key-list dictionary.""" - f = open(os.path.join(self._path, '.mh_sequences'), 'r+') + f = open(os.path.join(self._path, '.mh_sequences'), 'r+', encoding='ASCII') try: os.close(os.open(f.name, os.O_WRONLY | os.O_TRUNC)) for name, keys in sequences.items(): @@ -1523,9 +1526,10 @@ class Message(email.message.Message): def _become_message(self, message): """Assume the non-format-specific state of message.""" - for name in ('_headers', '_unixfrom', '_payload', '_charset', - 'preamble', 'epilogue', 'defects', '_default_type'): - self.__dict__[name] = message.__dict__[name] + type_specific = getattr(message, '_type_specific_attributes', []) + for name in message.__dict__: + if name not in type_specific: + self.__dict__[name] = message.__dict__[name] def _explain_to(self, message): """Copy format-specific state to message insofar as possible.""" @@ -1538,6 +1542,8 @@ class Message(email.message.Message): class MaildirMessage(Message): """Message with Maildir-specific properties.""" + _type_specific_attributes = ['_subdir', '_info', '_date'] + def __init__(self, message=None): """Initialize a MaildirMessage instance.""" self._subdir = 'new' @@ -1645,6 +1651,8 @@ class MaildirMessage(Message): class _mboxMMDFMessage(Message): """Message with mbox- or MMDF-specific properties.""" + _type_specific_attributes = ['_from'] + def __init__(self, message=None): """Initialize an mboxMMDFMessage instance.""" self.set_from('MAILER-DAEMON', True) @@ -1760,6 +1768,8 @@ class mboxMessage(_mboxMMDFMessage): class MHMessage(Message): """Message with MH-specific properties.""" + _type_specific_attributes = ['_sequences'] + def __init__(self, message=None): """Initialize an MHMessage instance.""" self._sequences = [] @@ -1830,6 +1840,8 @@ class MHMessage(Message): class BabylMessage(Message): """Message with Babyl-specific properties.""" + _type_specific_attributes = ['_labels', '_visible'] + def __init__(self, message=None): """Initialize an BabylMessage instance.""" self._labels = [] |
