;;; message.el --- composing mail and news messages
-;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
-;; Free Software Foundation, Inc.
+
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+;; 2005 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: mail, news
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;; Commentary:
(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)
(put 'user-full-name 'custom-type 'string)
(defgroup message-various nil
- "Various Message Variables"
+ "Various Message Variables."
:link '(custom-manual "(message)Various Message Variables")
:group 'message)
(defgroup message-buffers nil
- "Message Buffers"
+ "Message Buffers."
:link '(custom-manual "(message)Message Buffers")
:group 'message)
(defgroup message-sending nil
- "Message Sending"
+ "Message Sending."
:link '(custom-manual "(message)Sending Variables")
:group 'message)
(defgroup message-interface nil
- "Message Interface"
+ "Message Interface."
:link '(custom-manual "(message)Interface")
:group 'message)
(defgroup message-forwarding nil
- "Message Forwarding"
+ "Message Forwarding."
:link '(custom-manual "(message)Forwarding")
:group 'message-interface)
(defgroup message-insertion nil
- "Message Insertion"
+ "Message Insertion."
:link '(custom-manual "(message)Insertion")
:group 'message)
(defgroup message-headers nil
- "Message Headers"
+ "Message Headers."
:link '(custom-manual "(message)Message Headers")
:group 'message)
(defgroup message-news nil
- "Composing News Messages"
+ "Composing News Messages."
:group 'message)
(defgroup message-mail nil
- "Composing Mail Messages"
+ "Composing Mail Messages."
:group 'message)
(defgroup message-faces nil
(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)
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\\):"
(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)
"*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")
(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")
:group 'message-news
:group 'message-headers
:link '(custom-manual "(message)Message Headers")
- :type 'regexp)
+ :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:"
: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
:link '(custom-manual "(message)Superseding")
- :type 'regexp)
+ :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]*"
`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))
`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)
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?
-
;;; marking inserted text
-;;;###autoload
(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
-(defcustom message-archive-header
- "X-No-Archive: Yes\n"
+(defcustom message-archive-header "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
(defcustom message-archive-note
"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)
"Old target for cross-posts or follow-ups.")
(make-variable-buffer-local 'message-cross-post-old-target)
-;;;###autoload
(defcustom message-cross-post-default t
"When non-nil `message-cross-post-followup-to' will perform a crosspost.
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)
-;;;###autoload
-(defcustom message-cross-post-note
- "Crosspost & Followup-To: "
+(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)
-;;;###autoload
-(defcustom message-followup-to-note
- "Followup-To: "
+(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)
-;;;###autoload
-(defcustom message-cross-post-note-function
- 'message-cross-post-insert-note
+(defcustom message-cross-post-note-function 'message-cross-post-insert-note
"Function to use to insert note about Crosspost or Followup-To.
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)
:link '(custom-manual "(message)Message Buffers")
:type 'boolean)
+(defcustom message-kill-buffer-query t
+ "*Non-nil means that killing a modified message buffer has to be confirmed.
+This is used by `message-kill-buffer'."
+ :version "23.0" ;; No Gnus
+ :group 'message-buffers
+ :type 'boolean)
+
(eval-when-compile
(defvar gnus-local-organization))
(defcustom message-user-organization
"*All headers that match this regexp will be deleted when resending a message."
:group 'message-interface
:link '(custom-manual "(message)Resending")
- :type 'regexp)
+ :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 "."
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)
;; 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'.
: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
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)
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))
"*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
:link '(custom-manual "(message)Mailing Lists")
- :type '(radio (file :format "%t: %v\n" :size 0)
- (const nil)))
+ :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))
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))
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)
"*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))
(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"
+ :group 'message-various)
;;;###autoload
(defcustom message-citation-line-function 'message-insert-citation-line
(defcustom message-yank-prefix "> "
"*Prefix inserted on the lines of yanked messages.
Fix `message-cite-prefix-regexp' if it is set to an abnormal value.
-See also `message-yank-cited-prefix'."
+See also `message-yank-cited-prefix' and `message-yank-empty-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.
+ "*Prefix inserted on cited lines of yanked messages.
Fix `message-cite-prefix-regexp' if it is set to an abnormal value.
-See also `message-yank-prefix'."
+See also `message-yank-prefix' and `message-yank-empty-prefix'."
+ :version "22.1"
+ :type 'string
+ :link '(custom-manual "(message)Insertion Variables")
+ :group 'message-insertion)
+
+(defcustom message-yank-empty-prefix ">"
+ "*Prefix inserted on empty lines of yanked messages.
+See also `message-yank-prefix' and `message-yank-cited-prefix'."
+ :version "22.1"
:type 'string
:link '(custom-manual "(message)Insertion Variables")
:group 'message-insertion)
"*Function for citing an original message.
Predefined functions include `message-cite-original' and
`message-cite-original-without-signature'.
-Note that `message-cite-original' uses `mail-citation-hook' if that is non-nil."
+Note that these functions use `mail-citation-hook' if that is non-nil."
:type '(radio (function-item message-cite-original)
(function-item message-cite-original-without-signature)
(function-item sc-cite-original)
;;;###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)
(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."
+ :version "22.1"
:group 'message
:link '(custom-manual "(message)Message Headers")
- :type '(repeat regexp))
+ :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."
table)
"Syntax table used while in Message mode.")
-(defface message-header-to-face
+(defface message-header-to
'((((class color)
(background dark))
(:foreground "green2" :bold t))
(:bold t :italic t)))
"Face used for displaying From headers."
:group 'message-faces)
+;; backward-compatibility alias
+(put 'message-header-to-face 'face-alias 'message-header-to)
-(defface message-header-cc-face
+(defface message-header-cc
'((((class color)
(background dark))
(:foreground "green4" :bold t))
(:bold t)))
"Face used for displaying Cc headers."
:group 'message-faces)
+;; backward-compatibility alias
+(put 'message-header-cc-face 'face-alias 'message-header-cc)
-(defface message-header-subject-face
+(defface message-header-subject
'((((class color)
(background dark))
(:foreground "green3"))
(:bold t)))
"Face used for displaying subject headers."
:group 'message-faces)
+;; backward-compatibility alias
+(put 'message-header-subject-face 'face-alias 'message-header-subject)
-(defface message-header-newsgroups-face
+(defface message-header-newsgroups
'((((class color)
(background dark))
(:foreground "yellow" :bold t :italic t))
(:bold t :italic t)))
"Face used for displaying newsgroups headers."
:group 'message-faces)
+;; backward-compatibility alias
+(put 'message-header-newsgroups-face 'face-alias 'message-header-newsgroups)
-(defface message-header-other-face
+(defface message-header-other
'((((class color)
(background dark))
(:foreground "#b00000"))
(:bold t :italic t)))
"Face used for displaying newsgroups headers."
:group 'message-faces)
+;; backward-compatibility alias
+(put 'message-header-other-face 'face-alias 'message-header-other)
-(defface message-header-name-face
+(defface message-header-name
'((((class color)
(background dark))
(:foreground "DarkGreen"))
(:bold t)))
"Face used for displaying header names."
:group 'message-faces)
+;; backward-compatibility alias
+(put 'message-header-name-face 'face-alias 'message-header-name)
-(defface message-header-xheader-face
+(defface message-header-xheader
'((((class color)
(background dark))
(:foreground "blue"))
(:bold t)))
"Face used for displaying X-Header headers."
:group 'message-faces)
+;; backward-compatibility alias
+(put 'message-header-xheader-face 'face-alias 'message-header-xheader)
-(defface message-separator-face
+(defface message-separator
'((((class color)
(background dark))
(:foreground "blue3"))
(:bold t)))
"Face used for displaying the separator."
:group 'message-faces)
+;; backward-compatibility alias
+(put 'message-separator-face 'face-alias 'message-separator)
-(defface message-cited-text-face
+(defface message-cited-text
'((((class color)
(background dark))
(:foreground "red"))
(:bold t)))
"Face used for displaying cited text names."
:group 'message-faces)
+;; backward-compatibility alias
+(put 'message-cited-text-face 'face-alias 'message-cited-text)
-(defface message-mml-face
+(defface message-mml
'((((class color)
(background dark))
(:foreground "ForestGreen"))
(:bold t)))
"Face used for displaying MML."
:group 'message-faces)
+;; backward-compatibility alias
+(put 'message-mml-face 'face-alias 'message-mml)
(defun message-font-lock-make-header-matcher (regexp)
(let ((form
(let ((content "[ \t]*\\(.+\\(\n[ \t].*\\)*\\)\n?"))
`((,(message-font-lock-make-header-matcher
(concat "^\\([Tt]o:\\)" content))
- (1 'message-header-name-face)
- (2 'message-header-to-face nil t))
+ (1 'message-header-name)
+ (2 'message-header-to nil t))
(,(message-font-lock-make-header-matcher
(concat "^\\(^[GBF]?[Cc][Cc]:\\|^[Rr]eply-[Tt]o:\\)" content))
- (1 'message-header-name-face)
- (2 'message-header-cc-face nil t))
+ (1 'message-header-name)
+ (2 'message-header-cc nil t))
(,(message-font-lock-make-header-matcher
(concat "^\\([Ss]ubject:\\)" content))
- (1 'message-header-name-face)
- (2 'message-header-subject-face nil t))
+ (1 'message-header-name)
+ (2 'message-header-subject nil t))
(,(message-font-lock-make-header-matcher
(concat "^\\([Nn]ewsgroups:\\|Followup-[Tt]o:\\)" content))
- (1 'message-header-name-face)
- (2 'message-header-newsgroups-face nil t))
+ (1 'message-header-name)
+ (2 'message-header-newsgroups nil t))
(,(message-font-lock-make-header-matcher
(concat "^\\([A-Z][^: \n\t]+:\\)" content))
- (1 'message-header-name-face)
- (2 'message-header-other-face nil t))
+ (1 'message-header-name)
+ (2 'message-header-other nil t))
(,(message-font-lock-make-header-matcher
(concat "^\\(X-[A-Za-z0-9-]+:\\|In-Reply-To:\\)" content))
- (1 'message-header-name-face)
- (2 'message-header-name-face))
+ (1 'message-header-name)
+ (2 'message-header-name))
,@(if (and mail-header-separator
(not (equal mail-header-separator "")))
`((,(concat "^\\(" (regexp-quote mail-header-separator) "\\)$")
- 1 'message-separator-face))
+ 1 'message-separator))
nil)
((lambda (limit)
(re-search-forward (concat "^\\("
message-cite-prefix-regexp
"\\).*")
limit t))
- (0 'message-cited-text-face))
+ (0 'message-cited-text))
("<#/?\\(multipart\\|part\\|external\\|mml\\|secure\\)[^>]*>"
- (0 'message-mml-face))))
+ (0 'message-mml))))
"Additional expressions to highlight in Message mode.")
(integer 1000000)))
(defcustom message-alternative-emails nil
- "A regexp to match the alternative email addresses.
-The first matched address (not primary one) is used in the From field."
+ "*Regexp matching alternative email addresses.
+The first address in the To, Cc or From headers of the original
+article matching this variable is used as the From field of
+outgoing messages.
+
+This variable has precedence over posting styles and anything that runs
+off `message-setup-hook'."
:group 'message-headers
:link '(custom-manual "(message)Message Headers")
:type '(choice (const :tag "Always use primary" nil)
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)))
"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)
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."
+ "*Domain part of Message-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))
(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...")
"Alist of header names/filler functions.")
(defvar message-header-format-alist
- `((Newsgroups)
+ `((From)
+ (Newsgroups)
(To)
(Cc)
(Subject)
"\\)")
"Regular expression that matches a valid FQDN."
;; see also: gnus-button-valid-fqdn-regexp
+ :version "22.1"
:group 'message-headers
:type 'regexp)
(autoload 'rmail-msg-restore-non-pruned-header "rmail")
(autoload 'rmail-output "rmailout"))
-(eval-when-compile
- (autoload 'sha1 "sha1-el"))
-
\f
;;;
(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))
(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)
;;; Start of functions adopted from `message-utils.el'.
(defun message-strip-subject-trailing-was (subject)
- "Remove trailing \"(Was: <old subject>)\" from SUBJECT lines.
+ "Remove trailing \"(was: <old subject>)\" from SUBJECT lines.
Leading \"Re: \" is not stripped by this function. Use the function
`message-strip-subject-re' for this."
(let* ((query message-subject-trailing-was-query)
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)
;; 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)
See also `message-forbidden-properties'."
(when (and message-strip-special-text-properties
(message-tamago-not-in-use-p begin))
- (dolist (from-to (message-text-with-property 'message-hidden
- begin end t))
- (remove-text-properties (car from-to) (cdr from-to)
- message-forbidden-properties))))
+ (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"
(set (make-local-variable 'message-mime-part) 0)
(message-setup-fill-variables)
;; 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)
(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."
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))
;; 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)))
(new-header (cdr header))
(end-of-line -1)))
(unless (= point (point))
(kill-region point (point))
- (insert "\n"))))))
+ (unless (bolp)
+ (insert "\n")))))))
(defun message-newline-and-reformat (&optional arg not-break)
"Insert four newlines, and then reformat if inside quoted text.
Prefix arg means justify as well."
(interactive (list (if current-prefix-arg 'full)))
- (let (quoted point beg end leading-space bolp)
+ (let (quoted point beg end leading-space bolp fill-paragraph-function)
(setq point (point))
(beginning-of-line)
(setq beg (point))
(save-excursion
(goto-char start)
(while (< (point) (mark t))
- (if (or (looking-at ">") (looking-at "^$"))
- (insert message-yank-cited-prefix)
- (insert message-yank-prefix))
+ (cond ((looking-at ">")
+ (insert message-yank-cited-prefix))
+ ((looking-at "^$")
+ (insert message-yank-empty-prefix))
+ (t
+ (insert message-yank-prefix)))
(forward-line 1))))
(goto-char start)))
(when (and message-reply-buffer
message-cite-function)
(delete-windows-on message-reply-buffer t)
- (insert-buffer message-reply-buffer)
+ (push-mark (save-excursion
+ (insert-buffer-substring message-reply-buffer)
+ (point)))
(unless arg
(funcall message-cite-function))
(message-exchange-point-and-mark)
(push (buffer-name buffer) buffers))))
(nreverse buffers)))
-(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))))
- ;; 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)
- (goto-char end)
- (when (re-search-backward message-signature-separator start t)
- ;; Also peel off any blank lines before the signature.
- (forward-line -1)
- (while (looking-at "^[ \t]*$")
- (forward-line -1))
- (forward-line 1)
- (delete-region (point) end)
- (unless (search-backward "\n\n" start t)
- ;; Insert a blank line if it is peeled off.
- (insert "\n")))
- (goto-char start)
- (while functions
- (funcall (pop functions)))
- (when message-citation-line-function
- (unless (bolp)
- (insert "\n"))
- (funcall message-citation-line-function))))
+(eval-when-compile (defvar mail-citation-hook)) ; Compiler directive
-(eval-when-compile (defvar mail-citation-hook)) ;Compiler directive
-(defun message-cite-original ()
- "Cite function in the standard Message manner."
+(defun message-cite-original-1 (strip-signature)
+ "Cite an original message.
+If STRIP-SIGNATURE is non-nil, strips off the signature from the
+original message.
+
+This function uses `mail-citation-hook' if that is non-nil."
(if (and (boundp 'mail-citation-hook)
mail-citation-hook)
(run-hooks 'mail-citation-hook)
(message-fetch-field "references")
0 0 ""))))
(mml-quote-region start end)
+ (when strip-signature
+ ;; Allow undoing.
+ (undo-boundary)
+ (goto-char end)
+ (when (re-search-backward message-signature-separator start t)
+ ;; Also peel off any blank lines before the signature.
+ (forward-line -1)
+ (while (looking-at "^[ \t]*$")
+ (forward-line -1))
+ (forward-line 1)
+ (delete-region (point) end)
+ (unless (search-backward "\n\n" start t)
+ ;; 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"))
(funcall message-citation-line-function))
(when (and x-no-archive
- message-cite-articles-with-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-cite-original ()
+ "Cite function in the standard Message manner."
+ (message-cite-original-1 nil))
+
+(defun message-cite-original-without-signature ()
+ "Cite function in the standard Message manner.
+This function strips off the signature from the original message."
+ (message-cite-original-1 t))
+
(defun message-insert-citation-line ()
"Insert a simple citation line."
(when message-reply-headers
"Kill the current buffer."
(interactive)
(when (or (not (buffer-modified-p))
+ (not message-kill-buffer-query)
(yes-or-no-p "Message modified; kill anyway? "))
(let ((actions message-kill-actions)
(draft-article message-draft-article)
(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))
"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))))
(setq end (point-max)))
(let (next regions)
(if reverse
- (progn
- (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
+ (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
(unless (bolp)
(insert "\n"))
;; Make the hidden headers visible.
- (dolist (from-to (message-text-with-property 'message-hidden))
- (add-text-properties (car from-to) (cdr from-to)
- '(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.
(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."
(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...
"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
(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)
(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"
(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.
(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-el)
+ (require 'sha1)
(let (sha1-maximum-internal-length)
(sha1 (concat (message-unique-id)
(format "%x%x%x" (random) (random t) (random))
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))
(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."
(when field
(dolist (address (mail-header-parse-addresses field))
(setq address (car address)
- rhs (downcase (cadr (split-string 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))
(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)
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))))
(insert "\n\t"))
(setq last (1+ (point))))
(setq last (1+ (point)))))))
-
+
(defun message-fill-field-general ()
(let ((begin (point))
(fill-column 78)
(when (looking-at "[ \t]*$")
(message-delete-line))
(goto-char begin)
- (re-search-forward ":" nil t)
+ (search-forward ":" nil t)
(when (looking-at "\n[ \t]+")
(replace-match " " t t))
(goto-char (point-max))))
;; 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 shuld.
+ ;; rather than the physical line length of each line, as it should.
;;
;; This hack should be removed when it's believed than INN 2.3 is
;; no longer widely used.
(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)
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))
(bol (progn (beginning-of-line n) (point)))
(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)
(when message-default-mail-headers
(insert message-default-mail-headers)
(or (bolp) (insert ?\n)))
- (save-restriction
- (message-narrow-to-headers)
- (if message-alternative-emails
- (message-use-alternative-email-as-from)))
(when message-generate-headers-first
(message-generate-headers
(message-headers-to-generate
(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)
+ ;; Do this last to give it precedence over posting styles, etc.
+ (when (message-mail-p)
+ (save-restriction
+ (message-narrow-to-headers)
+ (if message-alternative-emails
+ (message-use-alternative-email-as-from))))
(message-position-point)
(undo-boundary))
(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.
(save-restriction
(message-narrow-to-headers-or-head)
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")
fragmented and very difficult to follow.
Also, some source/announcement lists are not intended for discussion;
-responses here are directed to other addresses.")))
+responses here are directed to other addresses.
+
+You may customize the variable `message-use-mail-followup-to', if you
+want to get rid of this query permanently.")))
(setq recipients (concat ", " mft)))
(to-address
(setq recipients (concat ", " to-address))
(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 ", ".
`Followup-To: poster' sends your response via e-mail instead of news.
A typical situation where `Followup-To: poster' is used is when the poster
-does not read the newsgroup, so he wouldn't see any replies sent to it."))
+does not read the newsgroup, so he wouldn't see any replies sent to it.
+
+You may customize the variable `message-use-followup-to', if you
+want to get rid of this query permanently."))
(progn
(setq message-this-is-news nil)
(cons 'To (or mrt reply-to from "")))
be fragmented and very difficult to follow.
Also, some source/announcement newsgroups are not intended for discussion;
-responses here are directed to other newsgroups."))
+responses here are directed to other newsgroups.
+
+You may customize the variable `message-use-followup-to', if you
+want to get rid of this query permanently."))
(cons 'Newsgroups followup-to)
(cons 'Newsgroups newsgroups))))))
(posted-to
(defun message-is-yours-p ()
"Non-nil means current article is yours.
-If you have added 'cancel-messages to 'message-shoot-gnksa-feet', all articles
+If you have added 'cancel-messages to `message-shoot-gnksa-feet', all articles
are yours except those that have Cancel-Lock header not belonging to you.
-Instead of shooting GNKSA feet, you should modify 'message-alternative-emails'
+Instead of shooting GNKSA feet, you should modify `message-alternative-emails'
regexp to match all of yours addresses."
;; Canlock-logic as suggested by Per Abrahamsen
;; <abraham@dina.kvl.dk>
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
(setq e (point))
(insert
"\n-------------------- End of forwarded message --------------------\n")
- (when (and (not current-prefix-arg)
- message-forward-ignored-headers)
+ (when message-forward-ignored-headers
(save-restriction
(narrow-to-region b e)
(goto-char b)
(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)
(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))))))
'("^\\(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-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)
+ :type '(choice (const nil)
+ function))
(defun message-tab ()
"Complete names according to `message-completion-alist'.
(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)
(read-string prompt initial-contents))))
(defun message-use-alternative-email-as-from ()
+ "Set From field of the outgoing message to the first matching
+address in `message-alternative-emails', looking at To, Cc and
+From headers in the original article."
(require 'mail-utils)
- (let* ((fields '("To" "Cc"))
+ (let* ((fields '("To" "Cc" "From"))
(emails
(split-string
(mail-strip-quoted-names
emails nil))
(pop emails))
(unless (or (not email) (equal email user-mail-address))
+ (message-remove-header "From")
(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)))
(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
(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)
;; coding: iso-8859-1
;; End:
-;;; arch-tag: 94b32cac-4504-4b6c-8181-030ebf380ee0
+;; arch-tag: 94b32cac-4504-4b6c-8181-030ebf380ee0
;;; message.el ends here