From 51728ed815aa2ae399e80dcb85d8b6af619fafcb Mon Sep 17 00:00:00 2001 From: Sebastian Spaeth Date: Sat, 4 Feb 2012 21:08:44 +0100 Subject: [PATCH] Remove Gmail realdelete option It can lead to potential dataloss (see recent commit log where I added a scary warning about it to offlineimap.conf). Signed-off-by: Sebastian Spaeth --- offlineimap.conf | 15 ------------ offlineimap/folder/Gmail.py | 41 ++++++++------------------------- offlineimap/repository/Gmail.py | 5 ---- 3 files changed, 9 insertions(+), 52 deletions(-) diff --git a/offlineimap.conf b/offlineimap.conf index 66dd284..2656ef6 100644 --- a/offlineimap.conf +++ b/offlineimap.conf @@ -531,21 +531,6 @@ type = Gmail # Specify the Gmail user name. This is the only mandatory parameter. remoteuser = username@gmail.com -# WARNING: READ THIS BEFORE CONSIDERING TO CHANGE IT! Deleting a -# message from a Gmail folder via the IMAP interface will just remove -# that folder's label from the message: the message will continue to -# exist in the '[Gmail]/All Mail' folder. If `realdelete` is set to -# `True`, then deleted messages will be moved to the '[Gmail]/Trash' -# folder. BEWARE: this will immediately delete a messages from *all -# folders* it belongs to! AS OFFLINEIMAP IMPLEMENTS FOLDER MOVES AS 1) -# AN ADD and 2) A DELETE (the order can vary), THIS MEANS THAT A FOLDER -# MOVE CAN CAUSE DATALOSS. DO NOT USE IT AND MOVE MAIL TO -# "[Gmail]/Trash" TO DELETE MAIL FROM "[Gmail]/All Mail"! See the -# analysis at -# http://article.gmane.org/gmane.mail.imap.offlineimap.general/5265 See -# http://mail.google.com/support/bin/answer.py?answer=77657&topic=12815 -# realdelete = no !!!READ ABOVE BEFORE USING - # The trash folder name may be different from [Gmail]/Trash # for example on german googlemail, this setting should be # diff --git a/offlineimap/folder/Gmail.py b/offlineimap/folder/Gmail.py index 8d9c0bc..5d11119 100644 --- a/offlineimap/folder/Gmail.py +++ b/offlineimap/folder/Gmail.py @@ -18,16 +18,18 @@ """Folder implementation to support features of the Gmail IMAP server. """ - from IMAP import IMAPFolder -from offlineimap import imaputil - class GmailFolder(IMAPFolder): """Folder implementation to support features of the Gmail IMAP server. - Specifically, deleted messages are moved to folder `Gmail.TRASH_FOLDER` - (by default: ``[Gmail]/Trash``) prior to expunging them, since - Gmail maps to IMAP ``EXPUNGE`` command to "remove label". + + Removing a message from a folder will only remove the "label" from + the message and keep it in the "All mails" folder. To really delete + a message it needs to be copied to the Trash folder. However, this + is dangerous as our folder moves are implemented as a 1) delete in + one folder and 2) append to the other. If 2 comes before 1, this + will effectively delete the message from all folders. So we cannot + do that until we have a smarter folder move mechanism. For more information on the Gmail IMAP server: http://mail.google.com/support/bin/answer.py?answer=77657&topic=12815 @@ -35,31 +37,6 @@ class GmailFolder(IMAPFolder): def __init__(self, imapserver, name, repository): super(GmailFolder, self).__init__(imapserver, name, repository) - self.realdelete = repository.getrealdelete(name) self.trash_folder = repository.gettrashfolder(name) - #: Gmail will really delete messages upon EXPUNGE in these folders + # Gmail will really delete messages upon EXPUNGE in these folders self.real_delete_folders = [ self.trash_folder, repository.getspamfolder() ] - - def deletemessages_noconvert(self, uidlist): - uidlist = [uid for uid in uidlist if uid in self.messagelist] - if not len(uidlist): - return - - if self.realdelete and not (self.getname() in self.real_delete_folders): - # IMAP expunge is just "remove label" in this folder, - # so map the request into a "move into Trash" - - imapobj = self.imapserver.acquireconnection() - try: - imapobj.select(self.getfullname()) - result = imapobj.uid('copy', - imaputil.uid_sequence(uidlist), - self.trash_folder) - assert result[0] == 'OK', \ - "Bad IMAPlib result: %s" % result[0] - finally: - self.imapserver.releaseconnection(imapobj) - for uid in uidlist: - del self.messagelist[uid] - else: - IMAPFolder.deletemessages_noconvert(self, uidlist) diff --git a/offlineimap/repository/Gmail.py b/offlineimap/repository/Gmail.py index ada2146..f4260c0 100644 --- a/offlineimap/repository/Gmail.py +++ b/offlineimap/repository/Gmail.py @@ -64,11 +64,6 @@ class GmailRepository(IMAPRepository): def getfoldertype(self): return folder.Gmail.GmailFolder - def getrealdelete(self, foldername): - # XXX: `foldername` is currently ignored - the `realdelete` - # setting is repository-wide - return self.getconfboolean('realdelete', 0) - def gettrashfolder(self, foldername): #: Where deleted mail should be moved return self.getconf('trashfolder','[Gmail]/Trash')