Revision: miles@gnu.org--gnu-2005/gnus--devo--0--patch-37
[gnus] / lisp / message.el
index ef7d368..e585501 100644 (file)
@@ -1,5 +1,5 @@
 ;;; message.el --- composing mail and news messages
-;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
 ;;        Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
@@ -33,7 +33,8 @@
 (eval-when-compile
   (require 'cl)
   (defvar gnus-message-group-art)
-  (defvar gnus-list-identifiers)) ; gnus-sum is required where necessary
+  (defvar gnus-list-identifiers) ; gnus-sum is required where necessary
+  (require 'hashcash))
 (require 'canlock)
 (require 'mailheader)
 (require 'nnheader)
 (require 'mail-parse)
 (require 'mml)
 (require 'rfc822)
-(eval-and-compile
-  (autoload 'sha1 "sha1-el")
-  (autoload 'gnus-find-method-for-group "gnus")
-  (autoload 'nnvirtual-find-group-art "nnvirtual"))
 
 (defgroup message '((user-mail-address custom-variable)
                    (user-full-name custom-variable))
@@ -135,6 +132,7 @@ mailbox format."
 
 (defcustom message-fcc-externalize-attachments nil
   "If non-nil, attachments are included as external parts in Fcc copies."
+  :version "22.1"
   :type 'boolean
   :group 'message-sending)
 
@@ -145,7 +143,7 @@ If the string contains the format spec \"%s\", the Newsgroups
 the article has been posted to will be inserted there.
 If this variable is nil, no such courtesy message will be added."
   :group 'message-sending
-  :type '(radio (string :format "%t: %v\n" :size 0) (const nil)))
+  :type '(radio string (const nil)))
 
 (defcustom message-ignored-bounced-headers
   "^\\(Received\\|Return-Path\\|Delivered-To\\):"
@@ -174,7 +172,7 @@ Otherwise, most addresses look like `angles', but they look like
 
 (defcustom message-insert-canlock t
   "Whether to insert a Cancel-Lock header in news postings."
-  :version "21.3"
+  :version "22.1"
   :group 'message-headers
   :type 'boolean)
 
@@ -203,14 +201,18 @@ Checks include `subject-cmsg', `multiple-headers', `sendsys',
   "*Headers to be generated or prompted for when sending a message.
 Also see `message-required-news-headers' and
 `message-required-mail-headers'."
+  :version "22.1"
   :group 'message-news
   :group 'message-headers
+  :link '(custom-manual "(message)Message Headers")
   :type '(repeat sexp))
 
 (defcustom message-draft-headers '(References From)
   "*Headers to be generated when saving a draft message."
+  :version "22.1"
   :group 'message-news
   :group 'message-headers
+  :link '(custom-manual "(message)Message Headers")
   :type '(repeat sexp))
 
 (defcustom message-required-news-headers
@@ -224,6 +226,7 @@ User-Agent are optional.  If don't you want message to insert some
 header, remove it from this list."
   :group 'message-news
   :group 'message-headers
+  :link '(custom-manual "(message)Message Headers")
   :type '(repeat sexp))
 
 (defcustom message-required-mail-headers
@@ -234,11 +237,13 @@ It is recommended that From, Date, To, Subject and Message-ID be
 included.  Organization and User-Agent are optional."
   :group 'message-mail
   :group 'message-headers
+  :link '(custom-manual "(message)Message Headers")
   :type '(repeat sexp))
 
 (defcustom message-deletable-headers '(Message-ID Date Lines)
   "Headers to be deleted if they already exist and were generated by message previously."
   :group 'message-headers
+  :link '(custom-manual "(message)Message Headers")
   :type 'sexp)
 
 (defcustom message-ignored-news-headers
@@ -246,32 +251,45 @@ included.  Organization and User-Agent are optional."
   "*Regexp of headers to be removed unconditionally before posting."
   :group 'message-news
   :group 'message-headers
-  :type 'regexp)
+  :link '(custom-manual "(message)Message Headers")
+  :type '(repeat :value-to-internal (lambda (widget value)
+                                     (custom-split-regexp-maybe value))
+                :match (lambda (widget value)
+                         (or (stringp value)
+                             (widget-editable-list-match widget value)))
+                regexp))
 
 (defcustom message-ignored-mail-headers
   "^[GF]cc:\\|^Resent-Fcc:\\|^Xref:\\|^X-Draft-From:\\|^X-Gnus-Agent-Meta-Information:"
   "*Regexp of headers to be removed unconditionally before mailing."
   :group 'message-mail
   :group 'message-headers
+  :link '(custom-manual "(message)Mail Headers")
   :type 'regexp)
 
-(defcustom message-ignored-supersedes-headers "^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|^Received:\\|^X-From-Line:\\|^X-Trace:\\|^X-Complaints-To:\\|Return-Path:\\|^Supersedes:\\|^NNTP-Posting-Date:\\|^X-Trace:\\|^X-Complaints-To:\\|^Cancel-Lock:\\|^Cancel-Key:\\|^X-Hashcash:\\|^X-Payment:"
+(defcustom message-ignored-supersedes-headers "^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|^Received:\\|^X-From-Line:\\|^X-Trace:\\|^X-Complaints-To:\\|Return-Path:\\|^Supersedes:\\|^NNTP-Posting-Date:\\|^X-Trace:\\|^X-Complaints-To:\\|^Cancel-Lock:\\|^Cancel-Key:\\|^X-Hashcash:\\|^X-Payment:\\|^Approved:"
   "*Header lines matching this regexp will be deleted before posting.
 It's best to delete old Path and Date headers before posting to avoid
 any confusion."
   :group 'message-interface
-  :type 'regexp)
+  :link '(custom-manual "(message)Superseding")
+  :type '(repeat :value-to-internal (lambda (widget value)
+                                     (custom-split-regexp-maybe value))
+                :match (lambda (widget value)
+                         (or (stringp value)
+                             (widget-editable-list-match widget value)))
+                regexp))
 
 (defcustom message-subject-re-regexp
   "^[ \t]*\\([Rr][Ee]\\(\\[[0-9]*\\]\\)*:[ \t]*\\)*[ \t]*"
   "*Regexp matching \"Re: \" in the subject line."
   :group 'message-various
+  :link '(custom-manual "(message)Message Headers")
   :type 'regexp)
 
 ;;; Start of variables adopted from `message-utils.el'.
 
 (defcustom message-subject-trailing-was-query 'ask
-  ;; should it default to nil or ask?
   "*What to do with trailing \"(was: <old subject>)\" in subject lines.
 If nil, leave the subject unchanged.  If it is the symbol `ask', query
 the user what do do.  In this case, the subject is matched against
@@ -279,9 +297,11 @@ the user what do do.  In this case, the subject is matched against
 `message-subject-trailing-was-query' is t, always strip the trailing
 old subject.  In this case, `message-subject-trailing-was-regexp' is
 used."
+  :version "22.1"
   :type '(choice (const :tag "never" nil)
                 (const :tag "always strip" t)
                  (const ask))
+  :link '(custom-manual "(message)Message Headers")
   :group 'message-various)
 
 (defcustom message-subject-trailing-was-ask-regexp
@@ -294,7 +314,9 @@ the variable is t instead of `ask', use
 `message-subject-trailing-was-regexp' instead.
 
 It is okay to create some false positives here, as the user is asked."
+  :version "22.1"
   :group 'message-various
+  :link '(custom-manual "(message)Message Headers")
   :type 'regexp)
 
 (defcustom message-subject-trailing-was-regexp
@@ -305,7 +327,9 @@ If `message-subject-trailing-was-query' is set to t, the subject is
 matched against `message-subject-trailing-was-regexp' in
 `message-strip-subject-trailing-was'.  You should use a regexp creating very
 few false positives here."
+  :version "22.1"
   :group 'message-various
+  :link '(custom-manual "(message)Message Headers")
   :type 'regexp)
 
 ;; Fixme: Why are all these things autoloaded?
@@ -316,14 +340,18 @@ few false positives here."
 (defcustom message-mark-insert-begin
   "--8<---------------cut here---------------start------------->8---\n"
   "How to mark the beginning of some inserted text."
+  :version "22.1"
   :type 'string
+  :link '(custom-manual "(message)Insertion Variables")
   :group 'message-various)
 
 ;;;###autoload
 (defcustom message-mark-insert-end
   "--8<---------------cut here---------------end--------------->8---\n"
   "How to mark the end of some inserted text."
+  :version "22.1"
   :type 'string
+  :link '(custom-manual "(message)Insertion Variables")
   :group 'message-various)
 
 ;;;###autoload
@@ -331,7 +359,9 @@ few false positives here."
   "X-No-Archive: Yes\n"
   "Header to insert when you don't want your article to be archived.
 Archives \(such as groups.google.com\) respect this header."
+  :version "22.1"
   :type 'string
+  :link '(custom-manual "(message)Header Commands")
   :group 'message-various)
 
 ;;;###autoload
@@ -339,8 +369,9 @@ Archives \(such as groups.google.com\) respect this header."
   "X-No-Archive: Yes - save http://groups.google.com/"
   "Note to insert why you wouldn't want this posting archived.
 If nil, don't insert any text in the body."
-  :type '(radio (string :format "%t: %v\n" :size 0)
-               (const nil))
+  :version "22.1"
+  :type '(radio string (const nil))
+  :link '(custom-manual "(message)Header Commands")
   :group 'message-various)
 
 ;;; Crossposts and Followups
@@ -357,6 +388,7 @@ If nil, don't insert any text in the body."
 If nil, `message-cross-post-followup-to' will only do a followup.  Note that
 you can explicitly override this setting by calling
 `message-cross-post-followup-to' with a prefix."
+  :version "22.1"
   :type 'boolean
   :group 'message-various)
 
@@ -364,6 +396,7 @@ you can explicitly override this setting by calling
 (defcustom message-cross-post-note
   "Crosspost & Followup-To: "
   "Note to insert before signature to notify of cross-post and follow-up."
+  :version "22.1"
   :type 'string
   :group 'message-various)
 
@@ -371,6 +404,7 @@ you can explicitly override this setting by calling
 (defcustom message-followup-to-note
   "Followup-To: "
   "Note to insert before signature to notify of follow-up only."
+  :version "22.1"
   :type 'string
   :group 'message-various)
 
@@ -381,6 +415,7 @@ you can explicitly override this setting by calling
 The function will be called with four arguments.  The function should not only
 insert a note, but also ensure old notes are deleted.  See the documentation
 for `message-cross-post-insert-note'."
+  :version "22.1"
   :type 'function
   :group 'message-various)
 
@@ -390,11 +425,13 @@ for `message-cross-post-insert-note'."
 (defcustom message-signature-separator "^-- *$"
   "Regexp matching the signature separator."
   :type 'regexp
+  :link '(custom-manual "(message)Various Message Variables")
   :group 'message-various)
 
 (defcustom message-elide-ellipsis "\n[...]\n\n"
   "*The string which is inserted for elided text."
   :type 'string
+  :link '(custom-manual "(message)Various Commands")
   :group 'message-various)
 
 (defcustom message-interactive t
@@ -402,6 +439,7 @@ for `message-cross-post-insert-note'."
 nil means let mailer mail back a message to report errors."
   :group 'message-sending
   :group 'message-mail
+  :link '(custom-manual "(message)Sending Variables")
   :type 'boolean)
 
 (defcustom message-generate-new-buffers 'unique
@@ -410,6 +448,7 @@ If this is a function, call that function with three parameters:  The type,
 the to address and the group name.  (Any of these may be nil.)  The function
 should return the new buffer name."
   :group 'message-buffers
+  :link '(custom-manual "(message)Message Buffers")
   :type '(choice (const :tag "off" nil)
                 (const :tag "unique" unique)
                 (const :tag "unsent" unsent)
@@ -418,6 +457,7 @@ should return the new buffer name."
 (defcustom message-kill-buffer-on-exit nil
   "*Non-nil means that the message buffer will be killed after sending a message."
   :group 'message-buffers
+  :link '(custom-manual "(message)Message Buffers")
   :type 'boolean)
 
 (eval-when-compile
@@ -438,6 +478,7 @@ If t, use `message-user-organization-file'."
 (defcustom message-user-organization-file "/usr/lib/news/organization"
   "*Local news organization file."
   :type 'file
+  :link '(custom-manual "(message)News Headers")
   :group 'message-headers)
 
 (defcustom message-make-forward-subject-function
@@ -455,6 +496,7 @@ The provided functions are:
 * `message-forward-subject-fwd' Subject of article with 'Fwd:' prepended
       to it."
   :group 'message-forwarding
+  :link '(custom-manual "(message)Forwarding")
   :type '(radio (function-item message-forward-subject-author-subject)
                (function-item message-forward-subject-fwd)
                (function-item message-forward-subject-name-subject)
@@ -465,6 +507,7 @@ The provided functions are:
 Otherwise, directly inline the old message in the forwarded message."
   :version "21.1"
   :group 'message-forwarding
+  :link '(custom-manual "(message)Forwarding")
   :type 'boolean)
 
 (defcustom message-forward-show-mml 'best
@@ -490,55 +533,81 @@ digital signature."
   "*Non-nil means try to remove as much cruft as possible from the subject.
 Done before generating the new subject of a forward."
   :group 'message-forwarding
+  :link '(custom-manual "(message)Forwarding")
   :type 'boolean)
 
 (defcustom message-ignored-resent-headers "^Return-receipt\\|^X-Gnus\\|^Gnus-Warning:\\|^>?From "
   "*All headers that match this regexp will be deleted when resending a message."
   :group 'message-interface
-  :type 'regexp)
+  :link '(custom-manual "(message)Resending")
+  :type '(repeat :value-to-internal (lambda (widget value)
+                                     (custom-split-regexp-maybe value))
+                :match (lambda (widget value)
+                         (or (stringp value)
+                             (widget-editable-list-match widget value)))
+                regexp))
 
 (defcustom message-forward-ignored-headers "^Content-Transfer-Encoding:\\|^X-Gnus"
   "*All headers that match this regexp will be deleted when forwarding a message."
   :version "21.1"
   :group 'message-forwarding
-  :type '(choice (const :tag "None" nil)
+  :type '(repeat :value-to-internal (lambda (widget value)
+                                     (custom-split-regexp-maybe value))
+                :match (lambda (widget value)
+                         (or (stringp value)
+                             (widget-editable-list-match widget value)))
                 regexp))
 
 (defcustom message-ignored-cited-headers "."
   "*Delete these headers from the messages you yank."
   :group 'message-insertion
+  :link '(custom-manual "(message)Insertion Variables")
   :type 'regexp)
 
 (defcustom message-cite-prefix-regexp
   (if (string-match "[[:digit:]]" "1") ;; support POSIX?
       "\\([ \t]*[-_.[:word:]]+>+\\|[ \t]*[]>|}+]\\)+"
     ;; ?-, ?_ or ?. MUST NOT be in syntax entry w.
-    (let ((old-table (syntax-table))
-         non-word-constituents)
-      (set-syntax-table text-mode-syntax-table)
-      (setq non-word-constituents
-           (concat
-            (if (string-match "\\w" "-")  "" "-")
-            (if (string-match "\\w" "_")  "" "_")
-            (if (string-match "\\w" ".")  "" ".")))
-      (set-syntax-table old-table)
+    (let (non-word-constituents)
+      (with-syntax-table text-mode-syntax-table
+       (setq non-word-constituents
+             (concat
+              (if (string-match "\\w" "-")  "" "-")
+              (if (string-match "\\w" "_")  "" "_")
+              (if (string-match "\\w" ".")  "" "."))))
       (if (equal non-word-constituents "")
          "\\([ \t]*\\(\\w\\)+>+\\|[ \t]*[]>|}+]\\)+"
        (concat "\\([ \t]*\\(\\w\\|["
                non-word-constituents
                "]\\)+>+\\|[ \t]*[]>|}+]\\)+"))))
   "*Regexp matching the longest possible citation prefix on a line."
+  :version "22.1"
   :group 'message-insertion
+  :link '(custom-manual "(message)Insertion Variables")
   :type 'regexp)
 
 (defcustom message-cancel-message "I am canceling my own article.\n"
   "Message to be inserted in the cancel message."
   :group 'message-interface
+  :link '(custom-manual "(message)Canceling News")
   :type 'string)
 
 ;; Useful to set in site-init.el
 ;;;###autoload
-(defcustom message-send-mail-function 'message-send-mail-with-sendmail
+(defcustom message-send-mail-function
+  (let ((program (if (boundp 'sendmail-program)
+                    ;; see paths.el
+                    sendmail-program)))
+    (cond
+     ((and program
+          (string-match "/" program) ;; Skip path
+          (file-executable-p program))
+      'message-send-mail-with-sendmail)
+     ((and program
+          (executable-find program))
+      'message-send-mail-with-sendmail)
+     (t
+      'smtpmail-send-it)))
   "Function to call to send the current buffer as mail.
 The headers should be delimited by a line whose contents match the
 variable `mail-header-separator'.
@@ -556,6 +625,7 @@ See also `send-mail-function'."
                (function-item feedmail-send-it)
                (function :tag "Other"))
   :group 'message-sending
+  :link '(custom-manual "(message)Mail Variables")
   :group 'message-mail)
 
 (defcustom message-send-news-function 'message-send-news
@@ -564,6 +634,7 @@ The headers should be delimited by a line whose contents match the
 variable `mail-header-separator'."
   :group 'message-sending
   :group 'message-news
+  :link '(custom-manual "(message)News Variables")
   :type 'function)
 
 (defcustom message-reply-to-function nil
@@ -571,6 +642,7 @@ variable `mail-header-separator'."
 This function should pick out addresses from the To, Cc, and From headers
 and respond with new To and Cc headers."
   :group 'message-interface
+  :link '(custom-manual "(message)Reply")
   :type '(choice function (const nil)))
 
 (defcustom message-wide-reply-to-function nil
@@ -578,6 +650,7 @@ and respond with new To and Cc headers."
 This function should pick out addresses from the To, Cc, and From headers
 and respond with new To and Cc headers."
   :group 'message-interface
+  :link '(custom-manual "(message)Wide Reply")
   :type '(choice function (const nil)))
 
 (defcustom message-followup-to-function nil
@@ -585,8 +658,15 @@ and respond with new To and Cc headers."
 This function should pick out addresses from the To, Cc, and From headers
 and respond with new To and Cc headers."
   :group 'message-interface
+  :link '(custom-manual "(message)Followup")
   :type '(choice function (const nil)))
 
+(defcustom message-extra-wide-headers nil
+  "If non-nil, a list of additional address headers.
+These are used when composing a wide reply."
+  :group 'message-sending
+  :type '(repeat string))
+
 (defcustom message-use-followup-to 'ask
   "*Specifies what to do with Followup-To header.
 If nil, always ignore the header.  If it is t, use its value, but
@@ -594,6 +674,7 @@ query before using the \"poster\" value.  If it is the symbol `ask',
 always query the user whether to use the value.  If it is the symbol
 `use', always use the value."
   :group 'message-interface
+  :link '(custom-manual "(message)Followup")
   :type '(choice (const :tag "ignore" nil)
                 (const :tag "use & query" t)
                 (const use)
@@ -604,7 +685,9 @@ always query the user whether to use the value.  If it is the symbol
 If nil, always ignore the header.  If it is the symbol `ask', always
 query the user whether to use the value.  If it is the symbol `use',
 always use the value."
+  :version "22.1"
   :group 'message-interface
+  :link '(custom-manual "(message)Mailing Lists")
   :type '(choice (const :tag "ignore" nil)
                 (const use)
                 (const ask)))
@@ -616,23 +699,28 @@ If non-nil, this variable contains a list of functions which return
 regular expressions to match lists.  These functions can be used in
 conjunction with `message-subscribed-regexps' and
 `message-subscribed-addresses'."
+  :version "22.1"
   :group 'message-interface
+  :link '(custom-manual "(message)Mailing Lists")
   :type '(repeat sexp))
 
 (defcustom message-subscribed-address-file nil
   "*A file containing addresses the user is subscribed to.
 If nil, do not look at any files to determine list subscriptions.  If
 non-nil, each line of this file should be a mailing list address."
+  :version "22.1"
   :group 'message-interface
-  :type '(radio (file :format "%t: %v\n" :size 0)
-               (const nil)))
+  :link '(custom-manual "(message)Mailing Lists")
+  :type '(radio file (const nil)))
 
 (defcustom message-subscribed-addresses nil
   "*Specifies a list of addresses the user is subscribed to.
 If nil, do not use any predefined list subscriptions.  This list of
 addresses can be used in conjunction with
 `message-subscribed-address-functions' and `message-subscribed-regexps'."
+  :version "22.1"
   :group 'message-interface
+  :link '(custom-manual "(message)Mailing Lists")
   :type '(repeat string))
 
 (defcustom message-subscribed-regexps nil
@@ -640,7 +728,9 @@ addresses can be used in conjunction with
 If nil, do not use any predefined list subscriptions.  This list of
 regular expressions can be used in conjunction with
 `message-subscribed-address-functions' and `message-subscribed-addresses'."
+  :version "22.1"
   :group 'message-interface
+  :link '(custom-manual "(message)Mailing Lists")
   :type '(repeat regexp))
 
 (defcustom message-allow-no-recipients 'ask
@@ -648,7 +738,9 @@ regular expressions can be used in conjunction with
 If it is the symbol `always', the posting is allowed.  If it is the
 symbol `never', the posting is not allowed.  If it is the symbol
 `ask', you are prompted."
+  :version "22.1"
   :group 'message-interface
+  :link '(custom-manual "(message)Message Headers")
   :type '(choice (const always)
                 (const never)
                 (const ask)))
@@ -657,21 +749,25 @@ symbol `never', the posting is not allowed.  If it is the symbol
   "*Non-nil means don't add \"-f username\" to the sendmail command line.
 Doing so would be even more evil than leaving it out."
   :group 'message-sending
+  :link '(custom-manual "(message)Mail Variables")
   :type 'boolean)
 
 (defcustom message-sendmail-envelope-from nil
   "*Envelope-from when sending mail with sendmail.
 If this is nil, use `user-mail-address'.  If it is the symbol
 `header', use the From: header of the message."
+  :version "22.1"
   :type '(choice (string :tag "From name")
                 (const :tag "Use From: header from message" header)
                 (const :tag "Use `user-mail-address'" nil))
+  :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."
   :group 'message-sending
+  :link '(custom-manual "(message)Mail Variables")
   :type 'file)
 
 (defcustom message-qmail-inject-args nil
@@ -683,14 +779,10 @@ For e.g., if you wish to set the envelope sender address so that bounces
 go to the right place or to deal with listserv's usage of that address, you
 might set this variable to '(\"-f\" \"you@some.where\")."
   :group 'message-sending
+  :link '(custom-manual "(message)Mail Variables")
   :type '(choice (function)
                 (repeat string)))
 
-(defvar message-cater-to-broken-inn t
-  "Non-nil means Gnus should not fold the `References' header.
-Folding `References' makes ancient versions of INN create incorrect
-NOV lines.")
-
 (eval-when-compile
   (defvar gnus-post-method)
   (defvar gnus-select-method))
@@ -716,16 +808,16 @@ variable isn't used."
 ;; will *not* have a `References:' header if `message-generate-headers-first'
 ;; is nil.  See: http://article.gmane.org/gmane.emacs.gnus.general/51138
 (defcustom message-generate-headers-first '(references)
-  "*If non-nil, generate all required headers before composing.
-The variables `message-required-news-headers' and
+  "Which headers should be generated before starting to compose a message.
+If t, generate all required headers.  This can also be a list of headers to
+generate.  The variables `message-required-news-headers' and
 `message-required-mail-headers' specify which headers to generate.
-This can also be a list of headers that should be generated before
-composing.
 
 Note that the variable `message-deletable-headers' specifies headers which
 are to be deleted and then re-generated before sending, so this variable
 will not have a visible effect for those headers."
   :group 'message-headers
+  :link '(custom-manual "(message)Message Headers")
   :type '(choice (const :tag "None" nil)
                  (const :tag "References" '(references))
                  (const :tag "All" t)
@@ -735,11 +827,13 @@ will not have a visible effect for those headers."
   "Normal hook, run each time a new outgoing message is initialized.
 The function `message-setup' runs this hook."
   :group 'message-various
+  :link '(custom-manual "(message)Various Message Variables")
   :type 'hook)
 
 (defcustom message-cancel-hook nil
   "Hook run when cancelling articles."
   :group 'message-various
+  :link '(custom-manual "(message)Various Message Variables")
   :type 'hook)
 
 (defcustom message-signature-setup-hook nil
@@ -747,6 +841,7 @@ The function `message-setup' runs this hook."
 It is run after the headers have been inserted and before
 the signature is inserted."
   :group 'message-various
+  :link '(custom-manual "(message)Various Message Variables")
   :type 'hook)
 
 (defcustom message-mode-hook nil
@@ -762,13 +857,15 @@ the signature is inserted."
 (defcustom message-header-setup-hook nil
   "Hook called narrowed to the headers when setting up a message buffer."
   :group 'message-various
+  :link '(custom-manual "(message)Various Message Variables")
   :type 'hook)
 
 (defcustom message-minibuffer-local-map
   (let ((map (make-sparse-keymap 'message-minibuffer-local-map)))
     (set-keymap-parent map minibuffer-local-map)
     map)
-  "Keymap for `message-read-from-minibuffer'.")
+  "Keymap for `message-read-from-minibuffer'."
+  :version "22.1")
 
 ;;;###autoload
 (defcustom message-citation-line-function 'message-insert-citation-line
@@ -779,6 +876,7 @@ Note that Gnus provides a feature where the reader can click on
 people who read your message will have to change their Gnus
 configuration.  See the variable `gnus-cite-attribution-suffix'."
   :type 'function
+  :link '(custom-manual "(message)Insertion Variables")
   :group 'message-insertion)
 
 ;;;###autoload
@@ -787,19 +885,23 @@ configuration.  See the variable `gnus-cite-attribution-suffix'."
 Fix `message-cite-prefix-regexp' if it is set to an abnormal value.
 See also `message-yank-cited-prefix'."
   :type 'string
+  :link '(custom-manual "(message)Insertion Variables")
   :group 'message-insertion)
 
 (defcustom message-yank-cited-prefix ">"
   "*Prefix inserted on cited or empty lines of yanked messages.
 Fix `message-cite-prefix-regexp' if it is set to an abnormal value.
 See also `message-yank-prefix'."
+  :version "22.1"
   :type 'string
+  :link '(custom-manual "(message)Insertion Variables")
   :group 'message-insertion)
 
 (defcustom message-indentation-spaces 3
   "*Number of spaces to insert at the beginning of each cited line.
 Used by `message-yank-original' via `message-yank-cite'."
   :group 'message-insertion
+  :link '(custom-manual "(message)Insertion Variables")
   :type 'integer)
 
 ;;;###autoload
@@ -812,6 +914,7 @@ Note that `message-cite-original' uses `mail-citation-hook' if that is non-nil."
                (function-item message-cite-original-without-signature)
                (function-item sc-cite-original)
                (function :tag "Other"))
+  :link '(custom-manual "(message)Insertion Variables")
   :group 'message-insertion)
 
 ;;;###autoload
@@ -821,6 +924,7 @@ This can also be a list of functions.  Each function can find the
 citation between (point) and (mark t).  And each function should leave
 point and mark around the citation text as modified."
   :type 'function
+  :link '(custom-manual "(message)Insertion Variables")
   :group 'message-insertion)
 
 ;;;###autoload
@@ -830,6 +934,7 @@ If t, the `message-signature-file' file will be inserted instead.
 If a function, the result from the function will be used instead.
 If a form, the result from the form will be used instead."
   :type 'sexp
+  :link '(custom-manual "(message)Insertion Variables")
   :group 'message-insertion)
 
 ;;;###autoload
@@ -838,18 +943,22 @@ If a form, the result from the form will be used instead."
 Ignored if the named file doesn't exist.
 If nil, don't insert a signature."
   :type '(choice file (const :tags "None" nil))
+  :link '(custom-manual "(message)Insertion Variables")
   :group 'message-insertion)
 
 ;;;###autoload
 (defcustom message-signature-insert-empty-line t
   "*If non-nil, insert an empty line before the signature separator."
+  :version "22.1"
   :type 'boolean
+  :link '(custom-manual "(message)Insertion Variables")
   :group 'message-insertion)
 
 (defcustom message-distribution-function nil
   "*Function called to return a Distribution header."
   :group 'message-news
   :group 'message-headers
+  :link '(custom-manual "(message)News Headers")
   :type '(choice function (const nil)))
 
 (defcustom message-expires 14
@@ -898,18 +1007,21 @@ It is a vector of the following headers:
 It is inserted before you edit the message, so you can edit or delete
 these lines."
   :group 'message-headers
+  :link '(custom-manual "(message)Message Headers")
   :type 'message-header-lines)
 
 (defcustom message-default-mail-headers ""
   "*A string of header lines to be inserted in outgoing mails."
   :group 'message-headers
   :group 'message-mail
+  :link '(custom-manual "(message)Mail Headers")
   :type 'message-header-lines)
 
 (defcustom message-default-news-headers ""
   "*A string of header lines to be inserted in outgoing news articles."
   :group 'message-headers
   :group 'message-news
+  :link '(custom-manual "(message)News Headers")
   :type 'message-header-lines)
 
 ;; Note: could use /usr/ucb/mail instead of sendmail;
@@ -937,6 +1049,7 @@ these lines."
 The value should be an expression to test whether the problem will
 actually occur."
   :group 'message-sending
+  :link '(custom-manual "(message)Mail Variables")
   :type 'sexp)
 
 ;;;###autoload
@@ -975,6 +1088,7 @@ mail aliases off."
   "*Directory where Message auto-saves buffers if Gnus isn't running.
 If nil, Message won't auto-save."
   :group 'message-buffers
+  :link '(custom-manual "(message)Various Message Variables")
   :type '(choice directory (const :tag "Don't auto-save" nil)))
 
 (defcustom message-default-charset
@@ -983,6 +1097,7 @@ If nil, Message won't auto-save."
 If nil, you might be asked to input the charset."
   :version "21.1"
   :group 'message
+  :link '(custom-manual "(message)Various Message Variables")
   :type 'symbol)
 
 (defcustom message-dont-reply-to-names
@@ -991,6 +1106,7 @@ If nil, you might be asked to input the charset."
 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))
 
@@ -1010,12 +1126,27 @@ candidates:
   (or (not (listp message-shoot-gnksa-feet))
       (memq feature message-shoot-gnksa-feet)))
 
-(defcustom message-hidden-headers nil
+(defcustom message-hidden-headers "^References:"
   "Regexp of headers to be hidden when composing new messages.
 This can also be a list of regexps to match headers.  Or a list
-starting with `not' and followed by regexps.."
+starting with `not' and followed by regexps."
+  :version "22.1"
   :group 'message
-  :type '(repeat regexp))
+  :link '(custom-manual "(message)Message Headers")
+  :type '(choice
+         :format "%{%t%}: %[Value Type%] %v"
+         (regexp :menu-tag "regexp" :format "regexp\n%t: %v")
+         (repeat :menu-tag "(regexp ...)" :format "(regexp ...)\n%v%i"
+                 (regexp :format "%t: %v"))
+         (cons :menu-tag "(not regexp ...)" :format "(not regexp ...)\n%v"
+               (const not)
+               (repeat :format "%v%i"
+                       (regexp :format "%t: %v")))))
+
+(defcustom message-cite-articles-with-x-no-archive t
+  "If non-nil, cite text from articles that has X-No-Archive set."
+  :group 'message
+  :type 'boolean)
 
 ;;; Internal variables.
 ;;; Well, not really internal.
@@ -1226,6 +1357,7 @@ The cdr of each entry is a function for applying the face to a region.")
 This hook is run quite early when sending."
   :group 'message-various
   :options '(ispell-message)
+  :link '(custom-manual "(message)Various Message Variables")
   :type 'hook)
 
 (defcustom message-send-mail-hook nil
@@ -1233,6 +1365,7 @@ This hook is run quite early when sending."
 This hook is run very late -- just before the message is sent as
 mail."
   :group 'message-various
+  :link '(custom-manual "(message)Various Message Variables")
   :type 'hook)
 
 (defcustom message-send-news-hook nil
@@ -1240,6 +1373,7 @@ mail."
 This hook is run very late -- just before the message is sent as
 news."
   :group 'message-various
+  :link '(custom-manual "(message)Various Message Variables")
   :type 'hook)
 
 (defcustom message-sent-hook nil
@@ -1263,6 +1397,7 @@ The lower bound of message size in characters, beyond which the message
 should be sent in several parts.  If it is nil, the size is unlimited."
   :version "21.1"
   :group 'message-buffers
+  :link '(custom-manual "(message)Mail Variables")
   :type '(choice (const :tag "unlimited" nil)
                 (integer 1000000)))
 
@@ -1270,6 +1405,7 @@ should be sent in several parts.  If it is nil, the size is unlimited."
   "A regexp to match the alternative email addresses.
 The first matched address (not primary one) is used in the From field."
   :group 'message-headers
+  :link '(custom-manual "(message)Message Headers")
   :type '(choice (const :tag "Always use primary" nil)
                 regexp))
 
@@ -1283,6 +1419,7 @@ subaddresses.  So if the first address appears in the recipient list
 for a message, the subaddresses will be removed (if present) before
 the mail is sent.  All addresses in this structure should be
 downcased."
+  :version "22.1"
   :group 'message-headers
   :type '(repeat (repeat string)))
 
@@ -1290,6 +1427,7 @@ downcased."
   "Like `mail-user-agent'.
 Except if it is nil, use Gnus native MUA; if it is t, use
 `mail-user-agent'."
+  :version "22.1"
   :type '(radio (const :tag "Gnus native"
                       :format "%t\n"
                       nil)
@@ -1313,16 +1451,18 @@ If this variable is non-nil, pose the question \"Reply to all
 recipients?\" before a wide reply to multiple recipients.  If the user
 answers yes, reply to all recipients as usual.  If the user answers
 no, only reply back to the author."
-  :version "21.3"
+  :version "22.1"
   :group 'message-headers
+  :link '(custom-manual "(message)Wide Reply")
   :type 'boolean)
 
 (defcustom message-user-fqdn nil
   "*Domain part of Messsage-Ids."
+  :version "22.1"
   :group 'message-headers
   :link '(custom-manual "(message)News Headers")
   :type '(radio (const :format "%v  " nil)
-               (string :format "FQDN: %v\n" :size 0)))
+               (string :format "FQDN: %v")))
 
 (defcustom message-use-idna (and (condition-case nil (require 'idna)
                                   (file-error))
@@ -1330,11 +1470,20 @@ no, only reply back to the author."
                                 (executable-find idna-program)
                                 'ask)
   "Whether to encode non-ASCII in domain names into ASCII according to IDNA."
+  :version "22.1"
   :group 'message-headers
+  :link '(custom-manual "(message)IDNA")
   :type '(choice (const :tag "Ask" ask)
                 (const :tag "Never" nil)
                 (const :tag "Always" t)))
 
+(defcustom message-generate-hashcash nil
+  "*Whether to generate X-Hashcash: headers.
+You must have the \"hashcash\" binary installed, see `hashcash-path'."
+  :group 'message-headers
+  :link '(custom-manual "(message)Mail Headers")
+  :type 'boolean)
+
 ;;; Internal variables.
 
 (defvar message-sending-message "Sending...")
@@ -1417,10 +1566,17 @@ no, only reply back to the author."
          "^|? *---+ +Message text follows: +---+ *|?$")
   "A regexp that matches the separator before the text of a failed message.")
 
+(defvar message-field-fillers
+  '((To message-fill-field-address)
+    (Cc message-fill-field-address)
+    (From message-fill-field-address))
+  "Alist of header names/filler functions.")
+
 (defvar message-header-format-alist
-  `((Newsgroups)
-    (To . message-fill-address)
-    (Cc . message-fill-address)
+  `((From)
+    (Newsgroups)
+    (To)
+    (Cc)
     (Subject)
     (In-Reply-To)
     (Fcc)
@@ -1454,29 +1610,36 @@ no, only reply back to the author."
          "\\)")
   "Regular expression that matches a valid FQDN."
   ;; see also: gnus-button-valid-fqdn-regexp
+  :version "22.1"
   :group 'message-headers
   :type 'regexp)
 
 (eval-and-compile
+  (autoload 'gnus-alive-p "gnus-util")
+  (autoload 'gnus-delay-article "gnus-delay")
+  (autoload 'gnus-extract-address-components "gnus-util")
+  (autoload 'gnus-find-method-for-group "gnus")
+  (autoload 'gnus-group-decoded-name "gnus-group")
+  (autoload 'gnus-group-name-charset "gnus-group")
+  (autoload 'gnus-group-name-decode "gnus-group")
+  (autoload 'gnus-groups-from-server "gnus")
+  (autoload 'gnus-make-local-hook "gnus-util")
+  (autoload 'gnus-open-server "gnus-int")
+  (autoload 'gnus-output-to-mail "gnus-util")
+  (autoload 'gnus-output-to-rmail "gnus-util")
+  (autoload 'gnus-request-post "gnus-int")
+  (autoload 'gnus-server-string "gnus")
+  (autoload 'idna-to-ascii "idna")
   (autoload 'message-setup-toolbar "messagexmas")
   (autoload 'mh-new-draft-name "mh-comp")
   (autoload 'mh-send-letter "mh-comp")
-  (autoload 'gnus-point-at-eol "gnus-util")
-  (autoload 'gnus-point-at-bol "gnus-util")
-  (autoload 'gnus-output-to-rmail "gnus-util")
-  (autoload 'gnus-output-to-mail "gnus-util")
   (autoload 'nndraft-request-associate-buffer "nndraft")
   (autoload 'nndraft-request-expire-articles "nndraft")
-  (autoload 'gnus-open-server "gnus-int")
-  (autoload 'gnus-request-post "gnus-int")
-  (autoload 'gnus-alive-p "gnus-util")
-  (autoload 'gnus-server-string "gnus")
-  (autoload 'gnus-group-name-charset "gnus-group")
-  (autoload 'gnus-group-name-decode "gnus-group")
-  (autoload 'gnus-groups-from-server "gnus")
-  (autoload 'rmail-output "rmailout")
-  (autoload 'gnus-delay-article "gnus-delay")
-  (autoload 'gnus-make-local-hook "gnus-util"))
+  (autoload 'nnvirtual-find-group-art "nnvirtual")
+  (autoload 'rmail-dont-reply-to "mail-utils")
+  (autoload 'rmail-msg-is-pruned "rmail")
+  (autoload 'rmail-msg-restore-non-pruned-header "rmail")
+  (autoload 'rmail-output "rmailout"))
 
 \f
 
@@ -1513,11 +1676,11 @@ is used by default."
   (if (not header)
       nil
     (let ((regexp (format "[%s]+" (or separator ",")))
-         (beg 1)
          (first t)
-         quoted elems paren)
+         beg quoted elems paren)
       (with-temp-buffer
        (mm-enable-multibyte)
+       (setq beg (point-min))
        (insert header)
        (goto-char (point-min))
        (while (not (eobp))
@@ -1556,25 +1719,30 @@ is used by default."
 The buffer is expected to be narrowed to just the header of the message;
 see `message-narrow-to-headers-or-head'."
   (let* ((inhibit-point-motion-hooks t)
-        (case-fold-search t)
         (value (mail-fetch-field header nil (not not-all))))
     (when value
       (while (string-match "\n[\t ]+" value)
        (setq value (replace-match " " t t value)))
-      (set-text-properties 0 (length value) nil value)
       value)))
 
+(defun message-field-value (header &optional not-all)
+  "The same as `message-fetch-field', only narrow to the headers first."
+  (save-excursion
+    (save-restriction
+      (message-narrow-to-headers-or-head)
+      (message-fetch-field header not-all))))
+
 (defun message-narrow-to-field ()
   "Narrow the buffer to the header on the current line."
   (beginning-of-line)
+  (while (looking-at "[ \t]")
+    (forward-line -1))
   (narrow-to-region
    (point)
    (progn
      (forward-line 1)
      (if (re-search-forward "^[^ \n\t]" nil t)
-        (progn
-          (beginning-of-line)
-          (point))
+        (point-at-bol)
        (point-max))))
   (goto-char (point-min)))
 
@@ -1672,6 +1840,7 @@ Leading \"Re: \" is not stripped by this function.  Use the function
 ;;;###autoload
 (defun message-change-subject (new-subject)
   "Ask for NEW-SUBJECT header, append (was: <Old Subject>)."
+  ;; <URL:http://www.landfield.com/usefor/drafts/draft-ietf-usefor-useage--1.02.unpaged>
   (interactive
    (list
     (read-from-minibuffer "New subject: ")))
@@ -1706,7 +1875,7 @@ Leading \"Re: \" is not stripped by this function.  Use the function
 See `message-mark-insert-begin' and `message-mark-insert-end'."
   (interactive "r")
   (save-excursion
-    ; add to the end of the region first, otherwise end would be invalid
+    ;; add to the end of the region first, otherwise end would be invalid
     (goto-char end)
     (insert message-mark-insert-end)
     (goto-char beg)
@@ -2049,6 +2218,12 @@ Point is left at the beginning of the narrowed-to region."
             (1+ max)))))
       (message-sort-headers-1))))
 
+(defun message-kill-address ()
+  "Kill the address under point."
+  (interactive)
+  (let ((start (point)))
+    (message-skip-to-next-address)
+    (kill-region start (point))))
 
 \f
 
@@ -2121,11 +2296,11 @@ Point is left at the beginning of the narrowed-to region."
   (define-key message-mode-map "\C-c\C-d" 'message-dont-send)
   (define-key message-mode-map "\C-c\n" 'gnus-delay-article)
 
+  (define-key message-mode-map "\C-c\M-k" 'message-kill-address)
   (define-key message-mode-map "\C-c\C-e" 'message-elide-region)
   (define-key message-mode-map "\C-c\C-v" 'message-delete-not-region)
   (define-key message-mode-map "\C-c\C-z" 'message-kill-to-signature)
   (define-key message-mode-map "\M-\r" 'message-newline-and-reformat)
-  ;;(define-key message-mode-map "\M-q" 'message-fill-paragraph)
   (define-key message-mode-map [remap split-line]  'message-split-line)
 
   (define-key message-mode-map "\C-c\C-a" 'mml-attach-file)
@@ -2181,9 +2356,6 @@ Point is left at the beginning of the narrowed-to region."
 (easy-menu-define
   message-mode-field-menu message-mode-map ""
   `("Field"
-    ["Fetch To" message-insert-to t]
-    ["Fetch Newsgroups" message-insert-newsgroups t]
-    "----"
     ["To" message-goto-to t]
     ["From" message-goto-from t]
     ["Subject" message-goto-subject t]
@@ -2207,6 +2379,7 @@ Point is left at the beginning of the narrowed-to region."
     ["Summary" message-goto-summary t]
     ["Keywords" message-goto-keywords t]
     ["Newsgroups" message-goto-newsgroups t]
+    ["Fetch Newsgroups" message-insert-newsgroups t]
     ["Followup-To" message-goto-followup-to t]
     ;; ["Followup-To (with note in body)" message-cross-post-followup-to t]
     ["Crosspost / Followup-To..." message-cross-post-followup-to t]
@@ -2214,8 +2387,19 @@ Point is left at the beginning of the narrowed-to region."
     ["X-No-Archive:" message-add-archive-header t ]
     "----"
     ;; (typical) mailing-lists stuff
+    ["Fetch To" message-insert-to
+     ,@(if (featurep 'xemacs) '(t)
+        '(:help "Insert a To header that points to the author."))]
+    ["Fetch To and Cc" message-insert-wide-reply
+     ,@(if (featurep 'xemacs) '(t)
+        '(:help
+          "Insert To and Cc headers as if you were doing a wide reply."))]
+    "----"
     ["Send to list only" message-to-list-only t]
     ["Mail-Followup-To" message-goto-mail-followup-to t]
+    ["Unsubscribed list post" message-generate-unsubscribed-mail-followup-to
+     ,@(if (featurep 'xemacs) '(t)
+        '(:help "Insert a reasonable `Mail-Followup-To:' header."))]
     ["Reduce To: to Cc:" message-reduce-to-to-cc t]
     "----"
     ["Sort Headers" message-sort-headers t]
@@ -2244,7 +2428,9 @@ these properties from the message composition buffer.  However, some
 packages requires these properties to be present in order to work.
 If you use one of these packages, turn this option off, and hope the
 message composition doesn't break too bad."
+  :version "22.1"
   :group 'message-various
+  :link '(custom-manual "(message)Various Message Variables")
   :type 'boolean)
 
 (defconst message-forbidden-properties
@@ -2259,7 +2445,7 @@ message composition doesn't break too bad."
   ;; fontified: is used by font-lock.
   ;; syntax-table, local-map: I dunno.
   ;; We need to add XEmacs names to the list.
-  "Property list of with properties.forbidden in message buffers.
+  "Property list of with properties forbidden in message buffers.
 The values of the properties are ignored, only the property names are used.")
 
 (defun message-tamago-not-in-use-p (pos)
@@ -2282,11 +2468,9 @@ This function is intended to be called from `after-change-functions'.
 See also `message-forbidden-properties'."
   (when (and message-strip-special-text-properties
             (message-tamago-not-in-use-p begin))
-    (while (not (= begin end))
-      (when (not (get-text-property begin 'message-hidden))
-       (remove-text-properties begin (1+ begin)
-                               message-forbidden-properties))
-      (incf begin))))
+    (let ((buffer-read-only nil)
+         (inhibit-read-only t))
+      (remove-text-properties begin end message-forbidden-properties))))
 
 ;;;###autoload
 (define-derived-mode message-mode text-mode "Message"
@@ -2351,13 +2535,12 @@ M-RET    `message-newline-and-reformat' (break the line and reformat)."
   (set (make-local-variable 'message-checksum) nil)
   (set (make-local-variable 'message-mime-part) 0)
   (message-setup-fill-variables)
-  (set
-   (make-local-variable 'paragraph-separate)
-   (format "\\(%s\\)\\|\\(%s\\)"
-          paragraph-separate
-          "<#!*/?\\(multipart\\|part\\|external\\|mml\\|secure\\)"))
   ;; Allow using comment commands to add/remove quoting.
-  (set (make-local-variable 'comment-start) message-yank-prefix)
+  ;; (set (make-local-variable 'comment-start) message-yank-prefix)
+  (when message-yank-prefix
+    (set (make-local-variable 'comment-start) message-yank-prefix)
+    (set (make-local-variable 'comment-start-skip)
+        (concat "^" (regexp-quote message-yank-prefix) "[ \t]*")))
   (if (featurep 'xemacs)
       (message-setup-toolbar)
     (set (make-local-variable 'font-lock-defaults)
@@ -2407,7 +2590,9 @@ M-RET    `message-newline-and-reformat' (break the line and reformat)."
           "---+$\\|"              ; delimiters for forwarded messages
           page-delimiter "$\\|"        ; spoiler warnings
           ".*wrote:$\\|"               ; attribution lines
-          quote-prefix-regexp "$"))    ; empty lines in quoted text
+          quote-prefix-regexp "$\\|"   ; empty lines in quoted text
+                                       ; mml tags
+          "<#!*/?\\(multipart\\|part\\|external\\|mml\\|secure\\)"))
     (setq paragraph-separate paragraph-start)
     (setq adaptive-fill-regexp
          (concat quote-prefix-regexp "\\|" adaptive-fill-regexp))
@@ -2488,7 +2673,7 @@ M-RET    `message-newline-and-reformat' (break the line and reformat)."
 (defun message-goto-mail-followup-to ()
   "Move point to the Mail-Followup-To header."
   (interactive)
-  (message-position-on-field "Mail-Followup-To" "From"))
+  (message-position-on-field "Mail-Followup-To" "To"))
 
 (defun message-goto-keywords ()
   "Move point to the Keywords header."
@@ -2554,22 +2739,24 @@ Cc: header are also put into the MFT."
 
 (defun message-insert-to (&optional force)
   "Insert a To header that points to the author of the article being replied to.
-If the original author requested not to be sent mail, the function signals
-an error.
-With the prefix argument FORCE, insert the header anyway."
+If the original author requested not to be sent mail, don't insert unless the
+prefix FORCE is given."
   (interactive "P")
-  (let ((co (message-fetch-reply-field "mail-copies-to")))
-    (when (and (null force)
-              co
-              (or (equal (downcase co) "never")
-                  (equal (downcase co) "nobody")))
-      (error "The user has requested not to have copies sent via mail")))
-  (message-carefully-insert-headers
-   (list (cons 'To
-              (or (message-fetch-reply-field "mail-reply-to")
-                  (message-fetch-reply-field "reply-to")
-                  (message-fetch-reply-field "from")
-                  "")))))
+  (let* ((mct (message-fetch-reply-field "mail-copies-to"))
+         (dont (and mct (or (equal (downcase mct) "never")
+                           (equal (downcase mct) "nobody"))))
+         (to (or (message-fetch-reply-field "mail-reply-to")
+                 (message-fetch-reply-field "reply-to")
+                 (message-fetch-reply-field "from"))))
+    (when (and dont to)
+      (message
+       (if force
+          "Ignoring the user request not to have copies sent via mail"
+        "Complying with the user request not to have copies sent via mail")))
+    (when (and force (not to))
+      (error "No mail address in the article"))
+    (when (and to (or force (not dont)))
+      (message-carefully-insert-headers (list (cons 'To to))))))
 
 (defun message-insert-wide-reply ()
   "Insert To and Cc headers as if you were doing a wide reply."
@@ -2578,15 +2765,42 @@ With the prefix argument FORCE, insert the header anyway."
                   (message-get-reply-headers t))))
     (message-carefully-insert-headers headers)))
 
+(defcustom message-header-synonyms
+  '((To Cc Bcc))
+  "List of lists of header synonyms.
+E.g., if this list contains a member list with elements `Cc' and `To',
+then `message-carefully-insert-headers' will not insert a `To' header
+when the message is already `Cc'ed to the recipient."
+  :version "22.1"
+  :group 'message-headers
+  :link '(custom-manual "(message)Message Headers")
+  :type '(repeat sexp))
+
 (defun message-carefully-insert-headers (headers)
+  "Insert the HEADERS, an alist, into the message buffer.
+Does not insert the headers when they are already present there
+or in the synonym headers, defined by `message-header-synonyms'."
+  ;; FIXME: Should compare only the address and not the full name.  Comparison
+  ;; should be done case-folded (and with `string=' rather than
+  ;; `string-match').
+  ;; (mail-strip-quoted-names "Foo Bar <foo@bar>, bla@fasel (Bla Fasel)")
   (dolist (header headers)
-    (let ((header-name (symbol-name (car header))))
-      (when (and (message-position-on-field header-name)
-                (mail-fetch-field header-name)
-                (not (string-match "\\` *\\'"
-                                   (mail-fetch-field header-name))))
-       (insert ", "))
-      (insert (cdr header)))))
+    (let* ((header-name (symbol-name (car header)))
+           (new-header (cdr header))
+           (synonyms (loop for synonym in message-header-synonyms
+                          when (memq (car header) synonym) return synonym))
+           (old-header
+            (loop for synonym in synonyms
+                 for old-header = (mail-fetch-field (symbol-name synonym))
+                 when (and old-header (string-match new-header old-header))
+                 return synonym)))
+      (if old-header
+          (message "already have `%s' in `%s'" new-header old-header)
+       (when (and (message-position-on-field header-name)
+                   (setq old-header (mail-fetch-field header-name))
+                   (not (string-match "\\` *\\'" old-header)))
+         (insert ", "))
+        (insert new-header)))))
 
 (defun message-widen-reply ()
   "Widen the reply to include maximum recipients."
@@ -2644,16 +2858,23 @@ With the prefix argument FORCE, insert the header anyway."
   (when (message-goto-signature)
     (forward-line -2)))
 
-(defun message-kill-to-signature ()
-  "Deletes all text up to the signature."
-  (interactive)
-  (let ((point (point)))
-    (message-goto-signature)
-    (unless (eobp)
-      (end-of-line -1))
-    (kill-region point (point))
-    (unless (bolp)
-      (insert "\n"))))
+(defun message-kill-to-signature (&optional arg)
+  "Kill all text up to the signature.
+If a numberic argument or prefix arg is given, leave that number
+of lines before the signature intact."
+  (interactive "p")
+  (save-excursion
+    (save-restriction
+      (let ((point (point)))
+       (narrow-to-region point (point-max))
+       (message-goto-signature)
+       (unless (eobp)
+         (if (and arg (numberp arg))
+             (forward-line (- -1 arg))
+           (end-of-line -1)))
+       (unless (= point (point))
+         (kill-region point (point))
+         (insert "\n"))))))
 
 (defun message-newline-and-reformat (&optional arg not-break)
   "Insert four newlines, and then reformat if inside quoted text.
@@ -2748,7 +2969,9 @@ Prefix arg means justify as well."
   (interactive (list (if current-prefix-arg 'full)))
   (if (if (boundp 'filladapt-mode) filladapt-mode)
       nil
-    (message-newline-and-reformat arg t)
+    (if (message-point-in-header-p)
+       (message-fill-field)
+      (message-newline-and-reformat arg t))
     t))
 
 ;; Is it better to use `mail-header-end'?
@@ -2857,10 +3080,8 @@ Note that this should not be used in newsgroups."
       (message-remove-header "Disposition-Notification-To"))
     (message-goto-eoh)
     (insert (format "Disposition-Notification-To: %s\n"
-                   (or (save-excursion
-                         (save-restriction
-                           (message-narrow-to-headers)
-                           (message-fetch-field "From")))
+                   (or (message-field-value "Reply-to")
+                       (message-field-value "From")
                        (message-make-from))))))
 
 (defun message-elide-region (b e)
@@ -3039,7 +3260,7 @@ prefix, and don't delete any headers."
 (defun message-yank-buffer (buffer)
   "Insert BUFFER into the current buffer and quote it."
   (interactive "bYank buffer: ")
-  (let ((message-reply-buffer buffer))
+  (let ((message-reply-buffer (get-buffer buffer)))
     (save-window-excursion
       (message-yank-original))))
 
@@ -3056,13 +3277,27 @@ prefix, and don't delete any headers."
 
 (defun message-cite-original-without-signature ()
   "Cite function in the standard Message manner."
-  (let ((start (point))
-       (end (mark t))
-       (functions
-        (when message-indent-citation-function
-          (if (listp message-indent-citation-function)
-              message-indent-citation-function
-            (list message-indent-citation-function)))))
+  (let* ((start (point))
+        (end (mark t))
+        (functions
+         (when message-indent-citation-function
+           (if (listp message-indent-citation-function)
+               message-indent-citation-function
+             (list message-indent-citation-function))))
+        ;; This function may be called by `gnus-summary-yank-message' and
+        ;; may insert a different article from the original.  So, we will
+        ;; modify the value of `message-reply-headers' with that article.
+        (message-reply-headers
+         (save-restriction
+           (narrow-to-region start end)
+           (message-narrow-to-head-1)
+           (vector 0
+                   (or (message-fetch-field "subject") "none")
+                   (message-fetch-field "from")
+                   (message-fetch-field "date")
+                   (message-fetch-field "message-id" t)
+                   (message-fetch-field "references")
+                   0 0 ""))))
     (mml-quote-region start end)
     ;; Allow undoing.
     (undo-boundary)
@@ -3078,8 +3313,7 @@ prefix, and don't delete any headers."
        ;; Insert a blank line if it is peeled off.
        (insert "\n")))
     (goto-char start)
-    (while functions
-      (funcall (pop functions)))
+    (mapc 'funcall functions)
     (when message-citation-line-function
       (unless (bolp)
        (insert "\n"))
@@ -3091,21 +3325,43 @@ prefix, and don't delete any headers."
   (if (and (boundp 'mail-citation-hook)
           mail-citation-hook)
       (run-hooks 'mail-citation-hook)
-    (let ((start (point))
-         (end (mark t))
-         (functions
-          (when message-indent-citation-function
-            (if (listp message-indent-citation-function)
-                message-indent-citation-function
-              (list message-indent-citation-function)))))
+    (let* ((start (point))
+          (end (mark t))
+          (x-no-archive nil)
+          (functions
+           (when message-indent-citation-function
+             (if (listp message-indent-citation-function)
+                 message-indent-citation-function
+               (list message-indent-citation-function))))
+          ;; This function may be called by `gnus-summary-yank-message' and
+          ;; may insert a different article from the original.  So, we will
+          ;; modify the value of `message-reply-headers' with that article.
+          (message-reply-headers
+           (save-restriction
+             (narrow-to-region start end)
+             (message-narrow-to-head-1)
+             (setq x-no-archive (message-fetch-field "x-no-archive"))
+             (vector 0
+                     (or (message-fetch-field "subject") "none")
+                     (message-fetch-field "from")
+                     (message-fetch-field "date")
+                     (message-fetch-field "message-id" t)
+                     (message-fetch-field "references")
+                     0 0 ""))))
       (mml-quote-region start end)
       (goto-char start)
-      (while functions
-       (funcall (pop functions)))
+      (mapc 'funcall functions)
       (when message-citation-line-function
        (unless (bolp)
          (insert "\n"))
-       (funcall message-citation-line-function)))))
+       (funcall message-citation-line-function))
+      (when (and x-no-archive
+                (not message-cite-articles-with-x-no-archive)
+                (string-match "yes" x-no-archive))
+       (undo-boundary)
+       (delete-region (point) (mark t))
+       (insert "> [Quoted text removed due to X-No-Archive]\n")
+       (forward-line -1)))))
 
 (defun message-insert-citation-line ()
   "Insert a simple citation line."
@@ -3209,8 +3465,15 @@ Instead, just auto-save the buffer and then bury it."
                          (file-exists-p auto-save-file-name))
                     (and file-name
                          (file-exists-p file-name)))
-              (yes-or-no-p (format "Remove the backup file%s? "
-                                   (if modified " too" ""))))
+                (progn
+                  ;; If the message buffer has lived in a dedicated window,
+                  ;; `kill-buffer' has killed the frame.  Thus the
+                  ;; `yes-or-no-p' may show up in a lowered frame.  Make sure
+                  ;; that the user can see the question by raising the
+                  ;; current frame:
+                  (raise-frame)
+                  (yes-or-no-p (format "Remove the backup file%s? "
+                                       (if modified " too" "")))))
        (ignore-errors
          (delete-file auto-save-file-name))
        (let ((message-draft-article draft-article))
@@ -3221,8 +3484,7 @@ Instead, just auto-save the buffer and then bury it."
   "Bury this mail BUFFER."
   (let ((newbuf (other-buffer buffer)))
     (bury-buffer buffer)
-    (if (and (fboundp 'frame-parameters)
-            (cdr (assq 'dedicated (frame-parameters)))
+    (if (and (window-dedicated-p (selected-window))
             (not (null (delq (selected-frame) (visible-frame-list)))))
        (delete-frame (selected-frame))
       (switch-to-buffer newbuf))))
@@ -3310,16 +3572,31 @@ It should typically alter the sending method in some way or other."
 (put 'message-check 'lisp-indent-function 1)
 (put 'message-check 'edebug-form-spec '(form body))
 
-(defun message-text-with-property (prop)
-  "Return a list of all points where the text has PROP."
-  (let ((points nil)
-       (point (point-min)))
-    (save-excursion
-      (while (< point (point-max))
-       (when (get-text-property point prop)
-         (push point points))
-       (incf point)))
-    (nreverse points)))
+(defun message-text-with-property (prop &optional start end reverse)
+  "Return a list of start and end positions where the text has PROP.
+START and END bound the search, they default to `point-min' and
+`point-max' respectively.  If REVERSE is non-nil, find text which does
+not have PROP."
+  (unless start
+    (setq start (point-min)))
+  (unless end
+    (setq end (point-max)))
+  (let (next regions)
+    (if reverse
+       (while (and start
+                   (setq start (text-property-any start end prop nil)))
+         (setq next (next-single-property-change start prop nil end))
+         (push (cons start (or next end)) regions)
+         (setq start next))
+      (while (and start
+                 (or (get-text-property start prop)
+                     (and (setq start (next-single-property-change
+                                       start prop nil end))
+                          (get-text-property start prop))))
+       (setq next (text-property-any start end prop nil))
+       (push (cons start (or next end)) regions)
+       (setq start next)))
+    (nreverse regions)))
 
 (defun message-fix-before-sending ()
   "Do various things to make the message nice before sending it."
@@ -3328,22 +3605,22 @@ It should typically alter the sending method in some way or other."
   (unless (bolp)
     (insert "\n"))
   ;; Make the hidden headers visible.
-  (let ((points (message-text-with-property 'message-hidden)))
-    (when points
-      (goto-char (car points))
-      (dolist (point points)
-       (add-text-properties point (1+ point)
-                            '(invisible nil intangible nil)))))
+  (widen)
+  ;; Sort headers before sending the message.
+  (message-sort-headers)
   ;; Make invisible text visible.
   ;; It doesn't seem as if this is useful, since the invisible property
   ;; is clobbered by an after-change hook anyhow.
   (message-check 'invisible-text
-    (let ((points (message-text-with-property 'invisible)))
-      (when points
-       (goto-char (car points))
-       (dolist (point points)
-         (put-text-property point (1+ point) 'invisible nil)
-         (message-overlay-put (message-make-overlay point (1+ point))
+    (let ((regions (message-text-with-property 'invisible))
+         from to)
+      (when regions
+       (while regions
+         (setq from (caar regions)
+               to (cdar regions)
+               regions (cdr regions))
+         (put-text-property from to 'invisible nil)
+         (message-overlay-put (message-make-overlay from to)
                               'face 'highlight))
        (unless (yes-or-no-p
                 "Invisible text found and made visible; continue sending? ")
@@ -3356,9 +3633,11 @@ It should typically alter the sending method in some way or other."
        (when (let ((char (char-after)))
                (or (< (mm-char-int char) 128)
                    (and (mm-multibyte-p)
-                        (> (length (mm-find-mime-charset-region
-                                    (point) (point-max)))
-                           1))))
+                        (memq (char-charset char)
+                              '(eight-bit-control eight-bit-graphic
+                                                  control-1))
+                        (not (get-text-property
+                              (point) 'untranslated-utf-8)))))
          (message-overlay-put (message-make-overlay (point) (1+ (point)))
                               'face 'highlight)
          (setq found t))
@@ -3385,7 +3664,9 @@ It should typically alter the sending method in some way or other."
                           ;; use find-coding-systems-region.
                           (memq (char-charset char)
                                 '(eight-bit-control eight-bit-graphic
-                                                    control-1)))))
+                                                    control-1))
+                          (not (get-text-property
+                                (point) 'untranslated-utf-8)))))
            (if (eq choice ?i)
                (message-kill-all-overlays)
              (delete-char 1)
@@ -3410,16 +3691,15 @@ It should typically alter the sending method in some way or other."
 (defun message-do-actions (actions)
   "Perform all actions in ACTIONS."
   ;; Now perform actions on successful sending.
-  (while actions
+  (dolist (action actions)
     (ignore-errors
       (cond
        ;; A simple function.
-       ((functionp (car actions))
-       (funcall (car actions)))
+       ((functionp action)
+       (funcall action))
        ;; Something to be evaled.
        (t
-       (eval (car actions)))))
-    (pop actions)))
+       (eval action))))))
 
 (defun message-send-mail-partially ()
   "Send mail as message/partial."
@@ -3504,6 +3784,14 @@ It should typically alter the sending method in some way or other."
              (gnus-setup-posting-charset nil)
            message-posting-charset))
         (headers message-required-mail-headers))
+    (when message-generate-hashcash
+      (message "Generating hashcash...")
+      ;; Wait for calculations already started to finish...
+      (hashcash-wait-async)
+      ;; ...and do calculations not already done.  mail-add-payment
+      ;; will leave existing X-Hashcash headers alone.
+      (mail-add-payment)
+      (message "Generating hashcash...done"))
     (save-restriction
       (message-narrow-to-headers)
       ;; Generate the Mail-Followup-To header if the header is not there...
@@ -3571,13 +3859,13 @@ It should typically alter the sending method in some way or other."
                                   "content-transfer-encoding")))))))
            (message-insert-courtesy-copy))
          (if (or (not message-send-mail-partially-limit)
-                 (< (point-max) message-send-mail-partially-limit)
+                 (< (buffer-size) message-send-mail-partially-limit)
                  (not (message-y-or-n-p
                        "The message size is too large, split? "
                        t
                        "\
 The message size, "
-                       (/ (point-max) 1000) "KB, is too large.
+                       (/ (buffer-size) 1000) "KB, is too large.
 
 Some mail gateways (MTA's) bounce large messages.  To avoid the
 problem, answer `y', and the message will be split into several
@@ -3630,8 +3918,7 @@ If you always want Gnus to send messages in one piece, set
            (when (eval message-mailer-swallows-blank-line)
              (newline))
            (when message-interactive
-             (save-excursion
-               (set-buffer errbuf)
+             (with-current-buffer errbuf
                (erase-buffer))))
          (let* ((default-directory "/")
                 (coding-system-for-write message-send-coding-system)
@@ -3666,7 +3953,7 @@ If you always want Gnus to send messages in one piece, set
            (save-excursion
              (set-buffer errbuf)
              (goto-char (point-min))
-             (while (re-search-forward "\n\n* *" nil t)
+             (while (re-search-forward "\n+ *" nil t)
                (replace-match "; "))
              (if (not (zerop (buffer-size)))
                  (error "Sending...failed to %s"
@@ -3688,8 +3975,8 @@ to find out how to use this."
   (case
       (let ((coding-system-for-write message-send-coding-system))
        (apply
-        'call-process-region 1 (point-max) message-qmail-inject-program
-        nil nil nil
+        'call-process-region (point-min) (point-max)
+        message-qmail-inject-program nil nil nil
         ;; qmail-inject's default behaviour is to look for addresses on the
         ;; command line; if there're none, it scans the headers.
         ;; yes, it does The Right Thing w.r.t. Resent-To and it's kin.
@@ -3740,14 +4027,15 @@ to find out how to use this."
   "Send the prepared message buffer with `smtpmail-send-it'.
 This only differs from `smtpmail-send-it' that this command evaluates
 `message-send-mail-hook' just before sending a message.  It is useful
-if your ISP requires the POP-before-SMTP authentication.  See the
-documentation for the function `mail-source-touch-pop'."
+if your ISP requires the POP-before-SMTP authentication.  See the Gnus
+manual for details."
   (run-hooks 'message-send-mail-hook)
   (smtpmail-send-it))
 
 (defun message-canlock-generate ()
   "Return a string that is non-trivial to guess.
 Do not use this for anything important, it is cryptographically weak."
+  (require 'sha1)
   (let (sha1-maximum-internal-length)
     (sha1 (concat (message-unique-id)
                  (format "%x%x%x" (random) (random t) (random))
@@ -4218,7 +4506,9 @@ Otherwise, generate and save a value for `canlock-password' first."
             nil))))
    ;; Check for control characters.
    (message-check 'control-chars
-     (if (re-search-forward "[\000-\007\013\015-\032\034-\037\200-\237]" nil t)
+     (if (re-search-forward
+         (mm-string-as-multibyte "[\000-\007\013\015-\032\034-\037\200-\237]")
+         nil t)
         (y-or-n-p
          "The article contains control characters.  Really post? ")
        t))
@@ -4374,24 +4664,8 @@ Otherwise, generate and save a value for `canlock-password' first."
 (defun message-make-date (&optional now)
   "Make a valid data header.
 If NOW, use that time instead."
-  (let* ((now (or now (current-time)))
-        (zone (nth 8 (decode-time now)))
-        (sign "+"))
-    (when (< zone 0)
-      (setq sign "-")
-      (setq zone (- zone)))
-    (concat
-     ;; The day name of the %a spec is locale-specific.  Pfff.
-     (format "%s, " (capitalize (car (rassoc (nth 6 (decode-time now))
-                                            parse-time-weekdays))))
-     (format-time-string "%d" now)
-     ;; The month name of the %b spec is locale-specific.  Pfff.
-     (format " %s "
-            (capitalize (car (rassoc (nth 4 (decode-time now))
-                                     parse-time-months))))
-     (format-time-string "%Y %H:%M:%S " now)
-     ;; We do all of this because XEmacs doesn't have the %z spec.
-     (format "%s%02d%02d" sign (/ zone 3600) (/ (% zone 3600) 60)))))
+  (let ((system-time-locale "C"))
+    (format-time-string "%a, %d %b %Y %T %z" now)))
 
 (defun message-make-message-id ()
   "Make a unique Message-ID."
@@ -4630,7 +4904,8 @@ give as trustworthy answer as possible."
         (user-domain
          (if (and user-mail
                   (string-match "@\\(.*\\)\\'" user-mail))
-             (match-string 1 user-mail))))
+             (match-string 1 user-mail)))
+        (case-fold-search t))
     (cond
      ((and message-user-fqdn
           (stringp message-user-fqdn)
@@ -4726,57 +5001,25 @@ subscribed address (and not the additional To and Cc header contents)."
              list
            msg-recipients))))))
 
-(defun message-idna-inside-rhs-p ()
-  "Return t iff point is inside a RHS (heuristically).
-Only works properly if header contains mailbox-list or address-list.
-I.e., calling it on a Subject: header is useless."
-  (save-restriction
-    (narrow-to-region (save-excursion (or (re-search-backward "^[^ \t]" nil t)
-                                         (point-min)))
-                     (save-excursion (or (re-search-forward "^[^ \t]" nil t)
-                                         (point-max))))
-    (if (re-search-backward "[\\\n\r\t ]"
-                           (save-excursion (search-backward "@" nil t)) t)
-       ;; whitespace between @ and point
-       nil
-      (let ((dquote 1) (paren 1))
-       (while (save-excursion (re-search-backward "[^\\]\"" nil t dquote))
-         (incf dquote))
-       (while (save-excursion (re-search-backward "[^\\]\(" nil t paren))
-         (incf paren))
-       (and (= (% dquote 2) 1) (= (% paren 2) 1))))))
-
-(autoload 'idna-to-ascii "idna")
-
 (defun message-idna-to-ascii-rhs-1 (header)
   "Interactively potentially IDNA encode domain names in HEADER."
-  (let (rhs ace start startpos endpos ovl)
-    (goto-char (point-min))
-    (while (re-search-forward (concat "^" header) nil t)
-      (while (re-search-forward "@\\([^ \t\r\n>,]+\\)"
-                               (or (save-excursion
-                                     (re-search-forward "^[^ \t]" nil t))
-                                   (point-max))
-                               t)
-       (setq rhs (match-string-no-properties 1)
-             startpos (match-beginning 1)
-             endpos (match-end 1))
-       (when (save-match-data
-               (and (message-idna-inside-rhs-p)
-                    (setq ace (idna-to-ascii rhs))
-                    (not (string= rhs ace))
-                    (if (eq message-use-idna 'ask)
-                        (unwind-protect
-                            (progn
-                              (setq ovl (message-make-overlay startpos
-                                                              endpos))
-                              (message-overlay-put ovl 'face 'highlight)
-                              (y-or-n-p
-                               (format "Replace with `%s'? " ace)))
-                          (message "")
-                          (message-delete-overlay ovl))
-                      message-use-idna)))
-         (replace-match (concat "@" ace)))))))
+  (let ((field (message-fetch-field header))
+       rhs ace  address)
+    (when field
+      (dolist (address (mail-header-parse-addresses field))
+       (setq address (car address)
+             rhs (downcase (or (cadr (split-string address "@")) ""))
+             ace (downcase (idna-to-ascii rhs)))
+       (when (and (not (equal rhs ace))
+                  (or (not (eq message-use-idna 'ask))
+                      (y-or-n-p (format "Replace %s with %s? " rhs ace))))
+         (goto-char (point-min))
+         (while (re-search-forward (concat "^" header ":") nil t)
+           (message-narrow-to-field)
+           (while (search-forward (concat "@" rhs) nil t)
+             (replace-match (concat "@" ace) t t))
+           (goto-char (point-max))
+           (widen)))))))
 
 (defun message-idna-to-ascii-rhs ()
   "Possibly IDNA encode non-ASCII domain names in From:, To: and Cc: headers.
@@ -4788,6 +5031,7 @@ See `message-idna-encode'."
        (message-narrow-to-head)
        (message-idna-to-ascii-rhs-1 "From")
        (message-idna-to-ascii-rhs-1 "To")
+       (message-idna-to-ascii-rhs-1 "Reply-To")
        (message-idna-to-ascii-rhs-1 "Cc")))))
 
 (defun message-generate-headers (headers)
@@ -4897,19 +5141,21 @@ Headers already prepared in the buffer are not modified."
                      (if formatter
                          (funcall formatter header value)
                        (insert header-string ": " value))
+                     (goto-char (message-fill-field))
                      ;; We check whether the value was ended by a
-                     ;; newline.  If now, we insert one.
+                     ;; newline.  If not, we insert one.
                      (unless (bolp)
                        (insert "\n"))
                      (forward-line -1)))
                ;; The value of this header was empty, so we clear
                ;; totally and insert the new value.
-               (delete-region (point) (gnus-point-at-eol))
+               (delete-region (point) (point-at-eol))
                ;; If the header is optional, and the header was
                ;; empty, we con't insert it anyway.
                (unless optionalp
                  (push header-string message-inserted-headers)
-                 (insert value)))
+                 (insert value)
+                 (message-fill-field)))
              ;; Add the deletable property to the headers that require it.
              (and (memq header message-deletable-headers)
                   (progn (beginning-of-line) (looking-at "[^:]+: "))
@@ -4965,66 +5211,89 @@ Headers already prepared in the buffer are not modified."
 ;;; Setting up a message buffer
 ;;;
 
+(defun message-skip-to-next-address ()
+  (let ((end (save-excursion
+              (message-next-header)
+              (point)))
+       quoted char)
+    (when (looking-at ",")
+      (forward-char 1))
+    (while (and (not (= (point) end))
+               (or (not (eq char ?,))
+                   quoted))
+      (skip-chars-forward "^,\"" (point-max))
+      (when (eq (setq char (following-char)) ?\")
+       (setq quoted (not quoted)))
+      (unless (= (point) end)
+       (forward-char 1)))
+    (skip-chars-forward " \t\n")))
+
 (defun message-fill-address (header value)
-  (save-restriction
-    (narrow-to-region (point) (point))
-    (insert (capitalize (symbol-name header))
-           ": "
-           (if (consp value) (car value) value)
-           "\n")
-    (narrow-to-region (point-min) (1- (point-max)))
-    (let (quoted last)
-      (goto-char (point-min))
-      (while (not (eobp))
-       (skip-chars-forward "^,\"" (point-max))
-       (if (or (eq (char-after) ?,)
-               (eobp))
-           (when (not quoted)
-             (if (and (> (current-column) 78)
-                      last)
-                 (progn
-                   (save-excursion
-                     (goto-char last)
-                     (insert "\n\t"))
-                   (setq last (1+ (point))))
-               (setq last (1+ (point)))))
-         (setq quoted (not quoted)))
-       (unless (eobp)
-         (forward-char 1))))
-    (goto-char (point-max))
-    (widen)
-    (forward-line 1)))
+  (insert (capitalize (symbol-name header))
+         ": "
+         (if (consp value) (car value) value)
+         "\n")
+  (message-fill-field-address))
 
 (defun message-split-line ()
   "Split current line, moving portion beyond point vertically down.
 If the current line has `message-yank-prefix', insert it on the new line."
   (interactive "*")
   (condition-case nil
-      (split-line message-yank-prefix) ;; Emacs 21.3.50+ supports arg.
+      (split-line message-yank-prefix) ;; Emacs 22.1+ supports arg.
     (error
      (split-line))))
-     
 
-(defun message-fill-header (header value)
+(defun message-insert-header (header value)
+  (insert (capitalize (symbol-name header))
+         ": "
+         (if (consp value) (car value) value)))
+
+(defun message-field-name ()
+  (save-excursion
+    (goto-char (point-min))
+    (when (looking-at "\\([^:]+\\):")
+      (intern (capitalize (match-string 1))))))
+
+(defun message-fill-field ()
+  (save-excursion
+    (save-restriction
+      (message-narrow-to-field)
+      (let ((field-name (message-field-name)))
+       (funcall (or (cadr (assq field-name message-field-fillers))
+                    'message-fill-field-general)))
+      (point-max))))
+
+(defun message-fill-field-address ()
+  (while (not (eobp))
+    (message-skip-to-next-address)
+    (let (last)
+      (if (and (> (current-column) 78)
+              last)
+         (progn
+           (save-excursion
+             (goto-char last)
+             (insert "\n\t"))
+           (setq last (1+ (point))))
+       (setq last (1+ (point)))))))
+
+(defun message-fill-field-general ()
   (let ((begin (point))
        (fill-column 78)
        (fill-prefix "\t"))
-    (insert (capitalize (symbol-name header))
-           ": "
-           (if (consp value) (car value) value)
-           "\n")
-    (save-restriction
-      (narrow-to-region begin (point))
-      (fill-region-as-paragraph begin (point))
-      ;; Tapdance around looong Message-IDs.
-      (forward-line -1)
-      (when (looking-at "[ \t]*$")
-       (message-delete-line))
-      (goto-char begin)
-      (re-search-forward ":" nil t)
-      (when (looking-at "\n[ \t]+")
-       (replace-match " " t t))
-      (goto-char (point-max)))))
+    (while (and (search-forward "\n" nil t)
+               (not (eobp)))
+      (replace-match " " t t))
+    (fill-region-as-paragraph begin (point-max))
+    ;; Tapdance around looong Message-IDs.
+    (forward-line -1)
+    (when (looking-at "[ \t]*$")
+      (message-delete-line))
+    (goto-char begin)
+    (search-forward ":" nil t)
+    (when (looking-at "\n[ \t]+")
+      (replace-match " " t t))
+    (goto-char (point-max))))
 
 (defun message-shorten-1 (list cut surplus)
   "Cut SURPLUS elements out of LIST, beginning with CUTth one."
@@ -5033,8 +5302,9 @@ If the current line has `message-yank-prefix', insert it on the new line."
 
 (defun message-shorten-references (header references)
   "Trim REFERENCES to be 21 Message-ID long or less, and fold them.
-If folding is disallowed, also check that the REFERENCES are less
-than 988 characters long, and if they are not, trim them until they are."
+When sending via news, also check that the REFERENCES are less
+than 988 characters long, and if they are not, trim them until
+they are."
   (let ((maxcount 21)
        (count 0)
        (cut 2)
@@ -5056,33 +5326,26 @@ than 988 characters long, and if they are not, trim them until they are."
        (message-shorten-1 refs cut surplus)
        (decf count surplus)))
 
-    ;; If folding is disallowed, make sure the total length (including
-    ;; the spaces between) will be less than MAXSIZE characters.
+    ;; When sending via news, make sure the total folded length will
+    ;; be less than 998 characters.  This is to cater to broken INN
+    ;; 2.3 which counts the total number of characters in a header
+    ;; rather than the physical line length of each line, as it should.
     ;;
-    ;; Only disallow folding for News messages. At this point the headers
-    ;; have not been generated, thus we use message-this-is-news directly.
-    (when (and message-this-is-news message-cater-to-broken-inn)
-      (let ((maxsize 988)
-           (totalsize (+ (apply #'+ (mapcar #'length refs))
-                         (1- count)))
-           (surplus 0)
-           (ptr (nthcdr (1- cut) refs)))
-       ;; Decide how many elements to cut off...
-       (while (> totalsize maxsize)
-         (decf totalsize (1+ (length (car ptr))))
-         (incf surplus)
-         (setq ptr (cdr ptr)))
-       ;; ...and do it.
-       (when (> surplus 0)
-         (message-shorten-1 refs cut surplus))))
-
+    ;; This hack should be removed when it's believed than INN 2.3 is
+    ;; no longer widely used.
+    ;;
+    ;; At this point the headers have not been generated, thus we use
+    ;; message-this-is-news directly.
+    (when message-this-is-news
+      (while (< 998
+               (with-temp-buffer
+                 (message-insert-header
+                  header (mapconcat #'identity refs " "))
+                 (buffer-size)))
+       (message-shorten-1 refs cut 1)))
     ;; Finally, collect the references back into a string and insert
     ;; it into the buffer.
-    (let ((refstring (mapconcat #'identity refs " ")))
-      (if (and message-this-is-news message-cater-to-broken-inn)
-         (insert (capitalize (symbol-name header)) ": "
-                 refstring "\n")
-       (message-fill-header header refstring)))))
+    (message-insert-header header (mapconcat #'identity refs " "))))
 
 (defun message-position-point ()
   "Move point to where the user probably wants to find it."
@@ -5106,7 +5369,9 @@ than 988 characters long, and if they are not, trim them until they are."
 (defcustom message-beginning-of-line t
   "Whether \\<message-mode-map>\\[message-beginning-of-line]\
  goes to beginning of header values."
+  :version "22.1"
   :group 'message-buffers
+  :link '(custom-manual "(message)Movement")
   :type 'boolean)
 
 (defun message-beginning-of-line (&optional n)
@@ -5118,10 +5383,10 @@ outside the message header or if the option `message-beginning-of-line'
 is nil.
 
 If point is in the message header and on a (non-continued) header
-line, move point to the beginning of the header value.  If point
-is already there, move point to beginning of line.  Therefore,
-repeated calls will toggle point between beginning of field and
-beginning of line."
+line, move point to the beginning of the header value or the beginning of line,
+whichever is closer.  If point is already at beginning of line, move point to
+beginning of header value.  Therefore, repeated calls will toggle point
+between beginning of field and beginning of line."
   (interactive "p")
   (let ((zrs 'zmacs-region-stays))
     (when (and (interactive-p) (boundp zrs))
@@ -5130,11 +5395,11 @@ beginning of line."
           (message-point-in-header-p))
       (let* ((here (point))
             (bol (progn (beginning-of-line n) (point)))
-            (eol (gnus-point-at-eol))
+            (eol (point-at-eol))
             (eoh (re-search-forward ": *" eol t)))
-       (if (or (not eoh) (equal here eoh))
-           (goto-char bol)
-         (goto-char eoh)))
+       (goto-char
+        (if (and eoh (or (< eoh here) (= bol here)))
+            eoh bol)))
     (beginning-of-line n)))
 
 (defun message-buffer-name (type &optional to group)
@@ -5309,12 +5574,7 @@ are not included."
   (when message-default-headers
     (insert message-default-headers)
     (or (bolp) (insert ?\n)))
-  (put-text-property
-   (point)
-   (progn
-     (insert mail-header-separator "\n")
-     (1- (point)))
-   'read-only nil)
+  (insert mail-header-separator "\n")
   (forward-line -1)
   (when (message-news-p)
     (when message-default-news-headers
@@ -5349,6 +5609,9 @@ are not included."
     (run-hooks 'message-header-setup-hook))
   (set-buffer-modified-p nil)
   (setq buffer-undo-list nil)
+  (when message-generate-hashcash
+    ;; Generate hashcash headers for recipients already known
+    (mail-add-payment-async))
   (run-hooks 'message-setup-hook)
   (message-position-point)
   (undo-boundary))
@@ -5435,17 +5698,30 @@ OTHER-HEADERS is an alist of header/value pairs."
                     (Subject . ,(or subject ""))))))
 
 (defun message-get-reply-headers (wide &optional to-address address-headers)
-  (let (follow-to mct never-mct to cc author mft recipients)
+  (let (follow-to mct never-mct to cc author mft recipients extra)
     ;; Find all relevant headers we need.
-    (setq to (message-fetch-field "to")
-         cc (message-fetch-field "cc")
-         mct (message-fetch-field "mail-copies-to")
-         author (or (message-fetch-field "mail-reply-to")
-                    (message-fetch-field "reply-to")
-                    (message-fetch-field "from")
-                    "")
-         mft (and message-use-mail-followup-to
-                  (message-fetch-field "mail-followup-to")))
+    (save-restriction
+      (message-narrow-to-headers-or-head)
+      ;; Gmane renames "To".  Look at "Original-To", too, if it is present in
+      ;; message-header-synonyms.
+      (setq to (or (message-fetch-field "to")
+                  (and (loop for synonym in message-header-synonyms
+                             when (memq 'Original-To synonym)
+                             return t)
+                       (message-fetch-field "original-to")))
+           cc (message-fetch-field "cc")
+           extra (when message-extra-wide-headers
+                   (mapconcat 'identity
+                              (mapcar 'message-fetch-field
+                                      message-extra-wide-headers)
+                              ", "))
+           mct (message-fetch-field "mail-copies-to")
+           author (or (message-fetch-field "mail-reply-to")
+                      (message-fetch-field "reply-to")
+                      (message-fetch-field "from")
+                      "")
+           mft (and message-use-mail-followup-to
+                    (message-fetch-field "mail-followup-to"))))
 
     ;; Handle special values of Mail-Copies-To.
     (when mct
@@ -5498,8 +5774,9 @@ responses here are directed to other addresses.")))
        (if mct (setq recipients (concat recipients ", " mct))))
        (t
        (setq recipients (if never-mct "" (concat ", " author)))
-       (if to  (setq recipients (concat recipients ", " to)))
-       (if cc  (setq recipients (concat recipients ", " cc)))
+       (if to (setq recipients (concat recipients ", " to)))
+       (if cc (setq recipients (concat recipients ", " cc)))
+       (if extra (setq recipients (concat recipients ", " extra)))
        (if mct (setq recipients (concat recipients ", " mct)))))
       (if (>= (length recipients) 2)
          ;; Strip the leading ", ".
@@ -5898,43 +6175,48 @@ Previous forwarders, replyers, etc. may add it."
 (defvar message-forward-decoded-p nil
   "Non-nil means the original message is decoded.")
 
-(defun message-forward-subject-author-subject (subject)
+(defun message-forward-subject-name-subject (subject)
   "Generate a SUBJECT for a forwarded message.
 The form is: [Source] Subject, where if the original message was mail,
-Source is the sender, and if the original message was news, Source is
-the list of newsgroups is was posted to."
-  (concat "["
-         (let ((prefix
-                (or (message-fetch-field "newsgroups")
-                    (message-fetch-field "from")
-                    "(nowhere)")))
+Source is the name of the sender, and if the original message was
+news, Source is the list of newsgroups is was posted to."
+  (let* ((group (message-fetch-field "newsgroups"))
+        (from (message-fetch-field "from"))
+        (prefix
+         (if group
+             (gnus-group-decoded-name group)
+           (or (and from (car (gnus-extract-address-components from)))
+               "(nowhere)"))))
+    (concat "["
            (if message-forward-decoded-p
                prefix
-             (mail-decode-encoded-word-string prefix)))
-         "] " subject))
+             (mail-decode-encoded-word-string prefix))
+           "] " subject)))
 
-(defun message-forward-subject-name-subject (subject)
+(defun message-forward-subject-author-subject (subject)
   "Generate a SUBJECT for a forwarded message.
 The form is: [Source] Subject, where if the original message was mail,
-Source is the name of the sender, and if the original message was
-news, Source is the list of newsgroups is was posted to."
-  (concat "["
-         (let ((prefix
-                (or (message-fetch-field "newsgroups")
-                    (let ((from (message-fetch-field "from")))
-                      (and from
-                           (cdr (mail-header-parse-address from))))
-                    "(nowhere)")))
+Source is the sender, and if the original message was news, Source is
+the list of newsgroups is was posted to."
+  (let* ((group (message-fetch-field "newsgroups"))
+        (prefix
+         (if group
+             (gnus-group-decoded-name group)
+           (or (message-fetch-field "from")
+               "(nowhere)"))))
+    (concat "["
            (if message-forward-decoded-p
                prefix
-             (mail-decode-encoded-word-string prefix)))
-         "] " subject))
+             (mail-decode-encoded-word-string prefix))
+           "] " subject)))
 
 (defun message-forward-subject-fwd (subject)
   "Generate a SUBJECT for a forwarded message.
 The form is: Fwd: Subject, where Subject is the original subject of
 the message."
-  (concat "Fwd: " subject))
+  (if (string-match "^Fwd: " subject)
+      subject
+    (concat "Fwd: " subject)))
 
 (defun message-make-forward-subject ()
   "Return a Subject header suitable for the message in the current buffer."
@@ -5949,18 +6231,17 @@ the message."
                      subject
                    (mail-decode-encoded-word-string subject))
                ""))
-       (if message-wash-forwarded-subjects
-           (setq subject (message-wash-subject subject)))
+       (when message-wash-forwarded-subjects
+         (setq subject (message-wash-subject subject)))
        ;; Make sure funcs is a list.
        (and funcs
             (not (listp funcs))
             (setq funcs (list funcs)))
        ;; Apply funcs in order, passing subject generated by previous
        ;; func to the next one.
-       (while funcs
-         (when (functionp (car funcs))
-           (setq subject (funcall (car funcs) subject)))
-         (setq funcs (cdr funcs)))
+       (dolist (func funcs)
+         (when (functionp func)
+           (setq subject (funcall func subject))))
        subject))))
 
 (eval-when-compile
@@ -5988,16 +6269,28 @@ Optional DIGEST will use digest to forward."
   (insert
    "\n-------------------- Start of forwarded message --------------------\n")
   (let ((b (point)) e)
-    (save-restriction
-      (narrow-to-region (point) (point))
-      (mml-insert-buffer forward-buffer)
-      (goto-char (point-min))
-      (when (looking-at "From ")
-       (replace-match "X-From-Line: "))
-      (goto-char (point-max)))
+    (insert
+     (with-temp-buffer
+       (mm-disable-multibyte)
+       (insert
+       (with-current-buffer forward-buffer
+         (mm-with-unibyte-current-buffer (buffer-string))))
+       (mm-enable-multibyte)
+       (mime-to-mml)
+       (goto-char (point-min))
+       (when (looking-at "From ")
+        (replace-match "X-From-Line: "))
+       (buffer-string)))
     (setq e (point))
     (insert
-     "\n-------------------- End of forwarded message --------------------\n")))
+     "\n-------------------- End of forwarded message --------------------\n")
+    (when message-forward-ignored-headers
+      (save-restriction
+       (narrow-to-region b e)
+       (goto-char b)
+       (narrow-to-region (point)
+                         (or (search-forward "\n\n" nil t) (point)))
+       (message-remove-header message-forward-ignored-headers t)))))
 
 (defun message-forward-make-body-mime (forward-buffer)
   (insert "\n\n<#part type=message/rfc822 disposition=inline raw=t>\n")
@@ -6037,7 +6330,7 @@ Optional DIGEST will use digest to forward."
        (goto-char (point-max))))
     (setq e (point))
     (insert "<#/mml>\n")
-    (when (and (not current-prefix-arg)
+    (when (and (not message-forward-decoded-p)
               message-forward-ignored-headers)
       (save-restriction
        (narrow-to-region b e)
@@ -6091,16 +6384,14 @@ Optional DIGEST will use digest to forward."
                              "Content-Type: *multipart/\\(signed\\|encrypted\\)"
                              nil t)))))
            (message-forward-make-body-mml forward-buffer)
-         (message-forward-make-body-mime forward-buffer)))
-    (message-forward-make-body-plain forward-buffer))
+         (message-forward-make-body-mime forward-buffer))
+      (message-forward-make-body-plain forward-buffer)))
   (message-position-point))
 
 ;;;###autoload
 (defun message-forward-rmail-make-body (forward-buffer)
   (save-window-excursion
     (set-buffer forward-buffer)
-    ;; Rmail doesn't have rmail-msg-restore-non-pruned-header in Emacs
-    ;; 20.  FIXIT, or we drop support for rmail in Emacs 20.
     (if (rmail-msg-is-pruned)
        (rmail-msg-restore-non-pruned-header)))
   (message-forward-make-body forward-buffer))
@@ -6166,7 +6457,8 @@ Optional DIGEST will use digest to forward."
        (replace-match "X-From-Line: "))
       ;; Send it.
       (let ((message-inhibit-body-encoding t)
-           message-required-mail-headers)
+           message-required-mail-headers
+           rfc2047-encode-encoded-words)
        (message-send-mail))
       (kill-buffer (current-buffer)))
     (message "Resending message to %s...done" address)))
@@ -6189,16 +6481,20 @@ you."
       (mm-insert-part handles)
       (undo-boundary)
       (goto-char (point-min))
-      (search-forward "\n\n" nil t)
-      (if (or (and (re-search-forward message-unsent-separator nil t)
-                  (forward-line 1))
-             (re-search-forward "^Return-Path:.*\n" nil t))
-         ;; We remove everything before the bounced mail.
-         (delete-region
-          (point-min)
-          (if (re-search-forward "^[^ \n\t]+:" nil t)
-              (match-beginning 0)
-            (point)))
+      (re-search-forward "\n\n+" nil t)
+      (setq boundary (point))
+      ;; We remove everything before the bounced mail.
+      (if (or (re-search-forward message-unsent-separator nil t)
+             (progn
+               (search-forward "\n\n" nil 'move)
+               (re-search-backward "^Return-Path:.*\n" boundary t)))
+         (progn
+           (forward-line 1)
+           (delete-region (point-min)
+                          (if (re-search-forward "^[^ \n\t]+:" nil t)
+                              (match-beginning 0)
+                            (point))))
+       (goto-char boundary)
        (when (re-search-backward "^.?From .*\n" nil t)
          (delete-region (match-beginning 0) (match-end 0)))))
     (mm-enable-multibyte)
@@ -6301,11 +6597,17 @@ which specify the range to operate on."
     (let ((end1 (make-marker)))
       (move-marker end1 (max start end))
       (goto-char (min start end))
-      (while (re-search-forward "\b" end1 t)
+      (while (search-forward "\b" end1 t)
        (if (eq (char-after) (char-after (- (point) 2)))
            (delete-char -2))))))
 
-(defalias 'message-exchange-point-and-mark 'exchange-point-and-mark)
+(defun message-exchange-point-and-mark ()
+  "Exchange point and mark, but don't activate region if it was inactive."
+  (unless (prog1
+             (message-mark-active-p)
+           (exchange-point-and-mark))
+    (setq mark-active nil)))
+
 (defalias 'message-make-overlay 'make-overlay)
 (defalias 'message-delete-overlay 'delete-overlay)
 (defalias 'message-overlay-put 'overlay-put)
@@ -6381,13 +6683,23 @@ which specify the range to operate on."
        '("^\\(Disposition-Notification-To\\|Return-Receipt-To\\):"
          . message-expand-name))
   "Alist of (RE . FUN).  Use FUN for completion on header lines matching RE."
+  :version "22.1"
   :group 'message
   :type '(alist :key-type regexp :value-type function))
 
+(defcustom message-expand-name-databases
+  (list 'bbdb 'eudc)
+  "List of databases to try for name completion (`message-expand-name').
+Each element is a symbol and can be `bbdb' or `eudc'."
+  :group 'message
+  :type '(set (const bbdb) (const eudc)))
+
 (defcustom message-tab-body-function nil
   "*Function to execute when `message-tab' (TAB) is executed in the body.
 If nil, the function bound in `text-mode-map' or `global-map' is executed."
+  :version "22.1"
   :group 'message
+  :link '(custom-manual "(message)Various Commands")
   :type 'function)
 
 (defun message-tab ()
@@ -6448,9 +6760,15 @@ those headers."
            (delete-region (point) (progn (forward-line 3) (point))))))))))
 
 (defun message-expand-name ()
-  (if (fboundp 'bbdb-complete-name)
-      (bbdb-complete-name)
-    (expand-abbrev)))
+  (cond ((and (memq 'eudc message-expand-name-databases)
+                   (boundp 'eudc-protocol)
+                   eudc-protocol)
+        (eudc-expand-inline))
+       ((and (memq 'bbdb message-expand-name-databases)
+             (fboundp 'bbdb-complete-name))
+        (bbdb-complete-name))
+       (t
+        (expand-abbrev))))
 
 ;;; Help stuff.
 
@@ -6496,7 +6814,7 @@ regexp VARSTR."
   (let ((locals (save-excursion
                  (set-buffer buffer)
                  (buffer-local-variables)))
-       (regexp "^gnus\\|^nn\\|^message\\|^user-mail-address"))
+       (regexp "^gnus\\|^nn\\|^message\\|^sendmail\\|^smtp\\|^user-mail-address"))
     (mapcar
      (lambda (local)
        (when (and (consp local)
@@ -6573,7 +6891,7 @@ regexp VARSTR."
 
 (defun message-use-alternative-email-as-from ()
   (require 'mail-utils)
-  (let* ((fields '("To" "Cc"))
+  (let* ((fields '("To" "Cc" "From"))
         (emails
          (split-string
           (mail-strip-quoted-names
@@ -6587,7 +6905,8 @@ regexp VARSTR."
       (pop emails))
     (unless (or (not email) (equal email user-mail-address))
       (goto-char (point-max))
-      (insert "From: " email "\n"))))
+      (insert "From: " (let ((user-mail-address email)) (message-make-from))
+             "\n"))))
 
 (defun message-options-get (symbol)
   (cdr (assq symbol message-options)))
@@ -6626,7 +6945,8 @@ regexp VARSTR."
                     (list message-hidden-headers)
                   message-hidden-headers))
        (inhibit-point-motion-hooks t)
-       (after-change-functions nil))
+       (after-change-functions nil)
+       (end-of-headers 0))
     (when regexps
       (save-excursion
        (save-restriction
@@ -6635,11 +6955,17 @@ regexp VARSTR."
          (while (not (eobp))
            (if (not (message-hide-header-p regexps))
                (message-next-header)
-             (let ((begin (point)))
+             (let ((begin (point))
+                   header header-len)
                (message-next-header)
-               (add-text-properties
-                begin (point)
-                '(invisible t message-hidden t))))))))))
+               (setq header (buffer-substring begin (point))
+                     header-len (- (point) begin))
+               (delete-region begin (point))
+               (goto-char (1+ end-of-headers))
+               (insert header)
+               (setq end-of-headers
+                     (+ end-of-headers header-len))))))))
+    (narrow-to-region (1+ end-of-headers) (point-max))))
 
 (defun message-hide-header-p (regexps)
   (let ((result nil)
@@ -6665,4 +6991,5 @@ regexp VARSTR."
 ;; coding: iso-8859-1
 ;; End:
 
+;; arch-tag: 94b32cac-4504-4b6c-8181-030ebf380ee0
 ;;; message.el ends here