]> code.delx.au - gnu-emacs/blobdiff - lisp/mail/rmail.el
(mail-unsent-separator): Handle "returned message follows".
[gnu-emacs] / lisp / mail / rmail.el
index c874ade81fc0c2bd1ae003e90b424ed6895e8d24..972f7d004777b39153824fde26aef0473d2ef581 100644 (file)
@@ -1,6 +1,7 @@
 ;;; rmail.el --- main code of "RMAIL" mail reader for Emacs.
 
-;; Copyright (C) 1985,86,87,88,93,94,95,96,97 Free Software Foundation, Inc.
+;; Copyright (C) 1985,86,87,88,93,94,95,96,97,1998
+;;             Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 ;; Keywords: mail
 
 (require 'mail-utils)
 
-;; For Emacs V18 compatibility
-(and (not (fboundp 'buffer-disable-undo))
-     (fboundp 'buffer-flush-undo)
-     (defalias 'buffer-disable-undo 'buffer-flush-undo))
-
 ; These variables now declared in paths.el.
 ;(defvar rmail-spool-directory "/usr/spool/mail/"
 ;  "This is the name of the directory used by the system mailer for\n\
   :group 'rmail)
 
 
-(defvar rmail-movemail-program nil
-  "If non-nil, name of program for fetching new mail.")
+(defcustom rmail-movemail-program nil
+  "If non-nil, name of program for fetching new mail."
+  :group 'rmail-retrieve
+  :type 'string)
 
 (defcustom rmail-pop-password nil
   "*Password to use when reading mail from a POP server, if required."
   :type 'boolean
   :group 'rmail-retrieve)
 
+(defcustom rmail-movemail-flags nil
+  "*List of flags to pass to movemail.
+Most commonly used to specify `-g' to enable GSS-API authentication
+or `-k' to enable Kerberos authentication."
+  :type '(repeat string)
+  :group 'rmail-retrieve
+  :version "20.3")
+
 (defvar rmail-pop-password-error "invalid usercode or password"
   "Regular expression matching incorrect-password POP server error messages.
 If you get an incorrect-password error that this expression does not match,
@@ -129,7 +135,7 @@ value is the user's name.)
 It is useful to set this variable in the site customization file.")
 
 ;;;###autoload
-(defcustom rmail-ignored-headers "^via:\\|^mail-from:\\|^origin:\\|^references:\\|^status:\\|^received:\\|^x400-originator:\\|^x400-recipients:\\|^x400-received:\\|^x400-mts-identifier:\\|^x400-content-type:\\|^\\(resent-\\|\\)message-id:\\|^summary-line:\\|^resent-date:\\|^nntp-posting-host:\\|^path:\\|^x-char.*:\\|^x-face:\\|^x-mailer:\\|^delivered-to:\\|^lines:\\|^mime-version:\\|^content-transfer-encoding:"
+(defcustom rmail-ignored-headers "^via:\\|^mail-from:\\|^origin:\\|^references:\\|^status:\\|^received:\\|^x400-originator:\\|^x400-recipients:\\|^x400-received:\\|^x400-mts-identifier:\\|^x400-content-type:\\|^\\(resent-\\|\\)message-id:\\|^summary-line:\\|^resent-date:\\|^nntp-posting-host:\\|^path:\\|^x-char.*:\\|^x-face:\\|^x-mailer:\\|^delivered-to:\\|^lines:\\|^mime-version:\\|^content-transfer-encoding:\\|^x-coding-system:\\|^return-path:\\|^errors-to:\\|^return-receipt-to:\\|^x-attribution:\\|^x-disclaimer:"
   "*Regexp to match header fields that Rmail should normally hide."
   :type 'regexp
   :group 'rmail-headers)
@@ -229,10 +235,12 @@ still the current message in the Rmail buffer.")
 (defvar rmail-mmdf-delim2 "^\001\001\001\001\n"
   "Regexp marking the end of an mmdf message")
 
-(defvar rmail-message-filter nil
+(defcustom rmail-message-filter nil
   "If non-nil, a filter function for new messages in RMAIL.
 Called with region narrowed to the message, including headers,
-before obeying `rmail-ignored-headers'.")
+before obeying `rmail-ignored-headers'."
+  :group 'rmail-headers
+  :type 'function)
 
 (defvar rmail-reply-prefix "Re: "
   "String to prepend to Subject line when replying to a message.")
@@ -242,13 +250,16 @@ before obeying `rmail-ignored-headers'.")
 (defvar rmail-reply-regexp "\\`\\(Re\\(([0-9]+)\\|\\[[0-9]+\\]\\|\\^[0-9]+\\)?: *\\)*"
   "Regexp to delete from Subject line before inserting `rmail-reply-prefix'.")
 
-(defvar rmail-display-summary nil
-  "If non-nil, Rmail always displays the summary buffer.")
-
-(defvar rmail-mode-map nil)
-
+(defcustom rmail-display-summary nil
+  "*If non-nil, Rmail always displays the summary buffer."
+  :group 'rmail-summary
+  :type 'boolean)
+\f
 (defvar rmail-inbox-list nil)
+(put 'rmail-inbox-list 'permanent-local t)
+
 (defvar rmail-keywords nil)
+(put 'rmail-keywords 'permanent-local t)
 
 (defvar rmail-buffer nil
   "The RMAIL buffer related to the current buffer.
@@ -259,38 +270,25 @@ In a summary buffer, this holds the RMAIL buffer it is a summary for.")
 ;; Message counters and markers.  Deleted flags.
 
 (defvar rmail-current-message nil)
+(put 'rmail-current-message 'permanent-local t)
+
 (defvar rmail-total-messages nil)
+(put 'rmail-total-messages 'permanent-local t)
+
 (defvar rmail-message-vector nil)
+(put 'rmail-message-vector 'permanent-local t)
+
 (defvar rmail-deleted-vector nil)
+(put 'rmail-deleted-vector 'permanent-local t)
+
 (defvar rmail-msgref-vector nil
   "In an Rmail buffer, a vector whose Nth element is a list (N).
 When expunging renumbers messages, these lists are modified
 by substituting the new message number into the existing list.")
+(put 'rmail-msgref-vector 'permanent-local t)
 
 (defvar rmail-overlay-list nil)
-
-(defvar rmail-font-lock-keywords
-  (eval-when-compile
-    (let* ((cite-chars "[>|}]")
-          (cite-prefix "A-Za-z")
-          (cite-suffix (concat cite-prefix "0-9_.@-`'\"")))
-      (list '("^\\(From\\|Sender\\):" . font-lock-function-name-face)
-           '("^Reply-To:.*$" . font-lock-function-name-face)
-           '("^Subject:" . font-lock-comment-face)
-           '("^\\(To\\|Apparently-To\\|Cc\\|Newsgroups\\):"
-             . font-lock-keyword-face)
-           ;; Use MATCH-ANCHORED to effectively anchor the regexp left side.
-           `(,cite-chars
-             (,(concat "\\=[ \t]*"
-                       "\\(\\([" cite-prefix "]+[" cite-suffix "]*\\)?"
-                       "\\(" cite-chars "[ \t]*\\)\\)+"
-                       "\\(.*\\)")
-              (beginning-of-line) (end-of-line)
-              (2 font-lock-constant-face nil t)
-              (4 font-lock-comment-face nil t)))
-           '("^\\(X-[A-Za-z0-9-]+\\|In-reply-to\\|Date\\):.*$"
-             . font-lock-string-face))))
-  "Additional expressions to highlight in Rmail mode.")
+(put 'rmail-overlay-list 'permanent-local t)
 
 ;; These are used by autoloaded rmail-summary.
 
@@ -299,13 +297,22 @@ by substituting the new message number into the existing list.")
 (defvar rmail-summary-vector nil)
 (put 'rmail-summary-vector 'permanent-local t)
 
+(defvar rmail-view-buffer nil
+  "Buffer which holds RMAIL message for MIME displaying.")
+(put 'rmail-view-buffer 'permanent-local t)
+\f
 ;; `Sticky' default variables.
 
 ;; Last individual label specified to a or k.
 (defvar rmail-last-label nil)
+(put 'rmail-last-label 'permanent-local t)
+
 ;; Last set of values specified to C-M-n, C-M-p, C-M-s or C-M-l.
 (defvar rmail-last-multi-labels nil)
+
 (defvar rmail-last-regexp nil)
+(put 'rmail-last-regexp 'permanent-local t)
+
 (defcustom rmail-default-file "~/xmail"
   "*Default file name for \\[rmail-output]."
   :type 'file
@@ -315,6 +322,35 @@ by substituting the new message number into the existing list.")
   :type 'file
   :group 'rmail-files)
 
+;; Mule and MIME related variables.
+
+;;;###autoload
+(defvar rmail-file-coding-system nil
+  "Coding system used in RMAIL file.
+
+This is set to nil by default.")
+
+;;;###autoload
+(defcustom rmail-enable-mime nil
+  "*If non-nil, RMAIL uses MIME feature.
+If the value is t, RMAIL automatically shows MIME decoded message.
+If the value is neither t nor nil, RMAIL does not show MIME decoded message
+until a user explicitly requires it."
+  :type '(choice (const :tag "on" t)
+                (const :tag "off" nil)
+                (sexp :tag "when asked" :format "%t\n" ask))
+  :group 'rmail)
+
+;;;###autoload
+(defvar rmail-show-mime-function nil
+  "Function to show MIME decoded message of RMAIL file.")
+
+;;;###autoload
+(defvar rmail-mime-feature 'rmail-mime
+  "Feature to require to load MIME support in Rmail.
+When starting Rmail, if `rmail-enable-mime' is non-nil,
+this feature is required with `require'.")
+\f
 ;;; 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
@@ -371,6 +407,29 @@ by substituting the new message number into the existing list.")
      "\n"))
   nil)
 
+(defvar rmail-font-lock-keywords
+  (eval-when-compile
+    (let* ((cite-chars "[>|}]")
+          (cite-prefix "A-Za-z")
+          (cite-suffix (concat cite-prefix "0-9_.@-`'\"")))
+      (list '("^\\(From\\|Sender\\):" . font-lock-function-name-face)
+           '("^Reply-To:.*$" . font-lock-function-name-face)
+           '("^Subject:" . font-lock-comment-face)
+           '("^\\(To\\|Apparently-To\\|Cc\\|Newsgroups\\):"
+             . font-lock-keyword-face)
+           ;; Use MATCH-ANCHORED to effectively anchor the regexp left side.
+           `(,cite-chars
+             (,(concat "\\=[ \t]*"
+                       "\\(\\([" cite-prefix "]+[" cite-suffix "]*\\)?"
+                       "\\(" cite-chars "[ \t]*\\)\\)+"
+                       "\\(.*\\)")
+              (beginning-of-line) (end-of-line)
+              (2 font-lock-constant-face nil t)
+              (4 font-lock-comment-face nil t)))
+           '("^\\(X-[A-Za-z0-9-]+\\|In-reply-to\\|Date\\):.*$"
+             . font-lock-string-face))))
+  "Additional expressions to highlight in Rmail mode.")
+
 ;; Perform BODY in the summary buffer
 ;; in such a way that its cursor is properly updated in its own window.
 (defmacro rmail-select-summary (&rest body)
@@ -393,39 +452,6 @@ by substituting the new message number into the existing list.")
           (let ((rmail-total-messages total))
             (,@ body))))
        (rmail-maybe-display-summary))))
-
-(defvar rmail-view-buffer nil
-  "Buffer which holds RMAIL message for MIME displaying.")
-
-;; Mule and MIME related variables.
-
-;;;###autoload
-(defvar rmail-file-coding-system nil
-  "Coding system used in RMAIL file.
-
-This is set to nil by default.")
-
-;;;###autoload
-(defcustom rmail-enable-mime nil
-  "*If non-nil, RMAIL uses MIME feature.
-If the value is t, RMAIL automatically shows MIME decoded message.
-If the value is neither t nor nil, RMAIL does not show MIME decoded message
-until a user explicitly requires it."
-  :type '(choice (const :tag "on" t)
-                (const :tag "off" nil)
-                (sexp :tag "when asked" :format "%t\n" ask))
-  :group 'rmail)
-
-;;;###autoload
-(defvar rmail-show-mime-function nil
-  "Function to show MIME decoded message of RMAIL file.")
-
-;;;###autoload
-(defvar rmail-mime-feature 'rmail-mime
-  "Feature to provide for using MIME feature in RMAIL.
-When starting rmail, this feature is requrired if rmail-enable-mime
-is non-nil.")
-
 \f
 ;;;; *** Rmail Mode ***
 
@@ -468,18 +494,19 @@ If `rmail-display-summary' is non-nil, make a summary for this RMAIL file."
         run-mail-hook msg-shown)
     ;; Like find-file, but in the case where a buffer existed
     ;; and the file was reverted, recompute the message-data.
+    ;; We used to bind enable-local-variables to nil here,
+    ;; but that should not be needed now that rmail-mode
+    ;; sets it locally to nil.
+    ;; (Binding a variable locally with let is not safe if it has
+    ;; buffer-local bindings.)
     (if (and existed (not (verify-visited-file-modtime existed)))
        (progn
-         ;; Don't be confused by apparent local-variables spec
-         ;; in the last message in the RMAIL file.
-         (let ((enable-local-variables nil))
-           (find-file file-name))
+         (find-file file-name)
          (if (and (verify-visited-file-modtime existed)
                   (eq major-mode 'rmail-mode))
              (progn (rmail-forget-messages)
                     (rmail-set-message-counters))))
-      (let ((enable-local-variables nil))
-       (find-file file-name)))
+      (find-file file-name))
     (if (eq major-mode 'rmail-edit-mode)
        (error "Exit Rmail Edit mode before getting new mail"))
     (if (and existed (> (buffer-size) 0))
@@ -529,6 +556,8 @@ If `rmail-display-summary' is non-nil, make a summary for this RMAIL file."
 ; I have checked that adding "-*- rmail -*-" to the BABYL OPTIONS line
 ; will not cause emacs 18.55 problems.
 
+;; This calls rmail-decode-babyl-format if the file is already Babyl.
+
 (defun rmail-convert-file ()
   (let (convert)
     (widen)
@@ -573,11 +602,10 @@ If `rmail-display-summary' is non-nil, make a summary for this RMAIL file."
          ;; We still have to decode BABYL part.
          (rmail-decode-babyl-format)))))
 
-;;; I have checked that adding "-*- rmail -*-" to the BABYL OPTIONS line
-;;; will not cause emacs 18.55 problems.
-
 (defun rmail-insert-rmail-file-header ()
   (let ((buffer-read-only nil))
+    ;; -*-rmail-*- is here so that visiting the file normally
+    ;; recognizes it as an Rmail file.
     (insert "BABYL OPTIONS: -*- rmail -*-
 Version: 5
 Labels:
@@ -591,30 +619,26 @@ Note:    it means the file has no messages in it.\n\^_")))
 (defun rmail-decode-babyl-format ()
   (let ((modifiedp (buffer-modified-p))
        (buffer-read-only nil)
+       (coding-system rmail-file-coding-system)
        from to)
     (goto-char (point-min))
-    (search-forward "\n\^_" nil t)     ; Skip BYBYL header.
+    (search-forward "\n\^_" nil t)     ; Skip BABYL header.
     (setq from (point))
     (goto-char (point-max))
     (search-backward "\n\^_" from 'mv)
     (setq to (point))
-    (if (not (and rmail-file-coding-system
-                 (coding-system-p rmail-file-coding-system)))
-       (setq rmail-file-coding-system (detect-coding-region from to t)))
-    (if (not (eq rmail-file-coding-system 'undecided))
-       (let ((count 1))
-         (goto-char from)
-         (while (search-forward "\n\^_" nil t)
-           (decode-coding-region from (1- (point)) rmail-file-coding-system)
-           (goto-char (point))
-           (setq from (point))
-           (if (= (% count 10) 0)
-               (message "Decoding messages...%d" count))
-           (setq count (1+ count)))
-         (message "Decoding messages...done")
-         (set-buffer-file-coding-system rmail-file-coding-system)
-         (set-buffer-modified-p modifiedp)))))
+    (unless (and coding-system
+                (coding-system-p coding-system))
+      (setq coding-system (detect-coding-region from to t)))
+    (unless (eq coding-system 'undecided)
+      (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)
+    (setq save-buffer-coding-system
+         (or coding-system 'undecided))))
 
+(defvar rmail-mode-map nil)
 (if rmail-mode-map
     nil
   (setq rmail-mode-map (make-keymap))
@@ -830,6 +854,7 @@ Instead, these commands are available:
 \\[rmail-forward]      Forward this message to another user.
 \\[rmail-output-to-rmail-file]       Output this message to an Rmail file (append it).
 \\[rmail-output]       Output this message to a Unix-format mail file (append it).
+\\[rmail-output-body-to-file]  Save message body to a file.  Default filename comes from Subject line.
 \\[rmail-input]        Input Rmail file.  Run Rmail on that file.
 \\[rmail-add-label]    Add label to message.  It will be displayed in the mode line.
 \\[rmail-kill-label]   Kill label.  Remove a label from current message.
@@ -853,6 +878,7 @@ Instead, these commands are available:
 (defun rmail-mode-2 ()
   (kill-all-local-variables)
   (rmail-mode-1)
+  (rmail-perm-variables)
   (rmail-variables))
 
 (defun rmail-mode-1 ()
@@ -870,16 +896,8 @@ Instead, these commands are available:
   (set-syntax-table text-mode-syntax-table)
   (setq local-abbrev-table text-mode-abbrev-table))
 
-(defun rmail-variables ()
-  (make-local-variable 'revert-buffer-function)
-  (setq revert-buffer-function 'rmail-revert)
-  (make-local-variable 'font-lock-defaults)
-  (setq font-lock-defaults
-   '(rmail-font-lock-keywords t nil nil nil
-     (font-lock-maximum-size . nil)
-     (font-lock-fontify-buffer-function . rmail-fontify-buffer-function)
-     (font-lock-unfontify-buffer-function . rmail-unfontify-buffer-function)
-     (font-lock-inhibit-thing-lock . (lazy-lock-mode fast-lock-mode))))
+;; Set up the permanent locals associated with an Rmail file.
+(defun rmail-perm-variables ()
   (make-local-variable 'rmail-last-label)
   (make-local-variable 'rmail-last-regexp)
   (make-local-variable 'rmail-deleted-vector)
@@ -891,16 +909,8 @@ Instead, these commands are available:
   (make-local-variable 'rmail-summary-vector)
   (make-local-variable 'rmail-current-message)
   (make-local-variable 'rmail-total-messages)
-  (make-local-variable 'require-final-newline)
-  (setq require-final-newline nil)
   (make-local-variable 'rmail-overlay-list)
   (setq rmail-overlay-list nil)
-  (make-local-variable 'version-control)
-  (setq version-control 'never)
-  (make-local-variable 'kill-buffer-hook)
-  (add-hook 'kill-buffer-hook 'rmail-mode-kill-summary)
-  (make-local-variable 'file-precious-flag)
-  (setq file-precious-flag t)
   (make-local-variable 'rmail-message-vector)
   (make-local-variable 'rmail-msgref-vector)
   (make-local-variable 'rmail-inbox-list)
@@ -919,6 +929,37 @@ Instead, these commands are available:
   ;; this gets generated as needed
   (setq rmail-keywords nil))
 
+;; Set up the non-permanent locals associated with Rmail mode.
+(defun rmail-variables ()
+  (make-local-variable 'save-buffer-coding-system)
+  ;; If we don't already have a value for save-buffer-coding-system,
+  ;; get it from buffer-file-coding-system, and clear that
+  ;; because it should be determined in rmail-show-message.
+  (unless save-buffer-coding-system
+    (setq save-buffer-coding-system (or buffer-file-coding-system 'undecided))
+    (setq buffer-file-coding-system nil))
+  ;; Don't let a local variables list in a message cause confusion.
+  (make-local-variable 'enable-local-variables)
+  (setq enable-local-variables nil)
+  (make-local-variable 'revert-buffer-function)
+  (setq revert-buffer-function 'rmail-revert)
+  (make-local-variable 'font-lock-defaults)
+  (setq font-lock-defaults
+       '(rmail-font-lock-keywords
+         t nil nil nil
+         (font-lock-maximum-size . nil)
+         (font-lock-fontify-buffer-function . rmail-fontify-buffer-function)
+         (font-lock-unfontify-buffer-function . rmail-unfontify-buffer-function)
+         (font-lock-inhibit-thing-lock . (lazy-lock-mode fast-lock-mode))))
+  (make-local-variable 'require-final-newline)
+  (setq require-final-newline nil)
+  (make-local-variable 'version-control)
+  (setq version-control 'never)
+  (make-local-variable 'kill-buffer-hook)
+  (add-hook 'kill-buffer-hook 'rmail-mode-kill-summary)
+  (make-local-variable 'file-precious-flag)
+  (setq file-precious-flag t))
+
 ;; Handle M-x revert-buffer done in an rmail-mode buffer.
 (defun rmail-revert (arg noconfirm)
   (let ((revert-buffer-function (default-value 'revert-buffer-function)))
@@ -1313,6 +1354,7 @@ It returns t if it got any new messages."
                             (if rmail-preserve-inbox 
                                 (list "-p")
                               nil)
+                            rmail-movemail-flags
                             (list file tofile)
                             (if rmail-pop-password 
                                 (list rmail-pop-password)
@@ -1421,11 +1463,27 @@ Optional DEFAULT is password to start with."
                              (save-excursion
                                (skip-chars-forward " \t\n")
                                (point)))
+              (setq last-coding-system-used nil)
               (or rmail-enable-mime
                   (not rmail-enable-multibyte)
                   (decode-coding-region start (point)
                                         (or rmail-file-coding-system
                                             'undecided)))
+              ;; Add an X-Coding-System: header if we don't have one.
+              (save-excursion
+                (goto-char start)
+                (forward-line 1)
+                (if (looking-at "0")
+                    (forward-line 1)
+                  (forward-line 2))
+                (or (save-restriction
+                      (narrow-to-region (point) (point-max))
+                      (rfc822-goto-eoh)
+                      (goto-char (point-min))
+                      (re-search-forward "^X-Coding-System:" nil t))
+                    (insert "X-Coding-System: "
+                            (symbol-name last-coding-system-used)
+                            "\n")))
               (narrow-to-region (point) (point-max)))
              ;;*** MMDF format
              ((let ((case-fold-search t))
@@ -1440,9 +1498,16 @@ Optional DEFAULT is password to start with."
                   (goto-char (point-min))
                   (while (search-forward "\n\^_" nil t); single char "\^_"
                     (replace-match "\n^_")))); 2 chars: "^" and "_"
+              (setq last-coding-system-used nil)
               (or rmail-enable-mime
                   (not rmail-enable-multibyte)
                   (decode-coding-region start (point) 'undecided))
+              (save-excursion
+                (goto-char start)
+                (forward-line 3)
+                (insert "X-Coding-System: "
+                        (symbol-name last-coding-system-used)
+                        "\n"))
               (narrow-to-region (point) (point-max))
               (setq count (1+ count)))
              ;;*** Mail format
@@ -1516,9 +1581,16 @@ Optional DEFAULT is password to start with."
                   (while (search-forward "\n\^_" nil t); single char
                     (replace-match "\n^_")))); 2 chars: "^" and "_"
               (insert ?\^_)
+              (setq last-coding-system-used nil)
               (or rmail-enable-mime
                   (not rmail-enable-multibyte)
                   (decode-coding-region start (point) 'undecided))
+              (save-excursion
+                (goto-char start)
+                (forward-line 3)
+                (insert "X-Coding-System: "
+                        (symbol-name last-coding-system-used)
+                        "\n"))
               (narrow-to-region (point) (point-max)))
              ;;
              ;; This kludge is because some versions of sendmail.el
@@ -1694,6 +1766,9 @@ Otherwise, delete all header fields whose names match `rmail-ignored-headers'."
   (save-restriction
     (save-excursion
   (narrow-to-region (rmail-msgbeg rmail-current-message) (point-max))
+                 (if (not (or (= ?\n (char-after (point)))
+                              (= ?\n (char-before (1- (point))))))
+                     (insert "\n"))
     (goto-char (point-min))
     (forward-line 1)
       (= (following-char) ?1))))
@@ -1983,7 +2058,7 @@ If summary buffer is currently displayed, update current message there also."
       (progn (narrow-to-region (point-min) (1- (point-max)))
             (goto-char (point-min))
             (setq mode-line-process nil))
-    (let (blurb)
+    (let (blurb coding-system)
       (if (not n)
          (setq n rmail-current-message)
        (cond ((<= n 0)
@@ -1999,10 +2074,25 @@ If summary buffer is currently displayed, update current message there also."
       (let ((beg (rmail-msgbeg n)))
        (goto-char beg)
        (forward-line 1)
+       (save-excursion
+         (let ((end (rmail-msgend n)))
+           (save-restriction
+             (if (prog1 (= (following-char) ?0)
+                   (forward-line 2)
+                   (narrow-to-region (point) end))
+                 (rfc822-goto-eoh)
+               (search-forward "\n*** EOOH ***\n" end t))
+             (narrow-to-region beg (point))
+             (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))
+               (setq buffer-file-coding-system nil)))))
        ;; Clear the "unseen" attribute when we show a message.
        (rmail-set-attribute "unseen" nil)
-       ;; Reformat the header, or else find the reformatted header.
        (let ((end (rmail-msgend n)))
+         ;; Reformat the header, or else find the reformatted header.
          (if (= (following-char) ?0)
              (rmail-reformat-message beg end)
            (search-forward "\n*** EOOH ***\n" end t)
@@ -2154,11 +2244,20 @@ or forward if N is negative."
 
 (defun rmail-message-regexp-p (msg regexp)
   "Return t, if for message number MSG, regexp REGEXP matches in the header."
-  (goto-char (rmail-msgbeg msg))
-  (let ((end 
-         (save-excursion 
-           (search-forward "*** EOOH ***" (point-max)) (point))))
-    (re-search-forward regexp end t)))
+  (save-excursion
+    (goto-char (rmail-msgbeg msg))
+    (let (beg end)
+      (save-excursion
+       (forward-line 2)
+       (setq beg (point)))
+      (save-excursion 
+       (search-forward "\n*** EOOH ***\n" (point-max))
+       (when (= beg (match-beginning 0))
+         (setq beg (point))
+         (search-forward "\n\n" (point-max)))
+       (setq end (point)))
+      (goto-char beg)
+      (re-search-forward regexp end t))))
 
 (defvar rmail-search-last-regexp nil)
 (defun rmail-search (regexp &optional n)
@@ -2701,10 +2800,7 @@ see the documentation of `rmail-resend'."
          ;; The mail buffer is now current.
          (save-excursion
            ;; Insert after header separator--before signature if any.
-           (goto-char (point-min))
-           (search-forward-regexp
-            (concat "^" (regexp-quote mail-header-separator) "$"))
-           (forward-line 1)
+           (goto-char (mail-text-start))
            (insert "------- Start of forwarded message -------\n")
            ;; Quote lines with `- ' if they start with `-'.
            (let ((beg (point)) end)
@@ -2740,7 +2836,6 @@ typically for purposes of moderating a list."
   (require 'mailalias)
   (if (not from) (setq from user-mail-address))
   (let ((tembuf (generate-new-buffer " sendmail temp"))
-       (mail-header-separator "")
        (case-fold-search nil)
        (mailbuf (current-buffer)))
     (unwind-protect
@@ -2813,6 +2908,7 @@ typically for purposes of moderating a list."
 (defvar mail-unsent-separator
   (concat "^ *---+ +Unsent message follows +---+ *$\\|"
          "^ *---+ +Returned message +---+ *$\\|"
+         "^ *---+ *Returned mail follows *---+ *$\\|"
          "^Start of returned message$\\|"
          "^ *---+ +Original message +---+ *$\\|"
          "^ *--+ +begin message +--+ *$\\|"
@@ -2922,17 +3018,15 @@ specifying headers which should not be copied into the new message."
                (indent-rigidly (point-min) (point-max) bounce-indent))
            (rmail-clear-headers rmail-retry-ignored-headers)
            (rmail-clear-headers "^sender:\\|^from:\\|^return-path:")
-           (goto-char (point-min))
+           (mail-sendmail-delimit-header)
            (save-restriction
-             (search-forward "\n\n")
-             (forward-line -1)
-             (narrow-to-region (point-min) (point))
+             (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"))))
-           (insert mail-header-separator)
+           (goto-char (point-min))
            (mail-position-on-field (if resending "Resent-To" "To") t)
            (set-buffer rmail-this-buffer)
            (rmail-beginning-of-message))))))