* gnus-agent.el (gnus-agent-regenerate-group): Added interactive form.
[gnus] / lisp / nnmail.el
index 69fa9f7..cb1fb79 100644 (file)
@@ -57,7 +57,7 @@
   :group 'nnmail)
 
 (defgroup nnmail-split nil
-  "Organizing the incomming mail in folders."
+  "Organizing the incoming mail in folders."
   :group 'nnmail)
 
 (defgroup nnmail-files nil
@@ -104,7 +104,8 @@ The last element should always have \"\" as the regexp.
 
 This variable can also have a function as its value."
   :group 'nnmail-split
-  :type '(choice (repeat :tag "Alist" (group (string :tag "Name") regexp))
+  :type '(choice (repeat :tag "Alist" (group (string :tag "Name")
+                                            (choice regexp function)))
                 (function-item nnmail-split-fancy)
                 (function :tag "Other")))
 
@@ -116,8 +117,16 @@ If nil, the first match found will be used."
   :type 'boolean)
 
 (defcustom nnmail-split-fancy-with-parent-ignore-groups nil
-  "Regexp that matches group names to be ignored when applying
-`nnmail-split-fancy-with-parent'.  This can also be a list of regexps."
+  "Regexp that matches group names to be ignored when applying `nnmail-split-fancy-with-parent'.
+This can also be a list of regexps."
+  :group 'nnmail-split
+  :type '(choice (const :tag "none" nil)
+                (regexp :value ".*")
+                (repeat :value (".*") regexp)))
+
+(defcustom nnmail-cache-ignore-groups nil
+  "Regexp that matches group names to be ignored when inserting message ids into the cache (`nnmail-cache-insert').
+This can also be a list of regexps."
   :group 'nnmail-split
   :type '(choice (const :tag "none" nil)
                 (regexp :value ".*")
@@ -189,7 +198,7 @@ The return value should be `delete' or a group name (a string)."
                 (function :format "%v" nnmail-)
                 string))
 
-(defcustom nnmail-fancy-expiry-targets nil 
+(defcustom nnmail-fancy-expiry-targets nil
   "Determine expiry target based on articles using fancy techniques.
 
 This is a list of (\"HEADER\" \"REGEXP\" \"TARGET\") entries.  If
@@ -219,8 +228,8 @@ everything else will be expired to \"nnfolder:Archive-YYYY\"."
   :type '(repeat (list (choice :tag "Match against"
                               (string :tag "Header")
                               (const to-from))
-                       regexp
-                       (string :tag "Target group format string"))))
+                      regexp
+                      (string :tag "Target group format string"))))
 
 (defcustom nnmail-cache-accepted-message-ids nil
   "If non-nil, put Message-IDs of Gcc'd articles into the duplicate cache.
@@ -342,11 +351,12 @@ discarded after running the split process."
   :type 'hook)
 
 (defcustom nnmail-large-newsgroup 50
-  "*The number of the articles which indicates a large newsgroup.
+  "*The number of the articles which indicates a large newsgroup or nil.
 If the number of the articles is greater than the value, verbose
 messages will be shown to indicate the current status."
   :group 'nnmail-various
-  :type 'integer)
+  :type '(choice (const :tag "infinite" nil)
+                 (number :tag "count")))
 
 (defcustom nnmail-split-fancy "mail.misc"
   "Incoming mail can be split according to this fancy variable.
@@ -381,8 +391,8 @@ GROUP: Mail will be stored in GROUP (a string).
 junk: Mail will be deleted.  Use with care!  Do not submerge in water!
   Example:
   (setq nnmail-split-fancy
-        '(| (\"Subject\" \"MAKE MONEY FAST\" junk)
-            ...other.rules.omitted...))
+       '(| (\"Subject\" \"MAKE MONEY FAST\" junk)
+           ...other.rules.omitted...))
 
 FIELD must match a complete field name.  VALUE must match a complete
 word according to the `nnmail-split-fancy-syntax-table' syntax table.
@@ -483,6 +493,11 @@ parameter.  It should return nil, `warn' or `delete'."
   :group 'nnmail
   :type 'symbol)
 
+(defcustom nnmail-mail-splitting-decodes nil
+  "Whether the nnmail splitting functionality should MIME decode headers."
+  :group 'nnmail
+  :type 'boolean)
+
 ;;; Internal variables.
 
 (defvar nnmail-article-buffer " *nnmail incoming*"
@@ -523,7 +538,7 @@ parameter.  It should return nil, `warn' or `delete'."
   "Coding system used in reading inbox")
 
 (defvar nnmail-pathname-coding-system nil
-  "*Coding system for pathname.")
+  "*Coding system for file name.")
 
 (defun nnmail-find-file (file)
   "Insert FILE in server buffer safely."
@@ -540,7 +555,7 @@ parameter.  It should return nil, `warn' or `delete'."
       (file-error nil))))
 
 (defun nnmail-group-pathname (group dir &optional file)
-  "Make pathname for GROUP."
+  "Make file name for GROUP."
   (concat
    (let ((dir (file-name-as-directory (expand-file-name dir))))
      (setq group (nnheader-replace-duplicate-chars-in-string
@@ -771,7 +786,9 @@ If SOURCE is a directory spec, try to return the group name component."
     (if (not (and (re-search-forward "^From " nil t)
                  (goto-char (match-beginning 0))))
        ;; Possibly wrong format?
-       (error "Error, unknown mail format! (Possibly corrupted.)")
+       (error "Error, unknown mail format! (Possibly corrupted %s `%s'.)"
+              (if (buffer-file-name) "file" "buffer")
+              (or (buffer-file-name) (buffer-name)))
       ;; Carry on until the bitter end.
       (while (not (eobp))
        (setq start (point)
@@ -781,8 +798,8 @@ If SOURCE is a directory spec, try to return the group name component."
         start
         (if (search-forward "\n\n" nil t)
             (1- (point))
-        ;; This will never happen, but just to be on the safe side --
-      ;; if there is no head-body delimiter, we search a bit manually.
+          ;; This will never happen, but just to be on the safe side --
+          ;; if there is no head-body delimiter, we search a bit manually.
           (while (and (looking-at "From \\|[^ \t]+:")
                       (not (eobp)))
             (forward-line 1))
@@ -814,12 +831,12 @@ If SOURCE is a directory spec, try to return the group name component."
        (goto-char (point-max))
        (widen)
        (setq head-end (point))
-   ;; We try the Content-Length value.  The idea: skip over the header
-   ;; separator, then check what happens content-length bytes into the
-    ;; message body.  This should be either the end ot the buffer, the
-       ;; message separator or a blank line followed by the separator.
-      ;; The blank line should probably be deleted.  If neither of the
-       ;; three is met, the content-length header is probably invalid.
+       ;; We try the Content-Length value.  The idea: skip over the header
+       ;; separator, then check what happens content-length bytes into the
+       ;; message body.  This should be either the end of the buffer, the
+       ;; message separator or a blank line followed by the separator.
+       ;; The blank line should probably be deleted.  If neither of the
+       ;; three is met, the content-length header is probably invalid.
        (when content-length
          (forward-line 1)
          (setq skip (+ (point) content-length))
@@ -999,8 +1016,9 @@ FUNC will be called with the group name to determine the article number."
        ;; Copy the headers into the work buffer.
        (insert-buffer-substring obuf beg end)
        ;; Decode MIME headers and charsets.
-       (let ((mail-parse-charset nnmail-mail-splitting-charset))
-         (mail-decode-encoded-word-region (point-min) (point-max)))
+       (when nnmail-mail-splitting-decodes
+         (let ((mail-parse-charset nnmail-mail-splitting-charset))
+           (mail-decode-encoded-word-region (point-min) (point-max))))
        ;; Fold continuation lines.
        (goto-char (point-min))
        (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
@@ -1209,7 +1227,7 @@ to actually put the message in the right group."
 
 (defun nnmail-split-fancy ()
   "Fancy splitting method.
-See the documentation for the variable `nnmail-split-fancy' for documentation."
+See the documentation for the variable `nnmail-split-fancy' for details."
   (let ((syntab (syntax-table)))
     (unwind-protect
        (progn
@@ -1254,6 +1272,8 @@ See the documentation for the variable `nnmail-split-fancy' for documentation."
 
      ;; Builtin : operation.
      ((eq (car split) ':)
+      (when nnmail-split-tracing
+       (push split nnmail-split-trace))
       (nnmail-split-it (save-excursion (eval (cdr split)))))
 
      ;; Builtin ! operation.
@@ -1455,35 +1475,28 @@ See the documentation for the variable `nnmail-split-fancy' for documentation."
 (defvar group)
 (defvar group-art-list)
 (defvar group-art)
-(defun nnmail-cache-insert (id)
+(defun nnmail-cache-insert (id grp)
   (when nnmail-treat-duplicates
     ;; Store some information about the group this message is written
-    ;; to.  This function might have been called from various places.
-    ;; Sometimes, a function up in the calling sequence has an
-    ;; argument GROUP which is bound to a string, the group name.  At
-    ;; other times, there is a function up in the calling sequence
-    ;; which has an argument GROUP-ART which is a list of pairs, and
-    ;; the car of a pair is a group name.  Should we check that the
-    ;; length of the list is equal to 1? -- kai
-    (let ((g nil))
-      (cond ((and (boundp 'group) group)
-            (setq g group))
-           ((and (boundp 'group-art-list) group-art-list
-                 (listp group-art-list))
-            (setq g (caar group-art-list)))
-           ((and (boundp 'group-art) group-art (listp group-art))
-            (setq g (caar group-art)))
-           (t (setq g "")))
-      (unless (gnus-buffer-live-p nnmail-cache-buffer)
-       (nnmail-cache-open))
-      (save-excursion
-       (set-buffer nnmail-cache-buffer)
-       (goto-char (point-max))
-       (if (and g (not (string= "" g))
-                (gnus-methods-equal-p gnus-command-method
-                                      (nnmail-cache-primary-mail-backend)))
-           (insert id "\t" g "\n")
-         (insert id "\n"))))))
+    ;; to.  This is passed in as the grp argument -- all locations this
+    ;; has been called from have been checked and the group is available.
+    ;; The only ambiguous case is nnmail-check-duplication which will only
+    ;; pass the first (of possibly >1) group which matches. -Josh
+    (unless (gnus-buffer-live-p nnmail-cache-buffer)
+      (nnmail-cache-open))
+    (save-excursion
+      (set-buffer nnmail-cache-buffer)
+      (goto-char (point-max))
+      (if (and grp (not (string= "" grp))
+              (gnus-methods-equal-p gnus-command-method
+                                    (nnmail-cache-primary-mail-backend)))
+         (let ((regexp (if (consp nnmail-cache-ignore-groups)
+                           (mapconcat 'identity nnmail-cache-ignore-groups
+                                      "\\|")
+                         nnmail-cache-ignore-groups)))
+           (unless (and regexp (string-match regexp grp))
+             (insert id "\t" grp "\n")))
+       (insert id "\n")))))
 
 (defun nnmail-cache-primary-mail-backend ()
   (let ((be-list (cons gnus-select-method gnus-secondary-select-methods))
@@ -1507,7 +1520,7 @@ See the documentation for the variable `nnmail-split-fancy' for documentation."
       (when (search-backward id nil t)
        (beginning-of-line)
        (skip-chars-forward "^\n\r\t")
-       (unless (eolp)
+       (unless (looking-at "[\r\n]")
          (forward-char 1)
          (buffer-substring (point)
                            (progn (end-of-line) (point))))))))
@@ -1540,7 +1553,7 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details."
        (nnmail-cache-open))
       (mapcar (lambda (x)
                (setq res (or (nnmail-cache-fetch-group x) res))
-               (when (or (string= "drafts" res)
+               (when (or (member res '("delayed" "drafts" "queue"))
                          (and regexp res (string-match regexp res)))
                  (setq res nil)))
              references)
@@ -1585,7 +1598,7 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details."
      ((not duplication)
       (funcall func (setq group-art
                          (nreverse (nnmail-article-group artnum-func))))
-      (nnmail-cache-insert message-id))
+      (nnmail-cache-insert message-id (caar group-art)))
      ((eq action 'delete)
       (setq group-art nil))
      ((eq action 'warn)
@@ -1737,7 +1750,11 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details."
     (when (nnheader-functionp target)
       (setq target (funcall target group)))
     (unless (eq target 'delete)
-      (gnus-request-accept-article target nil nil t))))
+      (when (or (gnus-request-group target)
+               (gnus-request-create-group target))
+       (let ((group-art (gnus-request-accept-article target nil nil t)))
+         (when (consp group-art)
+           (gnus-group-mark-article-read target (cdr group-art))))))))
 
 (defun nnmail-fancy-expiry-target (group)
   "Returns a target expiry group determined by `nnmail-fancy-expiry-targets'."
@@ -1760,7 +1777,9 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details."
        (setq target (format-time-string (caddr regexp-target-pair) date)))
        ((and (not (equal header 'to-from))
             (string-match (cadr regexp-target-pair)
-                          (message-fetch-field header)))
+                          (or
+                           (message-fetch-field header)
+                           "")))
        (setq target
              (format-time-string (caddr regexp-target-pair) date)))))))