(message-signed-or-encrypted-p): New function.
[gnus] / lisp / message.el
index fe43782..611935c 100644 (file)
@@ -187,14 +187,13 @@ To disable checking of long signatures, for instance, add
 
 Don't touch this variable unless you really know what you're doing.
 
-Checks include `subject-cmsg', `multiple-headers', `sendsys',
-`message-id', `from', `long-lines', `control-chars', `size',
-`new-text', `quoting-style', `redirected-followup', `signature',
-`approved', `sender', `empty', `empty-headers', `message-id', `from',
-`subject', `shorten-followup-to', `existing-newsgroups',
-`buffer-file-name', `unchanged', `newsgroups', `reply-to',
-`continuation-headers', `long-header-lines', `invisible-text' and
-`illegible-text'."
+Checks include `approved', `continuation-headers', `control-chars',
+`empty', `existing-newsgroups', `from', `illegible-text',
+`invisible-text', `long-header-lines', `long-lines', `message-id',
+`multiple-headers', `new-text', `newsgroups', `quoting-style',
+`repeated-newsgroups', `reply-to', `sender', `sendsys', `shoot',
+`shorten-followup-to', `signature', `size', `subject', `subject-cmsg'
+and `valid-newsgroups'."
   :group 'message-news
   :type '(repeat sexp))                        ; Fixme: improve this
 
@@ -209,7 +208,7 @@ Also see `message-required-news-headers' and
   :link '(custom-manual "(message)Message Headers")
   :type '(repeat sexp))
 
