[PATCHv2 2/4] Factor out the date guessing/retrieving

Sebastian Spaeth Sebastian at SSpaeth.de
Sun Jan 23 16:50:26 GMT 2011


savemessage was too long and complex. Factor out the date guessing part
of the function and put it into a function of its own. The logic of the
date guessing is the same, however we don't need to run all our
datetuples through imaplib.Time2InternalDate() as the imaplib.append()
will do this for us.

Signed-off-by: Sebastian Spaeth <Sebastian at SSpaeth.de>
---
v2, with slightly improved error message on invalid date as per
Nicolas' suggestion. Unfortunately it is not easy here to give out the
message UID or some other identifying information from within this
function.

 offlineimap/folder/IMAP.py |   96 ++++++++++++++++++++++++++++---------------
 1 files changed, 62 insertions(+), 34 deletions(-)

diff --git a/offlineimap/folder/IMAP.py b/offlineimap/folder/IMAP.py
index 869ec5c..136c07b 100644
--- a/offlineimap/folder/IMAP.py
+++ b/offlineimap/folder/IMAP.py
@@ -302,53 +302,81 @@ class IMAPFolder(BaseFolder):
         matchinguids.sort()
         return long(matchinguids[0])
 
+
+    def getmessagedate(self, content, rtime=None):
+        """Parses mail and returns an 9-datetuple
+
+        It will use information in the following order, falling back as an attempt fails:
+          - rtime parameter
+          - Date header of email
+          - Local system time
+        :param rtime: epoch timestamp to be used rather than analyzing
+                  the email.
+        :returns: 9-tuple that can be passed directly to time.mktime()
+                  or None in case of failure. Indexes 6, 7, and 8 are not usable."""
+        if rtime is None:
+            message = rfc822.Message(StringIO(content))
+            # parsedate returns a 9-tuple that can be passed directly to
+            # time.mktime(); Will be None if missing or not in a valid
+            # format.  Note that indexes 6, 7, and 8 of the result tuple are
+            # not usable.
+            datetuple = rfc822.parsedate(message.getheader('Date'))
+
+            if datetuple is None:
+                #could not determine the date, use the local time.
+                datetuple = time.localtime()
+        else:
+            #rtime is set, use that instead
+            datetuple = time.localtime(rtime)
+
+        try:
+            # Sometimes we have a valid format, but year is 0102 or
+            # similar... It seems that Time2Internaldate will raise a
+            # ValueError if the year is 0102 but not 1902, but some IMAP
+            # servers nonetheless choke on 1902.
+            if datetuple[0] < 1981:
+                raise ValueError
+
+            # Check for invalid dates, by converting our datetuple forth
+            # and back and comparing it.
+            datetuple_check = time.localtime(time.mktime(datetuple))
+            if datetuple[:2] != datetuple_check[:2]:
+                raise ValueError
+
+        except (ValueError, OverflowError):
+            # invalid date
+            UIBase.getglobalui().debug("Message with invalid date %s, using localtime instead." % datetuple)
+            datetuple = time.localtime()
+
+        return datetuple
+
     def savemessage(self, uid, content, flags, rtime):
+        """Save the message on the Server
+
+        This backend always assigns a new uid, so the uid arg is ignored.
+
+        This function will update the self.messagelist dict to contain
+        the new message after sucessfully saving it.
+
+        :param rtime: A timestamp to be
+        :returns: the UID of the new message as assigned by the
+                  server. If the folder is read-only it will return 0."""
         imapobj = self.imapserver.acquireconnection()
         ui = UIBase.getglobalui()
         ui.debug('imap', 'savemessage: called')
+
         try:
             try:
                 imapobj.select(self.getfullname()) # Needed for search
             except imapobj.readonly:
                 ui.msgtoreadonly(self, uid, content, flags)
                 # Return indicating message taken, but no UID assigned.
-                # Fudge it.
                 return 0
             
-            # This backend always assigns a new uid, so the uid arg is ignored.
-            # In order to get the new uid, we need to save off the message ID.
-
-            message = rfc822.Message(StringIO(content))
-            datetuple_msg = rfc822.parsedate(message.getheader('Date'))
-            # Will be None if missing or not in a valid format.
+            # get the date of the message file, so we can pass it to the server.
+            date = self.getmessagedate(content, rtime)
 
-            # If time isn't known
-            if rtime == None and datetuple_msg == None:
-                datetuple = time.localtime()
-            elif rtime == None:
-                datetuple = datetuple_msg
-            else:
-                datetuple = time.localtime(rtime)
-
-            try:
-                if datetuple[0] < 1981:
-                    raise ValueError
-
-                # Check for invalid date
-                datetuple_check = time.localtime(time.mktime(datetuple))
-                if datetuple[:2] != datetuple_check[:2]:
-                    raise ValueError
-
-                # This could raise a value error if it's not a valid format.
-                date = imaplib.Time2Internaldate(datetuple) 
-            except (ValueError, OverflowError):
-                # Argh, sometimes it's a valid format but year is 0102
-                # or something.  Argh.  It seems that Time2Internaldate
-                # will rause a ValueError if the year is 0102 but not 1902,
-                # but some IMAP servers nonetheless choke on 1902.
-                date = imaplib.Time2Internaldate(time.localtime())
-
-            ui.debug('imap', 'savemessage: using date ' + str(date))
+            ui.debug('imap', 'savemessage: using date %s' % date)
             content = re.sub("(?<!\r)\n", "\r\n", content)
             ui.debug('imap', 'savemessage: initial content is: ' + repr(content))
 
-- 
1.7.1





More information about the OfflineIMAP-project mailing list