Synch with Oort Gnus (Translating gnus-ja.texi is incompleted).
[elisp/gnus.git-] / lisp / gnus-msg.el
index b6a61c8..ad0fef6 100644 (file)
@@ -1,5 +1,6 @@
 ;;; gnus-msg.el --- mail and post interface for Semi-gnus
-;; Copyright (C) 1995,96,97,98,99 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001
+;;        Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
 (defcustom gnus-post-method 'current
   "*Preferred method for posting USENET news.
 
-If this variable is `current', Gnus will use the \"current\" select
-method when posting.  If it is nil (which is the default), Gnus will
+If this variable is `current' (which is the default), Gnus will use
+the \"current\" select method when posting.  If it is nil, Gnus will
 use the native select method when posting.
 
 This method will not be used in mail groups and the like, only in
 \"real\" newsgroups.
 
 If not nil nor `native', the value must be a valid method as discussed
-in the documentation of `gnus-select-method'. It can also be a list of
-methods. If that is the case, the user will be queried for what select
+in the documentation of `gnus-select-method'.  It can also be a list of
+methods.  If that is the case, the user will be queried for what select
 method to use when posting."
   :group 'gnus-group-foreign
   :type `(choice (const nil)
-                 (const current)
+                (const current)
                 (const native)
                 (sexp :tag "Methods" ,gnus-select-method)))
 
-(defvar gnus-outgoing-message-group nil
+(defcustom gnus-outgoing-message-group nil
   "*All outgoing messages will be put in this group.
 If you want to store all your outgoing mail and articles in the group
 \"nnml:archive\", you set this variable to that value.  This variable
@@ -67,18 +68,25 @@ can also be a list of group names.
 If you want to have greater control over what group to put each
 message in, you can set this variable to a function that checks the
 current newsgroup name and then returns a suitable group name (or list
-of names).")
+of names)."
+  :group 'gnus-message
+  :type '(choice (string :tag "Group")
+                 (function)))
 
-(defvar gnus-mailing-list-groups nil
+(defcustom gnus-mailing-list-groups nil
   "*Regexp matching groups that are really mailing lists.
 This is useful when you're reading a mailing list that has been
 gatewayed to a newsgroup, and you want to followup to an article in
-the group.")
+the group."
+  :group 'gnus-message
+  :type 'regexp)
 
-(defvar gnus-add-to-list nil
-  "*If non-nil, add a `to-list' parameter automatically.")
+(defcustom gnus-add-to-list nil
+  "*If non-nil, add a `to-list' parameter automatically."
+  :group 'gnus-message
+  :type 'boolean)
 
-(defvar gnus-crosspost-complaint
+(defcustom gnus-crosspost-complaint
   "Hi,
 
 You posted the article below with the following Newsgroups header:
@@ -94,26 +102,77 @@ Thank you.
 "
   "Format string to be inserted when complaining about crossposts.
 The first %s will be replaced by the Newsgroups header;
-the second with the current group name.")
-
-(defvar gnus-message-setup-hook '(gnus-maybe-setup-default-charset)
-  "Hook run after setting up a message buffer.")
-
-(defvar gnus-bug-create-help-buffer t
-  "*Should we create the *Gnus Help Bug* buffer?")
-
-(defvar gnus-posting-styles nil
-  "*Alist of styles to use when posting.")
+the second with the current group name."
+  :group 'gnus-message
+  :type 'string)
+
+(defcustom gnus-message-setup-hook '(gnus-maybe-setup-default-charset)
+  "Hook run after setting up a message buffer."
+  :group 'gnus-message
+  :type 'hook)
+
+(defcustom gnus-bug-create-help-buffer t
+  "*Should we create the *Gnus Help Bug* buffer?"
+  :group 'gnus-message
+  :type 'boolean)
+
+(defcustom gnus-posting-styles nil
+  "*Alist of styles to use when posting."
+  :group 'gnus-message
+  :type '(repeat (cons (choice (regexp)
+                              (function)
+                              (variable)
+                              (sexp))
+                      (repeat (list
+                               (choice (const signature)
+                                       (const signature-file)
+                                       (const organization)
+                                       (const address)
+                                       (const name)
+                                       (const body)
+                                       (string :tag "Header"))
+                               (choice (string)
+                                       (function)
+                                       (variable)
+                                       (sexp)))))))
+
+(defcustom gnus-inews-mark-gcc-as-read nil
+  "If non-nil, automatically mark Gcc articles as read."
+  :group 'gnus-message
+  :type 'boolean)
 
 (defcustom gnus-group-posting-charset-alist
-  '(("^no\\." iso-8859-1)
-    (message-this-is-mail nil)
-    ("^de\\." nil)
-    (".*" iso-8859-1)
-    (message-this-is-news iso-8859-1))
-  "Alist of regexps (to match group names) and default charsets to be unencoded when posting."
-  :type '(repeat (list (regexp :tag "Group")
-                      (symbol :tag "Charset")))
+  '(("^\\(no\\|fr\\)\\.[^,]*\\(,[ \t\n]*\\(no\\|fr\\)\\.[^,]*\\)*$" iso-8859-1 (iso-8859-1))
+    ("^\\(fido7\\|relcom\\)\\.[^,]*\\(,[ \t\n]*\\(fido7\\|relcom\\)\\.[^,]*\\)*$" koi8-r (koi8-r))
+    (message-this-is-mail nil nil)
+    (message-this-is-news nil t))
+  "Alist of regexps and permitted unencoded charsets for posting.
+Each element of the alist has the form (TEST HEADER BODY-LIST), where
+TEST is either a regular expression matching the newsgroup header or a
+variable to query,
+HEADER is the charset which may be left unencoded in the header (nil
+means encode all charsets),
+BODY-LIST is a list of charsets which may be encoded using 8bit
+content-transfer encoding in the body, or one of the special values
+nil (always encode using quoted-printable) or t (always use 8bit).
+
+Note that any value other than nil for HEADER infringes some RFCs, so
+use this option with care."
+  :type '(repeat (list :tag "Permitted unencoded charsets"
+                      (choice :tag "Where"
+                              (regexp :tag "Group")
+                              (const :tag "Mail message"
+                                     :value message-this-is-mail)
+                              (const :tag "News article"
+                                     :value message-this-is-news))
+                      (choice :tag "Header"
+                              (const :tag "None" nil)
+                              (symbol :tag "Charset"))
+                      (choice :tag "Body"
+                              (const :tag "Any" :value t)
+                              (const :tag "None" :value nil)
+                              (repeat :tag "Charsets"
+                                      (symbol :tag "Charset")))))
   :group 'gnus-charset)
 
 ;;; Internal variables.
