From 2cd9616461e3551e3e2e556879fb3e83846754b7 Mon Sep 17 00:00:00 2001 From: Nikolaus Rath Date: Wed, 8 Jul 2015 19:10:46 -0700 Subject: [PATCH] Use IMAP MOVE extension if available Currently Gnus uses a combination of COPY, STORE + EXPUNGE to move messages from one IMAP group into another. This patch enables the use of the MOVE command instead if the server supports it. --- lisp/nnimap.el | 59 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/lisp/nnimap.el b/lisp/nnimap.el index cc1691b..db1a91a 100644 --- a/lisp/nnimap.el +++ b/lisp/nnimap.el @@ -960,17 +960,19 @@ If non-nil, articles flagged as deleted (using the IMAP ;; way. (let ((message-id (message-field-value "message-id"))) (if internal-move-group - (let ((result - (with-current-buffer (nnimap-buffer) - (nnimap-command "UID COPY %d %S" - article - (utf7-encode internal-move-group t))))) - (when (car result) - (nnimap-delete-article article) - (cons internal-move-group - (or (nnimap-find-uid-response "COPYUID" (cadr result)) - (nnimap-find-article-by-message-id - internal-move-group server message-id + (with-current-buffer (nnimap-buffer) + (let* ((can-move (nnimap-capability "MOVE")) + (command (if can-move + "UID MOVE %d %S" + "UID COPY %d %S")) + (result (nnimap-command command article + (utf7-encode internal-move-group t)))) + (when (and (car result) (not can-move)) + (nnimap-delete-article article)) + (cons internal-move-group + (or (nnimap-find-uid-response "COPYUID" (cadr result)) + (nnimap-find-article-by-message-id + internal-move-group server message-id nnimap-request-articles-find-limit))))) ;; Move the article to a different method. (let ((result (eval accept-form))) @@ -1009,11 +1011,12 @@ If non-nil, articles flagged as deleted (using the IMAP (gnus-sorted-complement articles deletable-articles)))))) (defun nnimap-process-expiry-targets (articles group server) - (let ((deleted-articles nil)) + (let ((deleted-articles nil) + (articles-to-delete nil)) (cond ;; shortcut further processing if we're going to delete the articles ((eq nnmail-expiry-target 'delete) - (setq deleted-articles articles) + (setq articles-to-delete articles) t) ;; or just move them to another folder on the same IMAP server ((and (not (functionp nnmail-expiry-target)) @@ -1023,11 +1026,14 @@ If non-nil, articles flagged as deleted (using the IMAP (and (nnimap-change-group group server) (with-current-buffer (nnimap-buffer) (nnheader-message 7 "Expiring articles from %s: %s" group articles) - (nnimap-command - "UID COPY %s %S" - (nnimap-article-ranges (gnus-compress-sequence articles)) - (utf7-encode (gnus-group-real-name nnmail-expiry-target) t)) - (setq deleted-articles articles))) + (let ((can-move (nnimap-capability "MOVE"))) + (nnimap-command + (if can-move + "UID MOVE %s %S" + "UID COPY %s %S") + (nnimap-article-ranges (gnus-compress-sequence articles)) + (utf7-encode (gnus-group-real-name nnmail-expiry-target) t)) + (set (if can-move 'deleted-articles 'articles-to-delete) articles)))) t) (t (dolist (article articles) @@ -1048,11 +1054,13 @@ If non-nil, articles flagged as deleted (using the IMAP (setq target nil)) (nnheader-message 7 "Expiring article %s:%d" group article)) (when target - (push article deleted-articles)))))) - (setq deleted-articles (nreverse deleted-articles)))) + (push article articles-to-delete)))))) + (setq articles-to-delete (nreverse articles-to-delete)))) ;; Change back to the current group again. (nnimap-change-group group server) - (nnimap-delete-article (gnus-compress-sequence deleted-articles)) + (when articles-to-delete + (nnimap-delete-article (gnus-compress-sequence articles-to-delete)) + (setq deleted-articles articles-to-delete)) deleted-articles)) (defun nnimap-find-expired-articles (group) @@ -2103,6 +2111,7 @@ Return the server's response to the SELECT or EXAMINE command." nnmail-split-fancy)) (nnmail-inhibit-default-split-group t) (groups (nnimap-get-groups)) + (can-move (nnimap-capability "MOVE")) new-articles) (erase-buffer) (nnimap-command "SELECT %S" nnimap-inbox) @@ -2137,14 +2146,16 @@ Return the server's response to the SELECT or EXAMINE command." ;; Don't copy if the message is already in its ;; target group. (unless (string= group nnimap-inbox) - (push (list (nnimap-send-command - "UID COPY %s %S" + (push (list (nnimap-send-command + (if can-move + "UID MOVE %d %S" + "UID COPY %s %S") (nnimap-article-ranges ranges) (utf7-encode group t)) ranges) sequences))))) ;; Wait for the last COPY response... - (when sequences + (when (and (not can-move) sequences) (nnimap-wait-for-response (caar sequences)) ;; And then mark the successful copy actions as deleted, ;; and possibly expunge them. -- 2.1.4