|
@@ -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 *******************/
|