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 <offlineimap@adamspiers.org>
Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
This commit is contained in:
Adam Spiers 2013-03-27 12:43:39 +00:00 committed by Eygene Ryabinkin
parent 3a580049ad
commit d39a1f864f
2 changed files with 18 additions and 1 deletions

View File

@ -22,6 +22,9 @@ OfflineIMAP v6.5.5-rc1 (2012-09-05)
* Execute pre/post-sync hooks during synchronizations * Execute pre/post-sync hooks during synchronizations
toggled by IMAP IDLE message processing. (maxgerer@gmail.com) 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) OfflineIMAP v6.5.5-rc1 (2012-09-05)
=================================== ===================================

View File

@ -548,6 +548,20 @@ class IMAPFolder(BaseFolder):
(typ, dat) = imapobj.append(self.getfullname(), (typ, dat) = imapobj.append(self.getfullname(),
imaputil.flagsmaildir2imap(flags), imaputil.flagsmaildir2imap(flags),
date, content) date, content)
# 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 retry_left = 0 # Mark as success
except imapobj.abort as e: except imapobj.abort as e:
# connection has been reset, release connection and retry. # connection has been reset, release connection and retry.