:group 'nnmail)
(defgroup nnmail-split nil
- "Organizing the incomming mail in folders."
+ "Organizing the incoming mail in folders."
:group 'nnmail)
(defgroup nnmail-files nil
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")))
: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 ".*")
(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
: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.
: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.
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.
:group 'nnmail
:type 'integer)
+(defcustom nnmail-mail-splitting-charset nil
+ "Default charset to be used when splitting incoming mail."
+ :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*"
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))
(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))
(erase-buffer)
;; Copy the headers into the work buffer.
(insert-buffer-substring obuf beg end)
+ ;; Decode MIME headers and charsets.
+ (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)
(or (funcall nnmail-split-methods)
'("bogus"))
(error
- (nnheader-message 5
- "Error in `nnmail-split-methods'; using `bogus' mail group")
+ (nnheader-message
+ 5 "Error in `nnmail-split-methods'; using `bogus' mail group")
(sit-for 1)
'("bogus")))))
(setq split (gnus-remove-duplicates split))
(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
;; Builtin : operation.
((eq (car split) ':)
+ (when nnmail-split-tracing
+ (push split nnmail-split-trace))
(nnmail-split-it (save-excursion (eval (cdr split)))))
;; Builtin ! operation.
(let ((value (nth 1 split)))
(if (symbolp value)
(setq value (cdr (assq value nnmail-split-abbrev-alist))))
- ;; Someone might want to do a \N sub on this match, so get the
+ ;; Someone might want to do a \N sub on this match, so get the
;; correct match positions.
(re-search-backward value start-of-value))
(dolist (sp (nnmail-split-it (car split-rest)))
(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))
(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))))))))
(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)
((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)
(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'."
(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)))))))