-(defcustom message-draft-headers '(References From)
+(defcustom message-draft-headers '(References From Date)
   "*Headers to be generated when saving a draft message."
   :version "22.1"
   :group 'message-news
@@ -762,6 +761,14 @@ If this is nil, use `user-mail-address'.  If it is the symbol
   :link '(custom-manual "(message)Mail Variables")
   :group 'message-sending)
 
+(defcustom message-sendmail-extra-arguments nil
+  "Additional arguments to `sendmail-program'."
+  ;; E.g. '("-a" "account") for msmtp
+  :version "23.0" ;; No Gnus
+  :type '(repeat string)
+  ;; :link '(custom-manual "(message)Mail Variables")
+  :group 'message-sending)
+
 ;; qmail-related stuff
 (defcustom message-qmail-inject-program "/var/qmail/bin/qmail-inject"
   "Location of the qmail-inject program."
@@ -885,7 +892,7 @@ configuration.  See the variable `gnus-cite-attribution-suffix'."
   :link '(custom-manual "(message)Insertion Variables")
   :group 'message-insertion)
 
-(defcustom message-citation-line-format "On %a, %b %d %Y, %n wrote:"
+(defcustom message-citation-line-format "On %a, %b %d %Y, %N wrote:"
   "Format of the \"Whomever writes:\" line.
 
 The string is formatted using `format-spec'.  The following
@@ -1149,13 +1156,28 @@ If nil, you might be asked to input the charset."
 
 (defcustom message-dont-reply-to-names
   (and (boundp 'rmail-dont-reply-to-names) rmail-dont-reply-to-names)
-  "*A regexp specifying addresses to prune when doing wide replies.
-A value of nil means exclude your own user name only."
+  "*Addresses to prune when doing wide replies.
+This can be a regexp or a list of regexps. Also, a value of nil means
+exclude your own user name only."
   :version "21.1"
   :group 'message
   :link '(custom-manual "(message)Wide Reply")
   :type '(choice (const :tag "Yourself" nil)
-                regexp))
+                regexp
+                (repeat :tag "Regexp List" regexp)))
+
+;; #### FIXME: this might become a generally usefull function at some point
+;; --dlv.
+(defsubst message-dont-reply-to-names ()
+  "Potentially convert a list of regexps into a single one."
+  (cond ((null message-dont-reply-to-names)
+        nil)
+       ((stringp message-dont-reply-to-names)
+        message-dont-reply-to-names)
+       ((listp message-dont-reply-to-names)
+        (mapconcat (lambda (elt) (concat "\\(" elt "\\)"))
+                   message-dont-reply-to-names
+                   "\\|"))))
 
 (defvar message-shoot-gnksa-feet nil
   "*A list of GNKSA feet you are allowed to shoot.
@@ -1557,10 +1579,16 @@ functionality to work."
 
 (defcustom message-generate-hashcash (if (executable-find "hashcash") t)
   "*Whether to generate X-Hashcash: headers.
+If `t', always generate hashcash headers.  If `opportunistic',
+only generate hashcash headers if it can be done without the user
+waiting (i.e., only asynchronously).
+
 You must have the \"hashcash\" binary installed, see `hashcash-path'."
   :group 'message-headers
   :link '(custom-manual "(message)Mail Headers")
-  :type 'boolean)
+  :type '(choice (const :tag "Always" t)
+                (const :tag "Never" nil)
+                (const :tag "Opportunistic" 'opportunistic)))
 
 ;;; Internal variables.
 
@@ -1884,6 +1912,96 @@ see `message-narrow-to-headers-or-head'."
       (substring subject (match-end 0))
     subject))
 
+(defcustom message-replacement-char "."
+  "Replacement character used instead of unprintable or not decodable chars."
+  :group 'message-various
+  :version "22.1" ;; Gnus 5.10.9
+  :type '(choice string
+                (const ".")
+                (const "?")))
+
+;; FIXME: We also should call `message-strip-subject-encoded-words'
+;; when forwarding.  Probably in `message-make-forward-subject' and
+;; `message-forward-make-body'.
+
+(defun message-strip-subject-encoded-words (subject)
+  "Fix non-decodable words in SUBJECT."
+  ;; Cf. `gnus-simplify-subject-fully'.
+  (let* ((case-fold-search t)
+        (replacement-chars (format "[%s%s%s]"
+                                   message-replacement-char
+                                   message-replacement-char
+                                   message-replacement-char))
+        (enc-word-re "=\\?\\([^?]+\\)\\?\\([QB]\\)\\?\\([^?]+\\)\\(\\?=\\)")
+        cs-string
+        (have-marker
+         (with-temp-buffer
+           (insert subject)
+           (goto-char (point-min))
+           (when (re-search-forward enc-word-re nil t)
+             (setq cs-string (match-string 1)))))
+        cs-coding q-or-b word-beg word-end)
+    (if (or (not have-marker) ;; No encoded word found...
+           ;; ... or double encoding was correct:
+           (and (stringp cs-string)
+                (setq cs-string (downcase cs-string))
+                (mm-coding-system-p (intern cs-string))
+                (not (prog1
+                         (y-or-n-p
+                          (format "\
+Decoded Subject \"%s\"
+contains a valid encoded word.  Decode again? "
+                                  subject))
+                       (setq cs-coding (intern cs-string))))))
+       subject
+      (with-temp-buffer
+       (insert subject)
+       (goto-char (point-min))
+       (while (re-search-forward enc-word-re nil t)
+         (setq cs-string (downcase (match-string 1))
+               q-or-b    (match-string 2)
+               word-beg (match-beginning 0)
+               word-end (match-end 0))
+         (setq cs-coding
+               (if (mm-coding-system-p (intern cs-string))
+                   (setq cs-coding (intern cs-string))
+                 nil))
+         ;; No double encoded subject? => bogus charset.
+         (unless cs-coding
+           (setq cs-coding
+                 (mm-read-coding-system
+                  (format "\
+Decoded Subject \"%s\"
+contains an encoded word.  The charset `%s' is unknown or invalid.
+Hit RET to replace non-decodable characters with \"%s\" or enter replacement
+charset: "
+                          subject cs-string message-replacement-char)))
+           (if cs-coding
+               (replace-match (concat "=?" (symbol-name cs-coding)
+                                      "?\\2?\\3\\4\\5"))
+             (save-excursion
+               (goto-char word-beg)
+               (re-search-forward "=\\?\\([^?]+\\)\\?\\([QB]\\)\\?" word-end t)
+               (replace-match "")
+               ;; QP or base64
+               (if (string-match "\\`Q\\'" q-or-b)
+                   ;; QP
+                   (progn
+                     (message "Replacing non-decodable characters with \"%s\"."
+                              message-replacement-char)
+                     (while (re-search-forward "\\(=[A-F0-9][A-F0-9]\\)+"
+                                               word-end t)
+                       (replace-match message-replacement-char)))
+                 ;; base64
+                 (message "Replacing non-decodable characters with \"%s\"."
+                          replacement-chars)
+                 (re-search-forward "[^?]+" word-end t)
+                 (replace-match replacement-chars))
+               (re-search-forward "\\?=")
+               (replace-match "")))))
+       (rfc2047-decode-region (point-min) (point-max))
+       (buffer-string)))))
+
 ;;; Start of functions adopted from `message-utils.el'.
 
 (defun message-strip-subject-trailing-was (subject)
@@ -3243,17 +3361,17 @@ text was killed."
      (substring table ?a (+ ?a n))
      (substring table (+ ?a 26) 255))))
 
-(defun message-caesar-buffer-body (&optional rotnum)
+(defun message-caesar-buffer-body (&optional rotnum wide)
   "Caesar rotate all letters in the current buffer by 13 places.
 Used to encode/decode possibly offensive messages (commonly in rec.humor).
 With prefix arg, specifies the number of places to rotate each letter forward.
-Mail and USENET news headers are not rotated."
+Mail and USENET news headers are not rotated unless WIDE is non-nil."
   (interactive (if current-prefix-arg
                   (list (prefix-numeric-value current-prefix-arg))
                 (list nil)))
   (save-excursion
     (save-restriction
-      (when (message-goto-body)
+      (when (and (not wide) (message-goto-body))
        (narrow-to-region (point) (point-max)))
       (message-caesar-region (point-min) (point-max) rotnum))))
 
@@ -3352,6 +3470,17 @@ However, if `message-yank-prefix' is non-nil, insert that prefix on each line."
        (forward-line 1))))
   (goto-char start))
 
