-;; "RMAIL" mail reader for Emacs.
-;; Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
+;;; rmail.el --- main code of "RMAIL" mail reader for Emacs.
+
+;; Copyright (C) 1985, 1986, 1987, 1988, 1991, 1992 Free Software Foundation, Inc.
+
+;; Maintainer: FSF
+;; Keywords: mail
;; This file is part of GNU Emacs.
;; 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 1, or (at your option)
+;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; along with GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;;; Code:
;; Souped up by shane@mit-ajax based on ideas of rlk@athena.mit.edu
;; New features include attribute and keyword support, message
;; expunging by dispatch table, sticky options for file commands.
(require 'mail-utils)
-(provide 'rmail)
-
; These variables now declared paths.el
;(defvar rmail-spool-directory "/usr/spool/mail/"
; "This is the name of the directory used by the system mailer for\n\
(defvar rmail-last-multi-labels nil)
(defvar rmail-last-file nil)
(defvar rmail-last-rmail-file nil)
+
+;;; Regexp matching the delimiter of messages in UNIX mail format
+;;; (UNIX From lines), minus the initial ^. Note that if you change
+;;; this expression, you must change the code in rmail-nuke-pinhead-header
+;;; that knows the exact ordering of the \\( \\) subexpressions.
+(defvar rmail-unix-mail-delimiter
+ "From \\([^ \n]*\\(\\|\".*\"[^ \n]*\\)\\) ?\\([^ \n]*\\) \\([^ ]*\\) *\\([0-9]*\\) \\([0-9:]*\\)\\( ?[A-Z]?[A-Z][A-Z]T\\( DST\\)?\\| ?[-+]?[0-9][0-9][0-9][0-9]\\|\\) [0-9][0-9]\\([0-9]*\\) *\\(remote from [^\n]*\\)?\n" nil)
\f
;;;; *** Rmail Mode ***
(define-key rmail-mode-map "\e\C-m" 'rmail-retry-failure)
(define-key rmail-mode-map "c" 'rmail-continue)
(define-key rmail-mode-map "f" 'rmail-forward)
+ (define-key rmail-mode-map "\er" 'rmail-search-backwards)
(define-key rmail-mode-map "\es" 'rmail-search)
(define-key rmail-mode-map "<" 'rmail-first-message)
(define-key rmail-mode-map ">" 'rmail-last-message)
(setq rmail-inbox-list (rmail-parse-file-inboxes))
(make-local-variable 'rmail-keywords)
;; this gets generated as needed
- (setq rmail-keywords nil)
- (make-local-variable 'save-buffers-skip)
- (setq save-buffers-skip t))
+ (setq rmail-keywords nil))
;; Handle M-x revert-buffer done in an rmail-mode buffer.
(defun rmail-revert (arg noconfirm)
(while files
(setq file (expand-file-name (substitute-in-file-name (car files)))
;;>> un*x specific <<
- tofile (concat file "~"))
+ ;; The "+" used to be "~", which is an extremely poor choice;
+ ;; it might accidentally be deleted when space is low
+ ;; (as happened to me!).
+ tofile (concat file "+"))
;; If getting from mail spool directory,
;; use movemail to move rather than just renaming,
;; so as to interlock with the mailer.
;; the rmail-break-forwarded-messages feature is not implemented
(defun rmail-convert-to-babyl-format ()
(let ((count 0) start
- (case-fold-search nil))
+ (case-fold-search nil)
+ (invalid-input-resync
+ (function (lambda ()
+ (message "Invalid Babyl format in inbox!")
+ (sit-for 1)
+ ;; Try to get back in sync with a real message.
+ (if (re-search-forward
+ (concat mmdf-delim1 "\\|^From") nil t)
+ (beginning-of-line)
+ (goto-char (point-max)))))))
(goto-char (point-min))
(save-restriction
(while (not (eobp))
(cond ((looking-at "BABYL OPTIONS:");Babyl header
- (search-forward "\n\^_")
- (delete-region (point-min) (point)))
+ (if (search-forward "\n\^_" nil t)
+ ;; If we find the proper terminator, delete through there.
+ (delete-region (point-min) (point))
+ (funcall invalid-input-resync)
+ (delete-region (point-min) (point))))
;; Babyl format message
((looking-at "\^L")
(or (search-forward "\n\^_" nil t)
- (progn
- (message "Invalid Babyl format in inbox!")
- (sit-for 1)
- (goto-char (point-max))))
+ (funcall invalid-input-resync))
(setq count (1+ count))
;; Make sure there is no extra white space after the ^_
;; at the end of the message.
(rmail-nuke-pinhead-header)
(if (re-search-forward
(concat "^[\^_]?\\("
- "From [^ \n]*\\(\\|\".*\"[^ \n]*\\) ?[^ \n]* [^ \n]* *"
- "[0-9]* [0-9:]*\\( ?[A-Z]?[A-Z][A-Z]T\\| ?[-+]?[0-9][0-9][0-9][0-9]\\|\\) " ; EDT, -0500
- "19[0-9]* *\\(remote from [^\n]*\\)?$\\|"
+ rmail-unix-mail-delimiter
+ "\\|"
mmdf-delim1 "\\|"
"^BABYL OPTIONS:\\|"
"\^L\n[01],\\)") nil t)
(setq has-date (and (search-forward "\nDate:" nil t) (point)))
(goto-char start))
(let ((case-fold-search nil))
- (if (re-search-forward
- "^From \\([^ ]*\\(\\|\".*\"[^ ]*\\)\\) ?\\([^ ]*\\) \\([^ ]*\\) *\\([0-9]*\\) \\([0-9:]*\\)\\( ?[A-Z]?[A-Z][A-Z]T\\| ?[-+]?[0-9][0-9][0-9][0-9]\\|\\) 19\\([0-9]*\\) *\\(remote from [^\n]*\\)?\n" nil t)
+ (if (re-search-forward (concat "^" rmail-unix-mail-delimiter) nil t)
(replace-match
(concat
"Mail-from: \\&"
""
;; If no time zone specified, assume est.
(if (= (match-beginning 7) (match-end 7))
- "Date: \\3, \\5 \\4 \\8 \\6 EST\n"
- "Date: \\3, \\5 \\4 \\8 \\6\\7\n"))
+ "Date: \\3, \\5 \\4 \\9 \\6 EST\n"
+ "Date: \\3, \\5 \\4 \\9 \\6\\7\n"))
;; Keep and reformat the sender if we don't
;; have a From: field.
(if has-from
FUNCTION may not change the visible text of the message, but it may
change the invisible header text."
(save-excursion
- (let ((obeg (- (point-max) (point-min)))
+ (let ((obeg (- (point-max) (point-min))))
(unwind-protect
(progn
(narrow-to-region (rmail-msgbeg rmail-current-message)
;; before that restriction is restored.
;; Here we assume that changes made by FUNCTION
;; occur before the visible region of the message.
- (narrow-to-region (- (point-max) obeg) (point-max)))))))
+ (narrow-to-region (- (point-max) obeg) (point-max))))))
(defun rmail-forget-messages ()
(unwind-protect
(if (/= lastwin rmail-current-message)
(rmail-show-message lastwin))
(if (< n 0)
- (error "No previous nondeleted message"))
+ (message "No previous nondeleted message"))
(if (> n 0)
- (error "No following nondeleted message"))))
+ (message "No following nondeleted message"))))
(defun rmail-previous-undeleted-message (n)
"Show previous non-deleted message.
(if (>= where (rmail-msgbeg high)) high low)))
(defvar rmail-search-last-regexp nil)
-(defun rmail-search (regexp &optional reversep)
+(defun rmail-search (regexp &optional n)
"Show message containing next match for REGEXP.
-Search in reverse (earlier messages) with non-nil second arg REVERSEP.
-Interactively, empty argument means use same regexp used last time,
-and reverse search is specified by a negative numeric arg."
+Prefix argument gives repeat count; negative argument means search
+backwards (through earlier messages).
+Interactively, empty argument means use same regexp used last time."
(interactive
(let* ((reversep (< (prefix-numeric-value current-prefix-arg) 0))
(prompt
(setq rmail-search-last-regexp regexp))
((not rmail-search-last-regexp)
(error "No previous Rmail search string")))
- (list rmail-search-last-regexp reversep)))
+ (list rmail-search-last-regexp
+ (prefix-numeric-value current-prefix-arg))))
+ (or n (setq n 1))
(message "%sRmail search for %s..."
- (if reversep "Reverse " "")
+ (if (< n 0) "Reverse " "")
regexp)
(rmail-maybe-set-message-counters)
(let ((omin (point-min))
(omax (point-max))
(opoint (point))
win
+ (reversep (< n 0))
(msg rmail-current-message))
(unwind-protect
(progn
(widen)
- ;; Check messages one by one, advancing message number up or down
- ;; but searching forward through each message.
- (if reversep
- (while (and (null win) (> msg 1))
- (goto-char (rmail-msgbeg (setq msg (1- msg))))
- (setq win (re-search-forward
- regexp (rmail-msgend msg) t)))
- (while (and (null win) (< msg rmail-total-messages))
- (goto-char (rmail-msgbeg (setq msg (1+ msg))))
- (setq win (re-search-forward regexp (rmail-msgend msg) t)))))
+ (while (/= n 0)
+ ;; Check messages one by one, advancing message number up or down
+ ;; but searching forward through each message.
+ (if reversep
+ (while (and (null win) (> msg 1))
+ (goto-char (rmail-msgbeg (setq msg (1- msg))))
+ (setq win (re-search-forward
+ regexp (rmail-msgend msg) t)))
+ (while (and (null win) (< msg rmail-total-messages))
+ (goto-char (rmail-msgbeg (setq msg (1+ msg))))
+ (setq win (re-search-forward regexp (rmail-msgend msg) t))))
+ (setq n (+ n (if reversep 1 -1)))))
(if win
(progn
;; If this is a reverse search and we found a message,
(ding)
(message "Search failed: %s" regexp)))))
+(defun rmail-search-backwards (regexp &optional n)
+ "Show message containing previous match for REGEXP.
+Prefix argument gives repeat count; negative argument means search
+forward (through later messages).
+Interactively, empty argument means use same regexp used last time."
+ (interactive
+ (let* ((reversep (>= (prefix-numeric-value current-prefix-arg) 0))
+ (prompt
+ (concat (if reversep "Reverse " "") "Rmail search (regexp): "))
+ regexp)
+ (if rmail-search-last-regexp
+ (setq prompt (concat prompt
+ "(default "
+ rmail-search-last-regexp
+ ") ")))
+ (setq regexp (read-string prompt))
+ (cond ((not (equal regexp ""))
+ (setq rmail-search-last-regexp regexp))
+ ((not rmail-search-last-regexp)
+ (error "No previous Rmail search string")))
+ (list rmail-search-last-regexp
+ (prefix-numeric-value current-prefix-arg))))
+ (rmail-search regexp (- (or n -1))))
+
;; Show the first message which has the `unseen' attribute.
(defun rmail-first-unseen-message ()
(let ((current 1)
(save-restriction
(widen)
(while (and (not found) (< current rmail-total-messages))
- (setq current (1+ current))
(if (rmail-message-labels-p current ", ?\\(unseen\\),")
- (setq found current))))
+ (setq found current))
+ (setq current (1+ current))))
(if found
(rmail-show-message found))))
\f
(defun rmail-delete-forward (&optional backward)
"Delete this message and move to next nondeleted one.
Deleted messages stay in the file until the \\[rmail-expunge] command is given.
-With prefix argument, delete and move backward. If there is no nondeleted
-message to move to in the preferred or specified direction, move in the
-other direction."
+With prefix argument, delete and move backward."
(interactive "P")
(rmail-set-attribute "deleted" t)
- (condition-case ()
- (rmail-next-undeleted-message (if backward -1 1))
- (error
- (condition-case ()
- (rmail-previous-undeleted-message (if backward -1 1))
- (error nil)))))
+ (rmail-next-undeleted-message (if backward -1 1)))
(defun rmail-delete-backward ()
"Delete this message and move to previous nondeleted one.
"Break up a digest message into its constituent messages.
Leaves original message, deleted, before the undigestified messages."
t)
+
+(provide 'rmail)
+
+;;; rmail.el ends here