-;;; rmail.el --- main code of "RMAIL" mail reader for Emacs.
+;;; rmail.el --- main code of "RMAIL" mail reader for Emacs
;; Copyright (C) 1985,86,87,88,93,94,95,96,97,98,2000, 2001
;; Free Software Foundation, Inc.
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
+;;; Commentary:
+
;;; Code:
;; Souped up by shane@mit-ajax based on ideas of rlk@athena.mit.edu
;;
(require 'mail-utils)
+(eval-when-compile (require 'mule-util)) ; for detect-coding-with-priority
; These variables now declared in paths.el.
;(defvar rmail-spool-directory "/usr/spool/mail/"
;;;###autoload
(defcustom rmail-dont-reply-to-names nil "\
-*A regexp specifying names to prune of reply to messages.
-A value of nil means exclude your own login name as an address
+*A regexp specifying addresses to prune from a reply message.
+A value of nil means exclude your own email address as an address
plus whatever is specified by `rmail-default-dont-reply-to-names'."
:type '(choice regexp (const :tag "Your Name" nil))
:group 'rmail-reply)
A regular expression specifying part of the value of the default value of
the variable `rmail-dont-reply-to-names', for when the user does not set
`rmail-dont-reply-to-names' explicitly. (The other part of the default
-value is the user's name.)
+value is the user's email address and name.)
It is useful to set this variable in the site customization file.")
;;;###autoload
:group 'rmail
:version "21.1"
:type '(repeat (sexp :tag "Directive")))
-
+
(defvar rmail-reply-prefix "Re: "
"String to prepend to Subject line when replying to a message.")
(other :tag "when asked" ask))
:group 'rmail)
+(defvar rmail-enable-mime-composing nil
+ "*If non-nil, RMAIL uses `rmail-insert-mime-forwarded-message-function' to forward.")
+
;;;###autoload
(defvar rmail-show-mime-function nil
"Function to show MIME decoded message of RMAIL file.
;;;###autoload
(defvar rmail-insert-mime-forwarded-message-function nil
"Function to insert a message in MIME format so it can be forwarded.
+This function is called if `rmail-enable-mime' or
+`rmail-enable-mime-composing' is non-nil.
+It is called with one argument FORWARD-BUFFER, which is a
+buffer containing the message to forward. The current buffer
+is the outgoing mail buffer.")
+
+;;;###autoload
+(defvar rmail-insert-mime-resent-message-function nil
+ "Function to insert a message in MIME format so it can be resent.
This function is called if `rmail-enable-mime' is non-nil.
It is called with one argument FORWARD-BUFFER, which is a
buffer containing the message to forward. The current buffer
(let* ((cite-chars "[>|}]")
(cite-prefix "A-Za-z")
(cite-suffix (concat cite-prefix "0-9_.@-`'\"")))
- (list '("^\\(From\\|Sender\\):" . font-lock-function-name-face)
+ (list '("^\\(From\\|Sender\\|Resent-[Ff]rom\\):" . font-lock-function-name-face)
'("^Reply-To:.*$" . font-lock-function-name-face)
'("^Subject:" . font-lock-comment-face)
'("^\\(To\\|Apparently-To\\|Cc\\|Newsgroups\\):"
(list (read-file-name "Run rmail on RMAIL file: "))))
(rmail-require-mime-maybe)
(let* ((file-name (expand-file-name (or file-name-arg rmail-file-name)))
- (existed (get-file-buffer file-name))
- ;; This binding is necessary because we much decide if we
+ ;; Use find-buffer-visiting, not get-file-buffer, for those users
+ ;; who have find-file-visit-truename set to t.
+ (existed (find-buffer-visiting file-name))
+ ;; This binding is necessary because we must decide if we
;; need code conversion while the buffer is unibyte
;; (i.e. enable-multibyte-characters is nil).
(rmail-enable-multibyte
- (if existed
+ (if existed
(with-current-buffer existed enable-multibyte-characters)
(default-value 'enable-multibyte-characters)))
;; Since the file may contain messages of different encodings
(eq major-mode 'rmail-mode))
(progn (rmail-forget-messages)
(rmail-set-message-counters))))
- (switch-to-buffer
+ (switch-to-buffer
(let ((enable-local-variables nil))
(find-file-noselect file-name))))
(if (eq major-mode 'rmail-edit-mode)
(setq to (point))
(unless (and coding-system
(coding-system-p coding-system))
- (setq coding-system (detect-coding-region from to t)))
+ (setq coding-system
+ ;; Emacs 21.1 and later writes RMAIL files in emacs-mule, but
+ ;; earlier versions did that with the current buffer's encoding.
+ ;; So we want to favor detection of emacs-mule (whose normal
+ ;; priority is quite low), but still allow detection of other
+ ;; encodings if emacs-mule won't fit. The call to
+ ;; detect-coding-with-priority below achieves that.
+ (car (detect-coding-with-priority
+ from to
+ '((coding-category-emacs-mule . emacs-mule))))))
(unless (memq coding-system
'(undecided undecided-unix))
(set-buffer-modified-p t) ; avoid locking when decoding
- (decode-coding-region from to coding-system)
+ (let ((buffer-undo-list t))
+ (decode-coding-region from to coding-system))
(setq coding-system last-coding-system-used))
(set-buffer-modified-p modifiedp)
(setq buffer-file-coding-system nil)
;; Handle M-x revert-buffer done in an rmail-mode buffer.
(defun rmail-revert (arg noconfirm)
+ (set-buffer rmail-buffer)
(let* ((revert-buffer-function (default-value 'revert-buffer-function))
(rmail-enable-multibyte enable-multibyte-characters)
;; See similar code in `rmail'.
;; If the user said "yes", and we changed something,
;; reparse the messages.
(progn
- (rmail-mode-2)
+ (set-buffer rmail-buffer)
+ (rmail-mode-2)
;; Convert all or part to Babyl file if possible.
(rmail-convert-file)
;; We have read the file as raw-text, so the buffer is set to
(if (consp item)
(progn
(setq command
- (rmail-list-to-menu (car item) (cdr item)
- action
+ (rmail-list-to-menu (car item) (cdr item)
+ action
(if full-name
(concat full-name "/"
(car item))
(setq name (car item)))
(progn
(setq name item)
- (setq command
+ (setq command
(list 'lambda () '(interactive)
(list action
- (expand-file-name
+ (expand-file-name
(if full-name
(concat full-name "/" item)
item)
(cons name command)))))
(reverse l))
menu))
-
+
;; This command is always "disabled" when it appears in a menu.
(put 'rmail-disable-menu 'menu-enable ''nil)
(if files
(progn
(define-key rmail-mode-map [menu-bar classify input-menu]
- (cons "Input Rmail File"
- (rmail-list-to-menu "Input Rmail File"
+ (cons "Input Rmail File"
+ (rmail-list-to-menu "Input Rmail File"
files
'rmail-input)))
(define-key rmail-mode-map [menu-bar classify output-menu]
- (cons "Output Rmail File"
- (rmail-list-to-menu "Output Rmail File"
+ (cons "Output Rmail File"
+ (rmail-list-to-menu "Output Rmail File"
files
'rmail-output-to-rmail-file))))
(save-excursion
(setq errors (generate-new-buffer " *rmail loss*"))
(buffer-disable-undo errors)
- (let ((args
- (append
+ (let ((args
+ (append
(list (or rmail-movemail-program
(expand-file-name "movemail"
exec-directory))
nil errors nil)
- (if rmail-preserve-inbox
+ (if rmail-preserve-inbox
(list "-p")
nil)
rmail-movemail-flags
""
(concat
"Date: \\2, \\4 \\3 \\9 \\5 "
-
+
;; The timezone could be matched by group 7 or group 10.
;; If neither of them matched, assume EST, since only
;; Easterners would be so sloppy.
(goto-char beg)
(forward-line 1)
(if (/= (following-char) ?0)
- (error "Bad format in RMAIL file."))
- (let ((buffer-read-only nil)
+ (error "Bad format in RMAIL file"))
+ (let ((inhibit-read-only t)
(delta (- (buffer-size) end)))
(delete-char 1)
(insert ?1)
(forward-line 1)
(= (following-char) ?1))))
+(defun rmail-msg-restore-non-pruned-header ()
+ (let ((old-point (point))
+ new-point
+ new-start
+ (inhibit-read-only t))
+ (save-excursion
+ (narrow-to-region (rmail-msgbeg rmail-current-message) (point-max))
+ (goto-char (point-min))
+ (forward-line 1)
+ ;; Change 1 to 0.
+ (delete-char 1)
+ (insert ?0)
+ ;; Insert new EOOH line at the proper place.
+ (forward-line 1)
+ (let ((case-fold-search t))
+ (while (looking-at "Summary-Line:\\|Mail-From:")
+ (forward-line 1)))
+ (insert "*** EOOH ***\n")
+ (setq new-start (point))
+ ;; Delete the old reformatted header.
+ (forward-char -1)
+ (search-forward "\n*** EOOH ***\n")
+ (forward-line -1)
+ (let ((start (point)))
+ (search-forward "\n\n")
+ (if (and (<= start old-point)
+ (<= old-point (point)))
+ (setq new-point new-start))
+ (delete-region start (point)))
+ ;; Narrow to after the new EOOH line.
+ (narrow-to-region new-start (point-max)))
+ (if new-point
+ (goto-char new-point))))
+
+(defun rmail-msg-prune-header ()
+ (let ((new-point
+ (= (point) (point-min))))
+ (save-excursion
+ (narrow-to-region (rmail-msgbeg rmail-current-message) (point-max))
+ (rmail-reformat-message (point-min) (point-max)))
+ (if new-point
+ (goto-char (point-min)))))
+
(defun rmail-toggle-header (&optional arg)
"Show original message header if pruned header currently shown, or vice versa.
With argument ARG, show the message header pruned if ARG is greater than zero;
otherwise, show it in full."
(interactive "P")
- (switch-to-buffer rmail-buffer)
- (let* ((buffer-read-only nil)
- (pruned (rmail-msg-is-pruned))
+ (let* ((pruned (with-current-buffer rmail-buffer
+ (rmail-msg-is-pruned)))
(prune (if arg
(> (prefix-numeric-value arg) 0)
(not pruned))))
(if (eq pruned prune)
t
+ (set-buffer rmail-buffer)
(rmail-maybe-set-message-counters)
- (let* ((window (get-buffer-window (current-buffer)))
- (at-point-min (= (point) (point-min)))
- (all-headers-visible (= (window-start window) (point-min)))
- (on-header (save-excursion
- (and (not (search-backward "\n\n" nil t))
- (progn
- (end-of-line)
- (re-search-backward "^[-A-Za-z0-9]+:" nil t))
- (match-string 0))))
- (old-screen-line
- (rmail-count-screen-lines (window-start window) (point))))
- (save-excursion
- (narrow-to-region (rmail-msgbeg rmail-current-message) (point-max))
+ (if rmail-enable-mime
+ (let ((buffer-read-only nil))
+ (if pruned
+ (rmail-msg-restore-non-pruned-header)
+ (rmail-msg-prune-header))
+ (funcall rmail-show-mime-function))
+ (let* ((buffer-read-only nil)
+ (window (get-buffer-window (current-buffer)))
+ (at-point-min (= (point) (point-min)))
+ (all-headers-visible (= (window-start window) (point-min)))
+ (on-header
+ (save-excursion
+ (and (not (search-backward "\n\n" nil t))
+ (progn
+ (end-of-line)
+ (re-search-backward "^[-A-Za-z0-9]+:" nil t))
+ (match-string 0))))
+ (old-screen-line
+ (rmail-count-screen-lines (window-start window) (point))))
(if pruned
- (let (new-start)
- (goto-char (point-min))
- (forward-line 1)
- ;; Change 1 to 0.
- (delete-char 1)
- (insert ?0)
- ;; Insert new EOOH line at the proper place.
- (forward-line 1)
- (let ((case-fold-search t))
- (while (looking-at "Summary-Line:\\|Mail-From:")
- (forward-line 1)))
- (insert "*** EOOH ***\n")
- (setq new-start (point))
- ;; Delete the old reformatted header.
- (forward-char -1)
- (search-forward "\n*** EOOH ***\n")
- (forward-line -1)
- (let ((start (point)))
- (search-forward "\n\n")
- (delete-region start (point)))
- ;; Narrow to after the new EOOH line.
- (narrow-to-region new-start (point-max)))
- (rmail-reformat-message (point-min) (point-max))))
- (cond (rmail-enable-mime
- (funcall rmail-show-mime-function))
- (at-point-min
- (goto-char (point-min)))
- (on-header
- (goto-char (point-min))
- (search-forward "\n\n")
- (or (re-search-backward (concat "^" (regexp-quote on-header)) nil t)
- (goto-char (point-min))))
- (t
- (save-selected-window
- (select-window window)
- (recenter old-screen-line)
- (if (and all-headers-visible
- (not (= (window-start) (point-min))))
- (let ((lines-offscreen (rmail-count-screen-lines
- (point-min)
- (window-start window))))
- (recenter (min (+ old-screen-line lines-offscreen)
- ;; last line of window
- (- (window-height) 2)))))))))
+ (rmail-msg-restore-non-pruned-header)
+ (rmail-msg-prune-header))
+ (cond (at-point-min
+ (goto-char (point-min)))
+ (on-header
+ (goto-char (point-min))
+ (search-forward "\n\n")
+ (or (re-search-backward
+ (concat "^" (regexp-quote on-header)) nil t)
+ (goto-char (point-min))))
+ (t
+ (save-selected-window
+ (select-window window)
+ (recenter old-screen-line)
+ (if (and all-headers-visible
+ (not (= (window-start) (point-min))))
+ (recenter (- (window-height) 2))))))))
(rmail-highlight-headers))))
+(defun rmail-narrow-to-non-pruned-header ()
+ "Narrow to the whole (original) header of the current message."
+ (let (start end)
+ (narrow-to-region (rmail-msgbeg rmail-current-message) (point-max))
+ (goto-char (point-min))
+ (forward-line 1)
+ (if (= (following-char) ?1)
+ (progn
+ (forward-line 1)
+ (setq start (point))
+ (search-forward "*** EOOH ***\n")
+ (setq end (match-beginning 0)))
+ (forward-line 2)
+ (setq start (point))
+ (search-forward "\n\n")
+ (setq end (1- (point))))
+ (narrow-to-region start end)
+ (goto-char start)))
+
;; Lifted from repos-count-screen-lines.
;; Return number of screen lines between START and END.
(defun rmail-count-screen-lines (start end)
(aset rmail-msgref-vector i (list i))
(setq i (1+ i))))
(message "Counting messages...done")))))
-
+
(defun rmail-set-message-counters-counter (&optional stop)
(let ((start (point))
next)
(goto-char (point-min))
(if (re-search-forward "^X-Coding-System: *\\(.*\\)$" nil t)
(let ((coding-system (intern (match-string 1))))
- (check-coding-system coding-system)
- (setq buffer-file-coding-system coding-system))
+ (condition-case nil
+ (progn
+ (check-coding-system coding-system)
+ (setq buffer-file-coding-system coding-system))
+ (error
+ (setq buffer-file-coding-system nil))))
(setq buffer-file-coding-system nil)))))
;; Clear the "unseen" attribute when we show a message.
(rmail-set-attribute "unseen" nil)
(search-forward "\n*** EOOH ***\n" end t)
(narrow-to-region (point) end)))
(goto-char (point-min))
+ (walk-windows
+ (function (lambda (window)
+ (if (eq (window-buffer window) (current-buffer))
+ (set-window-point window (point)))))
+ nil t)
(rmail-display-labels)
(if (eq rmail-enable-mime t)
(funcall rmail-show-mime-function)
(or (eq major-mode 'rmail-mode)
(switch-to-buffer rmail-buffer))
(save-excursion
- (unwind-protect
- (let ((msgbeg (rmail-msgbeg rmail-current-message))
- (msgend (rmail-msgend rmail-current-message))
- x-coding-header)
- (narrow-to-region msgbeg msgend)
- (goto-char (point-min))
- (when (search-forward "\n*** EOOH ***\n" (point-max) t)
- (narrow-to-region msgbeg (point)))
- (goto-char (point-min))
- (if (re-search-forward "^X-Coding-System: *\\(.*\\)$" nil t)
- (let ((old-coding (intern (match-string 1)))
- (buffer-read-only nil))
- (check-coding-system old-coding)
- ;; Make sure the new coding system uses the same EOL
- ;; conversion, to prevent ^M characters from popping
- ;; up all over the place.
- (setq coding
- (coding-system-change-eol-conversion
- coding
- (coding-system-eol-type old-coding)))
- (setq x-coding-header (point-marker))
- (narrow-to-region msgbeg msgend)
- (encode-coding-region (point) msgend old-coding)
- (decode-coding-region (point) msgend coding)
- (setq last-coding-system-used coding)
- ;; Rewrite the coding-system header according
- ;; to what we did.
- (goto-char x-coding-header)
- (delete-region (point)
- (save-excursion
- (beginning-of-line)
- (point)))
- (insert "X-Coding-System: "
- (symbol-name last-coding-system-used))
- (set-marker x-coding-header nil)
- (rmail-show-message))
- (error "No X-Coding-System header found")))))))
+ (let ((pruned (rmail-msg-is-pruned)))
+ (unwind-protect
+ (let ((msgbeg (rmail-msgbeg rmail-current-message))
+ (msgend (rmail-msgend rmail-current-message))
+ x-coding-header)
+ ;; We need the message headers pruned (we later restore
+ ;; the pruned stat to what it was, see the end of
+ ;; unwind-protect form).
+ (or pruned
+ (rmail-toggle-header 1))
+ (narrow-to-region msgbeg msgend)
+ (goto-char (point-min))
+ (when (search-forward "\n*** EOOH ***\n" (point-max) t)
+ (narrow-to-region msgbeg (point)))
+ (goto-char (point-min))
+ (if (re-search-forward "^X-Coding-System: *\\(.*\\)$" nil t)
+ (let ((old-coding (intern (match-string 1)))
+ (buffer-read-only nil))
+ (check-coding-system old-coding)
+ ;; Make sure the new coding system uses the same EOL
+ ;; conversion, to prevent ^M characters from popping
+ ;; up all over the place.
+ (setq coding
+ (coding-system-change-eol-conversion
+ coding
+ (coding-system-eol-type old-coding)))
+ (setq x-coding-header (point-marker))
+ (narrow-to-region msgbeg msgend)
+ (encode-coding-region (point) msgend old-coding)
+ (decode-coding-region (point) msgend coding)
+ (setq last-coding-system-used coding)
+ ;; Rewrite the coding-system header according
+ ;; to what we did.
+ (goto-char x-coding-header)
+ (delete-region (point)
+ (save-excursion
+ (beginning-of-line)
+ (point)))
+ (insert "X-Coding-System: "
+ (symbol-name last-coding-system-used))
+ (set-marker x-coding-header nil)
+ (rmail-show-message))
+ (error "No X-Coding-System header found")))
+ (or pruned
+ (rmail-toggle-header 0)))))))
;; Find all occurrences of certain fields, and highlight them.
(defun rmail-highlight-headers ()
"Show previous message whether deleted or not.
With prefix arg N, moves backward N messages, or forward if N is negative."
(interactive "p")
- (rmail-next-message (- n)))
+ (rmail-next-message (- n)))
(defun rmail-next-undeleted-message (n)
"Show following non-deleted message.
(forward-line 1))
(setq beg (point))
(narrow-to-region (point) end))
- (progn
+ (progn
(rfc822-goto-eoh)
(setq end (point)))
(setq beg (point))
(msgnum rmail-current-message))
(save-excursion
(save-restriction
- ;; If rmail-enable-mime is non-nil, we are in a
- ;; rmail-view-buffer which doesn't contain any lines specific
- ;; to BABYL format (e.g. "*** EOOH ***"). Thus, there's no
- ;; need of narrowing in such a case.
- (unless rmail-enable-mime
+ (if rmail-enable-mime
+ (narrow-to-region
+ (goto-char (point-min))
+ (if (search-forward "\n\n" nil 'move)
+ (1+ (match-beginning 0))
+ (point)))
(widen)
(goto-char (rmail-msgbeg rmail-current-message))
(forward-line 1)
(save-excursion
;; Insert after header separator--before signature if any.
(goto-char (mail-text-start))
- (if rmail-enable-mime
+ (if (or rmail-enable-mime rmail-enable-mime-composing)
(funcall rmail-insert-mime-forwarded-message-function
forward-buffer)
(insert "------- Start of forwarded message -------\n")
(interactive "sResend to: ")
(require 'sendmail)
(require 'mailalias)
- (unless (eq rmail-buffer (current-buffer))
+ (unless (or (eq rmail-view-buffer (current-buffer))
+ (eq rmail-buffer (current-buffer)))
(error "Not an Rmail buffer"))
(if (not from) (setq from user-mail-address))
(let ((tembuf (generate-new-buffer " sendmail temp"))
(unwind-protect
(with-current-buffer tembuf
;;>> Copy message into temp buffer
- (insert-buffer-substring mailbuf)
+ (if rmail-enable-mime
+ (funcall rmail-insert-mime-resent-message-function mailbuf)
+ (insert-buffer-substring mailbuf))
(goto-char (point-min))
;; Delete any Sender field, since that's not specifiable.
; Only delete Sender fields in the actual header.
(if (and (not (vectorp mail-abbrevs))
(file-exists-p mail-personal-alias-file))
(build-mail-abbrevs))
+ (unless mail-abbrev-syntax-table
+ (mail-abbrev-make-syntax-table))
(set-syntax-table mail-abbrev-syntax-table)
(goto-char before)
(while (and (< (point) end)
(require 'mail-utils)
(let ((rmail-this-buffer (current-buffer))
(msgnum rmail-current-message)
- (pruned (rmail-msg-is-pruned))
- bounce-start bounce-end bounce-indent resending)
- (unwind-protect
- (progn
- (save-excursion
- ;; Un-prune the header; we need to search the whole thing.
- (if pruned
- (rmail-toggle-header 0))
- (goto-char (rmail-msgbeg msgnum))
- (let* ((case-fold-search t)
- (top (point))
- (content-type
- (save-restriction
- ;; Fetch any content-type header in current message
- (search-forward "\n\n") (narrow-to-region top (point))
- (mail-fetch-field "Content-Type") )) )
- ;; Handle MIME multipart bounce messages
- (if (and content-type
- (string-match
- ";[\n\t ]*boundary=\"?\\([-0-9a-z'()+_,./:=? ]+\\)\"?"
- content-type))
- (let ((codestring
- (concat "\n--"
- (substring content-type (match-beginning 1)
- (match-end 1)))))
- (unless (re-search-forward mail-mime-unsent-header nil t)
- (error "Cannot find beginning of header in failed message"))
- (unless (search-forward "\n\n" nil t)
- (error "Cannot find start of Mime data in failed message"))
- (setq bounce-start (point))
- (if (search-forward codestring nil t)
- (setq bounce-end (match-beginning 0))
- (setq bounce-end (point-max)))
- )
- ;; non-MIME bounce
- (or (re-search-forward mail-unsent-separator nil t)
- (error "Cannot parse this as a failure message"))
- (skip-chars-forward "\n")
- ;; Support a style of failure message in which the original
- ;; message is indented, and included within lines saying
- ;; `Start of returned message' and `End of returned message'.
- (if (looking-at " +Received:")
- (progn
- (setq bounce-start (point))
- (skip-chars-forward " ")
- (setq bounce-indent (- (current-column)))
- (goto-char (point-max))
- (re-search-backward "^End of returned message$" nil t)
- (setq bounce-end (point)))
- ;; One message contained a few random lines before
- ;; the old message header. The first line of the
- ;; message started with two hyphens. A blank line
- ;; followed these random lines. The same line
- ;; beginning with two hyphens was possibly marking
- ;; the end of the message.
- (if (looking-at "^--")
- (let ((boundary (buffer-substring-no-properties
- (point)
- (progn (end-of-line) (point)))))
- (search-forward "\n\n")
- (skip-chars-forward "\n")
- (setq bounce-start (point))
- (goto-char (point-max))
- (search-backward (concat "\n\n" boundary) bounce-start t)
- (setq bounce-end (point)))
- (setq bounce-start (point)
- bounce-end (point-max)))
- (unless (search-forward "\n\n" nil t)
- (error "Cannot find end of header in failed message"))
- ))))
- ;; Start sending new message; default header fields from original.
- ;; Turn off the usual actions for initializing the message body
- ;; because we want to get only the text from the failure message.
- (let (mail-signature mail-setup-hook)
- (if (rmail-start-mail nil nil nil nil nil rmail-this-buffer
- (list (list 'rmail-mark-message
- rmail-this-buffer
- (aref rmail-msgref-vector msgnum)
- "retried")))
- ;; Insert original text as initial text of new draft message.
- ;; Bind inhibit-read-only since the header delimiter
- ;; of the previous message was probably read-only.
- (let ((inhibit-read-only t)
- rmail-displayed-headers
- rmail-ignored-headers)
- (erase-buffer)
- (insert-buffer-substring rmail-this-buffer
- bounce-start bounce-end)
- (goto-char (point-min))
- (if bounce-indent
- (indent-rigidly (point-min) (point-max) bounce-indent))
- (rmail-clear-headers rmail-retry-ignored-headers)
- (rmail-clear-headers "^sender:\\|^return-path:\\|^received:")
- (mail-sendmail-delimit-header)
- (save-restriction
- (narrow-to-region (point-min) (mail-header-end))
- (setq resending (mail-fetch-field "resent-to"))
- (if mail-self-blind
- (if resending
- (insert "Resent-Bcc: " (user-login-name) "\n")
- (insert "BCC: " (user-login-name) "\n"))))
- (goto-char (point-min))
- (mail-position-on-field (if resending "Resent-To" "To") t)))))
- (with-current-buffer rmail-this-buffer
- (if pruned
- (rmail-toggle-header 1))))))
+ bounce-start bounce-end bounce-indent resending
+ ;; Fetch any content-type header in current message
+ ;; Must search thru the whole unpruned header.
+ (content-type
+ (save-excursion
+ (save-restriction
+ (rmail-narrow-to-non-pruned-header)
+ (mail-fetch-field "Content-Type") ))))
+ (save-excursion
+ (goto-char (point-min))
+ (let ((case-fold-search t))
+ (if (and content-type
+ (string-match
+ ";[\n\t ]*boundary=\"?\\([-0-9a-z'()+_,./:=? ]+\\)\"?"
+ content-type))
+ ;; Handle a MIME multipart bounce message.
+ (let ((codestring
+ (concat "\n--"
+ (substring content-type (match-beginning 1)
+ (match-end 1)))))
+ (unless (re-search-forward mail-mime-unsent-header nil t)
+ (error "Cannot find beginning of header in failed message"))
+ (unless (search-forward "\n\n" nil t)
+ (error "Cannot find start of Mime data in failed message"))
+ (setq bounce-start (point))
+ (if (search-forward codestring nil t)
+ (setq bounce-end (match-beginning 0))
+ (setq bounce-end (point-max))))
+ ;; Non-MIME bounce.
+ (or (re-search-forward mail-unsent-separator nil t)
+ (error "Cannot parse this as a failure message"))
+ (skip-chars-forward "\n")
+ ;; Support a style of failure message in which the original
+ ;; message is indented, and included within lines saying
+ ;; `Start of returned message' and `End of returned message'.
+ (if (looking-at " +Received:")
+ (progn
+ (setq bounce-start (point))
+ (skip-chars-forward " ")
+ (setq bounce-indent (- (current-column)))
+ (goto-char (point-max))
+ (re-search-backward "^End of returned message$" nil t)
+ (setq bounce-end (point)))
+ ;; One message contained a few random lines before
+ ;; the old message header. The first line of the
+ ;; message started with two hyphens. A blank line
+ ;; followed these random lines. The same line
+ ;; beginning with two hyphens was possibly marking
+ ;; the end of the message.
+ (if (looking-at "^--")
+ (let ((boundary (buffer-substring-no-properties
+ (point)
+ (progn (end-of-line) (point)))))
+ (search-forward "\n\n")
+ (skip-chars-forward "\n")
+ (setq bounce-start (point))
+ (goto-char (point-max))
+ (search-backward (concat "\n\n" boundary) bounce-start t)
+ (setq bounce-end (point)))
+ (setq bounce-start (point)
+ bounce-end (point-max)))
+ (unless (search-forward "\n\n" nil t)
+ (error "Cannot find end of header in failed message"))))))
+ ;; We have found the message that bounced, within the current message.
+ ;; Now start sending new message; default header fields from original.
+ ;; Turn off the usual actions for initializing the message body
+ ;; because we want to get only the text from the failure message.
+ (let (mail-signature mail-setup-hook)
+ (if (rmail-start-mail nil nil nil nil nil rmail-this-buffer
+ (list (list 'rmail-mark-message
+ rmail-this-buffer
+ (aref rmail-msgref-vector msgnum)
+ "retried")))
+ ;; Insert original text as initial text of new draft message.
+ ;; Bind inhibit-read-only since the header delimiter
+ ;; of the previous message was probably read-only.
+ (let ((inhibit-read-only t)
+ rmail-displayed-headers
+ rmail-ignored-headers)
+ (erase-buffer)
+ (insert-buffer-substring rmail-this-buffer
+ bounce-start bounce-end)
+ (goto-char (point-min))
+ (if bounce-indent
+ (indent-rigidly (point-min) (point-max) bounce-indent))
+ (rmail-clear-headers rmail-retry-ignored-headers)
+ (rmail-clear-headers "^sender:\\|^return-path:\\|^received:")
+ (mail-sendmail-delimit-header)
+ (save-restriction
+ (narrow-to-region (point-min) (mail-header-end))
+ (setq resending (mail-fetch-field "resent-to"))
+ (if mail-self-blind
+ (if resending
+ (insert "Resent-Bcc: " (user-login-name) "\n")
+ (insert "BCC: " (user-login-name) "\n"))))
+ (goto-char (point-min))
+ (mail-position-on-field (if resending "Resent-To" "To") t))))))
\f
(defun rmail-summary-exists ()
"Non-nil iff in an RMAIL buffer and an associated summary buffer exists.
(setq window (get-buffer-window rmail-summary-buffer))
;; Don't try to change the size if just one window in frame.
(not (eq window (frame-root-window (window-frame window))))
- (unwind-protect
+ (unwind-protect
(progn
(select-window window)
(enlarge-window (- rmail-summary-window-size (window-height))))
(defun rmail-fontify-buffer-function ()
;; This function's symbol is bound to font-lock-fontify-buffer-function.
- (make-local-hook 'rmail-show-message-hook)
(add-hook 'rmail-show-message-hook 'rmail-fontify-message nil t)
;; If we're already showing a message, fontify it now.
(if rmail-current-message (rmail-fontify-message))
"Set PASSWORD to be used for retrieving mail from a POP server."
(interactive "sPassword: ")
(if password
- (setq rmail-encoded-pop-password
+ (setq rmail-encoded-pop-password
(rmail-encode-string password (emacs-pid)))
(setq rmail-pop-password nil)
(setq rmail-encoded-pop-password nil)))
Returns the encoded string. Calling the function again with an
encoded string (and the same mask) will decode the string."
(setq mask (abs mask)) ; doesn't work if negative
- (let* ((string-vector (string-to-vector string)) (i 0)
+ (let* ((string-vector (string-to-vector string)) (i 0)
(len (length string-vector)) (curmask mask) charmask)
(while (< i len)
(if (= curmask 0)