*** empty log message ***
[gnus] / lisp / nnmail.el
index e4464e8..18778ea 100644 (file)
@@ -1,7 +1,7 @@
 ;;; nnmail.el --- mail support functions for the Gnus mail backends
-;; Copyright (C) 1995,96,97 Free Software Foundation, Inc.
+;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news, mail
 
 ;; This file is part of GNU Emacs.
 
 ;;; Code:
 
+(eval-when-compile (require 'cl))
+
 (require 'nnheader)
 (require 'timezone)
 (require 'message)
-(require 'cl)
 (require 'custom)
+(require 'gnus-util)
 
 (eval-and-compile
-  (autoload 'gnus-error "gnus-util"))
+  (autoload 'gnus-error "gnus-util")
+  (autoload 'gnus-buffer-live-p "gnus-util")
+  (autoload 'gnus-encode-coding-string "gnus-ems"))
 
 (defgroup nnmail nil
   "Reading mail with Gnus."
@@ -73,7 +77,7 @@
 
 (defcustom nnmail-split-methods
   '(("mail.misc" ""))
-  "Incoming mail will be split according to this variable.
+  "*Incoming mail will be split according to this variable.
 
 If you'd like, for instance, one mail group for mail from the
 \"4ad-l\" mailing list, one group for junk mail and one for everything
@@ -112,7 +116,9 @@ If nil, the first match found will be used."
 
 ;; Added by gord@enci.ucalgary.ca (Gordon Matzigkeit).
 (defcustom nnmail-keep-last-article nil
-  "If non-nil, nnmail will never delete the last expired article in a directory.
+  "If non-nil, nnmail will never delete/move a group's last article.
+It can be marked expirable, so it will be deleted when it is no longer last.
+
 You may need to set this variable if other programs are putting
 new mail into folder numbers that Gnus has marked as expired."
   :group 'nnmail-procmail
@@ -168,7 +174,7 @@ Eg.:
 (defcustom nnmail-spool-file
   (or (getenv "MAIL")
       (concat "/usr/spool/mail/" (user-login-name)))
-  "Where the mail backends will look for incoming mail.
+  "*Where the mail backends will look for incoming mail.
 This variable is \"/usr/spool/mail/$user\" by default.
 If this variable is nil, no mail backends will read incoming mail.
 If this variable is a list, all files mentioned in this list will be
@@ -213,10 +219,10 @@ several files - eg. \".spool[0-9]*\"."
   :type 'function)
 
 (defcustom nnmail-crosspost-link-function
-  (if (string-match "windows-nt\\|emx" (format "%s" system-type))
+  (if (string-match "windows-nt\\|emx" (symbol-name system-type))
       'copy-file
     'add-name-to-file)
-  "Function called to create a copy of a file.
+  "*Function called to create a copy of a file.
 This is `add-name-to-file' by default, which means that crossposts
 will use hard links.  If your file system doesn't allow hard
 links, you could set this variable to `copy-file' instead."
@@ -245,7 +251,7 @@ to be moved to."
   (if (eq system-type 'windows-nt)
       '(nnheader-ms-strip-cr)
     nil)
-  "Hook that will be run after the incoming mail has been transferred.
+  "*Hook that will be run after the incoming mail has been transferred.
 The incoming mail is moved from `nnmail-spool-file' (which normally is
 something like \"/usr/spool/mail/$user\") to the user's home
 directory.  This hook is called after the incoming mail box has been
@@ -297,8 +303,8 @@ that) from the headers before splitting and saving the messages."
 This can also be a list of regexps."
   :group 'nnmail-prepare
   :type '(choice (const :tag "none" nil)
-                regexp
-                (repeat regexp)))
+                (regexp :value ".*")
+                (repeat :value (".*") regexp)))
 
 (defcustom nnmail-pre-get-new-mail-hook nil
   "Hook called just before starting to handle new incoming mail."
@@ -338,7 +344,7 @@ messages will be shown to indicate the current status."
   "Incoming mail can be split according to this fancy variable.
 To enable this, set `nnmail-split-methods' to `nnmail-split-fancy'.
 
-The format is this variable is SPLIT, where SPLIT can be one of
+The format of this variable is SPLIT, where SPLIT can be one of
 the following:
 
 GROUP: Mail will be stored in GROUP (a string).
@@ -393,8 +399,12 @@ Example:
 
 (defcustom nnmail-split-abbrev-alist
   '((any . "from\\|to\\|cc\\|sender\\|apparently-to\\|resent-from\\|resent-to\\|resent-cc")
-    (mail . "mailer-daemon\\|postmaster\\|uucp"))
-  "Alist of abbreviations allowed in `nnmail-split-fancy'."
+    (mail . "mailer-daemon\\|postmaster\\|uucp")
+    (to . "to\\|cc\\|apparently-to\\|resent-to\\|resent-cc")
+    (from . "from\\|sender\\|resent-from")
+    (nato . "to\\|cc\\|resent-to\\|resent-cc")
+    (naany . "from\\|to\\|cc\\|sender\\|resent-from\\|resent-to\\|resent-cc"))
+  "*Alist of abbreviations allowed in `nnmail-split-fancy'."
   :group 'nnmail-split
   :type '(repeat (cons :format "%v" symbol regexp)))
 
@@ -438,6 +448,8 @@ parameter.  It should return nil, `warn' or `delete'."
 (defvar nnmail-split-history nil
   "List of group/article elements that say where the previous split put messages.")
 
+(defvar nnmail-current-spool nil)
+
 (defvar nnmail-pop-password nil
   "*Password to use when reading mail from a POP server, if required.")
 
@@ -457,6 +469,9 @@ parameter.  It should return nil, `warn' or `delete'."
 
 (defvar nnmail-internal-password nil)
 
+(defvar nnmail-split-tracing nil)
+(defvar nnmail-split-trace nil)
+
 \f
 
 (defconst nnmail-version "nnmail 1.0"
@@ -467,6 +482,9 @@ parameter.  It should return nil, `warn' or `delete'."
 (defun nnmail-request-post (&optional server)
   (mail-send-and-exit nil))
 
+(defvar nnmail-file-coding-system 'raw-text
+  "Coding system used in nnmail.")
+
 (defun nnmail-find-file (file)
   "Insert FILE in server buffer safely."
   (set-buffer nntp-server-buffer)
@@ -474,19 +492,31 @@ parameter.  It should return nil, `warn' or `delete'."
   (let ((format-alist nil)
         (after-insert-file-functions nil))
     (condition-case ()
-       (progn (insert-file-contents file) t)
+       (let ((coding-system-for-read nnmail-file-coding-system)
+             (pathname-coding-system 'binary))
+         (insert-file-contents file)
+         t)
       (file-error nil))))
 
+(defvar nnmail-pathname-coding-system
+  'iso-8859-1
+  "*Coding system for pathname.")
+
 (defun nnmail-group-pathname (group dir &optional file)
   "Make pathname for GROUP."
   (concat
    (let ((dir (file-name-as-directory (expand-file-name dir))))
+     (setq group (nnheader-translate-file-chars group))
      ;; If this directory exists, we use it directly.
      (if (or nnmail-use-long-file-names
             (file-directory-p (concat dir group)))
         (concat dir group "/")
        ;; If not, we translate dots into slashes.
-       (concat dir (nnheader-replace-chars-in-string group ?. ?/) "/")))
+       (concat dir
+              (gnus-encode-coding-string
+               (nnheader-replace-chars-in-string group ?. ?/)
+               nnmail-pathname-coding-system)
+              "/")))
    (or file "")))
 
 (defun nnmail-date-to-time (date)
@@ -515,7 +545,7 @@ parameter.  It should return nil, `warn' or `delete'."
   "Convert DAYS into time."
   (let* ((seconds (* 1.0 days 60 60 24))
         (rest (expt 2 16))
-        (ms (condition-case nil (round (/ seconds rest))
+        (ms (condition-case nil (floor (/ seconds rest))
               (range-error (expt 2 16)))))
     (list ms (condition-case nil (round (- seconds (* ms rest)))
               (range-error (expt 2 16))))))
@@ -535,18 +565,17 @@ parameter.  It should return nil, `warn' or `delete'."
 (defun nnmail-move-inbox (inbox)
   "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."
+      (gnus-error 1 "Can't write to crash box %s.  Not moving mail"
                  nnmail-crash-box)
     ;; If the crash box exists and is empty, we delete it.
     (when (and (file-exists-p nnmail-crash-box)
               (zerop (nnheader-file-size (file-truename nnmail-crash-box))))
       (delete-file nnmail-crash-box))
-    (let ((inbox (file-truename (expand-file-name inbox)))
-         (tofile (file-truename (expand-file-name nnmail-crash-box)))
-         movemail popmail errors result)
-      (if (setq popmail (string-match
-                        "^po:" (file-name-nondirectory inbox)))
-         (setq inbox (file-name-nondirectory inbox))
+    (let ((tofile (file-truename (expand-file-name nnmail-crash-box)))
+         (popmail (string-match "^po:" inbox))
+         movemail errors result)
+      (unless popmail
+       (setq inbox (file-truename (expand-file-name inbox)))
        (setq movemail t)
        ;; On some systems, /usr/spool/mail/foo is a directory
        ;; and the actual inbox is /usr/spool/mail/foo/foo.
@@ -566,12 +595,12 @@ parameter.  It should return nil, `warn' or `delete'."
                      (nnmail-read-passwd
                       (format "Password for %s: "
                               (substring inbox (+ popmail 3))))))
-             (message "Getting mail from post office ..."))
+             (nnheader-message 5 "Getting mail from the post office..."))
          (when (or (and (file-exists-p tofile)
                         (/= 0 (nnheader-file-size tofile)))
                    (and (file-exists-p inbox)
                         (/= 0 (nnheader-file-size inbox))))
-           (message "Getting mail from %s..." inbox)))
+           (nnheader-message 5 "Getting mail from %s..." inbox)))
        ;; Set TOFILE if have not already done so, and
        ;; rename or copy the file INBOX to TOFILE if and as appropriate.
        (cond
@@ -590,17 +619,17 @@ parameter.  It should return nil, `warn' or `delete'."
              (save-excursion
                (setq errors (generate-new-buffer " *nnmail loss*"))
                (buffer-disable-undo errors)
-               (let ((default-directory "/"))
-                 (if (nnheader-functionp nnmail-movemail-program)
-                     (condition-case err
-                         (progn
-                           (funcall nnmail-movemail-program inbox tofile)
-                           (setq result 0))
-                       (error
-                        (save-excursion
-                          (set-buffer errors)
-                          (insert (prin1-to-string err))
-                          (setq result 255))))
+               (if (nnheader-functionp nnmail-movemail-program)
+                   (condition-case err
+                       (progn
+                         (funcall nnmail-movemail-program inbox tofile)
+                         (setq result 0))
+                     (error
+                      (save-excursion
+                        (set-buffer errors)
+                        (insert (prin1-to-string err))
+                        (setq result 255))))
+                 (let ((default-directory "/"))
                    (setq result
                          (apply
                           'call-process
@@ -611,14 +640,14 @@ parameter.  It should return nil, `warn' or `delete'."
                             nil errors nil inbox tofile)
                            (when nnmail-internal-password
                              (list nnmail-internal-password)))))))
+               (push inbox nnmail-moved-inboxes)
                (if (and (not (buffer-modified-p errors))
                         (zerop result))
                    ;; No output => movemail won
                    (progn
                      (unless popmail
                        (when (file-exists-p tofile)
-                         (set-file-modes tofile nnmail-default-file-modes)))
-                     (push inbox nnmail-moved-inboxes))
+                         (set-file-modes tofile nnmail-default-file-modes))))
                  (set-buffer errors)
                  ;; There may be a warning about older revisions.  We
                  ;; ignore those.
@@ -627,8 +656,8 @@ parameter.  It should return nil, `warn' or `delete'."
                      (progn
                        (unless popmail
                          (when (file-exists-p tofile)
-                           (set-file-modes tofile nnmail-default-file-modes)))
-                       (push inbox nnmail-moved-inboxes))
+                           (set-file-modes
+                            tofile nnmail-default-file-modes))))
                    ;; Probably a real error.
                    (subst-char-in-region (point-min) (point-max) ?\n ?\  )
                    (goto-char (point-max))
@@ -642,7 +671,7 @@ parameter.  It should return nil, `warn' or `delete'."
                &nb