diff --git a/offlineimap/folder/Base.py b/offlineimap/folder/Base.py index df2e654..e033ab2 100644 --- a/offlineimap/folder/Base.py +++ b/offlineimap/folder/Base.py @@ -365,7 +365,8 @@ class BaseFolder(object): dryrun mode.""" for uid in uidlist: - self.addmessageflags(uid, flags) + if self.uidexists(uid): + self.addmessageflags(uid, flags) def deletemessageflags(self, uid, flags): """Removes each flag given from the message's flag set. If a given @@ -695,11 +696,6 @@ class BaseFolder(object): content = self.getmessage(uid) rtime = emailutil.get_message_date(content, 'Date') - if uid > 0 and dstfolder.uidexists(uid): - # dst has message with that UID already, only update status - statusfolder.savemessage(uid, None, flags, rtime) - return - # If any of the destinations actually stores the message body, # load it up. if dstfolder.storesmessages(): @@ -766,6 +762,16 @@ class BaseFolder(object): # bail out on CTRL-C or SIGTERM if offlineimap.accounts.Account.abort_NOW_signal.is_set(): break + if uid > 0 and dstfolder.uidexists(uid): + # dst has message with that UID already, only update status + flags = self.getmessageflags(uid) + rtime = self.getmessagetime(uid) + if dstfolder.utime_from_message: + content = self.getmessage(uid) + rtime = emailutil.get_message_date(content, 'Date') + statusfolder.savemessage(uid, None, flags, rtime) + copylist.remove(uid) + self.ui.copyingmessage(uid, num+1, num_to_copy, self, dstfolder) # exceptions are caught in copymessageto() if self.suggeststhreads() and not globals.options.singlethreading: @@ -790,19 +796,24 @@ class BaseFolder(object): that were deleted in 'self'. Delete those from dstfolder and statusfolder. - This function checks and protects us from action in ryrun mode. + This function checks and protects us from action in dryrun mode. """ deletelist = filter(lambda uid: uid >= 0 and not self.uidexists(uid), statusfolder.getmessageuidlist()) if len(deletelist): - self.ui.deletingmessages(deletelist, [dstfolder]) - if self.repository.account.dryrun: - return #don't delete messages in dry-run mode - # delete in statusfolder first to play safe. In case of abort, we - # won't lose message, we will just retransmit some unneccessary. - for folder in [statusfolder, dstfolder]: - folder.deletemessages(deletelist) + # Delete in statusfolder first to play safe. In case of abort, we + # won't lose message, we will just unneccessarily retransmit some. + # Delete messages from statusfolder that were either deleted by the + # user, or not being tracked (e.g. because of maxage). + statusfolder.deletemessages(deletelist) + # Filter out untracked messages + deletelist = filter(lambda uid: dstfolder.uidexists(uid), deletelist) + if len(deletelist): + self.ui.deletingmessages(deletelist, [dstfolder]) + if self.repository.account.dryrun: + return #don't delete messages in dry-run mode + dstfolder.deletemessages(deletelist) def __syncmessagesto_flags(self, dstfolder, statusfolder): """Pass 3: Flag synchronization. diff --git a/offlineimap/folder/IMAP.py b/offlineimap/folder/IMAP.py index ccc83b0..4b470a2 100644 --- a/offlineimap/folder/IMAP.py +++ b/offlineimap/folder/IMAP.py @@ -836,8 +836,6 @@ class IMAPFolder(BaseFolder): self.__deletemessages_noconvert(uidlist) def __deletemessages_noconvert(self, uidlist): - # Weed out ones not in self.messagelist - uidlist = [uid for uid in uidlist if self.uidexists(uid)] if not len(uidlist): return diff --git a/offlineimap/folder/Maildir.py b/offlineimap/folder/Maildir.py index 77f7ebb..6df8180 100644 --- a/offlineimap/folder/Maildir.py +++ b/offlineimap/folder/Maildir.py @@ -439,9 +439,6 @@ class MaildirFolder(BaseFolder): :return: Nothing, or an Exception if UID but no corresponding file found. """ - if not self.uidexists(uid): - return - filename = self.messagelist[uid]['filename'] filepath = os.path.join(self.getfullname(), filename) try: diff --git a/offlineimap/imaplibutil.py b/offlineimap/imaplibutil.py index 30aed9a..4f33be1 100644 --- a/offlineimap/imaplibutil.py +++ b/offlineimap/imaplibutil.py @@ -222,6 +222,8 @@ def Internaldate2epoch(resp): Returns seconds since the epoch.""" + from calendar import timegm + mo = InternalDate.match(resp) if not mo: return None @@ -245,4 +247,4 @@ def Internaldate2epoch(resp): tt = (year, mon, day, hour, min, sec, -1, -1, -1) - return time.mktime(tt) + return timegm(tt) - zone