Embiggen pictures slightly.
[gnus] / lisp / nnimap.el
index 4a77836..7846aa2 100644 (file)
@@ -91,14 +91,14 @@ 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 select-result newlinep)
+  group process commands capabilities select-result newlinep server)
 
 (defvar nnimap-object nil)
 
 (defvar nnimap-mark-alist
-  '((read "\\Seen")
-    (tick "\\Flagged")
-    (reply "\\Answered")
+  '((read "\\Seen" %Seen)
+    (tick "\\Flagged" %Flagged)
+    (reply "\\Answered" %Answered)
     (expire "gnus-expire")
     (dormant "gnus-dormant")
     (score "gnus-score")
@@ -212,7 +212,8 @@ not done by default on servers that doesn't support that command.")
     (buffer-disable-undo)
     (gnus-add-buffer)
     (set (make-local-variable 'after-change-functions) nil)
-    (set (make-local-variable 'nnimap-object) (make-nnimap))
+    (set (make-local-variable 'nnimap-object)
+        (make-nnimap :server (nnoo-current-server 'nnimap)))
     (push (list buffer (current-buffer)) nnimap-connection-alist)
     (current-buffer)))
 
@@ -420,8 +421,9 @@ not done by default on servers that doesn't support that command.")
              (goto-char (point-max))
              (cond
               (marks
-               (setq high (nth 3 (car marks))
-                     low (nth 4 (car marks))))
+               (let ((uidnext (nth 5 (car marks))))
+                 (setq high (or (nth 3 (car marks)) (1- uidnext))
+                       low (or (nth 4 (car marks)) uidnext))))
               ((re-search-backward "UIDNEXT \\([0-9]+\\)" nil t)
                (setq high (1- (string-to-number (match-string 1)))
                      low 1)))))
@@ -501,7 +503,8 @@ not done by default on servers that doesn't support that command.")
     nil)
    (t
     (let ((deletable-articles
-          (if force
+          (if (or force
+                  (eq nnmail-expiry-wait 'immediate))
               articles
             (gnus-sorted-intersection
              articles
@@ -586,9 +589,9 @@ not done by default on servers that doesn't support that command.")
 
 (deffoo nnimap-request-scan (&optional group server)
   (when (and (nnimap-possibly-change-group nil server)
-            (equal group nnimap-inbox)
             nnimap-inbox
             nnimap-split-methods)
+    (message "nnimap %s splitting mail..." server)
     (nnimap-split-incoming-mail)))
 
 (defun nnimap-marks-to-flags (marks)
@@ -666,6 +669,7 @@ not done by default on servers that doesn't support that command.")
          sequences responses)
       (when groups
        (with-current-buffer (nnimap-buffer)
+         (setf (nnimap-group nnimap-object) nil)
          (dolist (group groups)
            (push (list (nnimap-send-command "EXAMINE %S" (utf7-encode group t))
                        group)
@@ -715,6 +719,7 @@ not done by default on servers that doesn't support that command.")
                groups))
        ;; Then request the data.
        (erase-buffer)
+       (setf (nnimap-group nnimap-object) nil)
        (dolist (elem groups)
          (if (and qresyncp
                   (nth 2 elem))
@@ -772,7 +777,8 @@ not done by default on servers that doesn't support that command.")
 
 (defun nnimap-update-info (info marks)
   (when marks
-    (destructuring-bind (existing flags high low uidnext start-article) marks
+    (destructuring-bind (existing flags high low uidnext start-article
+                                 permanent-flags) marks
       (let ((group (gnus-info-group info))
            (completep (and start-article
                            (= start-article 1))))
@@ -783,16 +789,18 @@ not done by default on servers that doesn't support that command.")
                             (if high
                                 (cons low high)
                               ;; No articles in this group.
-                              (cons (1- uidnext) uidnext)))
-         (setcdr (gnus-active group) high))
+                              (cons uidnext (1- uidnext))))
+         (setcdr (gnus-active group) (or high (1- uidnext))))
+       (unless high
+         (setq high (1- uidnext)))
        ;; Then update the list of read articles.
        (let* ((unread
                (gnus-compress-sequence
                 (gnus-set-difference
                  (gnus-set-difference
                   existing
-                  (cdr (assoc "\\Seen" flags)))
-                 (cdr (assoc "\\Flagged" flags)))))
+                  (cdr (assoc '%Seen flags)))
+                 (cdr (assoc '%Flagged flags)))))
               (read (gnus-range-difference
                      (cons start-article high) unread)))
          (when (> start-article 1)
@@ -814,8 +822,10 @@ not done by default on servers that doesn't support that command.")
              (push (cons 'active (gnus-active group)) marks)))
          (dolist (type (cdr nnimap-mark-alist))
            (let ((old-marks (assoc (car type) marks))
-                 (new-marks (gnus-compress-sequence
-                             (cdr (assoc (cadr type) flags)))))
+                 (new-marks
+                  (gnus-compress-sequence
+                   (cdr (or (assoc (caddr type) flags)     ; %Flagged
+                            (assoc (cadr type) flags)))))) ; "\Flagged"
              (setq marks (delq old-marks marks))
              (pop old-marks)
              (when (and old-marks
@@ -837,12 +847,13 @@ not done by default on servers that doesn't support that command.")
       (push (list group info active) nnimap-current-infos))))
 
 (defun nnimap-flags-to-marks (groups)
-  (let (data group totalp uidnext articles start-article mark)
+  (let (data group totalp uidnext articles start-article mark permanent-flags)
     (dolist (elem groups)
       (setq group (car elem)
-           uidnext (cadr elem)
-           start-article (caddr elem)
-           articles (cdddr elem))
+           uidnext (nth 1 elem)
+           start-article (nth 2 elem)
+           permanent-flags (nth 3 elem)
+           articles (nthcdr 4 elem))
       (let ((high (caar articles))
            marks low existing)
        (dolist (article articles)
@@ -852,36 +863,49 @@ not done by default on servers that doesn't support that command.")
            (setq mark (assoc flag marks))
            (if (not mark)
                (push (list flag (car article)) marks)
-             (setcdr mark (cons (car article) (cdr mark)))))
-         (push (list group existing marks high low uidnext start-article)
-               data))))
+             (setcdr mark (cons (car article) (cdr mark))))))
+       (push (list group existing marks high low uidnext start-article
+                   permanent-flags)
+             data)))
     data))
 
 (defun nnimap-parse-flags (sequences)
   (goto-char (point-min))
-  (let (start end articles groups uidnext elems)
+  ;; Change \Delete etc to %Delete, so that the reader can read it.
+  (subst-char-in-region (point-min) (point-max)
+                       ?\\ ?% t)
+  (let (start end articles groups uidnext elems permanent-flags)
     (dolist (elem sequences)
       (destructuring-bind (group-sequence flag-sequence totalp group) elem
+       (setq start (point))
        ;; The EXAMINE was successful.
        (when (and (search-forward (format "\n%d OK " group-sequence) nil t)
                   (progn
                     (forward-line 1)
-                    (setq start (point))
-                    (if (re-search-backward "UIDNEXT \\([0-9]+\\)"
-                                              (or end (point-min)) t)
-                        (setq uidnext (string-to-number (match-string 1)))
-                      (setq uidnext nil))
-                    (goto-char start))
+                    (setq end (point))
+                    (goto-char start)
+                    (setq permanent-flags
+                          (and (search-forward "PERMANENTFLAGS "
+                                                (or end (point-min)) t)
+                               (read (current-buffer))))
+                    (goto-char start)
+                    (setq uidnext
+                          (and (search-forward "UIDNEXT "
+                                                (or end (point-min)) t)
+                               (read (current-buffer))))
+                    (goto-char end)
+                    (forward-line -1))
                   ;; The UID FETCH FLAGS was successful.
                   (search-forward (format "\n%d OK " flag-sequence) nil t))
-         (setq end (point))
-         (goto-char start)
-         (while (re-search-forward "^\\* [0-9]+ FETCH (\\(.*\\))" end t)
-           (setq elems (nnimap-parse-line (match-string 1)))
-           (push (cons (string-to-number (cadr (member "UID" elems)))
-                       (cadr (member "FLAGS" elems)))
+         (setq start (point))
+         (goto-char end)
+         (while (search-forward " FETCH " start t)
+           (setq elems (read (current-buffer)))
+           (push (cons (cadr (memq 'UID elems))
+                       (cadr (memq 'FLAGS elems)))
                  articles))
-         (push (nconc (list group uidnext totalp) articles) groups)
+         (push (nconc (list group uidnext totalp permanent-flags) articles)
+               groups)
          (setq articles nil))))
     groups))
 
@@ -1084,32 +1108,38 @@ not done by default on servers that doesn't support that command.")
        (nnmail-split-incoming (current-buffer)
                               #'nnimap-save-mail-spec
                               nil nil
-                              #'nnimap-dummy-active-number)
+                              #'nnimap-dummy-active-number
+                              #'nnimap-save-mail-spec)
        (when nnimap-incoming-split-list
          (let ((specs (nnimap-make-split-specs nnimap-incoming-split-list))
-               sequences)
+               sequences junk-articles)
            ;; Create any groups that doesn't already exist on the
            ;; server first.
            (dolist (spec specs)
-             (unless (member (car spec) groups)
+             (when (and (not (member (car spec) groups))
+                        (not (eq (car spec) 'junk)))
                (nnimap-command "CREATE %S" (utf7-encode (car spec) t))))
            ;; Then copy over all the messages.
            (erase-buffer)
            (dolist (spec specs)
              (let ((group (car spec))
                    (ranges (cdr spec)))
-               (push (list (nnimap-send-command "UID COPY %s %S"
-                                                (nnimap-article-ranges ranges)
-                                                (utf7-encode group t))
-                           ranges)
-                     sequences)))
+               (if (eq group 'junk)
+                   (setq junk-articles ranges)
+                 (push (list (nnimap-send-command
+                              "UID COPY %s %S"
+                              (nnimap-article-ranges ranges)
+                              (utf7-encode group t))
+                             ranges)
+                       sequences))))
            ;; Wait for the last COPY response...
            (when sequences
              (nnimap-wait-for-response (caar sequences))
              ;; And then mark the successful copy actions as deleted,
              ;; and possibly expunge them.
              (nnimap-mark-and-expunge-incoming
-              (nnimap-parse-copied-articles sequences)))))))))
+              (nnimap-parse-copied-articles sequences))
+             (nnimap-mark-and-expunge-incoming junk-articles))))))))
 
 (defun nnimap-mark-and-expunge-incoming (range)
   (when range
@@ -1141,8 +1171,8 @@ not done by default on servers that doesn't support that command.")
   (let (new)
     (dolist (elem flags)
       (when (or (null (cdr elem))
-               (and (not (member "\\Deleted" (cdr elem)))
-                    (not (member "\\Seen" (cdr elem)))))
+               (and (not (memq '%Deleted (cdr elem)))
+                    (not (memq '%Seen (cdr elem)))))
        (push (car elem) new)))
     (gnus-compress-sequence (nreverse new))))
 
@@ -1189,7 +1219,10 @@ not done by default on servers that doesn't support that command.")
     (if (not (re-search-forward "X-nnimap-article: \\([0-9]+\\)" nil t))
        (error "Invalid nnimap mail")
       (setq article (string-to-number (match-string 1))))
-    (push (list article group-art)
+    (push (list article
+               (if (eq group-art 'junk)
+                   (list (cons 'junk 1))
+                 group-art))
          nnimap-incoming-split-list)))
 
 (provide 'nnimap)