* lisp/gnus.el (gnus-version-number): Update to 6.12.20
[elisp/gnus.git-] / lisp / nnmail.el
index 6ae7287..8ed80ab 100644 (file)
@@ -252,6 +252,20 @@ to be moved to."
   :group 'nnmail-retrieve
   :type 'string)
 
+(defcustom nnmail-movemail-program-apop-option "-A"
+  "*APOP option parameter for a command to be executed to move mail
+ from the inbox.
+The default is \"-A\"."
+  :group 'nnmail-files
+  :group 'nnmail-retrieve
+  :type 'string)
+
+(defcustom nnmail-movemail-program-pop-password-required t
+  "*Non-nil if a password is required when reading mail using POP
+with `movemail' external program."
+  :group 'nnmail-retrieve
+  :type 'boolean)
+
 (defcustom nnmail-pop-password-required nil
   "*Non-nil if a password is required when reading mail using POP."
   :group 'nnmail-retrieve
@@ -631,7 +645,7 @@ If this variable is `t', do not use password cache.")
                        (list (cons inbox password)))))
 
 ;; Function rewritten from rmail.el.
-(defun nnmail-move-inbox (inbox)
+(defun nnmail-move-inbox (inbox &optional inbox-options)
   "Move INBOX to `nnmail-crash-box'."
   (if (not (file-writable-p nnmail-crash-box))
       (gnus-error 1 "Can't write to crash box %s.  Not moving mail"
@@ -654,13 +668,8 @@ If this variable is `t', do not use password cache.")
          ;; We don't try to move an already moved inbox.
          nil
        (if popmail
-           (progn
-             (when (and nnmail-pop-password
-                        (not nnmail-internal-password-cache))
-               (setq nnmail-internal-password-cache nnmail-pop-password))
-             (setq nnmail-internal-password (nnmail-get-password inbox))
-             (nnheader-message 5 "Getting mail from the post office %s..."
-                               inbox))
+           (nnheader-message 5 "Getting mail from the post office %s..."
+                               inbox)
          (when (or (and (file-exists-p tofile)
                         (/= 0 (nnheader-file-size tofile)))
                    (and (file-exists-p inbox)
@@ -680,6 +689,11 @@ If this variable is `t', do not use password cache.")
          ;; If getting from mail spool directory, use movemail to move
          ;; rather than just renaming, so as to interlock with the
          ;; mailer.
+         (when popmail
+           (when (and (not nnmail-internal-password-cache)
+                      nnmail-pop-password)
+             (nnmail-set-password nil nnmail-pop-password))
+           (setq nnmail-internal-password (nnmail-get-password inbox)))
          (unwind-protect
              (save-excursion
                (setq errors (generate-new-buffer " *nnmail loss*"))
@@ -687,38 +701,23 @@ If this variable is `t', do not use password cache.")
                (if (nnheader-functionp nnmail-movemail-program)
                    (condition-case err
                        (progn
-                         (funcall nnmail-movemail-program inbox tofile)
+                         (funcall nnmail-movemail-program
+                                  inbox tofile inbox-options)
                          (setq result 0))
                      (error
                       (save-excursion
                         (set-buffer errors)
                         (insert (prin1-to-string err))
                         (setq result 255))))
-                 (let ((default-directory "/")
-                       (inbox-info (nnmail-parse-spool-file-name inbox)))
-                   (and popmail
-                        (setenv "MAILHOST"
-                                (nnmail-spool-mailhost inbox-info)))
-                   (setq result
-                         (apply
-                          'call-process
-                          (append
-                           (list
-                            (expand-file-name
-                             nnmail-movemail-program exec-directory)
-                            nil errors nil 
-                            (concat (if popmail "po:" "")
-                                    (nnmail-spool-maildrop inbox-info))
-                            tofile)
-                           (and popmail
-                                nnmail-internal-password
-                                (list nnmail-internal-password)))))))
+                 (setq result (nnmail-exec-movemail-program
+                               inbox tofile popmail errors inbox-options)))
                (push inbox nnmail-moved-inboxes)
                (if (and (not (buffer-modified-p errors))
                         (zerop result))
                    ;; No output => movemail won
                    (progn
-                     (unless popmail
+                     (if popmail
+                         (nnmail-set-password inbox nnmail-internal-password)
                        (when (file-exists-p tofile)
                          (set-file-modes tofile nnmail-default-file-modes))))
                  (set-buffer errors)
@@ -745,14 +744,12 @@ If this variable is `t', do not use password cache.")
                    (unless (yes-or-no-p
                             (format "movemail: %s (%d return).  Continue? "
                                     (buffer-string) result))
-                            (error "%s" (buffer-string)))
-                   (setq tofile nil)))
-               ))))
-       (nnmail-set-password inbox nnmail-internal-password)
+                     (error "%s" (buffer-string)))
+                   (setq tofile nil))))
+           (and errors
+                (buffer-name errors)
+                (kill-buffer errors)))))
        (nnheader-message 5 "Getting mail from %s...done" inbox)
