Browse Source

implement Forwarded flag

maildir supports a 'P' flag which denotes the fact that a message has
been 'passed' on (forwarded, bounced). notmuch syncs this to the
'passed' tag.

Per https://tools.ietf.org/html/rfc5788, IMAP has a user-defined flag
(keyword) '$Forwarded' that is supported by many servers and clients
these days. (Technically, one should check for '$Forwarded' in the
server response.)

Restructure mbsync's flag parser to accept keywords (flags starting with
'$') but still bail out on unknown system flags (flags starting with '\').
Support '$Forwarded' as a first keyword since it maps to maildir's 'P'
and needs to be sorted in between the system flags.

Signed-off-by: Michael J Gruber <github@grubix.eu>
Michael J Gruber 7 years ago
parent
commit
c4d7f0189c
6 changed files with 22 additions and 17 deletions
  1. 2 0
      NEWS
  2. 5 4
      src/driver.h
  3. 12 10
      src/drv_imap.c
  4. 1 1
      src/drv_maildir.c
  5. 1 1
      src/drv_proxy.c
  6. 1 1
      src/sync.c

+ 2 - 0
NEWS

@@ -2,6 +2,8 @@
 
 The 'isync' compatibility wrapper was removed.
 
+The IMAP '$Forwarded' / Maildir 'P' (passed) flag is supported now.
+
 [1.3.0]
 
 Network timeout handling has been added.

+ 5 - 4
src/driver.h

@@ -49,10 +49,11 @@ typedef struct store_conf {
 /* The order is according to alphabetical maildir flag sort */
 #define F_DRAFT	     (1<<0) /* Draft */
 #define F_FLAGGED    (1<<1) /* Flagged */
-#define F_ANSWERED   (1<<2) /* Replied */
-#define F_SEEN       (1<<3) /* Seen */
-#define F_DELETED    (1<<4) /* Trashed */
-#define NUM_FLAGS 5
+#define F_PASSED     (1<<2) /* Passed */
+#define F_ANSWERED   (1<<3) /* Replied */
+#define F_SEEN       (1<<4) /* Seen */
+#define F_DELETED    (1<<5) /* Trashed */
+#define NUM_FLAGS 6
 
 /* For message->status */
 #define M_RECENT       (1<<0) /* unsyncable flag; maildir_* depend on this being 1<<0 */

+ 12 - 10
src/drv_imap.c

@@ -247,11 +247,12 @@ static void imap_invoke_bad_callback( imap_store_t *ctx );
 /* grep for MAILBOX_DRIVER_FLAG */
 /* The order is according to alphabetical maildir flag sort */
 static const char *Flags[] = {
-	"Draft",
-	"Flagged",
-	"Answered",
-	"Seen",
-	"Deleted",
+	"\\Draft",	/* 'D' */
+	"\\Flagged",	/* 'F' */
+	"$Forwarded",	/* 'P' */
+	"\\Answered",	/* 'R' */
+	"\\Seen",	/* 'S' */
+	"\\Deleted",	/* 'T' */
 };
 
 static imap_cmd_t *
@@ -989,17 +990,19 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
 				if (is_list( tmp )) {
 					for (flags = tmp->child; flags; flags = flags->next) {
 						if (is_atom( flags )) {
-							if (flags->val[0] == '\\') { /* ignore user-defined flags for now */
-								if (!strcmp( "Recent", flags->val + 1)) {
+							if (flags->val[0] == '\\' || flags->val[0] == '$') {
+								if (!strcmp( "\\Recent", flags->val)) {
 									status |= M_RECENT;
 									goto flagok;
 								}
 								for (i = 0; i < as(Flags); i++)
-									if (!strcmp( Flags[i], flags->val + 1 )) {
+									if (!strcmp( Flags[i], flags->val)) {
 										mask |= 1 << i;
 										goto flagok;
 									}
-								if (flags->val[1] == 'X' && flags->val[2] == '-')
+								if (flags->val[0] == '$')
+									goto flagok; /* ignore unknown user-defined flags (keywords) */
+								if (flags->val[0] == '\\' && flags->val[1] == 'X' && flags->val[2] == '-')
 									goto flagok; /* ignore system flag extensions */
 								error( "IMAP warning: unknown system flag %s\n", flags->val );
 							}
@@ -2664,7 +2667,6 @@ imap_make_flags( int flags, char *buf )
 	for (i = d = 0; i < as(Flags); i++)
 		if (flags & (1 << i)) {
 			buf[d++] = ' ';
-			buf[d++] = '\\';
 			for (s = Flags[i]; *s; s++)
 				buf[d++] = *s;
 		}

+ 1 - 1
src/drv_maildir.c

@@ -111,7 +111,7 @@ debug( const char *msg, ... )
 /* Keep the mailbox driver flag definitions in sync: */
 /* grep for MAILBOX_DRIVER_FLAG */
 /* The order is according to alphabetical maildir flag sort */
-static const char Flags[] = { 'D', 'F', 'R', 'S', 'T' };
+static const char Flags[] = { 'D', 'F', 'P', 'R', 'S', 'T' };
 
 static uchar
 maildir_parse_flags( const char *info_prefix, const char *base )

+ 1 - 1
src/drv_proxy.c

@@ -58,7 +58,7 @@ debugn( const char *msg, ... )
 /* Keep the mailbox driver flag definitions in sync: */
 /* grep for MAILBOX_DRIVER_FLAG */
 /* The order is according to alphabetical maildir flag sort */
-static const char Flags[] = { 'D', 'F', 'R', 'S', 'T' };
+static const char Flags[] = { 'D', 'F', 'P', 'R', 'S', 'T' };
 
 static char *
 proxy_make_flags( int flags, char *buf )

+ 1 - 1
src/sync.c

@@ -100,7 +100,7 @@ Fprintf( FILE *f, const char *msg, ... )
 /* Keep the mailbox driver flag definitions in sync: */
 /* grep for MAILBOX_DRIVER_FLAG */
 /* The order is according to alphabetical maildir flag sort */
-static const char Flags[] = { 'D', 'F', 'R', 'S', 'T' };
+static const char Flags[] = { 'D', 'F', 'P', 'R', 'S', 'T' };
 
 static int
 parse_flags( const char *buf )