(defvar nnmail-movemail-program "movemail"
"*A command to be executed to move mail from the inbox.
-The default is \"movemail\".")
+The default is \"movemail\".
+
+This can also be a function. In that case, the function will be
+called with two parameters -- the name of the INBOX file, and the file
+to be moved to.")
(defvar nnmail-pop-password-required nil
"*Non-nil if a password is required when reading mail using POP.")
"*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
+directory. This hook is called after the incoming mail box has been
emptied, and can be used to call any mail box programs you have
running (\"xwatch\", etc.)
Eg.
\(add-hook 'nnmail-read-incoming-hook
- (lambda ()
+ (lambda ()
(start-process \"mailsend\" nil
\"/local/bin/mailsend\" \"read\" \"mbox\")))
(lambda ()
;; Update the displayed time, since that will clear out
;; the flag that says you have mail.
- (if (eq (process-status \"display-time\") 'run)
- (display-time-filter display-time-process \"\"))))")
+ (when (eq (process-status \"display-time\") 'run)
+ (display-time-filter display-time-process \"\"))))")
(when (eq system-type 'windows-nt)
(add-hook 'nnmail-prepare-incoming-hook 'nnheader-ms-strip-cr))
"*Hook called before treating incoming mail.
The hook is run in a buffer with all the new, incoming mail.")
+(defvar nnmail-prepare-incoming-header-hook nil
+ "*Hook called narrowed to the headers of each message.
+This can be used to remove excessive spaces (and stuff like
+that) from the headers before splitting and saving the messages.")
+
+(defvar nnmail-prepare-incoming-message-hook nil
+ "*Hook called narrowed to each message.")
+
+(defvar nnmail-list-identifiers nil
+ "Regexp that match list identifiers to be removed.
+This can also be a list of regexps.")
+
(defvar nnmail-pre-get-new-mail-hook nil
"Hook called just before starting to handle new incoming mail.")
\(setq nnmail-split-methods 'nnmail-split-fancy
nnmail-split-fancy
- ;; Messages from the mailer deamon are not crossposted to any of
+ ;; Messages from the mailer daemon are not crossposted to any of
;; the ordinary groups. Warnings are put in a separate group
;; from real errors.
'(| (\"from\" mail (| (\"subject\" \"warn.*\" \"mail.warning\")
;;; Internal variables.
+(defvar nnmail-split-history nil
+ "List of group/article elements that say where the previous split put messages.")
+
(defvar nnmail-pop-password nil
"*Password to use when reading mail from a POP server, if required.")
"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 (round (/ seconds rest))
(range-error (expt 2 16)))))
(list ms (condition-case nil (round (- seconds (* ms rest)))
(range-error (expt 2 16))))))
;; Convert date strings to internal time.
(setq time (nnmail-date-to-time time)))
(let* ((current (current-time))
- (rest (if (< (nth 1 current) (nth 1 time)) (expt 2 16))))
+ (rest (when (< (nth 1 current) (nth 1 time))
+ (expt 2 16))))
(list (- (+ (car current) (if rest -1 0)) (car time))
(- (+ (or rest 0) (nth 1 current)) (nth 1 time)))))
;; Function rewritten from rmail.el.
(defun nnmail-move-inbox (inbox)
"Move INBOX to `nnmail-crash-box'."
- (let ((inbox (file-truename (expand-file-name inbox)))
- (tofile (file-truename (expand-file-name nnmail-crash-box)))
- movemail popmail errors password)
- ;; If getting from mail spool directory,
- ;; use movemail to move rather than just renaming,
- ;; so as to interlock with the mailer.
- (unless (setq popmail (string-match "^po:" (file-name-nondirectory inbox)))
- (setq movemail t))
- (when popmail
- (setq inbox (file-name-nondirectory inbox)))
- (when (and movemail
- ;; On some systems, /usr/spool/mail/foo is a directory
- ;; and the actual inbox is /usr/spool/mail/foo/foo.
- (file-directory-p inbox))
- (setq inbox (expand-file-name (user-login-name) inbox)))
- (if (member inbox nnmail-moved-inboxes)
- nil
- (if popmail
- (progn
- (setq nnmail-internal-password nnmail-pop-password)
- (when (and nnmail-pop-password-required (not nnmail-pop-password))
- (setq nnmail-internal-password
- (nnmail-read-passwd
- (format "Password for %s: "
- (substring inbox (+ popmail 3))))))
- (message "Getting mail from 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)))
- ;; Set TOFILE if have not already done so, and
- ;; rename or copy the file INBOX to TOFILE if and as appropriate.
- (cond
- ((file-exists-p tofile)
- ;; The crash box exists already.
- t)
- ((and (not popmail)
- (not (file-exists-p inbox)))
- ;; There is no inbox.
- (setq tofile nil))
- ((and (not movemail) (not popmail))
- ;; Try copying. If that fails (perhaps no space),
- ;; rename instead.
- (condition-case nil
- (copy-file inbox tofile nil)
- (error
- ;; Third arg is t so we can replace existing file TOFILE.
- (rename-file inbox tofile t)))
- (push inbox nnmail-moved-inboxes)
- ;; Make the real inbox file empty.
- ;; Leaving it deleted could cause lossage
- ;; because mailers often won't create the file.
- (condition-case ()
- (write-region (point) (point) inbox)
- (file-error nil)))
- (t
- ;; Use movemail.
- (unwind-protect
- (save-excursion
- (setq errors (generate-new-buffer " *nnmail loss*"))
- (buffer-disable-undo errors)
- (let ((default-directory "/"))
- (apply
- 'call-process
- (append
- (list
- (expand-file-name nnmail-movemail-program exec-directory)
- nil errors nil inbox tofile)
- (when nnmail-internal-password
- (list nnmail-internal-password)))))
- (if (not (buffer-modified-p errors))
- ;; No output => movemail won
- (progn
- (set-file-modes inbox nnmail-default-file-modes)
- (push inbox nnmail-moved-inboxes))
- (set-buffer errors)
- ;; There may be a warning about older revisions. We
- ;; ignore those.
- (goto-char (point-min))
- (if (search-forward "older revision" nil t)
+ (if (not (file-writable-p nnmail-crash-box))
+ (gnus-error 1 "Can't write to crash box %s. Not moving mail."
+ nnmail-crash-box)
+ (let ((inbox (file-truename (expand-file-name inbox)))
+ (tofile (file-truename (expand-file-name nnmail-crash-box)))
+ movemail popmail errors)
+ ;; If getting from mail spool directory,
+ ;; use movemail to move rather than just renaming,
+ ;; so as to interlock with the mailer.
+ (unless (setq popmail (string-match "^po:" (file-name-nondirectory inbox)))
+ (setq movemail t))
+ (when popmail
+ (setq inbox (file-name-nondirectory inbox)))
+ (when (and movemail
+ ;; On some systems, /usr/spool/mail/foo is a directory
+ ;; and the actual inbox is /usr/spool/mail/foo/foo.
+ (file-directory-p inbox))
+ (setq inbox (expand-file-name (user-login-name) inbox)))
+ (if (member inbox nnmail-moved-inboxes)
+ nil
+ (if popmail
+ (progn
+ (setq nnmail-internal-password nnmail-pop-password)
+ (when (and nnmail-pop-password-required (not nnmail-pop-password))
+ (setq nnmail-internal-password
+ (nnmail-read-passwd
+ (format "Password for %s: "
+ (substring inbox (+ popmail 3))))))
+ (message "Getting mail from 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)))
+ ;; Set TOFILE if have not already done so, and
+ ;; rename or copy the file INBOX to TOFILE if and as appropriate.
+ (cond
+ ((file-exists-p tofile)
+ ;; The crash box exists already.
+ t)
+ ((and (not popmail)
+ (not (file-exists-p inbox)))
+ ;; There is no inbox.
+ (setq tofile nil))
+ ((and (not movemail) (not popmail))
+ ;; Try copying. If that fails (perhaps no space),
+ ;; rename instead.
+ (condition-case nil
+ (copy-file inbox tofile nil)
+ (error
+ ;; Third arg is t so we can replace existing file TOFILE.
+ (rename-file inbox tofile t)))
+ (push inbox nnmail-moved-inboxes)
+ ;; Make the real inbox file empty.
+ ;; Leaving it deleted could cause lossage
+ ;; because mailers often won't create the file.
+ (condition-case ()
+ (write-region (point) (point) inbox)
+ (file-error nil)))
+ (t
+ ;; Use movemail.
+ (unwind-protect
+ (save-excursion
+ (setq errors (generate-new-buffer " *nnmail loss*"))
+ (buffer-disable-undo errors)
+ (let ((default-directory "/"))
+ (if (nnheader-functionp nnmail-movemail-program)
+ (funcall nnmail-movemail-program inbox tofile)
+ (apply
+ 'call-process
+ (append
+ (list
+ (expand-file-name nnmail-movemail-program exec-directory)
+ nil errors nil inbox tofile)
+ (when nnmail-internal-password
+ (list nnmail-internal-password))))))
+ (if (not (buffer-modified-p errors))
+ ;; No output => movemail won
(progn
- (set-file-modes inbox nnmail-default-file-modes)
+ (or popmail
+ (set-file-modes tofile nnmail-default-file-modes))
(push inbox nnmail-moved-inboxes))
- ;; Probably a real error.
- (subst-char-in-region (point-min) (point-max) ?\n ?\ )
- (goto-char (point-max))
- (skip-chars-backward " \t")
- (delete-region (point) (point-max))
+ (set-buffer errors)
+ ;; There may be a warning about older revisions. We
+ ;; ignore those.
(goto-char (point-min))
- (when (looking-at "movemail: ")
- (delete-region (point-min) (match-end 0)))
- (unless (yes-or-no-p
- (format "movemail: %s. Continue? "
- (buffer-string)))
- (error "%s" (buffer-string)))
- (setq tofile nil)))))))
- (and errors
- (buffer-name errors)
- (kill-buffer errors))
- tofile)))
+ (if (search-forward "older revision" nil t)
+ (progn
+ (or popmail
+ (set-file-modes tofile nnmail-default-file-modes))
+ (push inbox nnmail-moved-inboxes))
+ ;; Probably a real error.
+ (subst-char-in-region (point-min) (point-max) ?\n ?\ )
+ (goto-char (point-max))
+ (skip-chars-backward " \t")
+ (delete-region (point) (point-max))
+ (goto-char (point-min))
+ (when (looking-at "movemail: ")
+ (delete-region (point-min) (match-end 0)))
+ (unless (yes-or-no-p
+ (format "movemail: %s. Continue? "
+ (buffer-string)))
+ (error "%s" (buffer-string)))
+ (setq tofile nil)))))))
+ (and errors
+ (buffer-name errors)
+ (kill-buffer errors))
+ tofile))))
(defun nnmail-get-active ()
"Returns an assoc of group names and active ranges.
(defun nnmail-save-active (group-assoc file-name)
"Save GROUP-ASSOC in ACTIVE-FILE."
(when file-name
- (let (group)
- (save-excursion
- (set-buffer (get-buffer-create " *nnmail active*"))
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (while group-assoc
- (setq group (pop group-assoc))
- (insert (format "%s %d %d y\n" (car group) (cdadr group)
- (caadr group))))
- (unless (file-exists-p (file-name-directory file-name))
- (make-directory (file-name-directory file-name) t))
- (nnmail-write-region
- 1 (point-max) (expand-file-name file-name) nil 'nomesg)
- (kill-buffer (current-buffer))))))
+ (nnheader-temp-write file-name
+ (nnmail-generate-active group-assoc))))
+
+(defun nnmail-generate-active (alist)
+ "Generate an active file from group-alist ALIST."
+ (erase-buffer)
+ (let (group)
+ (while (setq group (pop alist))
+ (insert (format "%s %d %d y\n" (car group) (cdadr group)
+ (caadr group))))))
(defun nnmail-get-split-group (file group)
+ "Find out whether this FILE is to be split into GROUP only.
+If GROUP is non-nil and we are using procmail, return the group name
+only when the file is the correct procmail file. When GROUP is nil,
+return nil if FILE is a spool file or the procmail group for which it
+is a spool. If not using procmail, return GROUP."
(if (or (eq nnmail-spool-file 'procmail)
nnmail-use-procmail)
- (cond (group group)
- ((string-match (concat "^" (expand-file-name
- (file-name-as-directory
- nnmail-procmail-directory))
- "\\([^/]*\\)" nnmail-procmail-suffix "$")
- (expand-file-name file))
- (substring (expand-file-name file)
- (match-beginning 1) (match-end 1)))
- (t
- group))
+ (if (string-match (concat "^" (expand-file-name
+ (file-name-as-directory
+ nnmail-procmail-directory))
+ "\\([^/]*\\)" nnmail-procmail-suffix "$")
+ (expand-file-name file))
+ (let ((procmail-group (substring (expand-file-name file)
+ (match-beginning 1)
+ (match-end 1))))
+ (if group
+ (if (string-equal group procmail-group)
+ group
+ nil)
+ procmail-group))
+ nil)
group))
(defun nnmail-process-babyl-mail-format (func artnum-func)
"\f\n0, *unseen,+\n\\(\\*\\*\\* EOOH \\*\\*\\*\n\\)?" nil t)
(goto-char (match-end 0))
(delete-region (match-beginning 0) (match-end 0))
- (setq start (point))
- ;; Skip all the headers in case there are more "From "s...
- (or (search-forward "\n\n" nil t)
- (search-forward-regexp "^[^:]*\\( .*\\|\\)$" nil t)
- (search-forward "\1f\f"))
+ (narrow-to-region
+ (setq start (point))
+ (progn
+ ;; Skip all the headers in case there are more "From "s...
+ (or (search-forward "\n\n" nil t)
+ (search-forward-regexp "^[^:]*\\( .*\\|\\)$" nil t)
+ (search-forward "\1f\f"))
+ (point)))
+ (run-hooks 'nnmail-prepare-incoming-header-hook)
+ (widen)
;; Find the Message-ID header.
(save-excursion
(if (re-search-backward "^Message-ID:[ \t]*\\(<[^>]*>\\)" nil t)
(setq do-search t)))
;; Go to the beginning of the next article - or to the end
;; of the buffer.
- (if do-search
- (if (re-search-forward "^\1f" nil t)
- (goto-char (match-beginning 0))
- (goto-char (1- (point-max)))))
+ (when do-search
+ (if (re-search-forward "^\1f" nil t)
+ (goto-char (match-beginning 0))
+ (goto-char (1- (point-max)))))
(delete-char 1) ; delete ^_
(save-excursion
(save-restriction
;; having a (possibly) faulty header.
(beginning-of-line)
(insert "X-"))
+ (run-hooks 'nnmail-prepare-incoming-header-hook)
;; Find the end of this article.
(goto-char (point-max))
(widen)
(insert "Original-")))
(forward-line 1)
(insert "Message-ID: " (setq message-id (nnmail-message-id)) "\n"))
+ (run-hooks 'nnmail-prepare-incoming-header-hook)
;; Find the end of this article.
(goto-char (point-max))
(widen)
(nnmail-process-mmdf-mail-format func artnum-func))
(t
(nnmail-process-unix-mail-format func artnum-func))))
- (if exit-func (funcall exit-func))
+ (when exit-func
+ (funcall exit-func))
(kill-buffer (current-buffer)))))
;; Mail crossposts suggested by Brian Edmonds <edmonds@cs.ubc.ca>.
(if (or methods
(not (equal "" (nth 1 method))))
(when (and
- (condition-case ()
+ (condition-case ()
(if (stringp (nth 1 method))
(re-search-backward (cadr method) nil t)
;; Function to say whether this is a match.
;; Don't enter the article into the same
;; group twice.
(not (assoc (car method) group-art)))
- (push (cons (car method) (funcall func (car method)))
+ (push (cons (car method) (funcall func (car method)))
group-art))
;; This is the final group, which is used as a
;; catch-all.
(unless group-art
(setq group-art
- (list (cons (car method)
+ (list (cons (car method)
(funcall func (car method)))))))))
;; See whether the split methods returned `junk'.
(if (equal group-art '(junk))
(let (lines chars)
(save-excursion
(goto-char (point-min))
- (when (search-forward "\n\n" nil t)
+ (when (search-forward "\n\n" nil t)
(setq chars (- (point-max) (point)))
(setq lines (count-lines (point) (point-max)))
(forward-char -1)
"Insert an Xref line based on the (group . article) alist."
(save-excursion
(goto-char (point-min))
- (when (search-forward "\n\n" nil t)
+ (when (search-forward "\n\n" nil t)
(forward-char -1)
(when (re-search-backward "^Xref: " nil t)
- (delete-region (match-beginning 0)
+ (delete-region (match-beginning 0)
(progn (forward-line 1) (point))))
(insert (format "Xref: %s" (system-name)))
(while group-alist
(setq group-alist (cdr group-alist)))
(insert "\n"))))
+;;; Message washing functions
+
+(defun nnmail-remove-leading-whitespace ()
+ "Remove excessive whitespace from all headers."
+ (goto-char (point-min))
+ (while (re-search-forward "^\\([^ :]+: \\) +" nil t)
+ (replace-match "\\1" t t)))
+
+(defun nnmail-remove-list-identifiers ()
+ "Remove list identifiers from Subject headers."
+ (let ((regexp (if (stringp nnmail-list-identifiers) nnmail-list-identifiers
+ (mapconcat 'identity nnmail-list-identifiers "\\|"))))
+ (when regexp
+ (goto-char (point-min))
+ (when (re-search-forward
+ (concat "Subject: +\\(Re: +\\)?\\(" regexp "\\) *")
+ nil t)
+ (delete-region (match-beginning 2) (match-end 0))))))
+
+(defun nnmail-remove-tabs ()
+ "Translate TAB characters into SPACE characters."
+ (subst-char-in-region (point-min) (point-max) ?\t ? t))
+
+;;; Utility functions
+
;; Written by byer@mv.us.adobe.com (Scott Byer).
(defun nnmail-make-complex-temp-name (prefix)
(let ((newname (make-temp-name prefix))
((assq split nnmail-split-cache)
;; A compiled match expression.
(goto-char (point-max))
- (if (re-search-backward (cdr (assq split nnmail-split-cache)) nil t)
- (nnmail-split-it (nth 2 split))))
+ (when (re-search-backward (cdr (assq split nnmail-split-cache)) nil t)
+ (nnmail-split-it (nth 2 split))))
(t
;; An uncompiled match.
(let* ((field (nth 0 split))
(cdr (assq value nnmail-split-abbrev-alist))
value)
"\\)\\>")))
- (setq nnmail-split-cache
- (cons (cons split regexp) nnmail-split-cache))
+ (push (cons split regexp) nnmail-split-cache)
(goto-char (point-max))
- (if (re-search-backward regexp nil t)
- (nnmail-split-it (nth 2 split)))))))
+ (when (re-search-backward regexp nil t)
+ (nnmail-split-it (nth 2 split)))))))
;; Get a list of spool files to read.
(defun nnmail-get-spool-files (&optional group)
(p procmails)
(crash (when (and (file-exists-p nnmail-crash-box)
(> (nnheader-file-size
- (file-truename nnmail-crash-box)) 0))
+ (file-truename nnmail-crash-box))
+ 0))
(list nnmail-crash-box))))
- ;; Remove any directories that inadvertantly match the procmail
+ ;; Remove any directories that inadvertently match the procmail
;; suffix, which might happen if the suffix is "".
(while p
(when (file-directory-p (car p))
;; already activated.
(defun nnmail-activate (backend &optional force)
(let (file timestamp file-time)
- (if (or (not (symbol-value (intern (format "%s-group-alist" backend))))
- force
- (and (setq file (condition-case ()
- (symbol-value (intern (format "%s-active-file"
- backend)))
- (error nil)))
- (setq file-time (nth 5 (file-attributes file)))
- (or (not
- (setq timestamp
- (condition-case ()
- (symbol-value (intern
- (format "%s-active-timestamp"
- backend)))
- (error 'none))))
- (not (consp timestamp))
- (equal timestamp '(0 0))
- (> (nth 0 file-time) (nth 0 timestamp))
- (and (= (nth 0 file-time) (nth 0 timestamp))
- (> (nth 1 file-time) (nth 1 timestamp))))))
- (save-excursion
- (or (eq timestamp 'none)
- (set (intern (format "%s-active-timestamp" backend))
- (current-time)))
- (funcall (intern (format "%s-request-list" backend)))
- (set (intern (format "%s-group-alist" backend))
- (nnmail-get-active))))
+ (when (or (not (symbol-value (intern (format "%s-group-alist" backend))))
+ force
+ (and (setq file (condition-case ()
+ (symbol-value (intern (format "%s-active-file"
+ backend)))
+ (error nil)))
+ (setq file-time (nth 5 (file-attributes file)))
+ (or (not
+ (setq timestamp
+ (condition-case ()
+ (symbol-value (intern
+ (format "%s-active-timestamp"
+ backend)))
+ (error 'none))))
+ (not (consp timestamp))
+ (equal timestamp '(0 0))
+ (> (nth 0 file-time) (nth 0 timestamp))
+ (and (= (nth 0 file-time) (nth 0 timestamp))
+ (> (nth 1 file-time) (nth 1 timestamp))))))
+ (save-excursion
+ (or (eq timestamp 'none)
+ (set (intern (format "%s-active-timestamp" backend))
+ (current-time)))
+ (funcall (intern (format "%s-request-list" backend)))
+ (set (intern (format "%s-group-alist" backend))
+ (nnmail-get-active))))
t))
(defun nnmail-message-id ()
(setq nnmail-cache-buffer
(get-buffer-create " *nnmail message-id cache*")))
(buffer-disable-undo (current-buffer))
- (and (file-exists-p nnmail-message-id-cache-file)
- (insert-file-contents nnmail-message-id-cache-file))
+ (when (file-exists-p nnmail-message-id-cache-file)
+ (insert-file-contents nnmail-message-id-cache-file))
(set-buffer-modified-p nil)
(current-buffer))))
(set-buffer nnmail-cache-buffer)
;; Weed out the excess number of Message-IDs.
(goto-char (point-max))
- (and (search-backward "\n" nil t nnmail-message-id-cache-length)
- (progn
- (beginning-of-line)
- (delete-region (point-min) (point))))
+ (when (search-backward "\n" nil t nnmail-message-id-cache-length)
+ (progn
+ (beginning-of-line)
+ (delete-region (point-min) (point))))
;; Save the buffer.
(or (file-exists-p (file-name-directory nnmail-message-id-cache-file))
(make-directory (file-name-directory nnmail-message-id-cache-file)
(search-backward id nil t))))
(defun nnmail-check-duplication (message-id func artnum-func)
+ (run-hooks 'nnmail-prepare-incoming-message-hook)
;; If this is a duplicate message, then we do not save it.
(let* ((duplication (nnmail-cache-id-exists-p message-id))
+ (case-fold-search t)
(action (when duplication
(cond
((memq nnmail-treat-duplicates '(warn delete))
(funcall nnmail-treat-duplicates message-id))
(t
nnmail-treat-duplicates))))
- (group-art (nreverse (nnmail-article-group artnum-func))))
+ group-art)
+ ;; Let the backend save the article (or not).
(cond
- ((null group-art)
- (delete-region (point-min) (point-max)))
((not duplication)
(nnmail-cache-insert message-id)
- (funcall func group-art))
+ (funcall func (setq group-art
+ (nreverse (nnmail-article-group artnum-func)))))
((eq action 'delete)
- (delete-region (point-min) (point-max)))
+ (setq group-art nil))
((eq action 'warn)
;; We insert a warning.
(let ((case-fold-search t)
"Message-ID: " newid "\n"
"Gnus-Warning: This is a duplicate of message " message-id "\n")
(nnmail-cache-insert newid)
- (funcall func group-art)))
+ (funcall func (setq group-art
+ (nreverse (nnmail-article-group artnum-func))))))
(t
- (funcall func group-art)))))
+ (funcall func (setq group-art
+ (nreverse (nnmail-article-group artnum-func))))))
+ ;; Add the group-art list to the history list.
+ (if group-art
+ (push group-art nnmail-split-history)
+ (delete-region (point-min) (point-max)))))
;;; Get new mail.
(defun nnmail-get-new-mail (method exit-func temp
&optional group spool-func)
"Read new incoming mail."
+ ;; Nix out the previous split history.
+ (setq nnmail-split-history nil)
(let* ((spools (nnmail-get-spool-files group))
(group-in group)
incoming incomings spool)
(setq spool (pop spools))
;; We read each spool file if either the spool is a POP-mail
;; spool, or the file exists. We can't check for the
- ;; existance of POPped mail.
+ ;; existence of POPped mail.
(when (or (string-match "^po:" spool)
(and (file-exists-p spool)
(> (nnheader-file-size (file-truename spool)) 0)))
(setq group (nnmail-get-split-group spool group-in))
;; We split the mail
(nnmail-split-incoming
- nnmail-crash-box (intern (format "%s-save-mail" method))
+ nnmail-crash-box (intern (format "%s-save-mail" method))
spool-func group (intern (format "%s-active-number" method)))
;; Check whether the inbox is to be moved to the special tmp dir.
(setq incoming
(save-restriction
(message-narrow-to-head)
(let ((case-fold-search t))
- (unless (re-search-forward "^Message-Id:" nil t)
+ (unless (re-search-forward "^Message-ID:" nil t)
(insert "Message-ID: " (nnmail-message-id) "\n")))))
(defun nnmail-write-region (start end filename &optional append visit lockname)
(cdr elem))))
status " "))
+(defun nnmail-split-history ()
+ "Generate an overview of where the last mail split put articles."
+ (interactive)
+ (unless nnmail-split-history
+ (error "No current split history"))
+ (pop-to-buffer "*nnmail split history*")
+ (buffer-disable-undo (current-buffer))
+ (erase-buffer)
+ (let ((history nnmail-split-history)
+ elem ga)
+ (while (setq elem (pop history))
+ (insert (mapconcat (lambda (ga)
+ (concat (car ga) ":" (int-to-string (cdr ga))))
+ elem
+ ", ")
+ "\n"))
+ (goto-char (point-min))))
+
+(defun nnmail-new-mail-p (group)
+ "Say whether GROUP has new mail."
+ (let ((his nnmail-split-history)
+ found)
+ (while his
+ (when (member group (pop his))
+ (setq found t
+ his nil)))
+ found))
+
(run-hooks 'nnmail-load-hook)
(provide 'nnmail)