@@ -123,9 +182,12 @@ the second with the current group name.")
 
 (defvar gnus-message-buffer "*Mail Gnus*")
 (defvar gnus-article-copy nil)
+(defvar gnus-check-before-posting nil)
 (defvar gnus-last-posting-server nil)
 (defvar gnus-message-group-art nil)
 
+(defvar gnus-msg-force-broken-reply-to nil)
+
 (defconst gnus-bug-message
   (format "Sending a bug report to the Gnus Towers.
 ========================================
@@ -180,15 +242,19 @@ Thank you for your help in stamping out bugs.
   "R" gnus-summary-reply-with-original
   "w" gnus-summary-wide-reply
   "W" gnus-summary-wide-reply-with-original
+  "v" gnus-summary-very-wide-reply
+  "V" gnus-summary-very-wide-reply-with-original
   "n" gnus-summary-followup-to-mail
   "N" gnus-summary-followup-to-mail-with-original
   "m" gnus-summary-mail-other-window
   "u" gnus-uu-post-news
   "\M-c" gnus-summary-mail-crosspost-complaint
+  "Br" gnus-summary-reply-broken-reply-to
+  "BR" gnus-summary-reply-broken-reply-to-with-original
   "om" gnus-summary-mail-forward
   "op" gnus-summary-post-forward
-  "Om" gnus-summary-mail-digest
-  "Op" gnus-summary-post-digest)
+  "Om" gnus-summary-digest-mail-forward
+  "Op" gnus-summary-digest-post-forward)
 
 (gnus-define-keys (gnus-send-bounce-map "D" gnus-summary-send-map)
   "b" gnus-summary-resend-bounced-mail
@@ -205,7 +271,7 @@ Thank you for your help in stamping out bugs.
        (group (make-symbol "gnus-setup-message-group")))
     `(let ((,winconf (current-window-configuration))
           (,buffer (buffer-name (current-buffer)))
-          (,article (and gnus-article-reply (gnus-summary-article-number)))
+          (,article gnus-article-reply)
           (,group gnus-newsgroup-name)
           (message-header-setup-hook
            (copy-sequence message-header-setup-hook))
@@ -220,18 +286,68 @@ Thank you for your help in stamping out bugs.
        (unwind-protect
           (progn
             ,@forms)
-        (gnus-inews-add-send-actions ,winconf ,buffer ,article)
+        (gnus-inews-add-send-actions ,winconf ,buffer ,article ,config)
+        (gnus-inews-insert-draft-meta-information ,group ,article)
         (setq gnus-message-buffer (current-buffer))
         (set (make-local-variable 'gnus-message-group-art)
              (cons ,group ,article))
         (set (make-local-variable 'gnus-newsgroup-name) ,group)
-        (set (make-local-variable 'message-posting-charset)
-             (gnus-setup-posting-charset ,group))
         (gnus-run-hooks 'gnus-message-setup-hook))
        (gnus-add-buffer)
        (gnus-configure-windows ,config t)
        (set-buffer-modified-p nil))))
 
+(defun gnus-inews-insert-draft-meta-information (group article)
+  (save-excursion
+    (when (and group
+              (not (string= group ""))
+              (not (message-fetch-field gnus-draft-meta-information-header)))
+      (goto-char (point-min))
+      (insert gnus-draft-meta-information-header ": (\"" group "\" "
+             (if article (number-to-string
+                          (if (listp article)
+                              (car article)
+                            article)) "\"\"")
+             ")\n"))))
+
+;;;###autoload
+(defun gnus-msg-mail (&optional to subject other-headers continue
+                               switch-action yank-action send-actions)
+  "Start editing a mail message to be sent.
+Like `message-mail', but with Gnus paraphernalia, particularly the
+Gcc: header for archiving purposes."
+  (interactive)
+  (let ((buf (current-buffer))
+       mail-buf)
+    (gnus-setup-message 'message
+      (message-mail to subject other-headers continue
+                   nil yank-action send-actions))
+    (when switch-action
+      (setq mail-buf (current-buffer))
+      (switch-to-buffer buf)
+      (apply switch-action mail-buf nil)))
+  ;; COMPOSEFUNC should return t if succeed.  Undocumented ???
+  t)
+
+;;;###autoload
+(defun gnus-button-mailto (address)
+  "Mail to ADDRESS."
+  (set-buffer (gnus-copy-article-buffer))
+  (gnus-setup-message 'message
+    (message-reply address)))
+
+;;;###autoload
+(defun gnus-button-reply (&optional to-address wide)
+  "Like `message-reply'."
+  (interactive)
+  (gnus-setup-message 'message
+    (message-reply to-address wide)))
+
+;;;###autoload
+(define-mail-user-agent 'gnus-user-agent
+  'gnus-msg-mail 'message-send-and-exit
+  'message-kill-buffer 'message-send-hook)
+
 (defun gnus-setup-posting-charset (group)
   (let ((alist gnus-group-posting-charset-alist)
        (group (or group ""))
@@ -245,11 +361,15 @@ Thank you for your help in stamping out bugs.
                         (funcall (car elem) group))
                    (and (symbolp (car elem))
                         (symbol-value (car elem))))
-           (throw 'found (cadr elem))))))))
+           (throw 'found (cons (cadr elem) (caddr elem)))))))))
 
-(defun gnus-inews-add-send-actions (winconf buffer article)
+(defun gnus-inews-add-send-actions (winconf buffer article &optional config)
   (make-local-hook 'message-sent-hook)
-  (add-hook 'message-sent-hook 'gnus-inews-do-gcc nil t)
+  (add-hook 'message-sent-hook (if gnus-agent 'gnus-agent-possibly-do-gcc
+                                'gnus-inews-do-gcc) nil t)
+  (when gnus-agent
+    (make-local-hook 'message-header-hook)
+    (add-hook 'message-header-hook 'gnus-agent-possibly-save-gcc nil t))
   (setq message-post-method
        `(lambda (arg)
           (gnus-post-method arg ,gnus-newsgroup-name)))
@@ -262,7 +382,9 @@ Thank you for your help in stamping out bugs.
       (save-excursion
        (set-buffer ,buffer)
        ,(when article
-          `(gnus-summary-mark-article-as-replied ,article))))
+          (if (eq config 'forward)
+              `(gnus-summary-mark-article-as-forwarded ',article)
+            `(gnus-summary-mark-article-as-replied ',article)))))
    'send))
 
 (put 'gnus-setup-message 'lisp-indent-function 1)
@@ -349,29 +471,32 @@ If prefix argument YANK is non-nil, original article is yanked automatically."
   (gnus-summary-followup (gnus-summary-work-articles arg) t))
 
 (defun gnus-inews-yank-articles (articles)
-  (let* ((more-than-one (cdr articles))
-        (frame (when (and message-use-multi-frames more-than-one)
-                 (window-frame (get-buffer-window (current-buffer)))))
-        refs beg article)
+  (let ((more-than-one (cdr articles))
+       (cur (current-buffer))
+       refs beg article window)
     (message-goto-body)
     (while (setq article (pop articles))
       (save-window-excursion
        (set-buffer gnus-summary-buffer)
        (gnus-summary-select-article nil nil nil article)
        (gnus-summary-remove-process-mark article))
-      (when frame
-       (select-frame frame))
 
       ;; Gathering references.
       (when more-than-one
        (setq refs (message-list-references
                    refs
                    (mail-header-references gnus-current-headers)
-                   (mail-header-message-id gnus-current-headers))))
+                   (mail-header-message-id gnus-current-headers)))
+       (when message-use-multi-frames
+         (when (setq window (get-buffer-window cur t))
+           (select-frame (window-frame window)))))
 
       (gnus-copy-article-buffer)
       (let ((message-reply-buffer gnus-article-copy)
-           (message-reply-headers gnus-current-headers))
+           (message-reply-headers
+            (with-current-buffer gnus-article-copy
+              ;; The headers are decoded.
+              (nnheader-parse-head t))))
        (message-yank-original)
        (setq beg (or beg (mark t))))
       (when articles
@@ -455,63 +580,75 @@ header line with the old Message-ID."
        (error "Can't find any article buffer")
       (save-excursion
        (set-buffer article-buffer)
-       (save-restriction
-         ;; Copy over the (displayed) article buffer, delete
-         ;; hidden text and remove text properties.
-         (widen)
-         (let ((inhibit-read-only t))
-           (copy-to-buffer gnus-article-copy (point-min) (point-max))
+       (let ((gnus-newsgroup-charset (or gnus-article-charset
+                                         gnus-newsgroup-charset))
+             (gnus-newsgroup-ignored-charsets
+              (or gnus-article-ignored-charsets
+                  gnus-newsgroup-ignored-charsets)))
+         (save-restriction
+           ;; Copy over the (displayed) article buffer, delete
+           ;; hidden text and remove text properties.
+           (widen)
+           (let ((inhibit-read-only t))
+             (copy-to-buffer gnus-article-copy (point-min) (point-max))
+             (set-buffer gnus-article-copy)
+             ;; Encode bitmap smileys to ordinary text.
+             ;; Possibly, the original text might be restored.
+             (static-unless (featurep 'xemacs)
+               (when (featurep 'smiley-mule)
+                 (smiley-encode-buffer)))
+             (gnus-article-delete-text-of-type 'annotation)
+             (gnus-remove-text-with-property 'gnus-prev)
+             (gnus-remove-text-with-property 'gnus-next)
+             (gnus-remove-text-with-property 'x-face-mule-bitmap-image)
+             (insert
+              (prog1
+                  (static-if (featurep 'xemacs)
+                      ;; Revome smiley extents for (possibly) XEmacs 21.1.
+                      (format "%s"
+                              (buffer-substring-no-properties (point-min)
+                                                              (point-max)))
+                    (buffer-substring-no-properties (point-min) (point-max)))
+                (erase-buffer))))
+           ;; Find the original headers.
+           (set-buffer gnus-original-article-buffer)
+           (goto-char (point-min))
+           (while (looking-at message-unix-mail-delimiter)
+             (forward-line 1))
+           (setq beg (point))
+           (setq end (or (message-goto-body) beg))
+           ;; Delete the headers from the displayed articles.
            (set-buffer gnus-article-copy)
-           (gnus-article-delete-text-of-type 'annotation)
-           (gnus-remove-text-with-property 'gnus-prev)
-           (gnus-remove-text-with-property 'gnus-next)
-           (gnus-remove-text-with-property 'x-face-mule-bitmap-image)
-           (insert
-            (prog1
-                (format "%s" (buffer-string))
-              (erase-buffer)))
-           )
-         ;; Find the original headers.
-         (set-buffer gnus-original-article-buffer)
-         (goto-char (point-min))
-         (while (looking-at message-unix-mail-delimiter)
-           (forward-line 1))
-         (setq beg (point))
-         (setq end (or (search-forward "\n\n" nil t) (point)))
-         ;; Delete the headers from the displayed articles.
-         (set-buffer gnus-article-copy)
-         (delete-region (goto-char (point-min))
-                        (or (search-forward "\n\n" nil t) (point-max)))
-         ;; Encode bitmap smileys to ordinary text.
-         (static-unless (featurep 'xemacs)
-           (when (featurep 'smiley-mule)
-             (smiley-encode-buffer)))
-         ;; Insert the original article headers.
-         (insert-buffer-substring gnus-original-article-buffer beg end)
-         (article-decode-encoded-words)))
+           (delete-region (goto-char (point-min))
+                          (or (message-goto-body) (point-max)))
+           ;; Insert the original article headers.
+           (insert-buffer-substring gnus-original-article-buffer beg end)
+           (article-decode-encoded-words))))
       gnus-article-copy)))
 
 (defun gnus-post-news (post &optional group header article-buffer yank subject
                            force-news)
   (when article-buffer
     (gnus-copy-article-buffer))
-  (let ((gnus-article-reply article-buffer)
+  (let ((gnus-article-reply (and article-buffer (gnus-summary-article-number)))
        (add-to-list gnus-add-to-list))
     (gnus-setup-message (cond (yank 'reply-yank)
                              (article-buffer 'reply)
                              (t 'message))
       (let* ((group (or group gnus-newsgroup-name))
+            (charset (gnus-group-name-charset nil group))
             (pgroup group)
             to-address to-group mailing-list to-list
             newsgroup-p)
        (when group
-         (setq to-address (gnus-group-find-parameter group 'to-address)
+         (setq to-address (gnus-parameter-to-address group)
                to-group (gnus-group-find-parameter group 'to-group)
-               to-list (gnus-group-find-parameter group 'to-list)
+               to-list (gnus-parameter-to-list group)
                newsgroup-p (gnus-group-find-parameter group 'newsgroup)
                mailing-list (when gnus-mailing-list-groups
                               (string-match gnus-mailing-list-groups group))
-               group (gnus-group-real-name group)))
+               group (gnus-group-name-decode (gnus-group-real-name group)
+                                             charset)))
        (if (or (and to-group
                     (gnus-news-group-p to-group))
                newsgroup-p
@@ -528,7 +665,13 @@ header line with the old Message-ID."
                (message-news (or to-group group))
              (set-buffer gnus-article-copy)
              (gnus-msg-treat-broken-reply-to)
-             (message-followup (if (or newsgroup-p force-news) nil to-group)))
+             (message-followup (if (or newsgroup-p force-news)
+                                   (if (save-restriction
+                                         (article-narrow-to-head)
+                                         (message-fetch-field "newsgroups"))
+                                       nil
+                                     "")
+                                 to-group)))
          ;; The is mail.
          (if post
              (progn
@@ -546,10 +689,11 @@ header line with the old Message-ID."
        (when yank
          (gnus-inews-yank-articles yank))))))
 
-(defun gnus-msg-treat-broken-reply-to ()
+(defun gnus-msg-treat-broken-reply-to (&optional force)
   "Remove the Reply-to header iff broken-reply-to."
-  (when (gnus-group-find-parameter
-        gnus-newsgroup-name 'broken-reply-to)
+  (when (or force
+           (gnus-group-find-parameter
+            gnus-newsgroup-name 'broken-reply-to))
     (save-restriction
       (message-narrow-to-head)
       (message-remove-header "reply-to"))))
@@ -557,13 +701,15 @@ header line with the old Message-ID."
 (defun gnus-post-method (arg group &optional silent)
   "Return the posting method based on GROUP and ARG.
 If SILENT, don't prompt the user."
-  (let ((group-method (gnus-find-method-for-group group)))
+  (let ((gnus-post-method (or (gnus-parameter-post-method group)
+                             gnus-post-method))
+       (group-method (gnus-find-method-for-group group)))
     (cond
      ;; If the group-method is nil (which shouldn't happen) we use
      ;; the default method.
      ((null group-method)
       (or (and (null (eq gnus-post-method 'active)) gnus-post-method)
-              gnus-select-method message-post-method))
+         gnus-select-method message-post-method))
      ;; We want the inverse of the default
      ((and arg (not (eq arg 0)))
       (if (eq gnus-post-method 'active)
@@ -599,7 +745,9 @@ If SILENT, don't prompt the user."
        (setq method-alist
              (mapcar
               (lambda (m)
-                (list (concat (cadr m) " (" (symbol-name (car m)) ")") m))
+                (if (equal (cadr m) "")
+                    (list (symbol-name (car m)) m)
+                  (list (concat (cadr m) " (" (symbol-name (car m)) ")") m)))
               post-methods))
        ;; Query the user.
        (cadr
@@ -626,57 +774,91 @@ If SILENT, don't prompt the user."
      (t gnus-select-method))))
 
 \f
-
-(defun gnus-extended-version ()
-  "Stringified gnus version."
-  (concat gnus-product-name "/" gnus-version-number
-         " (based on "
-         gnus-original-product-name " v" gnus-original-version-number ")"
-         (if (zerop (string-to-number gnus-revision-number))
-             ""
-           (concat " (revision " gnus-revision-number ")"))
-         ))
-
-(defun gnus-message-make-user-agent (&optional include-mime-info max-column)
-  "Return user-agent info.
-INCLUDE-MIME-INFO the optional first argument if it is non-nil and the variable
-  `mime-edit-user-agent-value' exists, the return value will include it.
-MAX-COLUMN the optional second argument if it is specified, the return value
-  will be folded up in the proper way."
+(defun gnus-message-make-user-agent (&optional include-mime-info max-column
+                                                newline-product)
+  "Return a user-agent info.  If INCLUDE-MIME-INFO is non-nil and the
+variable `mime-edit-user-agent-value' is bound, the value will be
+included in the return value.  If MAX-COLUMN is specified, the return
+value will be folded up as it were filled.  NEWLINE-PRODUCT specifies
+whether a newline should be inserted in front of each product-token.
+If the value is t or `hard', it works strictly.  Otherwise, if it is
+non-nil (e.g. `soft'), it works semi-strictly.
+
+Here is an example of how to use this function:
+
+\(add-hook 'gnus-message-setup-hook
+         (lambda nil
+           (setq message-user-agent nil)
+           (save-excursion
+             (save-restriction
+               (message-narrow-to-headers)
+               (goto-char (point-max))
+               (insert \"User-Agent: \"
+                       (gnus-message-make-user-agent t 76 'soft)
+                       \"\\n\")))))
+"
   (let ((user-agent (if (and include-mime-info
                             (boundp 'mime-edit-user-agent-value))
                        (concat (gnus-extended-version)
                                " "
                                mime-edit-user-agent-value)
                      (gnus-extended-version))))
-    (if max-column
-       (let (boundary)
-         (unless (natnump max-column) (setq max-column 76))
-         (with-temp-buffer
-           (insert "            " user-agent)
-           (goto-char 13)
-           (while (re-search-forward "[\n\t ]+" nil t)
-             (replace-match " "))
-           (goto-char 13)
-           (while (re-search-forward "[^ ()/]+\\(/[^ ()/]+\\)? ?" nil t)
-             (while (eq ?\( (char-after (point)))
-               (forward-list)
-               (skip-chars-forward " "))
-             (skip-chars-backward " ")
-             (if (> (current-column) max-column)
-                 (progn
-                   (if (or (not boundary) (eq ?\n (char-after boundary)))
-                       (progn
-                         (setq boundary (point))
-                         (unless (eobp)
-                           (delete-char 1)
-                           (insert "\n ")))
-                     (goto-char boundary)
-                     (delete-char 1)
-                     (insert "\n ")))
-               (setq boundary (point))))
-           (buffer-substring 13 (point-max))))
-      user-agent)))
+    (when max-column
+      (unless (natnump max-column)
+       (setq max-column 76))
+      (with-temp-buffer
+       (set-buffer-multibyte t)
+       (insert (mapconcat 'identity (split-string user-agent) " "))
+       (goto-char (point-min))
+       (let ((bol t)
+             start agent agents width element swidth)
+         (while (re-search-forward "\\([^ ]+\\) ?" nil t)
+           (setq start (match-beginning 0))
+           (if (eq (char-after start) ?\()
+               (progn
+                 (goto-char start)
+                 (forward-list)
+                 (push (buffer-substring start (point)) agent))
+             (when agent
+               (push (nreverse agent) agents))
+             (setq agent (list (match-string 1)))))
+         (when agent
+           (push (nreverse agent) agents))
+         (setq agents (nreverse agents))
+         (if (> (+ 12 (string-width (caar agents))) max-column)
+             (setq user-agent "\n"
+                   width 0)
+           (setq user-agent ""
+                 width 11))
+         (while agents
+           (setq agent (car agents)
+                 agents (cdr agents))
+           (when (and (not bol)
+                      (or (memq newline-product '(t hard))
+                          (and newline-product
+                               (> (+ width 1
+                                     (string-width (mapconcat 'identity
+                                                              agent " ")))
+                                  max-column))))
+             (setq user-agent (concat user-agent "\n")
+                   width 0
+                   bol t))
+           (while agent
+             (setq element (car agent)
+                   swidth (string-width element)
+                   agent (cdr agent))
+             (if bol
+                 (setq user-agent (if (member user-agent '("" "\n"))
+                                      (concat user-agent element)
+                                    (concat user-agent " " element))
+                       width (+ width 1 swidth)
+                       bol nil)
+               (if (> (+ width 1 swidth) max-column)
+                   (setq user-agent (concat user-agent "\n " element)
+                         width (1+ swidth))
+                 (setq user-agent (concat user-agent " " element)
+                       width (+ width 1 swidth)))))))))
+    user-agent))
 
 \f
 ;;;
@@ -685,21 +867,39 @@ MAX-COLUMN the optional second argument if it is specified, the return value
 
 ;;; Mail reply commands of Gnus summary mode
 
-(defun gnus-summary-reply (&optional yank wide)
-  "Start composing a reply mail to the current message.
+(defun gnus-summary-reply (&optional yank wide very-wide)
+  "Start composing a mail reply to the current message.
 If prefix argument YANK is non-nil, the original article is yanked
-automatically."
+automatically.
+If WIDE, make a wide reply.
+If VERY-WIDE, make a very wide reply."
   (interactive
    (list (and current-prefix-arg
              (gnus-summary-work-articles 1))))
   ;; Stripping headers should be specified with mail-yank-ignored-headers.
   (when yank
     (gnus-summary-goto-subject (car yank)))
-  (let ((gnus-article-reply t))
+  (let ((gnus-article-reply (or yank (gnus-summary-article-number)))
+       (headers ""))
     (gnus-setup-message (if yank 'reply-yank 'reply)
-      (gnus-summary-select-article)
+      (if (not very-wide)
+         (gnus-summary-select-article)
+       (dolist (article very-wide)
+         (gnus-summary-select-article nil nil nil article)
+         (save-excursion
+           (set-buffer (gnus-copy-article-buffer))
+           (gnus-msg-treat-broken-reply-to)
+           (save-restriction
+             (message-narrow-to-head)
+             (setq headers (concat headers (buffer-string)))))))
       (set-buffer (gnus-copy-article-buffer))
-      (gnus-msg-treat-broken-reply-to)
+      (gnus-msg-treat-broken-reply-to gnus-msg-force-broken-reply-to)
+      (save-restriction
+       (message-narrow-to-head)
+       (when very-wide
+         (erase-buffer)
+         (insert headers))
+       (goto-char (point-max)))
       (message-reply nil wide)
       (when yank
        (gnus-inews-yank-articles yank)))))
@@ -710,6 +910,24 @@ The original article will be yanked."
   (interactive "P")
   (gnus-summary-reply (gnus-summary-work-articles n) wide))
 
+(defun gnus-summary-reply-broken-reply-to (&optional yank wide very-wide)
+  "Like `gnus-summary-reply' except removing reply-to field.
+If prefix argument YANK is non-nil, the original article is yanked
+automatically.
+If WIDE, make a wide reply.
+If VERY-WIDE, make a very wide reply."
+  (interactive
+   (list (and current-prefix-arg
+             (gnus-summary-work-articles 1))))
+  (let ((gnus-msg-force-broken-reply-to t))
+    (gnus-summary-reply yank wide very-wide)))
+
+(defun gnus-summary-reply-broken-reply-to-with-original (n &optional wide)
+  "Like `gnus-summary-reply-with-original' except removing reply-to field.
+The original article will be yanked."
+  (interactive "P")
+  (gnus-summary-reply-broken-reply-to (gnus-summary-work-articles n) wide))
+
 (defun gnus-summary-wide-reply (&optional yank)
   "Start composing a wide reply mail to the current message.
 If prefix argument YANK is non-nil, the original article is yanked
@@ -725,6 +943,22 @@ The original article will be yanked."
   (interactive "P")
   (gnus-summary-reply-with-original n t))
 
+(defun gnus-summary-very-wide-reply (&optional yank)
+  "Start composing a very wide reply mail to the current message.
+If prefix argument YANK is non-nil, the original article is yanked
+automatically."
+  (interactive
+   (list (and current-prefix-arg
+             (gnus-summary-work-articles 1))))
+  (gnus-summary-reply yank t (gnus-summary-work-articles yank)))
+
+(defun gnus-summary-very-wide-reply-with-original (n)
+  "Start composing a very wide reply mail to the current message.
+The original article will be yanked."
+  (interactive "P")
+  (gnus-summary-reply
+   (gnus-summary-work-articles n) t (gnus-summary-work-articles n)))
+
 (defun gnus-summary-mail-forward (&optional full-headers post)
   "Forward the current message to another user.
 If FULL-HEADERS (the prefix), include full headers when forwarding."
@@ -734,53 +968,82 @@ If FULL-HEADERS (the prefix), include full headers when forwarding."
     (let ((charset default-mime-charset))
       (set-buffer gnus-original-article-buffer)
       (make-local-variable 'default-mime-charset)
-      (setq default-mime-charset charset)
-      )
+      (setq default-mime-charset charset))
     (let ((message-included-forward-headers
           (if full-headers "" message-included-forward-headers)))
       (message-forward post))))
 
-;;; XXX: generate Subject and ``Topics''?
-(defun gnus-summary-mail-digest (&optional n post)
-  "Digests and forwards all articles in this series."
+(defun gnus-summary-digest-mail-forward (&optional n post)
+  "Digests and forwards all articles in this series.
+If N is a positive number, forward the N next articles.
+If N is a negative number, forward the N previous articles.
+If N is nil and any articles have been marked with the process mark,
+forward those articles instead.
+Optional POST will use news to forward instead of mail."
   (interactive "P")
-  (let ((subject "Digested Articles")
-       (articles (gnus-summary-work-articles n))
-       article frame)
-    (gnus-setup-message 'forward
-      (gnus-summary-select-article)
-      (if post (message-news nil subject) (message-mail nil subject))
-      (when (and message-use-multi-frames (cdr articles))
-       (setq frame (window-frame (get-buffer-window (current-buffer)))))
-      (message-goto-body)
-      (while (setq article (pop articles))
-       (save-window-excursion
-         (set-buffer gnus-summary-buffer)
-         (gnus-summary-select-article nil nil nil article)
-         (gnus-summary-remove-process-mark article))
-       (when frame
-         (select-frame frame))
-       (insert (mime-make-tag "message" "rfc822") "\n")
-       (insert-buffer-substring gnus-original-article-buffer))
-      (push-mark)
-      (message-goto-body)
-      (mime-edit-enclose-digest-region (point)(mark t)))))
-
-(defun gnus-summary-post-digest (&optional n)
-  "Digest and forwards all articles in this series to a newsgroup."
+  (let ((articles (gnus-summary-work-articles n))
+       (topics "Topics:\n")
+       subject article frame)
+    (when (car articles)
+      (gnus-setup-message 'forward
+       (gnus-summary-select-article)
+       (if (cdr articles)
+           (setq articles (sort articles '<)
+                 subject "Digested Articles")
+         (with-current-buffer gnus-original-article-buffer
+           (setq subject (message-make-forward-subject))))
+       (if post
+           (message-news nil subject)
+         (message-mail nil subject))
+       (when (and message-use-multi-frames (cdr articles))
+         (setq frame (window-frame (get-buffer-window (current-buffer)))))
+       (message-goto-body)
+       (while (setq article (pop articles))
+         (save-window-excursion
+           (set-buffer gnus-summary-buffer)
+           (gnus-summary-select-article nil nil nil article)
+           (setq topics (concat topics "    "
+                                (mail-header-subject gnus-current-headers)
+                                "\n"))
+           (gnus-summary-remove-process-mark article))
+         (when frame
+           (select-frame frame))
+         (insert (mime-make-tag "message" "rfc822") "\n")
+         (narrow-to-region (point) (point))
+         (insert-buffer-substring gnus-original-article-buffer)
+         (save-restriction
+           (article-narrow-to-head)
+           (message-remove-header message-included-forward-headers t nil t))
+         (goto-char (point-max))
+         (widen))
+       (push-mark)
+       (message-goto-body)
+       (insert topics)
+       (message-goto-body)
+       (mime-edit-enclose-digest-region (point)(mark t))))))
+
+(defun gnus-summary-digest-post-forward (&optional n)
+  "Digest and forwards all articles in this series to a newsgroup.
+If N is a positive number, forward the N next articles.
+If N is a negative number, forward the N previous articles.
+If N is nil and any articles have been marked with the process mark,
+forward those articles instead."
   (interactive "P")
-  (gnus-summary-mail-digest n t))
+  (gnus-summary-digest-mail-forward n t))
 
 (defun gnus-summary-resend-message (address n)
   "Resend the current article to ADDRESS."
-  (interactive "sResend message(s) to: \nP")
+  (interactive
+   (list (message-read-from-minibuffer "Resend message(s) to: ")
+        current-prefix-arg))
   (let ((articles (gnus-summary-work-articles n))
        article)
     (while (setq article (pop articles))
       (gnus-summary-select-article nil nil nil article)
       (save-excursion
        (set-buffer gnus-original-article-buffer)
-       (message-resend address)))))
+       (message-resend address))
+      (gnus-summary-mark-article-as-forwarded article))))
 
 (defun gnus-summary-post-forward (&optional full-headers)
   "Forward the current article to a newsgroup.
@@ -890,35 +1153,32 @@ The current group name will be inserted at \"%s\".")
   (let ((reply gnus-article-reply)
        (winconf gnus-prev-winconf)
        (group gnus-newsgroup-name))
+    (unless (and group
+                (not (gnus-group-read-only-p group)))
+      (setq group (read-string "Put in group: " nil (gnus-writable-groups))))
 
-    (or (and group (not (gnus-group-read-only-p group)))
-       (setq group (read-string "Put in group: " nil
-                                (gnus-writable-groups))))
     (when (gnus-gethash group gnus-newsrc-hashtb)
       (error "No such group: %s" group))
-
     (save-excursion
       (save-restriction
        (widen)
        (message-narrow-to-headers)
-       (let (gnus-deletable-headers)
-         (if (message-news-p)
-             (message-generate-headers message-required-news-headers)
-           (message-generate-headers message-required-mail-headers)))
+       (let ((gnus-deletable-headers nil))
+         (message-generate-headers
+          (if (message-news-p)
+              message-required-news-headers
+            message-required-mail-headers)))
        (goto-char (point-max))
        (insert "Gcc: " group "\n")
        (widen)))
-
     (gnus-inews-do-gcc)
-
-    (when (get-buffer gnus-group-buffer)
-      (when (gnus-buffer-exists-p (car-safe reply))
-       (set-buffer (car reply))
-       (and (cdr reply)
-            (gnus-summary-mark-article-as-replied
-             (cdr reply))))
-      (when winconf
-       (set-window-configuration winconf)))))
+    (when (and (get-buffer gnus-group-buffer)
+              (gnus-buffer-exists-p (car-safe reply))
+              (cdr reply))
+      (set-buffer (car reply))
+      (gnus-summary-mark-article-as-replied (cdr reply)))
+    (when winconf
+      (set-window-configuration winconf))))
 
 (defun gnus-article-mail (yank)
   "Send a reply to the address near point.
@@ -939,15 +1199,19 @@ If YANK is non-nil, include the original article."
   (interactive)
   (unless (gnus-alive-p)
     (error "Gnus has been shut down"))
-  (gnus-setup-message 'bug
-    (delete-other-windows)
-    (when gnus-bug-create-help-buffer
-      (switch-to-buffer "*Gnus Help Bug*")
-      (erase-buffer)
-      (insert gnus-bug-message)
-      (goto-char (point-min)))
-    (message-pop-to-buffer "*Gnus Bug*")
-    (message-setup `((To . ,gnus-maintainer) (Subject . "")))
+  (gnus-setup-message (if (message-mail-user-agent) 'message 'bug)
+    (unless (message-mail-user-agent)
+      (message-pop-to-buffer "*Gnus Bug*")
+      (delete-other-windows)
+      (when gnus-bug-create-help-buffer
+       (switch-to-buffer "*Gnus Help Bug*")
+       (erase-buffer)
+       (insert gnus-bug-message)
+       (goto-char (point-min))
+       (sit-for 0)
+       (set-buffer "*Gnus Bug*")))
+    (let ((message-this-is-mail t))
+      (message-setup `((To . ,gnus-maintainer) (Subject . ""))))
     (when gnus-bug-create-help-buffer
       (push `(gnus-bug-kill-buffer) message-send-actions))
     (goto-char (point-min))
@@ -967,6 +1231,8 @@ If YANK is non-nil, include the original article."
     (insert (with-temp-buffer
              (gnus-debug)
              (buffer-string)))
+    (let (mime-content-types)
+      (mime-edit-insert-tag "text" "plain"))
     (goto-char (point-min))
     (search-forward "Subject: " nil t)
     (message "")))
@@ -980,13 +1246,33 @@ If YANK is non-nil, include the original article."
   (interactive
    (list (completing-read "Buffer: " (mapcar 'list (message-buffers)) nil t)
         current-prefix-arg))
-  (gnus-summary-iterate n
-    (let ((gnus-display-mime-function nil)
-         (gnus-inhibit-treatment t))
-      (gnus-summary-select-article))
-    (save-excursion
-      (set-buffer buffer)
-      (message-yank-buffer gnus-article-buffer))))
+  (when (gnus-buffer-live-p buffer)
+    (let ((summary-frame (selected-frame))
+         (message-frame (when (static-if (featurep 'xemacs)
+                                  (device-on-window-system-p)
+                                window-system)
+                          (let ((window (get-buffer-window buffer t)))
+                            (when window
+                              (window-frame window)))))
+         (separator (concat "^" (regexp-quote mail-header-separator)
+                            "\n")))
+      (gnus-summary-iterate n
+       (gnus-summary-select-article)
+       (gnus-copy-article-buffer)
+       (when (frame-live-p message-frame)
+         (raise-frame message-frame)
+         (select-frame message-frame))
+       (with-current-buffer buffer
+         (when (save-excursion
+                 (beginning-of-line)
+                 (let (case-fold-search)
+                   (and (not (re-search-backward separator nil t))
+                        (re-search-forward separator nil t))))
+           (goto-char (match-end 0)))
+         (message-yank-buffer gnus-article-copy))
+       (select-frame summary-frame))
+      (when (frame-live-p message-frame)
+       (select-frame message-frame)))))
 
 (defun gnus-debug ()
   "Attempts to go through the Gnus source file and report what variables have been changed.
@@ -995,13 +1281,13 @@ The source file has to be in the Emacs load path."
   (let ((files '("gnus.el" "gnus-sum.el" "gnus-group.el"
                 "gnus-art.el" "gnus-start.el" "gnus-async.el"
                 "gnus-msg.el" "gnus-score.el" "gnus-win.el" "gnus-topic.el"
-                "nnmail.el" "message.el"))
+                "nnmail.el" "nntp.el" "message.el"))
        (point (point))
        file expr olist sym)
     (gnus-message 4 "Please wait while we snoop your variables...")
-    (sit-for 0)
     ;; Go through all the files looking for non-default values for variables.
     (save-excursion
+      (sit-for 0)
       (set-buffer (gnus-get-buffer-create " *gnus bug info*"))
       (while files
        (erase-buffer)
@@ -1015,8 +1301,7 @@ The source file has to be in the Emacs load path."
            (goto-char (point-min))
            (while (setq expr (ignore-errors (read (current-buffer))))
              (ignore-errors
-               (and (or (eq (car expr) 'defvar)
-                        (eq (car expr) 'defcustom))
+               (and (memq (car expr) '(defvar defcustom defvoo))
                     (stringp (nth 3 expr))
                     (or (not (boundp (nth 1 expr)))
                         (not (equal (eval (nth 2 expr))
@@ -1024,7 +1309,7 @@ The source file has to be in the Emacs load path."
                     (push (nth 1 expr) olist)))))))
       (kill-buffer (current-buffer)))
     (when (setq olist (nreverse olist))
-      (insert "------------------ Environment follows ------------------\n\n"))
+      (insert ";----------------- Environment follows ------------------\n\n"))
     (while olist
       (if (boundp (car olist))
          (condition-case ()
@@ -1040,13 +1325,17 @@ The source file has to be in the Emacs load path."
             (format "(setq %s 'whatever)\n" (car olist))))
        (insert ";; (makeunbound '" (symbol-name (car olist)) ")\n"))
       (setq olist (cdr olist)))
-    (insert "\n\n")
     ;; Remove any control chars - they seem to cause trouble for some
     ;; mailers.  (Byte-compiled output from the stuff above.)
     (goto-char point)
     (while (re-search-forward "[\000-\010\013-\037\200-\237]" nil t)
       (replace-match (format "\\%03o" (string-to-char (match-string 0)))
-                    t t))))
+                    t t))
+    ;; Break MIME tags purposely.
+    (goto-char point)
+    (while (re-search-forward mime-edit-tag-regexp nil t)
+      (goto-char (1+ (match-beginning 0)))
+      (insert "X"))))
 
 ;;; Treatment of rejected articles.
 ;;; Bounced mail.
@@ -1073,55 +1362,60 @@ this is a reply."
 
 ;;; Gcc handling.
 
+(defun gnus-inews-group-method (group)
+  (cond
+   ;; If the group doesn't exist, we assume
+   ;; it's an archive group...
+   ((and (null (gnus-get-info group))
+        (eq (car (gnus-server-to-method gnus-message-archive-method))
+            (car (gnus-server-to-method (gnus-group-method group)))))
+    gnus-message-archive-method)
+   ;; Use the method.
+   ((gnus-info-method (gnus-get-info group))
+    (gnus-info-method (gnus-get-info group)))
+   ;; Find the method.
+   (t (gnus-server-to-method (gnus-group-method group)))))
+
 ;; Do Gcc handling, which copied the message over to some group.
 (defun gnus-inews-do-gcc (&optional gcc)
   (interactive)
-  (when (gnus-alive-p)
-    (save-excursion
-      (save-restriction
-       (message-narrow-to-headers)
-       (let ((gcc (or gcc (mail-fetch-field "gcc" nil t)))
-             (coding-system-for-write 'raw-text)
-             (output-coding-system 'raw-text)
-             groups group method)
-         (when gcc
-           (message-remove-header "gcc")
-           (widen)
-           (setq groups (message-tokenize-header gcc " ,"))
-           ;; Copy the article over to some group(s).
-           (while (setq group (pop groups))
-             (gnus-check-server
-              (setq method
-                    (cond ((and (null (gnus-get-info group))
-                                (eq (car gnus-message-archive-method)
-                                    (car
-                                     (gnus-server-to-method
-                                      (gnus-group-method group)))))
-                           ;; If the group doesn't exist, we assume
-                           ;; it's an archive group...
-                           gnus-message-archive-method)
-                          ;; Use the method.
-                          ((gnus-info-method (gnus-get-info group))
-                           (gnus-info-method (gnus-get-info group)))
-                          ;; Find the method.
-                          (t (gnus-group-method group)))))
-             (gnus-check-server method)
-             (unless (gnus-request-group group t method)
-               (gnus-request-create-group group method))
-             (save-excursion
-               (nnheader-set-temp-buffer " *acc*")
-               (insert-buffer-substring message-encoding-buffer)
-               (gnus-run-hooks 'gnus-before-do-gcc-hook)
-               (goto-char (point-min))
-               (when (re-search-forward
-                      (concat "^" (regexp-quote mail-header-separator) "$")
-                      nil t)
-                 (replace-match "" t t ))
-               (unless (gnus-request-accept-article group method t t)
-                 (gnus-message 1 "Couldn't store article in group %s: %s"
-                               group (gnus-status-message method))
-                 (sit-for 2))
-               (kill-buffer (current-buffer))))))))))
+  (save-excursion
+    (save-restriction
+      (message-narrow-to-headers)
+      (let ((gcc (or gcc (mail-fetch-field "gcc" nil t)))
+           (coding-system-for-write 'raw-text)
+           (output-coding-system 'raw-text)
+           groups group method group-art)
+       (when gcc
+         (message-remove-header "gcc")
+         (widen)
+         (setq groups (message-unquote-tokens
+                       (message-tokenize-header gcc " ,")))
+         ;; Copy the article over to some group(s).
+         (while (setq group (pop groups))
+           (unless (gnus-check-server
+                    (setq method (gnus-inews-group-method group)))
+             (error "Can't open server %s" (if (stringp method) method
+                                             (car method))))
+           (unless (gnus-request-group group nil method)
+             (gnus-request-create-group group method))
+           (save-excursion
+             (nnheader-set-temp-buffer " *acc*")
+             (insert-buffer-substring message-encoding-buffer)
+             (gnus-run-hooks 'gnus-before-do-gcc-hook)
+             (goto-char (point-min))
+             (when (re-search-forward
+                    (concat "^" (regexp-quote mail-header-separator) "$")
+                    nil t)
+               (replace-match "" t t ))
+             (unless (setq group-art
+                           (gnus-request-accept-article group method t t))
+               (gnus-message 1 "Couldn't store article in group %s: %s"
+                             group (gnus-status-message method))
+               (sit-for 2))
+             (when (and group-art gnus-inews-mark-gcc-as-read)
+               (gnus-group-mark-article-read group (cdr group-art)))
+             (kill-buffer (current-buffer)))))))))
 
 (defun gnus-inews-insert-gcc ()
   "Insert Gcc headers based on `gnus-outgoing-message-group'."
@@ -1146,6 +1440,7 @@ this is a reply."
         (group (or group gnus-newsgroup-name ""))
         (gcc-self-val
          (and gnus-newsgroup-name
+              (not (equal gnus-newsgroup-name ""))
               (gnus-group-find-parameter
                gnus-newsgroup-name 'gcc-self)))
         result
@@ -1239,9 +1534,11 @@ this is a reply."
                ;; Regexp string match on the group name.
                (string-match match group))
               ((eq match 'header)
-               (let ((header (message-fetch-field (pop style))))
-                 (and header
-                      (string-match (pop style) header))))
+               (and (gnus-buffer-live-p gnus-article-copy)
+                    (with-current-buffer gnus-article-copy
+                      (let ((header (message-fetch-field (pop style))))
+                        (and header
+                             (string-match (pop style) header))))))
               ((or (symbolp match)
                    (gnus-functionp match))
                (cond
@@ -1298,37 +1595,42 @@ this is a reply."
       (setq results (delq name (delq address results)))
       (make-local-variable 'message-setup-hook)
       (dolist (result results)
-       (when (cdr result)
-         (add-hook 'message-setup-hook
-                   (cond
-                    ((eq 'eval (car result))
-                     'ignore)
-                    ((eq 'body (car result))
-                     `(lambda ()
-                        (save-excursion
-                          (message-goto-body)
-                          (insert ,(cdr result)))))
-                    ((eq 'signature (car result))
-                     (set (make-local-variable 'message-signature) nil)
-                     (set (make-local-variable 'message-signature-file) nil)
+       (add-hook 'message-setup-hook
+                 (cond
+                  ((eq 'eval (car result))
+                   'ignore)
+                  ((eq 'body (car result))
+                   `(lambda ()
+                      (save-excursion
+                        (message-goto-body)
+                        (insert ,(cdr result)))))
+                  ((eq 'signature (car result))
+                   (set (make-local-variable 'message-signature) nil)
+                   (set (make-local-variable 'message-signature-file) nil)
+                   (if (not (cdr result))
+                       'ignore
                      `(lambda ()
                         (save-excursion
                           (let ((message-signature ,(cdr result)))
                             (when message-signature
-                              (message-insert-signature))))))
-                    (t
-                     (let ((header
-                            (if (symbolp (car result))
-                                (capitalize (symbol-name (car result)))
-                              (car result))))
-                       `(lambda ()
-                          (save-excursion
-                            (message-remove-header ,header)
-                            (message-goto-eoh)
-                            (insert ,header ": " ,(cdr result) "\n")))))))))
+                              (message-insert-signature)))))))
+                  (t
+                   (let ((header
+                          (if (symbolp (car result))
+                              (capitalize (symbol-name (car result)))
+                            (car result))))
+                     `(lambda ()
+                        (save-excursion
+                          (message-remove-header ,header)
+                          (let ((value ,(cdr result)))
+                            (when value
+                              (message-goto-eoh)
+                              (insert ,header ": " value "\n"))))))))))
       (when (or name address)
        (add-hook 'message-setup-hook
                  `(lambda ()
+                    (set (make-local-variable 'user-mail-address)
+                         ,(or (cdr address) user-mail-address))
                     (let ((user-full-name ,(or (cdr name) (user-full-name)))
                           (user-mail-address
                            ,(or (cdr address) user-mail-address)))
@@ -1344,7 +1646,7 @@ this is a reply."
 (defun gnus-maybe-setup-default-charset ()
   (let ((charset
         (and (boundp 'gnus-summary-buffer)
-              (buffer-live-p gnus-summary-buffer)
+             (buffer-live-p gnus-summary-buffer)
              (save-excursion
                (set-buffer gnus-summary-buffer)
                default-mime-charset))))