]> granicus.if.org Git - mutt/commitdiff
Add imap-fast-trash patch.
authorKevin McCarthy <kevin@8t8.us>
Mon, 18 Jul 2016 02:31:16 +0000 (19:31 -0700)
committerKevin McCarthy <kevin@8t8.us>
Mon, 18 Jul 2016 02:31:16 +0000 (19:31 -0700)
This is based on the patch by Paul Miller.

Modifications are:

* Create a new flag, MUTT_TRASH for imap_make_msg_set(), rather than
  use MUTT_EXPIRED.

* Change imap_make_msg_set(MUTT_TRASH) to only look at
  hdrs[n]->deleted && !hdrs[n]->purge, behaving like MUTT_TAG, rather
  than looking at the HEADER_DATA.

* Reimplement imap_fast_trash() based on imap_copy_message().
  It looks the old version was too, but it lacked handling of TRYCREATE
  and also queued the UID COPY but didn't exec it.  (Presumably this
  happened in the subsequent sync).

* Move the Context magic and mx_is_imap() checks outside of
  imap_fast_trash()

imap/imap.c
imap/imap.h
mutt.h
mx.c

index f5066b2547308c7d102f64b9c4980abd2b81f60e..460a3d68ea7e65860b4ecda5a7bd0d3992068df7 100644 (file)
@@ -924,6 +924,10 @@ static int imap_make_msg_set (IMAP_DATA* idata, BUFFER* buf, int flag,
          if (hdrs[n]->tagged)
            match = 1;
          break;
+        case MUTT_TRASH:
+          if (hdrs[n]->deleted && !hdrs[n]->purge)
+            match = 1;
+         break;
       }
 
     if (match && (!changed || hdrs[n]->changed))
@@ -2073,6 +2077,101 @@ int imap_complete(char* dest, size_t dlen, char* path) {
   return -1;
 }
 
+/* imap_fast_trash: use server COPY command to copy deleted
+ * messages to the trash folder.
+ *   Return codes:
+ *      -1: error
+ *       0: success
+ *       1: non-fatal error - try fetch/append */
+int imap_fast_trash (CONTEXT* ctx, char* dest)
+{
+  IMAP_DATA* idata;
+  char mbox[LONG_STRING];
+  char mmbox[LONG_STRING];
+  char prompt[LONG_STRING];
+  int rc;
+  IMAP_MBOX mx;
+  int triedcreate = 0;
+
+  idata = (IMAP_DATA*) ctx->data;
+
+  if (imap_parse_path (dest, &mx))
+  {
+    dprint (1, (debugfile, "imap_fast_trash: bad destination %s\n", dest));
+    return -1;
+  }
+
+  /* check that the save-to folder is in the same account */
+  if (!mutt_account_match (&(CTX_DATA->conn->account), &(mx.account)))
+  {
+    dprint (3, (debugfile, "imap_fast_trash: %s not same server as %s\n",
+      dest, ctx->path));
+    return 1;
+  }
+
+  imap_fix_path (idata, mx.mbox, mbox, sizeof (mbox));
+  if (!*mbox)
+    strfcpy (mbox, "INBOX", sizeof (mbox));
+  imap_munge_mbox_name (idata, mmbox, sizeof (mmbox), mbox);
+
+  /* loop in case of TRYCREATE */
+  do
+  {
+    rc = imap_exec_msgset (idata, "UID COPY", mmbox, MUTT_TRASH, 0, 0);
+    if (!rc)
+    {
+      dprint (1, (debugfile, "imap_fast_trash: No messages to trash\n"));
+      rc = -1;
+      goto out;
+    }
+    else if (rc < 0)
+    {
+      dprint (1, (debugfile, "could not queue copy\n"));
+      goto out;
+    }
+    else
+      mutt_message (_("Copying %d messages to %s..."), rc, mbox);
+
+    /* let's get it on */
+    rc = imap_exec (idata, NULL, IMAP_CMD_FAIL_OK);
+    if (rc == -2)
+    {
+      if (triedcreate)
+      {
+        dprint (1, (debugfile, "Already tried to create mailbox %s\n", mbox));
+        break;
+      }
+      /* bail out if command failed for reasons other than nonexistent target */
+      if (ascii_strncasecmp (imap_get_qualifier (idata->buf), "[TRYCREATE]", 11))
+        break;
+      dprint (3, (debugfile, "imap_fast_trash: server suggests TRYCREATE\n"));
+      snprintf (prompt, sizeof (prompt), _("Create %s?"), mbox);
+      if (option (OPTCONFIRMCREATE) && mutt_yesorno (prompt, 1) < 1)
+      {
+        mutt_clear_error ();
+        goto out;
+      }
+      if (imap_create_mailbox (idata, mbox) < 0)
+        break;
+      triedcreate = 1;
+    }
+  }
+  while (rc == -2);
+
+  if (rc != 0)
+  {
+    imap_error ("imap_fast_trash", idata->buf);
+    goto out;
+  }
+
+  rc = 0;
+
+ out:
+  FREE (&mx.mbox);
+
+  return rc < 0 ? -1 : rc;
+}
+
 struct mx_ops mx_imap_ops = {
   .open = imap_open_mailbox,
   .close = imap_close_mailbox,
index ff0a1ba01f5d8cc7226a68f6249d2d08209c8bf6..891cc0bf8748f29685fd9a58b2199bd5219f3dad 100644 (file)
@@ -43,6 +43,7 @@ int imap_status (char *path, int queue);
 int imap_search (CONTEXT* ctx, const pattern_t* pat);
 int imap_subscribe (char *path, int subscribe);
 int imap_complete (char* dest, size_t dlen, char* path);
+int imap_fast_trash (CONTEXT* ctx, char* dest);
 
 void imap_allow_reopen (CONTEXT *ctx);
 void imap_disallow_reopen (CONTEXT *ctx);
diff --git a/mutt.h b/mutt.h
index bd90a49b4d2d9b7fbd0ec705456686dbba8cf431..18fb2d1670ce7aecfe3152f1b6e33db00dd706e3 100644 (file)
--- a/mutt.h
+++ b/mutt.h
@@ -189,6 +189,7 @@ enum
   MUTT_LIMIT,
   MUTT_EXPIRED,
   MUTT_SUPERSEDED,
+  MUTT_TRASH,
 
   /* actions for mutt_pattern_comp/mutt_pattern_exec */
   MUTT_AND,
diff --git a/mx.c b/mx.c
index 07f3b4080da8f7d38ac39c6a0914e18e3b5e6c4b..70f31f7412c6f0bda4f7a9d8f0a058efc6d9b1d7 100644 (file)
--- a/mx.c
+++ b/mx.c
@@ -832,6 +832,14 @@ static int trash_append (CONTEXT *ctx)
       && stc.st_dev == st.st_dev && stc.st_rdev == st.st_rdev)
     return 0;  /* we are in the trash folder: simple sync */
 
+#ifdef USE_IMAP
+  if (Context->magic == MUTT_IMAP && mx_is_imap (TrashPath))
+  {
+    if (!imap_fast_trash (Context, TrashPath))
+      return 0;
+  }
+#endif
+
   if ((ctx_trash = mx_open_mailbox (TrashPath, MUTT_APPEND, NULL)) != NULL)
   {
     /* continue from initial scan above */