From d39a1f864f3549d5e518440f11b46a997194af56 Mon Sep 17 00:00:00 2001 From: Adam Spiers Date: Wed, 27 Mar 2013 12:43:39 +0000 Subject: [PATCH] make savemessage() handle NO response to APPEND correctly IMAP servers can return `NO` responses to the `APPEND` command, e.g. here's an example response from Groupwise's IMAP server: NO APPEND The 1500 MB storage limit has been exceeded. In this case, savemessage() should abort the repository sync rather than returning UID 0 which would cause the local copy of the message being saved to get irreversibly deleted. Signed-off-by: Adam Spiers Signed-off-by: Eygene Ryabinkin --- Changelog.rst | 3 +++ offlineimap/folder/IMAP.py | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Changelog.rst b/Changelog.rst index 3cf2381..0aab40b 100644 --- a/Changelog.rst +++ b/Changelog.rst @@ -22,6 +22,9 @@ OfflineIMAP v6.5.5-rc1 (2012-09-05) * Execute pre/post-sync hooks during synchronizations toggled by IMAP IDLE message processing. (maxgerer@gmail.com) +* Catch unsuccessful local mail uploads when IMAP server + responds with "NO" status; that resulted in a loss of such + local messages. (Adam Spiers) OfflineIMAP v6.5.5-rc1 (2012-09-05) =================================== diff --git a/offlineimap/folder/IMAP.py b/offlineimap/folder/IMAP.py index db23813..deba1db 100644 --- a/offlineimap/folder/IMAP.py +++ b/offlineimap/folder/IMAP.py @@ -548,7 +548,21 @@ class IMAPFolder(BaseFolder): (typ, dat) = imapobj.append(self.getfullname(), imaputil.flagsmaildir2imap(flags), date, content) - retry_left = 0 # Mark as success + # This should only catch 'NO' responses since append() + # will raise an exception for 'BAD' responses: + if typ != 'OK': + # For example, Groupwise IMAP server can return something like: + # + # NO APPEND The 1500 MB storage limit has been exceeded. + # + # In this case, we should immediately abort the repository sync + # and continue with the next account. + msg = \ + "Saving msg in folder '%s', repository '%s' failed (abort). " \ + "Server responded: %s %s\n" % \ + (self, self.getrepository(), typ, dat) + raise OfflineImapError(msg, OfflineImapError.ERROR.REPO) + retry_left = 0 # Mark as success except imapobj.abort as e: # connection has been reset, release connection and retry. retry_left -= 1