Store the IMAP greeting, so that we can tell what kind of server we're talking to.
[gnus] / lisp / nnimap.el
index 44d9bab..6c112fa 100644 (file)
@@ -62,6 +62,10 @@ Values are `ssl', `network', `starttls' or `shell'.")
 (defvoo nnimap-inbox nil
   "The mail box where incoming mail arrives and should be split out of.")
 
+(defvoo nnimap-split-methods nil
+  "How mail is split.
+Uses the same syntax as nnmail-split-methods")
+
 (defvoo nnimap-authenticator nil
   "How nnimap authenticate itself to the server.
 Possible choices are nil (use default methods) or `anonymous'.")
@@ -92,7 +96,7 @@ some servers.")
 
 (defstruct nnimap
   group process commands capabilities select-result newlinep server
-  last-command-time)
+  last-command-time greeting)
 
 (defvar nnimap-object nil)
 
@@ -107,8 +111,6 @@ some servers.")
     (download "gnus-download")
     (forward "gnus-forward")))
 
-(defvar nnimap-split-methods nil)
-
 (defun nnimap-buffer ()
   (nnimap-find-process-buffer nntp-server-buffer))
 
@@ -117,7 +119,6 @@ some servers.")
     (erase-buffer)
     (when (nnimap-possibly-change-group group server)
       (with-current-buffer (nnimap-buffer)
-       (nnimap-send-command "SELECT %S" (utf7-encode group t))
        (erase-buffer)
        (nnimap-wait-for-response
         (nnimap-send-command
@@ -236,7 +237,7 @@ some servers.")
                     ?s host
                     ?p port)))))
 
-(defun nnimap-credentials (address ports)
+(defun nnimap-credentials (address ports &optional inhibit-create)
   (let (port credentials)
     ;; Request the credentials from all ports, but only query on the
     ;; last port if all the previous ones have failed.
@@ -244,7 +245,10 @@ some servers.")
                (setq port (pop ports)))
       (setq credentials
            (auth-source-user-or-password
-            '("login" "password") address port nil (null ports))))
+            '("login" "password") address port nil
+            (if inhibit-create
+                nil
+              (null ports)))))
     credentials))
 
 (defun nnimap-keepalive ()
@@ -269,55 +273,71 @@ some servers.")
   (with-current-buffer (nnimap-make-process-buffer buffer)
     (let* ((coding-system-for-read 'binary)
           (coding-system-for-write 'binary)
+          (port nil)
           (ports
            (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")))
+              (setq port
+                    (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"))
+              (setq port (or nnimap-server-port "imap")))
              '("imap"))
             ((eq nnimap-stream 'starttls)
              (starttls-open-stream
               "*nnimap*" (current-buffer) nnimap-address
-              (or nnimap-server-port "imap"))
+              (setq port (or nnimap-server-port "imap")))
              '("imap"))
             ((eq nnimap-stream 'ssl)
              (open-tls-stream
               "*nnimap*" (current-buffer) nnimap-address
-              (or nnimap-server-port
-                  (if (netrc-find-service-number "imaps")
-                      "imaps"
-                    "993")))
+              (setq port
+                    (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)))
-      (when (and (nnimap-process nnimap-object)
-                (memq (process-status (nnimap-process nnimap-object))
-                      '(open run)))
+      (if (not (and (nnimap-process nnimap-object)
+                   (memq (process-status (nnimap-process nnimap-object))
+                         '(open run))))
+         (nnheader-report 'nnimap "Unable to contact %s:%s via %s"
+                          nnimap-address port nnimap-stream)
        (gnus-set-process-query-on-exit-flag (nnimap-process nnimap-object) nil)
-       (when (setq connection-result (nnimap-wait-for-connection))
+       (if (not (setq connection-result (nnimap-wait-for-connection)))
+           (nnheader-report 'nnimap
+                            "%s" (buffer-substring
+                                  (point) (line-end-position)))
+         (setf (nnimap-greeting nnimap-object)
+               (buffer-substring (line-beginning-position)
+                                 (line-end-position)))
          (when (eq nnimap-stream 'starttls)
            (nnimap-command "STARTTLS")
            (starttls-negotiate (nnimap-process nnimap-object)))
+         (when nnimap-server-port
+           (push (format "%s" nnimap-server-port) ports))
          (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)))))
+                            (or
+                             ;; First look for the credentials based
+                             ;; on the virtual server name.
+                             (nnimap-credentials
+                              (nnoo-current-server 'nnimap) ports t)
+                             ;; Then look them up based on the
+                             ;; physical address.
+                             (nnimap-credentials nnimap-address ports)))))
                (setq nnimap-object nil)
              (setq login-result (nnimap-command "LOGIN %S %S"
                                                 (car credentials)
@@ -608,7 +628,7 @@ some servers.")
     articles)
    ((and force
         (eq nnmail-expiry-target 'delete))
-    (unless (nnimap-delete-article articles)
+    (unless (nnimap-delete-article (gnus-compress-sequence articles))
       (message "Article marked for deletion, but not expunged."))
     nil)
    (t
@@ -622,7 +642,7 @@ some servers.")
       (if (null deletable-articles)
          articles
        (if (eq nnmail-expiry-target 'delete)
-           (nnimap-delete-article deletable-articles)
+           (nnimap-delete-article (gnus-compress-sequence deletable-articles))
          (setq deletable-articles
                (nnimap-process-expiry-targets
                 deletable-articles group server)))
@@ -649,7 +669,7 @@ some servers.")
     ;; Change back to the current group again.
     (nnimap-possibly-change-group group server)
     (setq deleted-articles (nreverse deleted-articles))
-    (nnimap-delete-article deleted-articles)
+    (nnimap-delete-article (gnus-compress-sequence deleted-articles))
     deleted-articles))
 
 (defun nnimap-find-expired-articles (group)
@@ -1129,9 +1149,12 @@ some servers.")
     (goto-char (point-max))
     (while (and (setq openp (memq (process-status process)
                                  '(open run)))
-               (not (re-search-backward (format "^%d .*\n" sequence)
-                                        (max (point-min) (- (point) 500))
-                                        t)))
+               (not (re-search-backward
+                     (format "^%d .*\n" sequence)
+                     (if nnimap-streaming
+                         (max (point-min) (- (point) 500))
+                       (point-min))
+                     t)))
       (when messagep
        (message "Read %dKB" (/ (buffer-size) 1000)))
       (nnheader-accept-process-output process)