[PATCH] Write IMAP keyword changes (maildir file renames) back to the server

Igor Almeida igor.contato at gmail.com
Tue May 14 04:16:19 BST 2019


Accomplish this by peeking at the source folder (which should be a Maildir) and
reversing the keyword-to-maildirflag mapping to discover which IMAP keyword
corresponds to which maildir flag.

It's quite dirty right now.

Signed-off-by: Igor Almeida <igor.contato at gmail.com>
---
 offlineimap/folder/IMAP.py | 21 ++++++++++++++++++++-
 offlineimap/imaputil.py    | 10 +++++++++-
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/offlineimap/folder/IMAP.py b/offlineimap/folder/IMAP.py
index ead4396..12d9840 100644
--- a/offlineimap/folder/IMAP.py
+++ b/offlineimap/folder/IMAP.py
@@ -899,6 +899,24 @@ class IMAPFolder(BaseFolder):
         self.__processmessagesflags('-', uidlist, flags)
 
     def __processmessagesflags_real(self, operation, uidlist, flags):
+        #before connecting, let us calculate the necessary flags & keywords to store/remove
+        repo = self.getrepository()
+        account = repo.getaccount()
+        otherfolder = account.get_local_folder(self) #this is supposed to be maildir
+        otherrepo = otherfolder.getrepository()
+        try:
+            keywordmap = otherrepo.getkeywordmap()
+            #now flip the map, because we need to translate flags into IMAP keywords
+            reversed_keywordmap = dict(zip(keywordmap.itervalues(), keywordmap.iterkeys()))
+
+            #TODO check other calls to imaputil.flagsmaildir2imap()
+            flagstring = imaputil.flagsmaildir2imap(flags, reversed_keywordmap)
+        except NotImplementedError:
+            #are we doing IMAP-to-IMAP then? just fail
+            raise OfflineImapError(
+                'Error getting keywordmap', OfflineImapError.ERROR.MESSAGE)
+
+        #done, now connect and do it
         imapobj = self.imapserver.acquireconnection()
         try:
             try:
@@ -908,7 +926,7 @@ class IMAPFolder(BaseFolder):
                 return
             response = imapobj.uid('store',
                 imaputil.uid_sequence(uidlist), operation + 'FLAGS',
-                    imaputil.flagsmaildir2imap(flags))
+                    flagstring)
             if response[0] != 'OK':
                 raise OfflineImapError(
                     'Error with store: %s'% '. '.join(response[1]),
@@ -932,6 +950,7 @@ class IMAPFolder(BaseFolder):
             flagstr = attributehash['FLAGS']
             uid = int(attributehash['UID'])
             self.messagelist[uid]['flags'] = imaputil.flagsimap2maildir(flagstr)
+            self.messagelist[uid]['keywords'] = imaputil.flagsimap2keywords(flagstr)
             try:
                 needupdate.remove(uid)
             except ValueError:  # Let it slide if it's not in the list.
diff --git a/offlineimap/imaputil.py b/offlineimap/imaputil.py
index 39bd8d4..28067ef 100644
--- a/offlineimap/imaputil.py
+++ b/offlineimap/imaputil.py
@@ -211,13 +211,21 @@ def flagsimap2keywords(flagstring):
     serverflagset = set([flag for (flag, c) in flagmap])
     return imapflagset - serverflagset
 
-def flagsmaildir2imap(maildirflaglist):
+def flagsmaildir2imap(maildirflaglist, letters_to_keywords_map=dict()):
     """Convert set of flags ([DR]) into a string '(\\Deleted \\Draft)'."""
 
     retval = []
     for imapflag, maildirflag in flagmap:
         if maildirflag in maildirflaglist:
             retval.append(imapflag)
+
+    #use the additional dict now
+    if len(letters_to_keywords_map) > 0:
+        for flag in maildirflaglist:
+            if flag in letters_to_keywords_map:
+                retval.append(letters_to_keywords_map[flag])
+
+    #NOTE there might be a problem with spaces in the keywordmap
     return '(' + ' '.join(sorted(retval)) + ')'
 
 def uid_sequence(uidlist):
-- 
2.21.0




More information about the OfflineIMAP-project mailing list