syncing custom IMAP flags

Dan Christensen jdc at
Thu Nov 18 23:08:06 GMT 2010

Now that offlineimap development is starting up again, I'm reposting
two messages from November 2009.


Dan Christensen <jdc at> writes:

> I've finally figured out why offlineimap isn't syncing the custom IMAP
> flags that Gnus marks messages with:  it simply doesn't support any
> flags except:
>     flagmap = {'\\seen': 'S',
>                '\\answered': 'R',
>                '\\flagged': 'F',
>                '\\deleted': 'T',
>                '\\draft': 'D'}
> (from  To use offlineimap with Gnus, it's essential that
> the gnus-expire mark be synced, as it is used to do a delayed deletion
> of messages.  It looks to me like this isn't supported by default (even
> for IMAP --> IMAP syncs) because the code is designed with a local
> maildir in mind.
> As a quick fix, I changed the above table to
>     flagmap = {'\\seen': 'S',
>                '\\answered': 'R',
>                '\\flagged': 'F',
>                '\\deleted': 'T',
>                'gnus-expire': 'E',
>                'gnus-dormant': 'Q',
>                'gnus-forward': 'W',
>                'gnus-save': 'V',
>                '\\draft': 'D'}
> (and adjusted the reverse table similarly) and now syncing works
> for me.
> Any chance this change could be accepted?  It shouldn't affect non-Gnus
> users, but will greatly help Gnus users.  I've included the four main
> additional marks that Gnus uses, from most to least important.  (If
> lower case letters are ok, one could also use e, d, f and s for these.)

[Note added: I don't think the above special case is really a good idea.
Instead, options 2 through 4 below seem better to me.]

> Alternatively, could offlineimap handle the IMAP --> IMAP case
> separately and simply copy the flags as is?
> Or, as a third alternative, offlineimap could do what dovecot does,
> which is to keep a mapping between custom flags and lower case letters,
> and use those letters when storing to the maildir.  This last solution
> means that *any* custom flags work, both with IMAP --> IMAP and IMAP -->
> Maildir.  See
> Thanks,
> Dan

Dan Christensen <jdc at> writes:

> A fourth alternative is to apply the patch attached below.  It combines
> the two flagmap dictionaries into one list which is used for both
> directions, and it makes this list a global.  The first change means
> that there is no chance of the two mappings getting out of sync.  The
> second change means that flagmap can be monkeypatched by code in
>, such as:
> import offlineimap.imaputil as IU
> if not hasattr(IU, 'monkeypatchdone'):
>     IU.flagmap += [('gnus-expire','E'),
>                    ('gnus-dormant', 'Q'),
>                    ('gnus-save', 'V'),
>                    ('gnus-forward', 'W')]
>     IU.monkeypatchdone = True
> The patch should produce results identical with the old code.  It just
> allows for easier customization.  (And it doesn't recreate the flagmap
> dictionaries every time the flag functions are called, so it might even
> be more efficient.  It also renames the variable list to another name,
> to avoid shadowing the list class.)
> I still like my second and third ideas above, but this fourth method
> will at least allow users with special needs to handle custom flags.
> The monkeypatching code above could be put in a FAQ somewhere, or in the
> advanced section of the default .offlineimaprc file.
> Best,
> Dan

---	2008-03-02 18:58:51.000000000 -0500
+++	2009-11-25 20:43:28.000000000 -0500
@@ -147,30 +147,26 @@
     debug("imapsplit() returning:", retval)
     return retval
+flagmap = [('\\Seen', 'S'),
+           ('\\Answered', 'R'),
+           ('\\Flagged', 'F'),
+           ('\\Deleted', 'T'),
+           ('\\Draft', 'D')]
 def flagsimap2maildir(flagstring):
-    flagmap = {'\\seen': 'S',
-               '\\answered': 'R',
-               '\\flagged': 'F',
-               '\\deleted': 'T',
-               '\\draft': 'D'}
     retval = []
     imapflaglist = [x.lower() for x in flagstring[1:-1].split()]
-    for imapflag in imapflaglist:
-        if flagmap.has_key(imapflag):
-            retval.append(flagmap[imapflag])
+    for imapflag, maildirflag in flagmap:
+        if imapflag.lower() in imapflaglist:
+            retval.append(maildirflag)
     return retval
-def flagsmaildir2imap(list):
-    flagmap = {'S': '\\Seen',
-               'R': '\\Answered',
-               'F': '\\Flagged',
-               'T': '\\Deleted',
-               'D': '\\Draft'}
+def flagsmaildir2imap(maildirflaglist):
     retval = []
-    for mdflag in list:
-        if flagmap.has_key(mdflag):
-            retval.append(flagmap[mdflag])
+    for imapflag, maildirflag in flagmap:
+        if maildirflag in maildirflaglist:
+            retval.append(imapflag)
     return '(' + ' '.join(retval) + ')'

More information about the OfflineIMAP-project mailing list