;;; nnmail.el --- mail support functions for the Gnus mail backends
-;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
-;; Free Software Foundation, Inc.
+
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+;; 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news, mail
;; This file is part of GNU Emacs.
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;; Code:
+;; For Emacs < 22.2.
+(eval-and-compile
+ (unless (fboundp 'declare-function) (defmacro declare-function (&rest r))))
+
(eval-when-compile (require 'cl))
+(require 'gnus) ; for macro gnus-kill-buffer, at least
(require 'nnheader)
(require 'message)
-(require 'custom)
(require 'gnus-util)
(require 'mail-source)
(require 'mm-util)
+(require 'gnus-int)
-(eval-and-compile
- (autoload 'gnus-error "gnus-util")
- (autoload 'gnus-buffer-live-p "gnus-util")
- (autoload 'gnus-add-buffer "gnus"))
+(autoload 'gnus-add-buffer "gnus")
+(autoload 'gnus-kill-buffer "gnus")
(defgroup nnmail nil
"Reading mail with Gnus."
:group 'nnmail)
(defgroup nnmail-prepare nil
- "Preparing (or mangling) new mail after retrival."
+ "Preparing (or mangling) new mail after retrieval."
:group 'nnmail)
(defgroup nnmail-duplicate nil
(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."
+ :version "22.1"
:group 'nnmail-split
:type '(choice (const :tag "none" nil)
(regexp :value ".*")
(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."
+ :version "22.1"
:group 'nnmail-split
:type '(choice (const :tag "none" nil)
(regexp :value ".*")
(defcustom nnmail-expiry-wait-function nil
"Variable that holds function to specify how old articles should be before they are expired.
- The function will be called with the name of the group that the
-expiry is to be performed in, and it should return an integer that
-says how many days an article can be stored before it is considered
-\"old\". It can also return the values `never' and `immediate'.
+The function will be called with the name of the group that the expiry
+is to be performed in, and it should return an integer that says how
+many days an article can be stored before it is considered \"old\".
+It can also return the values `never' and `immediate'.
Eg.:
:version "21.1"
:group 'nnmail-expire
:type '(choice (const delete)
- (function :format "%v" nnmail-)
+ function
string))
(defcustom nnmail-fancy-expiry-targets nil
articles containing the sting \"IMPORTANT\" in the Subject header will
be expired to the group \"nnfolder:IMPORTANT.YYYY.MMM\"; and
everything else will be expired to \"nnfolder:Archive-YYYY\"."
+ :version "22.1"
:group 'nnmail-expire
:type '(repeat (list (choice :tag "Match against"
(string :tag "Header")
:group 'nnmail
:type 'boolean)
-(defcustom nnmail-spool-file '((file))
- "*Where the mail backends will look for incoming mail.
-This variable is a list of mail source specifiers.
-This variable is obsolete; `mail-sources' should be used instead."
- :group 'nnmail-files
- :type 'sexp)
+(make-obsolete-variable 'nnmail-spool-file 'mail-sources
+ "Gnus 5.9 (Emacs 22.1)")
+;; revision 5.29 / p0-85 / Gnus 5.9
+;; Variable removed in No Gnus v0.7
(defcustom nnmail-resplit-incoming nil
"*If non-nil, re-split incoming procmail sorted mail."
\(add-hook 'nnmail-read-incoming-hook
(lambda ()
(call-process \"/local/bin/mailsend\" nil nil nil
- \"read\" nnmail-spool-file)))
+ \"read\"
+ ;; The incoming mail box file.
+ (expand-file-name (user-login-name)
+ rmail-spool-directory))))
If you have xwatch running, this will alert it that mail has been
read.
:group 'nnmail-split
:type 'hook)
+(defcustom nnmail-spool-hook nil
+ "*A hook called when a new article is spooled."
+ :version "22.1"
+ :group 'nnmail
+ :type 'hook)
+
(defcustom nnmail-large-newsgroup 50
- "*The number of the articles which indicates a large newsgroup or nil.
-If the number of the articles is greater than the value, verbose
+ "*The number of articles which indicates a large newsgroup or nil.
+If the number of articles is greater than the value, verbose
messages will be shown to indicate the current status."
:group 'nnmail-various
:type '(choice (const :tag "infinite" nil)
(number :tag "count")))
+(define-widget 'nnmail-lazy 'default
+ "Base widget for recursive datastructures.
+
+This is copy of the `lazy' widget in Emacs 22.1 provided for compatibility."
+ :format "%{%t%}: %v"
+ :convert-widget 'widget-value-convert-widget
+ :value-create (lambda (widget)
+ (let ((value (widget-get widget :value))
+ (type (widget-get widget :type)))
+ (widget-put widget :children
+ (list (widget-create-child-value
+ widget (widget-convert type) value)))))
+ :value-delete 'widget-children-value-delete
+ :value-get (lambda (widget)
+ (widget-value (car (widget-get widget :children))))
+ :value-inline (lambda (widget)
+ (widget-apply (car (widget-get widget :children))
+ :value-inline))
+ :default-get (lambda (widget)
+ (widget-default-get
+ (widget-convert (widget-get widget :type))))
+ :match (lambda (widget value)
+ (widget-apply (widget-convert (widget-get widget :type))
+ :match value))
+ :validate (lambda (widget)
+ (widget-apply (car (widget-get widget :children)) :validate)))
+
+(define-widget 'nnmail-split-fancy 'nnmail-lazy
+ "Widget for customizing splits in the variable of the same name."
+ :tag "Split"
+ :type '(menu-choice :value (any ".*value.*" "misc")
+ :tag "Type"
+ (string :tag "Destination")
+ (list :tag "Use first match (|)" :value (|)
+ (const :format "" |)
+ (editable-list :inline t nnmail-split-fancy))
+ (list :tag "Use all matches (&)" :value (&)
+ (const :format "" &)
+ (editable-list :inline t nnmail-split-fancy))
+ (list :tag "Function with fixed arguments (:)"
+ :value (:)
+ (const :format "" :value :)
+ function
+ (editable-list :inline t (sexp :tag "Arg"))
+ )
+ (list :tag "Function with split arguments (!)"
+ :value (!)
+ (const :format "" !)
+ function
+ (editable-list :inline t nnmail-split-fancy))
+ (list :tag "Field match"
+ (choice :tag "Field"
+ regexp symbol)
+ (choice :tag "Match"
+ regexp
+ (symbol :value mail))
+ (repeat :inline t
+ :tag "Restrictions"
+ (group :inline t
+ (const :format "" -)
+ regexp))
+ nnmail-split-fancy)
+ (const :tag "Junk (delete mail)" junk)))
+
(defcustom nnmail-split-fancy "mail.misc"
"Incoming mail can be split according to this fancy variable.
To enable this, set `nnmail-split-methods' to `nnmail-split-fancy'.
word according to the `nnmail-split-fancy-syntax-table' syntax table.
You can use \".*\" in the regexps to match partial field names or words.
-FIELD and VALUE can also be lisp symbols, in that case they are expanded
+FIELD and VALUE can also be Lisp symbols, in that case they are expanded
as specified in `nnmail-split-abbrev-alist'.
GROUP can contain \\& and \\N which will substitute from matching
;; Unmatched mail goes to the catch all group.
\"misc.misc\"))"
:group 'nnmail-split
- ;; Sigh!
- :type 'sexp)
+ :type 'nnmail-split-fancy)
(defcustom nnmail-split-abbrev-alist
'((any . "from\\|to\\|cc\\|sender\\|apparently-to\\|resent-from\\|resent-to\\|resent-cc")
:type '(choice (const :tag "disable" nil)
(integer :format "%v")))
-(defcustom nnmail-message-id-cache-file "~/.nnmail-cache"
- "*The file name of the nnmail Message-ID cache."
+(defcustom nnmail-message-id-cache-file
+ (nnheader-concat gnus-home-directory ".nnmail-cache")
+ "The file name of the nnmail Message-ID cache."
:group 'nnmail-duplicate
:group 'nnmail-files
:type 'file)
:group 'nnmail
:type '(repeat symbol))
-(defcustom nnmail-split-header-length-limit 512
+(defcustom nnmail-split-header-length-limit 2048
"Header lines longer than this limit are excluded from the split function."
:version "21.1"
:group 'nnmail
(defcustom nnmail-mail-splitting-charset nil
"Default charset to be used when splitting incoming mail."
+ :version "22.1"
:group 'nnmail
:type 'symbol)
(defcustom nnmail-mail-splitting-decodes nil
"Whether the nnmail splitting functionality should MIME decode headers."
+ :version "22.1"
+ :group 'nnmail
+ :type 'boolean)
+
+(defcustom nnmail-split-fancy-match-partial-words nil
+ "Whether to match partial words when fancy splitting.
+Normally, regexes given in `nnmail-split-fancy' are implicitly surrounded
+by \"\\=\\<...\\>\". If this variable is true, they are not implicitly\
+ surrounded
+by anything."
+ :version "22.1"
+ :group 'nnmail
+ :type 'boolean)
+
+(defcustom nnmail-split-lowercase-expanded t
+ "Whether to lowercase expanded entries (i.e. \\N) when splitting mails.
+This avoids the creation of multiple groups when users send to an address
+using different case (i.e. mailing-list@domain vs Mailing-List@Domain)."
+ :version "22.1"
:group 'nnmail
:type 'boolean)
(defvar nnmail-split-history nil
"List of group/article elements that say where the previous split put messages.")
-(defvar nnmail-split-fancy-syntax-table nil
+(defvar nnmail-split-fancy-syntax-table
+ (let ((table (make-syntax-table)))
+ ;; support the %-hack
+ (modify-syntax-entry ?\% "." table)
+ table)
"Syntax table used by `nnmail-split-fancy'.")
-(unless (syntax-table-p nnmail-split-fancy-syntax-table)
- (setq nnmail-split-fancy-syntax-table
- (copy-syntax-table (standard-syntax-table)))
- ;; support the %-hack
- (modify-syntax-entry ?\% "." nnmail-split-fancy-syntax-table))
(defvar nnmail-prepare-save-mail-hook nil
"Hook called before saving mail.")
\f
-(defconst nnmail-version "nnmail 1.0"
- "nnmail version.")
-
-\f
-
(defun nnmail-request-post (&optional server)
(mail-send-and-exit nil))
mm-text-coding-system
"Coding system used in reading inbox")
-(defvar nnmail-pathname-coding-system nil
+(defvar nnmail-pathname-coding-system
+ ;; This causes Emacs 22.2 and 22.3 to issue a useless warning.
+ ;;(if (and (featurep 'xemacs) (featurep 'file-coding))
+ (if (featurep 'xemacs)
+ (if (featurep 'file-coding)
+ ;; Work around a bug in many XEmacs 21.5 betas.
+ ;; Cf. http://thread.gmane.org/gmane.emacs.gnus.general/68134
+ (setq file-name-coding-system (coding-system-aliasee 'file-name))))
"*Coding system for file name.")
(defun nnmail-find-file (file)
(expand-file-name group dir)
;; If not, we translate dots into slashes.
(expand-file-name
- (mm-encode-coding-string
- (nnheader-replace-chars-in-string group ?. ?/)
- nnmail-pathname-coding-system)
+ (nnheader-replace-chars-in-string group ?. ?/)
dir))))
(or file "")))
(while (not (eobp))
(condition-case err
(progn
- (narrow-to-region (point) (gnus-point-at-eol))
+ (narrow-to-region (point) (point-at-eol))
(setq group (read buffer))
(unless (stringp group)
(setq group (symbol-name group)))
(if (and (numberp (setq max (read buffer)))
(numberp (setq min (read buffer))))
- (push (list group (cons min max))
+ (push (list (mm-string-as-unibyte group) (cons min max))
group-assoc)))
(error nil))
(widen)
(let ((coding-system-for-write nnmail-active-file-coding-system))
(when file-name
(with-temp-file file-name
+ (mm-disable-multibyte)
(nnmail-generate-active group-assoc)))))
(defun nnmail-generate-active (alist)
(if (not (save-excursion
(and (re-search-backward
"^Content-Length:[ \t]*\\([0-9]+\\)" start t)
- (setq content-length (string-to-int
+ (setq content-length (string-to-number
(buffer-substring
(match-beginning 1)
(match-end 1))))
(if (not (re-search-forward
"^Content-Length:[ \t]*\\([0-9]+\\)" nil t))
(setq content-length nil)
- (setq content-length (string-to-int (match-string 1)))
+ (setq content-length (string-to-number (match-string 1)))
;; We destroy the header, since none of the backends ever
;; use it, and we do not want to confuse other mailers by
;; having a (possibly) faulty header.
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))
(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.
+ ;; if there is no head-body delimiter, we search a bit manually.
(while (and (looking-at "From \\|[^ \t]+:")
(not (eobp)))
(forward-line 1))
(nnmail-check-duplication message-id func artnum-func))
1))
+(defvar nnmail-group-names-not-encoded-p nil
+ "Non-nil means group names are not encoded.")
+
(defun nnmail-split-incoming (incoming func &optional exit-func
group artnum-func)
"Go through the entire INCOMING file and pick out each individual mail.
(nnmail-split-methods (if (and group
(not nnmail-resplit-incoming))
(list (list group ""))
- nnmail-split-methods)))
+ nnmail-split-methods))
+ (nnmail-group-names-not-encoded-p t))
(save-excursion
;; Insert the incoming file.
(set-buffer (get-buffer-create nnmail-article-buffer))
(while (not (eobp))
(unless (< (move-to-column nnmail-split-header-length-limit)
nnmail-split-header-length-limit)
- (delete-region (point) (progn (end-of-line) (point))))
+ (delete-region (point) (point-at-eol)))
(forward-line 1))
;; Allow washing.
(goto-char (point-min))
(if (and (symbolp nnmail-split-methods)
(fboundp nnmail-split-methods))
(let ((split
- (condition-case nil
+ (condition-case error-info
;; `nnmail-split-methods' is a function, so we
;; just call this function here and use the
;; result.
'("bogus"))
(error
(nnheader-message
- 5 "Error in `nnmail-split-methods'; using `bogus' mail group")
+ 5 "Error in `nnmail-split-methods'; using `bogus' mail group: %S" error-info)
(sit-for 1)
'("bogus")))))
- (setq split (gnus-remove-duplicates split))
+ (setq split (mm-delete-duplicates split))
;; The article may be "cross-posted" to `junk'. What
;; to do? Just remove the `junk' spec. Don't really
;; see anything else to do...
(unless group-art
(setq group-art
(list (cons (car method)
- (funcall func (car method)))))))))
+ (funcall func (car method))))))))
+ ;; Fall back on "bogus" if all else fails.
+ (unless group-art
+ (setq group-art (list (cons "bogus" (funcall func "bogus"))))))
;; Produce a trace if non-empty.
(when (and trace nnmail-split-trace)
(let ((restore (current-buffer)))
(progn (forward-line 1) (point))))
(insert (format "Xref: %s" (system-name)))
(while group-alist
- (insert (format " %s:%d"
- (mm-encode-coding-string
- (caar group-alist)
- nnmail-pathname-coding-system)
- (cdar group-alist)))
+ (insert (if (mm-multibyte-p)
+ (mm-string-as-multibyte
+ (format " %s:%d" (caar group-alist) (cdar group-alist)))
+ (mm-string-as-unibyte
+ (format " %s:%d" (caar group-alist) (cdar group-alist)))))
(setq group-alist (cdr group-alist)))
(insert "\n")))
nil t)
(delete-region (match-beginning 2) (match-end 0))
(beginning-of-line))
- (when (re-search-forward "^Subject: +\\(\\(R[Ee]: +\\)+\\)R[Ee]: +" nil t)
+ (when (re-search-forward "^Subject: +\\(\\(R[Ee]: +\\)+\\)R[Ee]: +"
+ nil t)
(delete-region (match-beginning 1) (match-end 1))
(beginning-of-line)))))
"Translate TAB characters into SPACE characters."
(subst-char-in-region (point-min) (point-max) ?\t ? t))
-(defun nnmail-fix-eudora-headers ()
- "Eudora has a broken References line, but an OK In-Reply-To."
+(defcustom nnmail-broken-references-mailers
+ "^X-Mailer:.*\\(Eudora\\|Pegasus\\)"
+ "Header line matching mailer producing bogus References lines.
+See `nnmail-ignore-broken-references'."
+ :group 'nnmail-prepare
+ :version "23.1" ;; No Gnus
+ :type 'regexp)
+
+(defun nnmail-ignore-broken-references ()
+ "Ignore the References line and use In-Reply-To
+
+Eudora has a broken References line, but an OK In-Reply-To."
(goto-char (point-min))
- (when (re-search-forward "^X-Mailer:.*Eudora" nil t)
+ (when (re-search-forward nnmail-broken-references-mailers nil t)
(goto-char (point-min))
(when (re-search-forward "^References:" nil t)
(beginning-of-line)
(when (re-search-forward "^\\(In-Reply-To:[^\n]+\\)\n[ \t]+" nil t)
(replace-match "\\1" t))))
+(defalias 'nnmail-fix-eudora-headers 'nnmail-ignore-broken-references)
+(make-obsolete 'nnmail-fix-eudora-headers 'nnmail-ignore-broken-references "Emacs 23.1")
+
(custom-add-option 'nnmail-prepare-incoming-header-hook
- 'nnmail-fix-eudora-headers)
+ 'nnmail-ignore-broken-references)
;;; Utility functions
+(declare-function gnus-activate-group "gnus-start"
+ (group &optional scan dont-check method))
+
(defun nnmail-do-request-post (accept-func &optional server)
"Utility function to directly post a message to an nnmail-derived group.
Calls ACCEPT-FUNC (which should be `nnchoke-request-accept-article')
(defun nnmail-split-fancy ()
"Fancy splitting method.
See the documentation for the variable `nnmail-split-fancy' for details."
- (let ((syntab (syntax-table)))
- (unwind-protect
- (progn
- (set-syntax-table nnmail-split-fancy-syntax-table)
- (nnmail-split-it nnmail-split-fancy))
- (set-syntax-table syntab))))
+ (with-syntax-table nnmail-split-fancy-syntax-table
+ (nnmail-split-it nnmail-split-fancy)))
(defvar nnmail-split-cache nil)
;; Alist of split expressions their equivalent regexps.
;; correct match positions.
(re-search-backward value start-of-value))
(dolist (sp (nnmail-split-it (car split-rest)))
- (unless (memq sp split-result)
+ (unless (member sp split-result)
(push sp split-result))))))
split-result))
;; Not in cache, compute a regexp for the field/value pair.
(t
- (let* ((field (nth 0 split))
- (value (nth 1 split))
- partial-front regexp
- partial-rear regexp)
+ (let ((field (nth 0 split))
+ (value (nth 1 split))
+ (split-rest (cddr split))
+ partial-front
+ partial-rear
+ regexp)
(if (symbolp value)
(setq value (cdr (assq value nnmail-split-abbrev-alist))))
(if (and (>= (length value) 2)
(string= ".*" (substring value -2)))
(setq value (substring value 0 -2)
partial-rear ""))
+ ;; Invert the match-partial-words behavior if the optional
+ ;; last element is specified.
+ (while (eq (car split-rest) '-)
+ (setq split-rest (cddr split-rest)))
+ (when (if (cadr split-rest)
+ (not nnmail-split-fancy-match-partial-words)
+ nnmail-split-fancy-match-partial-words)
+ (setq partial-front ""
+ partial-rear ""))
(setq regexp (concat "^\\(\\("
(if (symbolp field)
(cdr (assq field nnmail-split-abbrev-alist))
(or partial-rear "\\>")))
(push (cons split regexp) nnmail-split-cache)
;; Now that it's in the cache, just call nnmail-split-it again
- ;; on the same split, which will find it immediately in the cache.
+ ;; on the same split, which will find it immediately in the cache.
(nnmail-split-it split))))))
(defun nnmail-expand-newtext (newtext)
(setq N 0)
(setq N (- c ?0)))
(when (match-beginning N)
- (push (buffer-substring (match-beginning N) (match-end N))
+ (push (if nnmail-split-lowercase-expanded
+ (downcase (buffer-substring (match-beginning N)
+ (match-end N)))
+ (buffer-substring (match-beginning N) (match-end N)))
expanded))))
(setq pos (1+ pos)))
(if did-expand
nnmail-message-id-cache-file nil 'silent)
(set-buffer-modified-p nil)
(setq nnmail-cache-buffer nil)
- (kill-buffer (current-buffer)))))
+ (gnus-kill-buffer (current-buffer)))))
;; Compiler directives.
(defvar group)
(defvar group-art-list)
(defvar group-art)
-(defun nnmail-cache-insert (id grp)
- (when nnmail-treat-duplicates
- ;; Store some information about the group this message is written
- ;; 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-insert (id grp &optional subject sender)
+ (when (stringp id)
+ ;; this will handle cases like `B r' where the group is nil
+ (let ((grp (or grp gnus-newsgroup-name "UNKNOWN")))
+ (run-hook-with-args 'nnmail-spool-hook
+ id grp subject sender))
+ (when nnmail-treat-duplicates
+ ;; Store some information about the group this message is written
+ ;; 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))
(be nil)
- (res nil))
+ (res nil)
+ (get-new-mail nil))
(while (and (null res) be-list)
(setq be (car be-list))
(setq be-list (cdr be-list))
(when (and (gnus-method-option-p be 'respool)
- (eval (intern (format "%s-get-new-mail" (car be)))))
+ (setq get-new-mail
+ (intern (format "%s-get-new-mail" (car be))))
+ (boundp get-new-mail)
+ (symbol-value get-new-mail))
(setq res be)))
res))
(skip-chars-forward "^\n\r\t")
(unless (looking-at "[\r\n]")
(forward-char 1)
- (buffer-substring (point)
- (progn (end-of-line) (point))))))))
+ (buffer-substring (point) (point-at-eol)))))))
;; Function for nnmail-split-fancy: look up all references in the
;; cache and if a match is found, return that group.
(defun nnmail-split-fancy-with-parent ()
"Split this message into the same group as its parent.
This function can be used as an entry in `nnmail-split-fancy', for
-example like this: (: nnmail-split-fancy)
+example like this: (: nnmail-split-fancy-with-parent)
For a message to be split, it looks for the parent message in the
References or In-Reply-To header and then looks in the message id
cache file (given by the variable `nnmail-message-id-cache-file') to
(setq references (nreverse (gnus-split-references refstr)))
(unless (gnus-buffer-live-p nnmail-cache-buffer)
(nnmail-cache-open))
- (mapcar (lambda (x)
- (setq res (or (nnmail-cache-fetch-group x) res))
- (when (or (member res '("delayed" "drafts" "queue"))
- (and regexp res (string-match regexp res)))
- (setq res nil)))
- references)
+ (dolist (x references)
+ (setq res (or (nnmail-cache-fetch-group x) res))
+ (when (or (member res '("delayed" "drafts" "queue"))
+ (and regexp res (string-match regexp res)))
+ (setq res nil)))
res)))
(defun nnmail-cache-id-exists-p (id)
(cond
((memq nnmail-treat-duplicates '(warn delete))
nnmail-treat-duplicates)
- ((nnheader-functionp nnmail-treat-duplicates)
+ ((functionp nnmail-treat-duplicates)
(funcall nnmail-treat-duplicates message-id))
(t
nnmail-treat-duplicates))))
(symbol-value sym))))
(defun nnmail-get-new-mail (method exit-func temp
- &optional group spool-func)
+ &optional group spool-func)
"Read new incoming mail."
- (let* ((sources (or mail-sources
- (if (listp nnmail-spool-file) nnmail-spool-file
- (list nnmail-spool-file))))
+ (nnmail-get-new-mail-1 method exit-func temp group nil spool-func))
+
+(defun nnmail-get-new-mail-1 (method exit-func temp
+ group in-group spool-func)
+ (let* ((sources mail-sources)
fetching-sources
- (group-in group)
(i 0)
(new 0)
(total 0)
(when (and (nnmail-get-value "%s-get-new-mail" method)
sources)
(while (setq source (pop sources))
- ;; Be compatible with old values.
- (cond
- ((stringp source)
- (setq source
- (cond
- ((string-match "^po:" source)
- (list 'pop :user (substring source (match-end 0))))
- ((file-directory-p source)
- (list 'directory :path source))
- (t
- (list 'file :path source)))))
- ((eq source 'procmail)
- (message "Invalid value for nnmail-spool-file: `procmail'")
- nil))
+ ;; Use group's parameter
+ (when (eq (car source) 'group)
+ (let ((mail-sources
+ (list
+ (gnus-group-find-parameter
+ (concat (symbol-name method) ":" group)
+ 'mail-source t))))
+ (nnmail-get-new-mail-1 method exit-func temp
+ group group spool-func))
+ (setq source nil))
;; Hack to only fetch the contents of a single group's spool file.
(when (and (eq (car source) 'directory)
(null nnmail-scan-directory-mail-source-once)
(nnmail-split-incoming
file ',(intern (format "%s-save-mail" method))
',spool-func
- (if (equal file orig-file)
- nil
- (nnmail-get-split-group orig-file ',source))
+ (or in-group
+ (if (equal file orig-file)
+ nil
+ (nnmail-get-split-group orig-file ',source)))
',(intern (format "%s-active-number" method)))))))
(incf total new)
(incf i)))
;; Compare the time with the current time.
(ignore-errors (time-less-p days (time-since time))))))))
+(declare-function gnus-group-mark-article-read "gnus-group" (group article))
+
(defun nnmail-expiry-target-group (target group)
;; Do not invoke this from nntp-server-buffer! At least nnfolder clears
;; that buffer if the nnfolder group isn't selected.
(let (nnmail-cache-accepted-message-ids)
;; Don't enter Message-IDs into cache.
;; Let users hack it in TARGET function.
- (when (nnheader-functionp target)
+ (when (functionp target)
(setq target (funcall target group)))
(unless (eq target 'delete)
(when (or (gnus-request-group target)
(case-fold-search nil)
(from (or (message-fetch-field "from") ""))
(to (or (message-fetch-field "to") ""))
- (date (date-to-time
- (or (message-fetch-field "date") (current-time-string))))
+ (date (message-fetch-field "date"))
(target 'delete))
+ (setq date (if date
+ (condition-case err
+ (date-to-time date)
+ (error
+ (message "%s" (error-message-string err))
+ (current-time)))
+ (current-time)))
(dolist (regexp-target-pair (reverse nnmail-fancy-expiry-targets) target)
(setq header (car regexp-target-pair))
(cond
;; To or From header
((and (equal header 'to-from)
(or (string-match (cadr regexp-target-pair) from)
- (and (string-match message-dont-reply-to-names from)
- (string-match (cadr regexp-target-pair) to))))
+ (and (string-match (cadr regexp-target-pair) to)
+ (let ((rmail-dont-reply-to-names
+ (message-dont-reply-to-names)))
+ (equal (rmail-dont-reply-to from) "")))))
(setq target (format-time-string (caddr regexp-target-pair) date)))
((and (not (equal header 'to-from))
(string-match (cadr regexp-target-pair)
(with-output-to-temp-buffer "*nnmail split history*"
(with-current-buffer standard-output
(fundamental-mode)) ; for Emacs 20.4+
- (let ((history nnmail-split-history)
- elem)
- (while (setq elem (pop history))
+ (dolist (elem nnmail-split-history)
(princ (mapconcat (lambda (ga)
(concat (car ga) ":" (int-to-string (cdr ga))))
elem
", "))
- (princ "\n")))))
+ (princ "\n"))))
(defun nnmail-purge-split-history (group)
"Remove all instances of GROUP from `nnmail-split-history'."
(let ((history nnmail-split-history))
(while history
- (setcar history (gnus-delete-if (lambda (e) (string= (car e) group))
+ (setcar history (gnus-remove-if (lambda (e) (string= (car e) group))
(car history)))
(pop history))
(setq nnmail-split-history (delq nil nnmail-split-history))))
(provide 'nnmail)
+;; arch-tag: fe8f671a-50db-428a-bb5d-f00462f72ed7
;;; nnmail.el ends here