Only delete articles immediately if the target is 'delete.
[gnus] / lisp / nnimap.el
index 4c3eaac..82c9976 100644 (file)
 (eval-when-compile
   (require 'cl))
 
 (eval-when-compile
   (require 'cl))
 
+(require 'nnheader)
+(require 'gnus-util)
+(require 'gnus)
+(require 'nnoo)
 (require 'netrc)
 
 (nnoo-declare nnimap)
 (require 'netrc)
 
 (nnoo-declare nnimap)
@@ -62,6 +66,17 @@ 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.")
 
 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)
 (defvoo nnimap-connection-alist nil)
 
 (defvoo nnimap-current-infos nil)
@@ -74,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
   "Internal variable with default value for `nnimap-split-download-body'.")
 
 (defstruct nnimap
-  group process commands capabilities select-result)
+  group process commands capabilities select-result newlinep)
 
 (defvar nnimap-object nil)
 
 
 (defvar nnimap-object nil)
 
@@ -122,7 +137,7 @@ not done by default on servers that doesn't support that command.")
 
 (defun nnimap-transform-headers ()
   (goto-char (point-min))
 
 (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]+\\)"))
     (block nil
       (while (not (eobp))
        (while (not (looking-at "^\\* [0-9]+ FETCH.*UID \\([0-9]+\\)"))
@@ -133,6 +148,12 @@ not done by default on servers that doesn't support that command.")
              bytes (nnimap-get-length)
              lines nil)
        (beginning-of-line)
              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)
        (when (search-forward "BODYSTRUCTURE" (line-end-position) t)
          (let ((structure (ignore-errors (read (current-buffer)))))
            (while (and (consp structure)
@@ -142,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)
        (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$")
        (when lines
          (insert (format "Lines: %s\n" lines)))
        (re-search-forward "^\r$")
@@ -193,16 +215,16 @@ not done by default on servers that doesn't support that command.")
     (current-buffer)))
 
 (defun nnimap-open-shell-stream (name buffer host port)
     (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))
-
-(defun nnimap-credentials (address &rest ports)
+  (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.
   (let (port credentials)
     ;; Request the credentials from all ports, but only query on the
     ;; last port if all the previous ones have failed.
@@ -217,45 +239,59 @@ not done by default on servers that doesn't support that command.")
   (with-current-buffer (nnimap-make-process-buffer buffer)
     (let* ((coding-system-for-read 'binary)
           (coding-system-for-write 'binary)
   (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)
            (cond
             ((eq nnimap-stream 'network)
-             (open-network-stream "*nnimap*" (current-buffer) nnimap-address
-                                  (or nnimap-server-port
-                                      (if (netrc-find-service-number "imap")
-                                          "imap"
-                                        "143")))
-             (nnimap-credentials nnimap-address "143" "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"))
              (nnimap-open-shell-stream
               "*nnimap*" (current-buffer) nnimap-address
               (or nnimap-server-port "imap"))
-             (nnimap-credentials nnimap-address "imap"))
+             '("imap"))
             ((eq nnimap-stream 'ssl)
             ((eq nnimap-stream 'ssl)
-             (open-tls-stream "*nnimap*" (current-buffer) nnimap-address
-                              (or nnimap-server-port
-                                  (if (netrc-find-service-number "imaps")
-                                      "imaps"
-                                    "993")))
-             (nnimap-credentials nnimap-address "143" "993" "imap" "imaps")))))
+             (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)))
       (setf (nnimap-process nnimap-object)
            (get-buffer-process (current-buffer)))
-      (unless credentials
-       (delete-process (nnimap-process nnimap-object)))
       (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)
       (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))))
-         (if (not (car result))
-             (progn
+       (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))
                (delete-process (nnimap-process nnimap-object))
-               nil)
+               (setq nnimap-object nil))))
+         (when nnimap-object
            (setf (nnimap-capabilities nnimap-object)
                  (mapcar
                   #'upcase
            (setf (nnimap-capabilities nnimap-object)
                  (mapcar
                   #'upcase
-                  (or (nnimap-find-parameter "CAPABILITY" (cdr result))
+                  (or (nnimap-find-parameter "CAPABILITY" (cdr login-result))
                       (nnimap-find-parameter
                        "CAPABILITY" (cdr (nnimap-command "CAPABILITY"))))))
            (when (member "QRESYNC" (nnimap-capabilities nnimap-object))
                       (nnimap-find-parameter
                        "CAPABILITY" (cdr (nnimap-command "CAPABILITY"))))))
            (when (member "QRESYNC" (nnimap-capabilities nnimap-object))
@@ -291,7 +327,8 @@ not done by default on servers that doesn't support that command.")
 
 (deffoo nnimap-request-article (article &optional group server to-buffer)
   (with-current-buffer nntp-server-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
       (when (stringp article)
        (setq article (nnimap-find-article-by-message-id group article)))
       (when (and result
@@ -299,15 +336,27 @@ not done by default on servers that doesn't support that command.")
        (erase-buffer)
        (with-current-buffer (nnimap-buffer)
          (erase-buffer)
        (erase-buffer)
        (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")
          (setq result
                (nnimap-command
                 (if (member "IMAP4REV1" (nnimap-capabilities nnimap-object))
                     "UID FETCH %d BODY.PEEK[]"
                   "UID FETCH %d RFC822.PEEK")
-                article)))
+                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)
        (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)))
              (insert-buffer-substring buffer)
              (goto-char (point-min))
              (let ((bytes (nnimap-get-length)))
@@ -316,12 +365,35 @@ 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))
                (goto-char (+ (point) bytes))
                (delete-region (point) (point-max))
                (nnheader-ms-strip-cr))
-             t)))))))
+             (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)
 
 (deffoo nnimap-request-group (group &optional server dont-check info)
-  (with-current-buffer nntp-server-buffer
-    (let ((result (nnimap-possibly-change-group group server))
-         articles active marks)
+  (let ((result (nnimap-possibly-change-group group server))
+       articles active marks high low)
+    (with-current-buffer nntp-server-buffer
       (when result
        (if (and dont-check
                 (setq active (nth 2 (assoc group nnimap-current-infos))))
       (when result
        (if (and dont-check
                 (setq active (nth 2 (assoc group nnimap-current-infos))))
@@ -333,7 +405,7 @@ not done by default on servers that doesn't support that command.")
          (with-current-buffer (nnimap-buffer)
            (erase-buffer)
            (let ((group-sequence
          (with-current-buffer (nnimap-buffer)
            (erase-buffer)
            (let ((group-sequence
-                  (nnimap-send-command "SELECT %S" (utf7-encode group)))
+                  (nnimap-send-command "SELECT %S" (utf7-encode group t)))
                  (flag-sequence
                   (nnimap-send-command "UID FETCH 1:* FLAGS")))
              (nnimap-wait-for-response flag-sequence)
                  (flag-sequence
                   (nnimap-send-command "UID FETCH 1:* FLAGS")))
              (nnimap-wait-for-response flag-sequence)
@@ -342,16 +414,35 @@ not done by default on servers that doesn't support that command.")
                     (nnimap-parse-flags
                      (list (list group-sequence flag-sequence 1 group)))))
              (when info
                     (nnimap-parse-flags
                      (list (list group-sequence flag-sequence 1 group)))))
              (when info
-               (nnimap-update-infos marks (list 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 (1- (string-to-number (match-string 1)))
+                     low 1)))))
          (erase-buffer)
          (erase-buffer)
-         (let ((high (nth 3 (car marks)))
-               (low (nth 4 (car marks))))
-           (insert
-            (format
-             "211 %d %d %d %S\n"
-             (1+ (- high low))
-             low high group))))
-       t))))
+         (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 t))))))
+
+(deffoo nnimap-request-expunge-group (group &optional server)
+  (when (nnimap-possibly-change-group group server)
+    (with-current-buffer (nnimap-buffer)
+      (car (nnimap-command "EXPUNGE")))))
 
 (defun nnimap-get-flags (spec)
   (let ((articles nil)
 
 (defun nnimap-get-flags (spec)
   (let ((articles nil)
@@ -389,16 +480,18 @@ 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
                    (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
    ((not (nnimap-possibly-change-group group server))
     articles)
 
 (deffoo nnimap-request-expire-articles (articles group &optional server force)
   (cond
    ((not (nnimap-possibly-change-group group server))
     articles)
-   (force
+   ((and force
+        (eq nnmail-expiry-target 'delete))
     (unless (nnimap-delete-article articles)
       (message "Article marked for deletion, but not expunged."))
     nil)
     (unless (nnimap-delete-article articles)
       (message "Article marked for deletion, but not expunged."))
     nil)
@@ -459,7 +552,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.
                                (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)
 
 (deffoo nnimap-request-accept-article (group &optional server last)
   (when (nnimap-possibly-change-group nil server)
@@ -472,7 +566,10 @@ not done by default on servers that doesn't support that command.")
                        "APPEND %S {%d}" (utf7-encode group t)
                        (length message)))
        (process-send-string (get-buffer-process (current-buffer)) message)
                        "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")
+       (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
        (let ((result (nnimap-get-response sequence)))
          (when result
            (cons group
@@ -589,7 +686,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)))
       (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)
 
 (defun nnimap-update-infos (flags infos)
   (dolist (info infos)
@@ -624,9 +733,11 @@ not done by default on servers that doesn't support that command.")
          (when (> start-article 1)
            (setq read
                  (gnus-range-nconcat
          (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.
                   read)))
          (gnus-info-set-read info read)
          ;; Update the marks.
@@ -645,12 +756,12 @@ 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
              (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)))
                (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)
            (nnimap-store-info info (gnus-active group))))))))
 
 (defun nnimap-store-info (info active)
@@ -754,9 +865,12 @@ not done by default on servers that doesn't support that command.")
   (process-send-string
    (get-buffer-process (current-buffer))
    (nnimap-log-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)
            (incf nnimap-sequence)
-           (apply #'format args))))
+           (apply #'format args)
+           (if (nnimap-newlinep nnimap-object)
+               ""
+             "\r"))))
   nnimap-sequence)
 
 (defun nnimap-log-command (command)
   nnimap-sequence)
 
 (defun nnimap-log-command (command)
@@ -772,23 +886,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"
     (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))
 
       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)
 (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))
 
 (defun nnimap-parse-response ()
   (let ((lines (split-string (nnimap-last-response-string) "\r\n" t))
@@ -867,7 +997,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
                 "BODY.PEEK[HEADER] BODY.PEEK"
               "RFC822.PEEK"))
            (if nnimap-split-download-body-default
-               ""
+               "[]"
              "[1]")))
    t))
 
              "[1]")))
    t))