-       (and errors
-            (buffer-name errors)
-            (kill-buffer errors))
        tofile))))
 
 (defun nnmail-get-active ()
@@ -1387,10 +1384,13 @@ See the documentation for the variable `nnmail-split-fancy' for documentation."
        ;; correct match positions.
        (goto-char (match-end 0))
        (let ((value (nth 1 split)))
-         (re-search-backward (if (symbolp value)
-                                 (cdr (assq value nnmail-split-abbrev-alist))
-                               value)
-                             (match-end 1)))
+         (re-search-backward
+          (concat "\\<"
+                  (if (symbolp value)
+                      (cdr (assq value nnmail-split-abbrev-alist))
+                    value)
+                  "\\>")
+          (match-end 1)))
        (nnmail-split-it (nth 2 split))))
 
      ;; Not in cache, compute a regexp for the field/value pair.
@@ -1488,10 +1488,11 @@ See the documentation for the variable `nnmail-split-fancy' for documentation."
                'nconc
                (mapcar
                 (lambda (file)
-                  (if (and (not (string-match "^po:" file))
-                           (file-directory-p file))
-                      (nnheader-directory-regular-files file)
-                    (list file)))
+                  (let ((file-name (if (listp file) (car file) file)))
+                    (if (and (not (string-match "^po:" file-name))
+                             (file-directory-p file-name))
+                        (nnheader-directory-regular-files file-name)
+                      (list file))))
                 nnmail-spool-file))
               procmails))
             ((stringp nnmail-spool-file)
@@ -1658,7 +1659,7 @@ See the documentation for the variable `nnmail-split-fancy' for documentation."
   "Read new incoming mail."
   (let* ((spools (nnmail-get-spool-files group))
         (group-in group)
-        nnmail-current-spool incoming incomings spool)
+        nnmail-current-spool incoming incomings spool spool-options)
     (when (and (nnmail-get-value "%s-get-new-mail" method)
               nnmail-spool-file)
       ;; We first activate all the groups.
@@ -1670,7 +1671,10 @@ See the documentation for the variable `nnmail-split-fancy' for documentation."
       ;; The we go through all the existing spool files and split the
       ;; mail from each.
       (while spools
-       (setq spool (pop spools))
+       (if (listp (setq spool (pop spools)))
+           (setq spool-options (cdr spool)
+                 spool (car spool))
+         (setq spool-options nil))
        ;; We read each spool file if either the spool is a POP-mail
        ;; spool, or the file exists.  We can't check for the
        ;; existence of POPped mail.
@@ -1678,7 +1682,7 @@ See the documentation for the variable `nnmail-split-fancy' for documentation."
                  (and (file-exists-p (file-truename spool))
                       (> (nnheader-file-size (file-truename spool)) 0)))
          (nnheader-message 3 "%s: Reading incoming mail..." method)
-         (when (and (nnmail-move-inbox spool)
+         (when (and (nnmail-move-inbox spool spool-options)
                     (file-exists-p nnmail-crash-box))
            (setq nnmail-current-spool spool)
            ;; There is new mail.  We first find out if all this mail
@@ -1873,15 +1877,54 @@ If ARGS, PROMPT is used as an argument to `format'."
              his nil)))
     found))
 
-(eval-and-compile
-  (autoload 'pop3-movemail "pop3"))
-
-(defun nnmail-pop3-movemail (inbox crashbox)
+(defun nnmail-exec-movemail-program (inbox tofile popmail err-buf
+                                          inbox-options)
+  (let ((default-directory "/")
+       (inbox-info (nnmail-parse-spool-file-name inbox))
+       args)
+    (if popmail
+       (let ((auth-scheme (car (cdr (memq :auth-scheme inbox-options))))
+             (password
+              (or nnmail-internal-password
+                  (and nnmail-movemail-program-pop-password-required
+                       (nnmail-read-passwd
+                        (format "Password for %s: " inbox))))))
+         (setenv "MAILHOST" (nnmail-spool-mailhost inbox-info))
+         (when password
+           (push password args))
+         (push tofile args)
+         (push (concat "po:" (nnmail-spool-maildrop inbox-info)) args)
+         (cond
+          ((or (not auth-scheme) (eq auth-scheme 'pass)))
+          ((eq auth-scheme 'apop)
+           (push nnmail-movemail-program-apop-option args))
+          (t (error "Invalid POP3 authentication scheme."))))
+      (setq args (list (nnmail-spool-maildrop inbox-info)
+                      tofile)))
+    (apply
+     'call-process
+     (expand-file-name nnmail-movemail-program exec-directory)
+     nil err-buf nil
+     args)))
+
+(eval-when-compile
+  (require 'pop3))
+
+(defun nnmail-pop3-movemail (inbox crashbox options)
   "Function to move mail from INBOX on a pop3 server to file CRASHBOX."
+  (require 'pop3)
   (let* ((inbox-info (nnmail-parse-spool-file-name inbox))
-        (pop3-maildrop (nnmail-spool-maildrop inbox-info))
-        (pop3-mailhost (nnmail-spool-mailhost inbox-info))
-        (pop3-password nnmail-internal-password))
+        (pop3-maildrop (or (nnmail-spool-maildrop inbox-info)
+                           pop3-maildrop))
+        (pop3-password (or nnmail-internal-password
+                           pop3-password))
+        (pop3-authentication-scheme
+         (or (car (cdr (memq :auth-scheme options)))
+             pop3-authentication-scheme))
+        (pop3-mailhost (or (nnmail-spool-mailhost inbox-info)
+                           pop3-mailhost))
+        (pop3-port (or (car (cdr (memq :port options)))
+                       pop3-port)))
     (pop3-movemail crashbox)))
 
 (defun nnmail-within-headers-p ()