+(defvar message-cite-reply-above nil
+  "If non-nil, start own text above the quote.
+
+Note: Top posting is bad netiquette.  Don't use it unless you
+really must.  You probably want to set variable only for specific
+groups, e.g. using `gnus-posting-styles':
+
+  (eval (set (make-local-variable 'message-cite-reply-above) t))
+
+This variable has no effect in news postings.")
+
 (defun message-yank-original (&optional arg)
   "Insert the message being replied to, if any.
 Puts point before the text and mark after.
@@ -3363,16 +3492,36 @@ This function uses `message-cite-function' to do the actual citing.
 Just \\[universal-argument] as argument means don't indent, insert no
 prefix, and don't delete any headers."
   (interactive "P")
-  (let ((modified (buffer-modified-p)))
+  (let ((modified (buffer-modified-p))
+       body-text)
     (when (and message-reply-buffer
               message-cite-function)
+      (when message-cite-reply-above
+       (if (and (not (message-news-p))
+                (or (eq message-cite-reply-above 'is-evil)
+                    (y-or-n-p "\
+Top posting is bad netiquette.  Please don't top post unless you really must.
+Really top post? ")))
+           (save-excursion
+             (setq body-text
+                   (buffer-substring (message-goto-body)
+                                     (point-max)))
+             (delete-region (message-goto-body) (point-max)))
+         (set (make-local-variable 'message-cite-reply-above) nil)))
       (delete-windows-on message-reply-buffer t)
       (push-mark (save-excursion
                   (insert-buffer-substring message-reply-buffer)
                   (point)))
       (unless arg
        (funcall message-cite-function))
-      (message-exchange-point-and-mark)
+      (if message-cite-reply-above
+         (progn
+           (message-goto-body)
+           (insert body-text)
+           (newline)
+           (message-goto-body)
+           (message-exchange-point-and-mark))
+       (message-exchange-point-and-mark))
       (unless (bolp)
        (insert ?\n))
       (unless modified
@@ -3425,7 +3574,7 @@ This function uses `mail-citation-hook' if that is non-nil."
              (setq x-no-archive (message-fetch-field "x-no-archive"))
              (vector 0
                      (or (message-fetch-field "subject") "none")
-                     (message-fetch-field "from")
+                     (or (message-fetch-field "from") "nobody")
                      (message-fetch-field "date")
                      (message-fetch-field "message-id" t)
                      (message-fetch-field "references")
@@ -3457,6 +3606,7 @@ This function uses `mail-citation-hook' if that is non-nil."
        (undo-boundary)
        (delete-region (point) (mark t))
        (insert "> [Quoted text removed due to X-No-Archive]\n")
+       (push-mark)
        (forward-line -1)))))
 
 (defun message-cite-original ()
@@ -3494,7 +3644,7 @@ See `message-citation-line-format'."
             date
             ;; We need Gnus functionality if the user wants date or time from
             ;; the original article:
-            (when (string-match "%[^EFLn]" message-citation-line-format)
+            (when (string-match "%[^fnNFL]" message-citation-line-format)
               (autoload 'gnus-date-get-time "gnus-util")
               (gnus-date-get-time (mail-header-date message-reply-headers)))))
           (flist
@@ -3514,19 +3664,19 @@ See `message-citation-line-format'."
                       (setq fname name
                             lname ""))))
              ;; The following letters are not used in `format-time-string':
-             (push ?E lst) (push net lst)
+             (push ?E lst) (push "<E>" lst)
              (push ?F lst) (push fname lst)
              ;; We might want to use "" instead of "<X>" later.
              (push ?J lst) (push "<J>" lst)
              (push ?K lst) (push "<K>" lst)
              (push ?L lst) (push lname lst)
-             (push ?N lst) (push "<N>" lst)
+             (push ?N lst) (push name-or-net lst)
              (push ?O lst) (push "<O>" lst)
              (push ?P lst) (push "<P>" lst)
              (push ?Q lst) (push "<Q>" lst)
-             (push ?f lst) (push "<f>" lst)
+             (push ?f lst) (push from lst)
              (push ?i lst) (push "<i>" lst)
-             (push ?n lst) (push name-or-net lst)
+             (push ?n lst) (push net lst)
              (push ?o lst) (push "<o>" lst)
              (push ?q lst) (push "<q>" lst)
              (push ?t lst) (push "<t>" lst)
@@ -3845,8 +3995,10 @@ not have PROP."
        (setq choice
              (gnus-multiple-choice
               "Non-printable characters found.  Continue sending?"
-              '((?d "Remove non-printable characters and send")
-                (?r "Replace non-printable characters with dots and send")
+              `((?d "Remove non-printable characters and send")
+                (?r ,(format
+                      "Replace non-printable characters with \"%s\" and send"
+                      message-replacement-char))
                 (?i "Ignore non-printable characters and send")
                 (?e "Continue editing"))))
        (if (eq choice ?e)
@@ -3869,7 +4021,7 @@ not have PROP."
                (message-kill-all-overlays)
              (delete-char 1)
              (when (eq choice ?r)
-               (insert "."))))
+               (insert message-replacement-char))))
          (forward-char)
          (skip-chars-forward mm-7bit-chars))))))
 
