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>
This commit is contained in:
Michael J Gruber 2018-06-21 16:52:01 +02:00 committed by Oswald Buddenhagen
parent e71f0ccc2a
commit c4d7f0189c
6 changed files with 22 additions and 17 deletions

2
NEWS
View File

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

View File

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

View File

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

View File

@ -111,7 +111,7 @@ debug( const char *msg, ... )
/* Keep the mailbox driver flag definitions in sync: */ /* Keep the mailbox driver flag definitions in sync: */
/* grep for MAILBOX_DRIVER_FLAG */ /* grep for MAILBOX_DRIVER_FLAG */
/* The order is according to alphabetical maildir flag sort */ /* 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 static uchar
maildir_parse_flags( const char *info_prefix, const char *base ) maildir_parse_flags( const char *info_prefix, const char *base )

View File

@ -58,7 +58,7 @@ debugn( const char *msg, ... )
/* Keep the mailbox driver flag definitions in sync: */ /* Keep the mailbox driver flag definitions in sync: */
/* grep for MAILBOX_DRIVER_FLAG */ /* grep for MAILBOX_DRIVER_FLAG */
/* The order is according to alphabetical maildir flag sort */ /* 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 * static char *
proxy_make_flags( int flags, char *buf ) proxy_make_flags( int flags, char *buf )

View File

@ -100,7 +100,7 @@ Fprintf( FILE *f, const char *msg, ... )
/* Keep the mailbox driver flag definitions in sync: */ /* Keep the mailbox driver flag definitions in sync: */
/* grep for MAILBOX_DRIVER_FLAG */ /* grep for MAILBOX_DRIVER_FLAG */
/* The order is according to alphabetical maildir flag sort */ /* 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 static int
parse_flags( const char *buf ) parse_flags( const char *buf )