diff --git a/src/drv_imap.c b/src/drv_imap.c index 692afe5..7982381 100644 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@ -1671,13 +1671,43 @@ imap_set_flags_p2( imap_store_t *ctx ATTR_UNUSED, struct imap_cmd *cmd, int resp /******************* imap_close *******************/ static void -imap_close( store_t *ctx, +imap_close( store_t *gctx, void (*cb)( int sts, void *aux ), void *aux ) { - struct imap_cmd_simple *cmd; + imap_store_t *ctx = (imap_store_t *)gctx; - INIT_IMAP_CMD(imap_cmd_simple, cmd, cb, aux) - imap_exec( (imap_store_t *)ctx, &cmd->gen, imap_done_simple_box, "CLOSE" ); + if (CAP(UIDPLUS)) { + struct imap_cmd_refcounted_state *sts = imap_refcounted_new_state( cb, aux ); + message_t *msg, *fmsg, *nmsg; + int bl; + char buf[1000]; + + for (msg = ctx->gen.msgs; ; ) { + for (bl = 0; msg && bl < 960; msg = msg->next) { + if (!(msg->flags & F_DELETED)) + continue; + if (bl) + buf[bl++] = ','; + bl += sprintf( buf + bl, "%d", msg->uid ); + fmsg = msg; + for (; (nmsg = msg->next) && (nmsg->flags & F_DELETED); msg = nmsg) {} + if (msg != fmsg) + bl += sprintf( buf + bl, ":%d", msg->uid ); + } + if (!bl) + break; + if (imap_exec( ctx, imap_refcounted_new_cmd( sts ), imap_refcounted_done_box, + "UID EXPUNGE %s", buf ) < 0) + break; + } + imap_refcounted_done( sts ); + } else { + /* This is inherently racy: it may cause messages which other clients + * marked as deleted to be expunged without being trashed. */ + struct imap_cmd_simple *cmd; + INIT_IMAP_CMD(imap_cmd_simple, cmd, cb, aux) + imap_exec( ctx, &cmd->gen, imap_done_simple_box, "CLOSE" ); + } } /******************* imap_trash_msg *******************/ diff --git a/src/mbsync.1 b/src/mbsync.1 index 7f653b6..3b2fa62 100644 --- a/src/mbsync.1 +++ b/src/mbsync.1 @@ -484,13 +484,13 @@ times within a Group. .SH INHERENT PROBLEMS Changes done after \fBmbsync\fR has retrieved the message list will not be synchronised until the next time \fBmbsync\fR is invoked. -.. -.SH BUGS -Using \fBTrash\fR on IMAP Stores bears a race condition: messages will be +.P +Using \fBTrash\fR on IMAP Stores without the UIDPLUS extension (notably, +M$ Exchange up to at least 2010) bears a race condition: messages will be lost if they are marked as deleted after the message list was retrieved but -before the mailbox is expunged. This can be fixed by using UID EXPUNGE. -There is no risk as long as the IMAP mailbox is not simultaneously accessed -by \fBmbsync\fR and another mail client. +before the mailbox is expunged. +There is no risk as long as the IMAP mailbox is accessed by only one client +(including \fBmbsync\fR) at a time. .. .SH FILES .TP