@@ -3982,7 +4134,8 @@ not have PROP."
              (gnus-setup-posting-charset nil)
            message-posting-charset))
         (headers message-required-mail-headers))
-    (when message-generate-hashcash
+    (when (and message-generate-hashcash
+              (not (eq message-generate-hashcash 'opportunistic)))
       (message "Generating hashcash...")
       ;; Wait for calculations already started to finish...
       (hashcash-wait-async)
@@ -4006,6 +4159,16 @@ not have PROP."
       (let ((message-deletable-headers
             (if news nil message-deletable-headers)))
        (message-generate-headers headers))
+      ;; Check continuation headers.
+      (message-check 'continuation-headers
+       (goto-char (point-min))
+       (while (re-search-forward "^[^ \t\n][^ \t\n:]*[ \t\n]" nil t)
+         (goto-char (match-beginning 0))
+         (if (y-or-n-p "Fix continuation lines? ")
+             (insert " ")
+           (forward-line 1)
+           (unless (y-or-n-p "Send anyway? ")
+             (error "Failed to send the message")))))
       ;; Let the user do all of the above.
       (run-hooks 'message-header-hook))
     (unwind-protect
@@ -4124,10 +4287,17 @@ If you always want Gnus to send messages in one piece, set
                       'call-process-region
                       (append
                        (list (point-min) (point-max)
-                             (if (boundp 'sendmail-program)
-                                 sendmail-program
-                               "/usr/lib/sendmail")
+                             (cond ((boundp 'sendmail-program)
+                                    sendmail-program)
+                                   ((file-exists-p "/usr/sbin/sendmail")
+                                    "/usr/sbin/sendmail")
+                                   ((file-exists-p "/usr/lib/sendmail")
+                                    "/usr/lib/sendmail")
+                                   ((file-exists-p "/usr/ucblib/sendmail")
+                                    "/usr/ucblib/sendmail")
+                                   (t "fakemail"))
                              nil errbuf nil "-oi")
+                       message-sendmail-extra-arguments
                        ;; Always specify who from,
                        ;; since some systems have broken sendmails.
                        ;; But some systems are more broken with -f, so
@@ -4562,11 +4732,11 @@ Otherwise, generate and save a value for `canlock-password' first."
    (message-check 'continuation-headers
      (goto-char (point-min))
      (let ((do-posting t))
-       (while (re-search-forward "^[^ \t\n][^:\n]*$" nil t)
+       (while (re-search-forward "^[^ \t\n][^ \t\n:]*[ \t\n]" nil t)
+        (goto-char (match-beginning 0))
         (if (y-or-n-p "Fix continuation lines? ")
-            (progn
-              (goto-char (match-beginning 0))
-              (insert " "))
+            (insert " ")
+          (forward-line 1)
           (unless (y-or-n-p "Send anyway? ")
             (setq do-posting nil))))
        do-posting))
@@ -5753,7 +5923,7 @@ between beginning of field and beginning of line."
 
 (defun message-headers-to-generate (headers included-headers excluded-headers)
   "Return a list that includes all headers from HEADERS.
-If INCLUDED-HEADERS is a list, just include those headers.  If if is
+If INCLUDED-HEADERS is a list, just include those headers.  If it is
 t, include all headers.  In any case, headers from EXCLUDED-HEADERS
 are not included."
   (let ((result nil)
@@ -6013,7 +6183,7 @@ want to get rid of this query permanently.")))
       (while (string-match "[ \t][ \t]+" recipients)
        (setq recipients (replace-match " " t t recipients)))
       ;; Remove addresses that match `rmail-dont-reply-to-names'.
-      (let ((rmail-dont-reply-to-names message-dont-reply-to-names))
+      (let ((rmail-dont-reply-to-names (message-dont-reply-to-names)))
        (setq recipients (rmail-dont-reply-to recipients)))
       ;; Perhaps "Mail-Copies-To: never" removed the only address?
       (if (string-equal recipients "")
@@ -6059,6 +6229,39 @@ want to get rid of this query permanently.")))
        (push (cons 'Cc recipients) follow-to)))
     follow-to))
 
+(defcustom message-simplify-subject-functions
+  '(message-strip-list-identifiers
+    message-strip-subject-re
+    message-strip-subject-trailing-was
+    message-strip-subject-encoded-words)
+  "List of functions taking a string argument that simplify subjects.
+The functions are applied when replying to a message.
+
+Useful functions to put in this list include:
+`message-strip-list-identifiers', `message-strip-subject-re',
+`message-strip-subject-trailing-was', and
+`message-strip-subject-encoded-words'."
+  :version "22.1" ;; Gnus 5.10.9
+  :group 'message-various
+  :type '(repeat function))
+
+(defun message-simplify-subject (subject &optional functions)
+  "Return simplified SUBJECT."
+  (unless functions
+    ;; Simplify fully:
+    (setq functions message-simplify-subject-functions))
+  (when (and (memq 'message-strip-list-identifiers functions)
+            gnus-list-identifiers)
+    (setq subject (message-strip-list-identifiers subject)))
+  (when (memq 'message-strip-subject-re functions)
+    (setq subject (concat "Re: " (message-strip-subject-re subject))))
+  (when (and (memq 'message-strip-subject-trailing-was functions)
+            message-subject-trailing-was-query)
+    (setq subject (message-strip-subject-trailing-was subject)))
+  (when (memq 'message-strip-subject-encoded-words functions)
+    (setq subject (message-strip-subject-encoded-words subject)))
+  subject)
+
 ;;;###autoload
 (defun message-reply (&optional to-address wide)
   "Start editing a reply to the article in the current buffer."
@@ -6086,13 +6289,11 @@ want to get rid of this query permanently.")))
       (setq message-id (message-fetch-field "message-id" t)
            references (message-fetch-field "references")
            date (message-fetch-field "date")
-           from (message-fetch-field "from")
+           from (or (message-fetch-field "from") "nobody")
            subject (or (message-fetch-field "subject") "none"))
-      (when gnus-list-identifiers
-       (setq subject (message-strip-list-identifiers subject)))
-      (setq subject (concat "Re: " (message-strip-subject-re subject)))
-      (when message-subject-trailing-was-query
-       (setq subject (message-strip-subject-trailing-was subject)))
+
+      ;; Strip list identifiers, "Re: ", and "was:"
+      (setq subject (message-simplify-subject subject))
 
       (when (and (setq gnus-warning (message-fetch-field "gnus-warning"))
                 (string-match "<[^>]+>" gnus-warning))
@@ -6162,11 +6363,8 @@ If TO-NEWSGROUPS, use that as the new Newsgroups line."
                 (let ((case-fold-search t))
                   (string-match "world" distribution)))
        (setq distribution nil))
-      (if gnus-list-identifiers
-         (setq subject (message-strip-list-identifiers subject)))
-      (setq subject (concat "Re: " (message-strip-subject-re subject)))
-      (when message-subject-trailing-was-query
-       (setq subject (message-strip-subject-trailing-was subject)))
+      ;; Strip list identifiers, "Re: ", and "was:"
+      (setq subject (message-simplify-subject subject))
       (widen))
 
     (message-pop-to-buffer (message-buffer-name "followup" from newsgroups))
@@ -6604,6 +6802,58 @@ Optional DIGEST will use digest to forward."
       (message-forward-make-body-digest-mime forward-buffer)
     (message-forward-make-body-digest-plain forward-buffer)))
 
+(eval-and-compile
+  (autoload 'mm-uu-dissect-text-parts "mm-uu")
+  (autoload 'mm-uu-dissect "mm-uu"))
+
+(defun message-signed-or-encrypted-p (&optional dont-emulate-mime handles)
+  "Say whether the current buffer contains signed or encrypted message.
+If DONT-EMULATE-MIME is nil, this function does the MIME emulation on
+messages that don't conform to PGP/MIME described in RFC2015.  HANDLES
+is for the internal use."
+  (unless handles
+    (if (setq handles (mm-dissect-buffer nil t))
+       (unless dont-emulate-mime
+         (mm-uu-dissect-text-parts handles))
+      (unless dont-emulate-mime
+       (setq handles (mm-uu-dissect)))))
+  ;; Check text/plain message in which there is a signed or encrypted
+  ;; body that has been encoded by B or Q.
+  (unless (or handles dont-emulate-mime)
+    (let ((cur (current-buffer)))
+      (with-temp-buffer
+       (insert-buffer-substring cur)
+       (when (setq handles (mm-dissect-buffer t t))
+         (if (and (prog1
+                      (bufferp (car handles))
+                    (mm-destroy-parts handles))
+                  (equal (mm-handle-media-type handles) "text/plain"))
+             (progn
+               (mm-decode-content-transfer-encoding
+                (mm-handle-encoding handles))
+               (setq handles (mm-uu-dissect)))
+           (setq handles nil))))))
+  (when handles
+    (prog1
+       (catch 'found
+         (dolist (handle (if (stringp (car handles))
+                             (if (member (car handles)
+                                         '("multipart/signed"
+                                           "multipart/encrypted"))
+                                 (throw 'found t)
+                               (cdr handles))
+                           (list handles)))
+           (if (stringp (car handle))
+               (when (message-signed-or-encrypted-p dont-emulate-mime handle)
+                 (throw 'found t))
+             (when (and (bufferp (car handle))
+                        (equal (mm-handle-media-type handle)
+                               "message/rfc822"))
+               (with-current-buffer (mm-handle-buffer handle)
+                 (when (message-signed-or-encrypted-p dont-emulate-mime)
+                   (throw 'found t)))))))
+      (mm-destroy-parts handles))))
+
 ;;;###autoload
 (defun message-forward-make-body (forward-buffer &optional digest)
   ;; Put point where we want it before inserting the forwarded
@@ -6616,11 +6866,13 @@ Optional DIGEST will use digest to forward."
     (if message-forward-as-mime
        (if (and message-forward-show-mml
                 (not (and (eq message-forward-show-mml 'best)
+                          ;; Use the raw form in the body if it contains
+                          ;; signed or encrypted message so as not to be
+                          ;; destroyed by re-encoding.
                           (with-current-buffer forward-buffer
-                            (goto-char (point-min))
-                            (re-search-forward
-                             "Content-Type: *multipart/\\(signed\\|encrypted\\)"
-                             nil t)))))
+                            (condition-case nil
+                                (message-signed-or-encrypted-p)
+                              (error t))))))
            (message-forward-make-body-mml forward-buffer)
          (message-forward-make-body-mime forward-buffer))
       (message-forward-make-body-plain forward-buffer)))