Does gnus-summary-move-article need to clear the marks?
Hey, I'm trying out Gnus and the IMAP server from which I'm getting my emails is running a Sieve script that takes some actions, including setting a bunch of IMAP keywords/flags ('client' ones, not the system ones like \Seen as per https://www.rfc-editor.org/rfc/rfc3501#section-2.3.2). When an email with these custom flags is marked as read (via 'd', gnus-summary-mark-as-read-forward) and moved to another IMAP folder (via 'B m', gnus-summary-move-article) it loses its flags. In the IMAP log (that I got with nnimap-record-commands) I can see: UID STORE 65 FLAGS.SILENT (\Seen) A quick Edebug breakpoint on nnimap-request-set-mark (where the magic seems to happen) gives the following backtrace: nnimap-request-set-mark("INBOX" (((65) set (read)) ((65) del (unexist seen forward unsend download cache save score dormant bookmark killed expire reply tick))) "$SERVER") gnus-request-set-mark("nnimap+$SERVER:INBOX" (((65) set (read)) ((65) del (unexist seen forward unsend download cache save score dormant bookmark killed expire reply tick gnus-summary-push-marks-to-backend(65) gnus-summary-move-article(nil) funcall-interactively(gnus-summary-move-article nil) command-execute(gnus-summary-move-article) So the issue appears to be that gnus-summary-push-marks-to-backend calls gnus-request-set-mark with 'set: https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/gnus/gnus-sum.el?h=emacs-28.2#n10390 Should it be 'add instead, which should preserve the set of flags? https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/gnus/nnimap.el?h=emacs-28.2#n1243 Similarly to what marking as read does: UID STORE 67 +FLAGS.SILENT (\Seen) >From around here: https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/gnus/gnus-sum.el?h=emacs-28.2#n12896 This patch appears to work but I'm not familiar with the code: diff --git i/lisp/gnus/gnus-sum.el w/lisp/gnus/gnus-sum.el index 3f350bffb3..a13777cd95 100644 --- i/lisp/gnus/gnus-sum.el +++ w/lisp/gnus/gnus-sum.el @@ -10390 +10390 @@ ACTION can be either `move' (the default), `crosspost' or `copy'." -(gnus-request-set-mark gnus-newsgroup-name `(((,article) set ,set) +(gnus-request-set-mark gnus-newsgroup-name `(((,article) add ,set) PS: I sent a similar email to d...@gnus.org a few days ago but it doesn't look like it went through. Apologies if it ends up duplicated.
Re: Keeping IMAP connection alive when using it in mail-sources
Adam Sjøgren wrote: > Here's the modified version of mail-source-fetch-imap > I cobbled together - the handling of deleting the buffer if > there is no process is not so pretty: > > (defun mail-source-fetch-imap (source callback) > "Fetcher for imap sources." > (mail-source-bind (imap source) > (mail-source-run-script > prescript > `((?p . ,password) (?t . ,mail-source-crash-box) >(?s . ,server) (?P . ,port) (?u . ,user)) > prescript-delay) > (let ((from (format "%s:%s:%s" server user port)) > (found 0) > (imap-shell-program (or (list program) imap-shell-program))) > (let ((buf (or (and (or (get-buffer-process " *imap source*") > (and (get-buffer " *imap source*") >(kill-buffer " *imap source*"))) > (get-buffer " *imap source*")) > (let ((newbuf (generate-new-buffer " *imap source*"))) > (if (and (imap-open server port stream authentication > newbuf) > (imap-authenticate >user (or (cdr (assoc from > mail-source-password-cache)) > password) > newbuf)) >newbuf > (progn >(imap-close newbuf) > ;; We nix out the password in case the error > ;; was because of a wrong password being given. > (setq mail-source-password-cache >(delq (assoc from mail-source-password-cache) > mail-source-password-cache)) > (error "IMAP error: %s" (imap-error-text > newbuf > (let ((mailbox-list (if (listp mailbox) mailbox (list mailbox > (dolist (mailbox mailbox-list) > (when (imap-mailbox-select mailbox nil buf) > (let ((coding-system-for-write > mail-source-imap-file-coding-system) > (mail-source-string (format "imap:%s:%s" server mailbox)) > str remove) > (message "Fetching from %s..." mailbox) > (with-temp-file mail-source-crash-box > ;; Avoid converting 8-bit chars from inserted strings to > ;; multibyte. > (mm-disable-multibyte) > ;; remember password > (with-current-buffer buf > (when (and imap-password > (not (member (cons from imap-password) > mail-source-password-cache))) > (push (cons from imap-password) > mail-source-password-cache))) > ;; if predicate is nil, use all uids > (dolist (uid (imap-search (or predicate "1:*") buf)) > (when (setq str > (if (imap-capability 'IMAP4rev1 buf) > (caddar (imap-fetch uid "BODY.PEEK[]" > 'BODYDETAIL nil buf)) > (imap-fetch uid "RFC822.PEEK" 'RFC822 nil > buf))) > (push uid remove) > (insert "From imap " (current-time-string) "\n") > (save-excursion > (insert str "\n\n")) > (while (let ((case-fold-search nil)) > (re-search-forward "^From " nil t)) > (replace-match ">From ")) > (goto-char (point-max > (nnheader-ms-strip-cr)) > (cl-incf found (mail-source-callback callback server)) > (mail-source-delete-crash-box) > (when (and remove fetchflag) > (setq remove (nreverse remove)) > (imap-message-flags-add > (imap-range-to-message-set (gnus-compress-sequence remove)) > fetchflag nil buf)) > (if dontexpunge > (imap-mailbox-unselect buf) > (imap-mailbox-close nil buf)) > (mail-source-run-script > postscript > `((?p . ,password) (?t . ,mail-source-crash-box) >(?s . ,server) (?P . ,port) (?u . ,user))) > found Good work but consider writing longer functions? -- underground experts united https://dataswamp.org/~incal
Re: Keeping IMAP connection alive when using it in mail-sources
Adam writes: > Eric writes: > >> Not with the code as it's written! There's a very definite >> (imap-close buf) at the end of the mail source fetching, then the buffer >> is deleted. I guess it wouldn't be a bad idea to add a keepalive option >> to imap.el, but someone would have to do that! > > I guess changing mail-source-fetch-imap to check if the buffer already > exists and if the connected process is still there, and then not closing > imap and not killing the buffer at the end, would be the bare minimum. I've tried doing that now. Fetching news and mail now takes me 1.3 second, down from 2.2 seconds. Nice! Here's the modified version of mail-source-fetch-imap I cobbled together - the handling of deleting the buffer if there is no process is not so pretty: (defun mail-source-fetch-imap (source callback) "Fetcher for imap sources." (mail-source-bind (imap source) (mail-source-run-script prescript `((?p . ,password) (?t . ,mail-source-crash-box) (?s . ,server) (?P . ,port) (?u . ,user)) prescript-delay) (let ((from (format "%s:%s:%s" server user port)) (found 0) (imap-shell-program (or (list program) imap-shell-program))) (let ((buf (or (and (or (get-buffer-process " *imap source*") (and (get-buffer " *imap source*") (kill-buffer " *imap source*"))) (get-buffer " *imap source*")) (let ((newbuf (generate-new-buffer " *imap source*"))) (if (and (imap-open server port stream authentication newbuf) (imap-authenticate user (or (cdr (assoc from mail-source-password-cache)) password) newbuf)) newbuf (progn (imap-close newbuf) ;; We nix out the password in case the error ;; was because of a wrong password being given. (setq mail-source-password-cache (delq (assoc from mail-source-password-cache) mail-source-password-cache)) (error "IMAP error: %s" (imap-error-text newbuf (let ((mailbox-list (if (listp mailbox) mailbox (list mailbox (dolist (mailbox mailbox-list) (when (imap-mailbox-select mailbox nil buf) (let ((coding-system-for-write mail-source-imap-file-coding-system) (mail-source-string (format "imap:%s:%s" server mailbox)) str remove) (message "Fetching from %s..." mailbox) (with-temp-file mail-source-crash-box ;; Avoid converting 8-bit chars from inserted strings to ;; multibyte. (mm-disable-multibyte) ;; remember password (with-current-buffer buf (when (and imap-password (not (member (cons from imap-password) mail-source-password-cache))) (push (cons from imap-password) mail-source-password-cache))) ;; if predicate is nil, use all uids (dolist (uid (imap-search (or predicate "1:*") buf)) (when (setq str (if (imap-capability 'IMAP4rev1 buf) (caddar (imap-fetch uid "BODY.PEEK[]" 'BODYDETAIL nil buf)) (imap-fetch uid "RFC822.PEEK" 'RFC822 nil buf))) (push uid remove) (insert "From imap " (current-time-string) "\n") (save-excursion (insert str "\n\n")) (while (let ((case-fold-search nil)) (re-search-forward "^From " nil t)) (replace-match ">From ")) (goto-char (point-max (nnheader-ms-strip-cr)) (cl-incf found (mail-source-callback callback server)) (mail-source-delete-crash-box) (when (and remove fetchflag) (setq remove (nreverse remove)) (imap-message-flags-add (imap-range-to-message-set (gnus-compress-sequence remove)) fetchflag nil buf)) (if dontexpunge (imap-mailbox-unselect buf) (imap-mailbox-close nil buf)) (mail-source-run-script postscript `((?p . ,password) (?t . ,mail-source-crash-box) (?s . ,server) (?P . ,port) (?u . ,user)
Re: Keeping IMAP connection alive when using it in mail-sources
Eric writes: > Not with the code as it's written! There's a very definite > (imap-close buf) at the end of the mail source fetching, then the buffer > is deleted. I guess it wouldn't be a bad idea to add a keepalive option > to imap.el, but someone would have to do that! I guess changing mail-source-fetch-imap to check if the buffer already exists and if the connected process is still there, and then not closing imap and not killing the buffer at the end, would be the bare minimum. Interesting. Thanks for the pointer! Best regards, Adam -- "Emacs [...] a [...] nuclear-powered Swiss ArmyAdam Sjøgren knife favored by top-notch programmers and computer a...@koldfront.dk scientists."