(require 'gnus)
(require 'nnoo)
(require 'netrc)
+(require 'parse-time)
(nnoo-declare nnimap)
likely value would be \"text/\" to automatically fetch all
textual parts.")
+(defvoo nnimap-expunge nil)
+
(defvoo nnimap-connection-alist nil)
(defvoo nnimap-current-infos nil)
(erase-buffer)
(insert
(format
- "211 %d %d %d %S\n" (1+ (- high low)) low high group))))
- t)))
+ "211 %d %d %d %S\n" (1+ (- high low)) low high group)))
+ t))))
(deffoo nnimap-request-create-group (group &optional server args)
(when (nnimap-possibly-change-group nil server)
(deffoo nnimap-request-move-article (article group server accept-form
&optional last internal-move-group)
- (when (nnimap-possibly-change-group group server)
- ;; If the move is internal (on the same server), just do it the easy
- ;; 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
- (nnimap-find-article-by-message-id
- internal-move-group message-id))))
- (with-temp-buffer
- (when (nnimap-request-article article group server (current-buffer))
- (let ((result (eval accept-form)))
- (when result
+ (with-temp-buffer
+ (when (nnimap-request-article article group server (current-buffer))
+ ;; If the move is internal (on the same server), just do it the easy
+ ;; 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)
- result))))))))
+ (cons internal-move-group
+ (nnimap-find-article-by-message-id
+ internal-move-group message-id))))
+ ;; Move the article to a different method.
+ (let ((result (eval accept-form)))
+ (when result
+ (nnimap-delete-article article)
+ result)))))))
(deffoo nnimap-request-expire-articles (articles group &optional server force)
(cond
+ ((null articles)
+ nil)
((not (nnimap-possibly-change-group group server))
articles)
((and force
(message "Article marked for deletion, but not expunged."))
nil)
(t
- articles)))
+ (let ((deletable-articles
+ (if force
+ articles
+ (gnus-sorted-intersection
+ articles
+ (nnimap-find-expired-articles group)))))
+ (if (null deletable-articles)
+ articles
+ (if (eq nnmail-expiry-target 'delete)
+ (nnimap-delete-article deletable-articles)
+ (setq deletable-articles
+ (nnimap-process-expiry-targets
+ deletable-articles group server)))
+ ;; Return the articles we didn't delete.
+ (gnus-sorted-complement articles deletable-articles))))))
+
+(defun nnimap-process-expiry-targets (articles group server)
+ (let ((deleted-articles nil))
+ (dolist (article articles)
+ (let ((target nnmail-expiry-target))
+ (with-temp-buffer
+ (when (nnimap-request-article article group server (current-buffer))
+ (message "Expiring article %s:%d" group article)
+ (when (functionp target)
+ (setq target (funcall target group)))
+ (when (and target
+ (not (eq target 'delete)))
+ (if (or (gnus-request-group target t)
+ (gnus-request-create-group target))
+ (nnmail-expiry-target-group target group)
+ (setq target nil)))
+ (when target
+ (push article deleted-articles))))))
+ ;; Change back to the current group again.
+ (nnimap-possibly-change-group group server)
+ (setq deleted-articles (nreverse deleted-articles))
+ (nnimap-delete-article deleted-articles)
+ deleted-articles))
+
+(defun nnimap-find-expired-articles (group)
+ (let ((cutoff (nnmail-expired-article-p group nil nil)))
+ (with-current-buffer (nnimap-buffer)
+ (let ((result
+ (nnimap-command
+ "UID SEARCH SENTBEFORE %s"
+ (format-time-string
+ (format "%%d-%s-%%Y"
+ (upcase
+ (car (rassoc (nth 4 (decode-time cutoff))
+ parse-time-months))))
+ cutoff))))
+ (and (car result)
+ (delete 0 (mapcar #'string-to-number
+ (cdr (assoc "SEARCH" (cdr result))))))))))
+
(defun nnimap-find-article-by-message-id (group message-id)
(when (nnimap-possibly-change-group group nil)
(with-current-buffer (nnimap-buffer)
(nnimap-command "UID STORE %s +FLAGS.SILENT (\\Deleted)"
(nnimap-article-ranges articles))
- (when (member "UIDPLUS" (nnimap-capabilities nnimap-object))
- (nnimap-send-command "UID EXPUNGE %s"
- (nnimap-article-ranges articles))
- t)))
+ (cond
+ ((member "UIDPLUS" (nnimap-capabilities nnimap-object))
+ (nnimap-command "UID EXPUNGE %s"
+ (nnimap-article-ranges articles))
+ t)
+ (nnimap-expunge
+ (nnimap-command "EXPUNGE")
+ t))))
(deffoo nnimap-request-scan (&optional group server)
(when (and (nnimap-possibly-change-group nil server)
(defun nnimap-mark-and-expunge-incoming (range)
(when range
(setq range (nnimap-article-ranges range))
- (nnimap-send-command
- "UID STORE %s +FLAGS.SILENT (\\Deleted)" range)
- (cond
- ;; If the server supports it, we now delete the message we have
- ;; just copied over.
- ((member "UIDPLUS" (nnimap-capabilities nnimap-object))
- (nnimap-send-command "UID EXPUNGE %s" range))
- ;; If it doesn't support UID EXPUNGE, then we only expunge if the
- ;; user has configured it.
- (nnimap-expunge-inbox
- (nnimap-send-command "EXPUNGE")))))
+ (let ((sequence
+ (nnimap-send-command
+ "UID STORE %s +FLAGS.SILENT (\\Deleted)" range)))
+ (cond
+ ;; If the server supports it, we now delete the message we have
+ ;; just copied over.
+ ((member "UIDPLUS" (nnimap-capabilities nnimap-object))
+ (setq sequence (nnimap-send-command "UID EXPUNGE %s" range)))
+ ;; If it doesn't support UID EXPUNGE, then we only expunge if the
+ ;; user has configured it.
+ (nnimap-expunge-inbox
+ (setq sequence (nnimap-send-command "EXPUNGE"))))
+ (nnimap-wait-for-response sequence))))
(defun nnimap-parse-copied-articles (sequences)
(let (sequence copied range)