X-Git-Url: http://cgit.sxemacs.org/?p=gnus;a=blobdiff_plain;f=lisp%2Fnnimap.el;h=ae9364b37ad40ea7b8a628515ff57b159b70b1a5;hp=00432aadb04ae3e2bb57b20a9182b77e041c02a4;hb=6d5b13cfa970b15832a3c8f46663a3bf8b369bcf;hpb=39e8f0ef57163301e2a3c6b3bf65602e597ba469 diff --git a/lisp/nnimap.el b/lisp/nnimap.el index 00432aadb..ae9364b37 100644 --- a/lisp/nnimap.el +++ b/lisp/nnimap.el @@ -29,6 +29,15 @@ (eval-and-compile (require 'nnheader)) +(eval-when-compile + (require 'cl)) + +(require 'nnheader) +(require 'gnus-util) +(require 'gnus) +(require 'nnoo) +(require 'netrc) + (nnoo-declare nnimap) (defvoo nnimap-address nil @@ -57,7 +66,21 @@ Values are `ssl' and `network'.") This is always done if the server supports UID EXPUNGE, but it's not done by default on servers that doesn't support that command.") +(defvoo nnimap-authenticator nil + "How nnimap authenticate itself to the server. +Possible choices are nil (use default methods) or `anonymous'.") + +(defvoo nnimap-fetch-partial-articles nil + "If non-nil, nnimap will fetch partial articles. +If t, nnimap will fetch only the first part. If a string, it +will fetch all parts that have types that match that string. A +likely value would be \"text/\" to automatically fetch all +textual parts.") + (defvoo nnimap-connection-alist nil) + +(defvoo nnimap-current-infos nil) + (defvar nnimap-process nil) (defvar nnimap-status-string "") @@ -66,7 +89,7 @@ not done by default on servers that doesn't support that command.") "Internal variable with default value for `nnimap-split-download-body'.") (defstruct nnimap - group process commands capabilities) + group process commands capabilities select-result newlinep) (defvar nnimap-object nil) @@ -86,11 +109,7 @@ not done by default on servers that doesn't support that command.") (defun nnimap-buffer () (nnimap-find-process-buffer nntp-server-buffer)) -(defmacro nnimap-with-process-buffer (&rest body) - `(with-current-buffer (nnimap-find-process-buffer (current-buffer)) - ,@body)) - -(defun nnimap-retrieve-headers (articles &optional group server fetch-old) +(deffoo nnimap-retrieve-headers (articles &optional group server fetch-old) (with-current-buffer nntp-server-buffer (erase-buffer) (when (nnimap-possibly-change-group group server) @@ -118,7 +137,7 @@ not done by default on servers that doesn't support that command.") (defun nnimap-transform-headers () (goto-char (point-min)) - (let (article bytes lines) + (let (article bytes lines size) (block nil (while (not (eobp)) (while (not (looking-at "^\\* [0-9]+ FETCH.*UID \\([0-9]+\\)")) @@ -129,6 +148,12 @@ not done by default on servers that doesn't support that command.") bytes (nnimap-get-length) lines nil) (beginning-of-line) + (setq size + (and (re-search-forward "RFC822.SIZE \\([0-9]+\\)" + (line-end-position) + t) + (match-string 1))) + (beginning-of-line) (when (search-forward "BODYSTRUCTURE" (line-end-position) t) (let ((structure (ignore-errors (read (current-buffer))))) (while (and (consp structure) @@ -138,7 +163,8 @@ not done by default on servers that doesn't support that command.") (delete-region (line-beginning-position) (line-end-position)) (insert (format "211 %s Article retrieved." article)) (forward-line 1) - (insert (format "Bytes: %d\n" bytes)) + (when size + (insert (format "Chars: %s\n" size))) (when lines (insert (format "Lines: %s\n" lines))) (re-search-forward "^\r$") @@ -166,7 +192,7 @@ not done by default on servers that doesn't support that command.") result)) (mapconcat #'identity (nreverse result) ","))))) -(defun nnimap-open-server (server &optional defs) +(deffoo nnimap-open-server (server &optional defs) (if (nnimap-server-opened server) t (unless (assq 'nnimap-address defs) @@ -189,58 +215,88 @@ not done by default on servers that doesn't support that command.") (current-buffer))) (defun nnimap-open-shell-stream (name buffer host port) - (let ((process (start-process name buffer shell-file-name - shell-command-switch - (format-spec - nnimap-shell-program - (format-spec-make - ?s host - ?p port))))) - process)) + (let ((process-connection-type nil)) + (start-process name buffer shell-file-name + shell-command-switch + (format-spec + nnimap-shell-program + (format-spec-make + ?s host + ?p port))))) + +(defun nnimap-credentials (address ports) + (let (port credentials) + ;; Request the credentials from all ports, but only query on the + ;; last port if all the previous ones have failed. + (while (and (null credentials) + (setq port (pop ports))) + (setq credentials + (auth-source-user-or-password + '("login" "password") address port nil (null ports)))) + credentials)) (defun nnimap-open-connection (buffer) (with-current-buffer (nnimap-make-process-buffer buffer) (let* ((coding-system-for-read 'binary) (coding-system-for-write 'binary) - (credentials + (ports (cond ((eq nnimap-stream 'network) - (open-network-stream "*nnimap*" (current-buffer) nnimap-address - (or nnimap-server-port "imap")) - (netrc-credentials nnimap-address "imap")) - ((eq nnimap-stream 'stream) + (open-network-stream + "*nnimap*" (current-buffer) nnimap-address + (or nnimap-server-port + (if (netrc-find-service-number "imap") + "imap" + "143"))) + '("143" "imap")) + ((eq nnimap-stream 'shell) (nnimap-open-shell-stream "*nnimap*" (current-buffer) nnimap-address (or nnimap-server-port "imap")) - (netrc-credentials nnimap-address "imap")) + '("imap")) ((eq nnimap-stream 'ssl) - (open-tls-stream "*nnimap*" (current-buffer) nnimap-address - (or nnimap-server-port "imaps")) - (netrc-credentials nnimap-address "imaps" "imap"))))) + (open-tls-stream + "*nnimap*" (current-buffer) nnimap-address + (or nnimap-server-port + (if (netrc-find-service-number "imaps") + "imaps" + "993"))) + '("143" "993" "imap" "imaps")))) + connection-result login-result credentials) (setf (nnimap-process nnimap-object) (get-buffer-process (current-buffer))) - (unless credentials - (delete-process (nnimap-process nnimap-object)) - (error "Can't find user name/password for %s" nnimap-address)) (when (and (nnimap-process nnimap-object) (memq (process-status (nnimap-process nnimap-object)) '(open run))) (gnus-set-process-query-on-exit-flag (nnimap-process nnimap-object) nil) - (let ((result (nnimap-command "LOGIN %S %S" - (car credentials) (cadr credentials)))) - (unless (car result) - (delete-process (nnimap-process nnimap-object)) - (error "Unable to login to the server: %s" - (mapconcat #'identity (cadr result) " "))) - (setf (nnimap-capabilities nnimap-object) - (mapcar - #'upcase - (or (nnimap-find-parameter "CAPABILITY" (cdr result)) - (nnimap-find-parameter - "CAPABILITY" (cdr (nnimap-command "CAPABILITY")))))) - (when (member "QRESYNC" (nnimap-capabilities nnimap-object)) - (nnimap-command "ENABLE QRESYNC")) - t))))) + (when (setq connection-result (nnimap-wait-for-connection)) + (unless (equal connection-result "PREAUTH") + (if (not (setq credentials + (if (eq nnimap-authenticator 'anonymous) + (list "anonymous" + (message-make-address)) + (nnimap-credentials + nnimap-address + (if nnimap-server-port + (cons (format "%s" nnimap-server-port) ports) + ports))))) + (setq nnimap-object nil) + (setq login-result (nnimap-command "LOGIN %S %S" + (car credentials) + (cadr credentials))) + (unless (car login-result) + (delete-process (nnimap-process nnimap-object)) + (setq nnimap-object nil)))) + (when nnimap-object + (setf (nnimap-capabilities nnimap-object) + (mapcar + #'upcase + (or (nnimap-find-parameter "CAPABILITY" (cdr login-result)) + (nnimap-find-parameter + "CAPABILITY" (cdr (nnimap-command "CAPABILITY")))))) + (when (member "QRESYNC" (nnimap-capabilities nnimap-object)) + (nnimap-command "ENABLE QRESYNC")) + t)))))) (defun nnimap-find-parameter (parameter elems) (let (result) @@ -254,40 +310,53 @@ not done by default on servers that doesn't support that command.") (setq result (cdr (cadr elem)))))) result)) -(defun nnimap-close-server (&optional server) +(deffoo nnimap-close-server (&optional server) t) -(defun nnimap-request-close () +(deffoo nnimap-request-close () t) -(defun nnimap-server-opened (&optional server) +(deffoo nnimap-server-opened (&optional server) (and (nnoo-current-server-p 'nnimap server) nntp-server-buffer (gnus-buffer-live-p nntp-server-buffer) (nnimap-find-connection nntp-server-buffer))) -(defun nnimap-status-message (&optional server) +(deffoo nnimap-status-message (&optional server) nnimap-status-string) -(defun nnimap-request-article (article &optional group server to-buffer) +(deffoo nnimap-request-article (article &optional group server to-buffer) (with-current-buffer nntp-server-buffer - (let ((result (nnimap-possibly-change-group group server))) + (let ((result (nnimap-possibly-change-group group server)) + parts) (when (stringp article) (setq article (nnimap-find-article-by-message-id group article))) (when (and result article) (erase-buffer) - (nnimap-with-process-buffer - (erase-buffer) - (setq result - (nnimap-command - (if (member "IMAP4REV1" (nnimap-capabilities nnimap-object)) - "UID FETCH %d BODY.PEEK[]" - "UID FETCH %d RFC822.PEEK") - article))) + (with-current-buffer (nnimap-buffer) + (erase-buffer) + (when nnimap-fetch-partial-articles + (if (eq nnimap-fetch-partial-articles t) + (setq parts '(1)) + (nnimap-command "UID FETCH %d (BODYSTRUCTURE)" article) + (goto-char (point-min)) + (when (re-search-forward "FETCH.*BODYSTRUCTURE" nil t) + (let ((structure (ignore-errors (read (current-buffer))))) + (setq parts (nnimap-find-wanted-parts structure)))))) + (setq result + (nnimap-command + (if (member "IMAP4REV1" (nnimap-capabilities nnimap-object)) + "UID FETCH %d BODY.PEEK[]" + "UID FETCH %d RFC822.PEEK") + article)) + ;; Check that we really got an article. + (goto-char (point-min)) + (unless (looking-at "\\* [0-9]+ FETCH") + (setq result nil))) (let ((buffer (nnimap-find-process-buffer (current-buffer)))) (when (car result) - (with-current-buffer to-buffer + (with-current-buffer (or to-buffer nntp-server-buffer) (insert-buffer-substring buffer) (goto-char (point-min)) (let ((bytes (nnimap-get-length))) @@ -296,23 +365,81 @@ not done by default on servers that doesn't support that command.") (goto-char (+ (point) bytes)) (delete-region (point) (point-max)) (nnheader-ms-strip-cr)) - t))))))) - -(defun nnimap-request-group (group &optional server dont-check) - (with-current-buffer nntp-server-buffer - (let ((result (nnimap-possibly-change-group group server)) - articles) + (cons group article)))))))) + +(defun nnimap-find-wanted-parts (structure) + (message-flatten-list (nnimap-find-wanted-parts-1 structure ""))) + +(defun nnimap-find-wanted-parts-1 (structure prefix) + (let ((num 1) + parts) + (while (consp (car structure)) + (let ((sub (pop structure))) + (if (consp (car sub)) + (push (nnimap-find-wanted-parts-1 + sub (if (string= prefix "") + (number-to-string num) + (format "%s.%s" prefix num))) + parts) + (let ((type (format "%s/%s" (nth 0 sub) (nth 1 sub)))) + (when (string-match nnimap-fetch-partial-articles type) + (push (if (string= prefix "") + (number-to-string num) + (format "%s.%s" prefix num)) + parts))) + (incf num)))) + (nreverse parts))) + +(deffoo nnimap-request-group (group &optional server dont-check info) + (let ((result (nnimap-possibly-change-group group server)) + articles active marks high low) + (with-current-buffer nntp-server-buffer (when result - (setq articles (nnimap-get-flags "1:*")) - (erase-buffer) - (insert - (format - "211 %d %d %d %S\n" - (length articles) - (or (caar articles) 0) - (or (caar (last articles)) 0) - group)) - t)))) + (if (and dont-check + (setq active (nth 2 (assoc group nnimap-current-infos)))) + (insert (format "211 %d %d %d %S\n" + (- (cdr active) (car active)) + (car active) + (cdr active) + group)) + (with-current-buffer (nnimap-buffer) + (erase-buffer) + (let ((group-sequence + (nnimap-send-command "SELECT %S" (utf7-encode group))) + (flag-sequence + (nnimap-send-command "UID FETCH 1:* FLAGS"))) + (nnimap-wait-for-response flag-sequence) + (setq marks + (nnimap-flags-to-marks + (nnimap-parse-flags + (list (list group-sequence flag-sequence 1 group))))) + (when info + (nnimap-update-infos marks (list info))) + (goto-char (point-max)) + (cond + (marks + (setq high (nth 3 (car marks)) + low (nth 4 (car marks)))) + ((re-search-backward "UIDNEXT \\([0-9]+\\)" nil t) + (setq high (string-to-number (match-string 1)) + low 1))))) + (erase-buffer) + (insert + (format + "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) + (with-current-buffer (nnimap-buffer) + (car (nnimap-command "CREATE %S" (utf7-encode group t)))))) + +(deffoo nnimap-request-delete-group (group &optional force server) + (when (nnimap-possibly-change-group nil server) + (with-current-buffer (nnimap-buffer) + (car (nnimap-command "DELETE %S" (utf7-encode group)))))) (defun nnimap-get-flags (spec) (let ((articles nil) @@ -329,7 +456,7 @@ not done by default on servers that doesn't support that command.") articles))) (nreverse articles))) -(defun nnimap-close-group (group &optional server) +(deffoo nnimap-close-group (group &optional server) t) (deffoo nnimap-request-move-article (article group server accept-form @@ -350,10 +477,11 @@ not done by default on servers that doesn't support that command.") (nnimap-find-article-by-message-id internal-move-group message-id)))) (with-temp-buffer - (let ((result (eval accept-form))) - (when result - (nnimap-delete-article article) - result))))))) + (when (nnimap-request-article article group server (current-buffer)) + (let ((result (eval accept-form))) + (when result + (nnimap-delete-article article) + result)))))))) (deffoo nnimap-request-expire-articles (articles group &optional server force) (cond @@ -401,10 +529,10 @@ not done by default on servers that doesn't support that command.") (push flag flags))) flags)) -(defun nnimap-request-set-mark (group actions &optional server) +(deffoo nnimap-request-set-mark (group actions &optional server) (when (nnimap-possibly-change-group group server) (let (sequence) - (with-current-buffer (nnimap-find-process-buffer nntp-server-buffer) + (with-current-buffer (nnimap-buffer) ;; Just send all the STORE commands without waiting for ;; response. If they're successful, they're successful. (dolist (action actions) @@ -420,7 +548,8 @@ not done by default on servers that doesn't support that command.") (mapconcat #'identity flags " "))))))) ;; Wait for the last command to complete to avoid later ;; syncronisation problems with the stream. - (nnimap-wait-for-response sequence))))) + (when sequence + (nnimap-wait-for-response sequence)))))) (deffoo nnimap-request-accept-article (group &optional server last) (when (nnimap-possibly-change-group nil server) @@ -428,17 +557,19 @@ not done by default on servers that doesn't support that command.") (let ((message (buffer-string)) (message-id (message-field-value "message-id")) sequence) - (with-current-buffer nntp-server-buffer - (nnimap-with-process-buffer - (setq sequence (nnimap-send-command - "APPEND %S {%d}" (utf7-encode group t) - (length message))) - (process-send-string (get-buffer-process (current-buffer)) message) - (process-send-string (get-buffer-process (current-buffer)) "\r\n") - (let ((result (nnimap-get-response sequence))) - (when result - (cons group - (nnimap-find-article-by-message-id group message-id))))))))) + (with-current-buffer (nnimap-buffer) + (setq sequence (nnimap-send-command + "APPEND %S {%d}" (utf7-encode group t) + (length message))) + (process-send-string (get-buffer-process (current-buffer)) message) + (process-send-string (get-buffer-process (current-buffer)) + (if (nnimap-newlinep nnimap-object) + "\n" + "\r\n")) + (let ((result (nnimap-get-response sequence))) + (when result + (cons group + (nnimap-find-article-by-message-id group message-id)))))))) (defun nnimap-add-cr () (goto-char (point-min)) @@ -451,27 +582,28 @@ not done by default on servers that doesn't support that command.") (when (car result) (dolist (line (cdr result)) (when (and (equal (car line) "LIST") - (not (string-match "noselect" (caadr line)))) + (not (and (caadr line) + (string-match "noselect" (caadr line))))) (push (car (last line)) groups))) (nreverse groups)))) -(defun nnimap-request-list (&optional server) +(deffoo nnimap-request-list (&optional server) (nnimap-possibly-change-group nil server) (with-current-buffer nntp-server-buffer (erase-buffer) (let ((groups - (nnimap-with-process-buffer - (nnimap-get-groups))) + (with-current-buffer (nnimap-buffer) + (nnimap-get-groups))) sequences responses) (when groups - (nnimap-with-process-buffer - (dolist (group groups) - (push (list (nnimap-send-command "EXAMINE %S" (utf7-encode group t)) - group) - sequences)) - (nnimap-wait-for-response (caar sequences)) - (setq responses - (nnimap-get-responses (mapcar #'car sequences)))) + (with-current-buffer (nnimap-buffer) + (dolist (group groups) + (push (list (nnimap-send-command "EXAMINE %S" (utf7-encode group t)) + group) + sequences)) + (nnimap-wait-for-response (caar sequences)) + (setq responses + (nnimap-get-responses (mapcar #'car sequences)))) (dolist (response responses) (let* ((sequence (car response)) (response (cadr response)) @@ -498,7 +630,7 @@ not done by default on servers that doesn't support that command.") (or highest exists))))))))) t)))) -(defun nnimap-retrieve-group-data-early (server infos) +(deffoo nnimap-retrieve-group-data-early (server infos) (when (nnimap-possibly-change-group nil server) (with-current-buffer (nnimap-buffer) ;; QRESYNC handling isn't implemented. @@ -538,8 +670,9 @@ not done by default on servers that doesn't support that command.") sequences)))) sequences)))) -(defun nnimap-finish-retrieve-group-infos (server infos sequences) - (when (nnimap-possibly-change-group nil server) +(deffoo nnimap-finish-retrieve-group-infos (server infos sequences) + (when (and sequences + (nnimap-possibly-change-group nil server)) (with-current-buffer (nnimap-buffer) ;; Wait for the final data to trickle in. (nnimap-wait-for-response (cadar sequences)) @@ -549,7 +682,19 @@ not done by default on servers that doesn't support that command.") (nnimap-update-infos (nnimap-flags-to-marks (nnimap-parse-flags (nreverse sequences))) - infos)))) + infos) + ;; Finally, just return something resembling an active file in + ;; the nntp buffer, so that the agent can save the info, too. + (with-current-buffer nntp-server-buffer + (erase-buffer) + (dolist (info infos) + (let* ((group (gnus-info-group info)) + (active (gnus-active group))) + (when active + (insert (format "%S %d %d y\n" + (gnus-group-real-name group) + (cdr active) + (car active)))))))))) (defun nnimap-update-infos (flags infos) (dolist (info infos) @@ -563,7 +708,8 @@ not done by default on servers that doesn't support that command.") (completep (and start-article (= start-article 1)))) ;; First set the active ranges based on high/low. - (if completep + (if (or completep + (not (gnus-active group))) (gnus-set-active group (if high (cons low high) @@ -583,9 +729,11 @@ not done by default on servers that doesn't support that command.") (when (> start-article 1) (setq read (gnus-range-nconcat - (gnus-sorted-range-intersection - (cons 1 start-article) - (gnus-info-read info)) + (if (> start-article 1) + (gnus-sorted-range-intersection + (cons 1 (1- start-article)) + (gnus-info-read info)) + (gnus-info-read info)) read))) (gnus-info-set-read info read) ;; Update the marks. @@ -604,12 +752,20 @@ not done by default on servers that doesn't support that command.") (when (and old-marks (> start-article 1)) (setq old-marks (gnus-range-difference - (cons start-article high) - old-marks)) + old-marks + (cons start-article high))) (setq new-marks (gnus-range-nconcat old-marks new-marks))) (when new-marks (push (cons (car type) new-marks) marks))) - (gnus-info-set-marks info marks))))))) + (gnus-info-set-marks info marks t) + (nnimap-store-info info (gnus-active group)))))))) + +(defun nnimap-store-info (info active) + (let* ((group (gnus-group-real-name (gnus-info-group info))) + (entry (assoc group nnimap-current-infos))) + (if entry + (setcdr entry (list info active)) + (push (list group info active) nnimap-current-infos)))) (defun nnimap-flags-to-marks (groups) (let (data group totalp uidnext articles start-article mark) @@ -663,23 +819,29 @@ not done by default on servers that doesn't support that command.") (defun nnimap-find-process-buffer (buffer) (cadr (assoc buffer nnimap-connection-alist))) -(defun nnimap-request-post (&optional server) +(deffoo nnimap-request-post (&optional server) (setq nnimap-status-string "Read-only server") nil) (defun nnimap-possibly-change-group (group server) - (when (and server - (not (nnimap-server-opened server))) - (nnimap-open-server server)) - (if (not group) - t - (with-current-buffer (nnimap-buffer) - (if (equal group (nnimap-group nnimap-object)) - t - (let ((result (nnimap-command "SELECT %S" (utf7-encode group t)))) - (when (car result) - (setf (nnimap-group nnimap-object) group) - result)))))) + (let ((open-result t)) + (when (and server + (not (nnimap-server-opened server))) + (setq open-result (nnimap-open-server server))) + (cond + ((not open-result) + nil) + ((not group) + t) + (t + (with-current-buffer (nnimap-buffer) + (if (equal group (nnimap-group nnimap-object)) + t + (let ((result (nnimap-command "SELECT %S" (utf7-encode group t)))) + (when (car result) + (setf (nnimap-group nnimap-object) group + (nnimap-select-result nnimap-object) result) + result)))))))) (defun nnimap-find-connection (buffer) "Find the connection delivering to BUFFER." @@ -699,9 +861,12 @@ not done by default on servers that doesn't support that command.") (process-send-string (get-buffer-process (current-buffer)) (nnimap-log-command - (format "%d %s\r\n" + (format "%d %s%s\n" (incf nnimap-sequence) - (apply #'format args)))) + (apply #'format args) + (if (nnimap-newlinep nnimap-object) + "" + "\r")))) nnimap-sequence) (defun nnimap-log-command (command) @@ -717,23 +882,39 @@ not done by default on servers that doesn't support that command.") (if (equal (caar response) "OK") (cons t response) (nnheader-report 'nnimap "%s" - (mapconcat #'identity (car response) " ")) + (mapconcat (lambda (a) + (format "%s" a)) + (car response) " ")) nil))) (defun nnimap-get-response (sequence) (nnimap-wait-for-response sequence) (nnimap-parse-response)) +(defun nnimap-wait-for-connection () + (let ((process (get-buffer-process (current-buffer)))) + (goto-char (point-min)) + (while (and (memq (process-status process) + '(open run)) + (not (re-search-forward "^\\* .*\n" nil t))) + (nnheader-accept-process-output process) + (goto-char (point-min))) + (forward-line -1) + (and (looking-at "\\* \\([A-Z0-9]+\\)") + (match-string 1)))) + (defun nnimap-wait-for-response (sequence &optional messagep) - (goto-char (point-max)) - (while (or (bobp) - (progn - (forward-line -1) - (not (looking-at (format "^%d .*\n" sequence))))) - (when messagep - (message "Read %dKB" (/ (buffer-size) 1000))) - (nnheader-accept-process-output (get-buffer-process (current-buffer))) - (goto-char (point-max)))) + (let ((process (get-buffer-process (current-buffer)))) + (goto-char (point-max)) + (while (and (memq (process-status process) + '(open run)) + (not (re-search-backward (format "^%d .*\n" sequence) + (max (point-min) (- (point) 500)) + t))) + (when messagep + (message "Read %dKB" (/ (buffer-size) 1000))) + (nnheader-accept-process-output process) + (goto-char (point-max))))) (defun nnimap-parse-response () (let ((lines (split-string (nnimap-last-response-string) "\r\n" t)) @@ -812,7 +993,7 @@ not done by default on servers that doesn't support that command.") "BODY.PEEK[HEADER] BODY.PEEK" "RFC822.PEEK")) (if nnimap-split-download-body-default - "" + "[]" "[1]"))) t))