;;; 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
;; Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
(eval-when-compile
(require 'cl)
+ (defvar gnus-message-group-art)
(defvar gnus-list-identifiers)) ; gnus-sum is required where necessary
(require 'canlock)
(require 'mailheader)
(require 'mml)
(require 'rfc822)
(eval-and-compile
+ (autoload 'gnus-find-method-for-group "gnus")
+ (autoload 'nnvirtual-find-group-art "nnvirtual")
+ (autoload 'gnus-group-decoded-name "gnus-group"))
+(eval-when-compile
(autoload 'sha1 "sha1-el"))
(defgroup message '((user-mail-address custom-variable)
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 'string)
+ :type '(radio (string :format "%t: %v\n" :size 0) (const nil)))
-(defcustom message-ignored-bounced-headers "^\\(Received\\|Return-Path\\):"
+(defcustom message-ignored-bounced-headers
+ "^\\(Received\\|Return-Path\\|Delivered-To\\):"
"*Regexp that matches headers to be removed in resent bounced mail."
:group 'message-interface
:type 'regexp)
`approved', `sender', `empty', `empty-headers', `message-id', `from',
`subject', `shorten-followup-to', `existing-newsgroups',
`buffer-file-name', `unchanged', `newsgroups', `reply-to',
-'continuation-headers', and `long-header-lines'."
+`continuation-headers', `long-header-lines', `invisible-text' and
+`illegible-text'."
:group 'message-news
:type '(repeat sexp)) ; Fixme: improve this
-(defcustom message-required-headers '((optional . References) From)
+(defcustom message-required-headers '((optional . References)
+ From)
"*Headers to be generated or prompted for when sending a message.
Also see `message-required-news-headers' and
`message-required-mail-headers'."
: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."
:group 'message-news
:group 'message-headers
+ :link '(custom-manual "(message)Message Headers")
:type '(repeat sexp))
(defcustom message-required-news-headers
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
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
"*Regexp of headers to be removed unconditionally before posting."
:group 'message-news
:group 'message-headers
+ :link '(custom-manual "(message)Message Headers")
:type 'regexp)
(defcustom message-ignored-mail-headers
"*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:"
+(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:"
"*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)
(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
: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
It is okay to create some false positives here, as the user is asked."
:group 'message-various
+ :link '(custom-manual "(message)Message Headers")
:type 'regexp)
(defcustom message-subject-trailing-was-regexp
`message-strip-subject-trailing-was'. You should use a regexp creating very
few false positives here."
:group 'message-various
+ :link '(custom-manual "(message)Message Headers")
:type 'regexp)
+;; Fixme: Why are all these things autoloaded?
+
;;; marking inserted text
;;;###autoload
"--8<---------------cut here---------------start------------->8---\n"
"How to mark the beginning of some inserted text."
:type 'string
+ :link '(custom-manual "(message)Insertion Variables")
:group 'message-various)
;;;###autoload
"--8<---------------cut here---------------end--------------->8---\n"
"How to mark the end of some inserted text."
:type 'string
+ :link '(custom-manual "(message)Insertion Variables")
:group 'message-various)
;;;###autoload
(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.googgle.com\) respect this header."
+Archives \(such as groups.google.com\) respect this header."
:type 'string
+ :link '(custom-manual "(message)Header Commands")
:group 'message-various)
;;;###autoload
"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 'string
+ :type '(radio (string :format "%t: %v\n" :size 0)
+ (const nil))
+ :link '(custom-manual "(message)Header Commands")
:group 'message-various)
;;; Crossposts and Followups
(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
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
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)
(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
(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
- 'message-forward-subject-author-subject
+ #'message-forward-subject-name-subject
"*List of functions called to generate subject headers for forwarded messages.
The subject generated by the previous function is passed into each
successive function.
The provided functions are:
-* `message-forward-subject-author-subject' (Source of article (author or
- newsgroup)), in brackets followed by the subject
-* `message-forward-subject-fwd' (Subject of article with 'Fwd:' prepended
+* `message-forward-subject-author-subject' Source of article (author or
+ newsgroup), in brackets followed by the subject
+* `message-forward-subject-name-subject' Source of article (name of author
+ or newsgroup), in brackets followed by the subject
+* `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)
(repeat :tag "List of functions" function)))
(defcustom message-forward-as-mime t
- "*If non-nil, forward messages as an inline/rfc822 MIME section. Otherwise, directly inline the old message in the forwarded message."
+ "*Non-nil means forward messages as an inline/rfc822 MIME section.
+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 t
- "*If non-nil, forward messages are shown as mml. Otherwise, forward messages are unchanged."
+(defcustom message-forward-show-mml 'best
+ "*Non-nil means show forwarded messages as MML (decoded from MIME).
+Otherwise, forwarded messages are unchanged.
+Can also be the symbol `best' to indicate that MML should be
+used, except when it is a bad idea to use MML. One example where
+it is a bad idea is when forwarding a signed or encrypted
+message, because converting MIME to MML would invalidate the
+digital signature."
:version "21.1"
:group 'message-forwarding
- :type 'boolean)
+ :type '(choice (const :tag "use MML" t)
+ (const :tag "don't use MML " nil)
+ (const :tag "use MML when appropriate" best)))
(defcustom message-forward-before-signature t
- "*If non-nil, put forwarded message before signature, else after."
+ "*Non-nil means put forwarded message before signature, else after."
:group 'message-forwarding
:type 'boolean)
(defcustom message-wash-forwarded-subjects nil
- "*If non-nil, try to remove as much old cruft as possible from the subject of messages before generating the new subject of a forward."
+ "*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
+ :link '(custom-manual "(message)Resending")
:type 'regexp)
(defcustom message-forward-ignored-headers "^Content-Transfer-Encoding:\\|^X-Gnus"
(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\\|["
"]\\)+>+\\|[ \t]*[]>|}+]\\)+"))))
"*Regexp matching the longest possible citation prefix on a line."
: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
(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
variable `mail-header-separator'."
:group 'message-sending
:group 'message-news
+ :link '(custom-manual "(message)News Variables")
:type 'function)
(defcustom message-reply-to-function nil
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
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
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-use-followup-to '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)
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)Mailing Lists")
:type '(choice (const :tag "ignore" nil)
(const use)
(const ask)))
(defcustom message-subscribed-address-functions nil
"*Specifies functions for determining list subscription.
-If nil, do not attempt to determine list subscribtion with functions.
+If nil, do not attempt to determine list subscription with functions.
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'."
:group 'message-interface
+ :link '(custom-manual "(message)Mailing Lists")
:type '(repeat sexp))
(defcustom message-subscribed-address-file nil
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."
:group 'message-interface
- :type 'string)
+ :link '(custom-manual "(message)Mailing Lists")
+ :type '(radio (file :format "%t: %v\n" :size 0)
+ (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 conjuction with
+addresses can be used in conjunction with
`message-subscribed-address-functions' and `message-subscribed-regexps'."
:group 'message-interface
+ :link '(custom-manual "(message)Mailing Lists")
:type '(repeat string))
(defcustom message-subscribed-regexps nil
"*Specifies a list of addresses the user is subscribed to.
If nil, do not use any predefined list subscriptions. This list of
-regular expressions can be used in conjuction with
+regular expressions can be used in conjunction with
`message-subscribed-address-functions' and `message-subscribed-addresses'."
:group 'message-interface
+ :link '(custom-manual "(message)Mailing Lists")
:type '(repeat regexp))
(defcustom message-allow-no-recipients 'ask
symbol `never', the posting is not allowed. If it is the symbol
`ask', you are prompted."
:group 'message-interface
+ :link '(custom-manual "(message)Message Headers")
:type '(choice (const always)
(const never)
(const ask)))
"*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
: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
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)))
;; create a dependence to `gnus.el'.
:type 'sexp)
-(defcustom message-generate-headers-first nil
- "*If non-nil, generate all required headers before composing.
-The variables `message-required-news-headers' and
+;; FIXME: This should be a temporary workaround until someone implements a
+;; proper solution. If a crash happens while replying, the auto-save file
+;; 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)
+ "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)
(repeat (sexp :tag "Header"))))
"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
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
(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
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
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 ">"
Fix `message-cite-prefix-regexp' if it is set to an abnormal value.
See also `message-yank-prefix'."
: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
(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
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
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
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."
: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
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;
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
"*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
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
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))
(or (not (listp message-shoot-gnksa-feet))
(memq feature message-shoot-gnksa-feet)))
+(defcustom message-hidden-headers nil
+ "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."
+ :group 'message
+ :link '(custom-manual "(message)Message Headers")
+ :type '(repeat regexp))
+
;;; Internal variables.
;;; Well, not really internal.
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
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
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
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)))
"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))
no, only reply back to the author."
:version "21.3"
:group 'message-headers
+ :link '(custom-manual "(message)Wide Reply")
:type 'boolean)
(defcustom message-user-fqdn nil
"*Domain part of Messsage-Ids."
:group 'message-headers
:link '(custom-manual "(message)News Headers")
- :type 'string)
+ :type '(radio (const :format "%v " nil)
+ (string :format "FQDN: %v\n" :size 0)))
+
+(defcustom message-use-idna (and (condition-case nil (require 'idna)
+ (file-error))
+ (mm-coding-system-p 'utf-8)
+ (executable-find idna-program)
+ 'ask)
+ "Whether to encode non-ASCII in domain names into ASCII according to IDNA."
+ :group 'message-headers
+ :link '(custom-manual "(message)IDNA")
+ :type '(choice (const :tag "Ask" ask)
+ (const :tag "Never" nil)
+ (const :tag "Always" t)))
;;; Internal variables.
(defvar message-draft-article nil)
(defvar message-mime-part nil)
(defvar message-posting-charset nil)
+(defvar message-inserted-headers nil)
;; Byte-compiler warning
(eval-when-compile
(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 'gnus-group-name-decode "gnus-group")
(autoload 'gnus-groups-from-server "gnus")
(autoload 'rmail-output "rmailout")
- (autoload 'gnus-delay-article "gnus-delay"))
+ (autoload 'gnus-delay-article "gnus-delay")
+ (autoload 'gnus-make-local-hook "gnus-util")
+ (autoload 'gnus-extract-address-components "gnus-util"))
\f
(beg 1)
(first t)
quoted elems paren)
- (save-excursion
- (message-set-work-buffer)
+ (with-temp-buffer
+ (mm-enable-multibyte)
(insert header)
(goto-char (point-min))
(while (not (eobp))
(looking-at message-unix-mail-delimiter))))
(defun message-fetch-field (header &optional not-all)
- "The same as `mail-fetch-field', only remove all newlines."
+ "The same as `mail-fetch-field', only remove all newlines.
+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))))
(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)
(mail-narrow-to-head)
(message-fetch-field header))))
-(defun message-set-work-buffer ()
- (if (get-buffer " *message work*")
- (progn
- (set-buffer " *message work*")
- (erase-buffer))
- (set-buffer (get-buffer-create " *message work*"))
- (kill-all-local-variables)
- (mm-enable-multibyte)))
-
-(defun message-functionp (form)
- "Return non-nil if FORM is funcallable."
- (or (and (symbolp form) (fboundp form))
- (and (listp form) (eq (car form) 'lambda))
- (byte-code-function-p form)))
-
(defun message-strip-list-identifiers (subject)
"Remove list identifiers in `gnus-list-identifiers' from string SUBJECT."
(require 'gnus-sum) ; for gnus-list-identifiers
;;;###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: ")))
(zerop (string-width new-subject))
(string-match "^[ \t]*$" new-subject))))
(save-excursion
- (let ((old-subject (message-fetch-field "Subject")))
+ (let ((old-subject
+ (save-restriction
+ (message-narrow-to-headers)
+ (message-fetch-field "Subject"))))
(cond ((not old-subject)
(error "No current subject"))
((not (string-match
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)
(defun message-reduce-to-to-cc ()
"Replace contents of To: header with contents of Cc: or Bcc: header."
(interactive)
- (let ((cc-content (message-fetch-field "cc"))
+ (let ((cc-content
+ (save-restriction (message-narrow-to-headers)
+ (message-fetch-field "cc")))
(bcc nil))
(if (and (not cc-content)
- (setq cc-content (message-fetch-field "bcc")))
+ (setq cc-content
+ (save-restriction
+ (message-narrow-to-headers)
+ (message-fetch-field "bcc"))))
(setq bcc t))
(cond (cc-content
(save-excursion
(message-goto-to)
(message-delete-line)
(insert (concat "To: " cc-content "\n"))
- (message-remove-header (if bcc
- "bcc"
- "cc")))))))
+ (save-restriction
+ (message-narrow-to-headers)
+ (message-remove-header (if bcc
+ "bcc"
+ "cc"))))))))
;;; End of functions adopted from `message-utils.el'.
(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)
["Insert Signature" message-insert-signature t]
["Caesar (rot13) Message" message-caesar-buffer-body t]
["Caesar (rot13) Region" message-caesar-region (message-mark-active-p)]
- ["Elide Region" message-elide-region
+ ["Elide Region" message-elide-region
:active (message-mark-active-p)
,@(if (featurep 'xemacs) nil
'(:help "Replace text in region with an ellipsis"))]
- ["Delete Outside Region" message-delete-not-region
+ ["Delete Outside Region" message-delete-not-region
:active (message-mark-active-p)
,@(if (featurep 'xemacs) nil
'(:help "Delete all quoted text outside 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]
["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]
["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]
+ ["Encode non-ASCII domain names" message-idna-to-ascii-rhs t]
["Goto Body" message-goto-body t]
["Goto Signature" message-goto-signature t]))
If you use one of these packages, turn this option off, and hope the
message composition doesn't break too bad."
:group 'message-various
+ :link '(custom-manual "(message)Various Message Variables")
:type 'boolean)
(defconst message-forbidden-properties
;; No reason this should be clutter up customize. We make it a
;; property list (rather than a list of property symbols), to be
;; directly useful for `remove-text-properties'.
- '(field nil read-only nil intangible nil invisible nil
+ '(field nil read-only nil invisible nil intangible nil
mouse-face nil modification-hooks nil insert-in-front-hooks nil
insert-behind-hooks nil point-entered nil point-left nil)
;; Other special properties:
See also `message-forbidden-properties'."
(when (and message-strip-special-text-properties
(message-tamago-not-in-use-p begin))
- (remove-text-properties begin end message-forbidden-properties)))
+ (while (not (= begin end))
+ (when (not (get-text-property begin 'message-hidden))
+ (remove-text-properties begin (1+ begin)
+ message-forbidden-properties))
+ (incf begin))))
;;;###autoload
(define-derived-mode message-mode text-mode "Message"
M-RET `message-newline-and-reformat' (break the line and reformat)."
(setq local-abbrev-table text-mode-abbrev-table)
(set (make-local-variable 'message-reply-buffer) nil)
- (make-local-variable 'message-send-actions)
- (make-local-variable 'message-exit-actions)
- (make-local-variable 'message-kill-actions)
- (make-local-variable 'message-postpone-actions)
- (make-local-variable 'message-draft-article)
+ (set (make-local-variable 'message-inserted-headers) nil)
+ (set (make-local-variable 'message-send-actions) nil)
+ (set (make-local-variable 'message-exit-actions) nil)
+ (set (make-local-variable 'message-kill-actions) nil)
+ (set (make-local-variable 'message-postpone-actions) nil)
+ (set (make-local-variable 'message-draft-article) nil)
(setq buffer-offer-save t)
(set (make-local-variable 'facemenu-add-face-function)
(lambda (face end)
(set (make-local-variable 'tool-bar-map) (message-tool-bar-map))))
(easy-menu-add message-mode-menu message-mode-map)
(easy-menu-add message-mode-field-menu message-mode-map)
- ;; make-local-hook is harmless though obsolete in Emacs 21.
- ;; Emacs 20 and XEmacs need make-local-hook.
- (make-local-hook 'after-change-functions)
+ (gnus-make-local-hook 'after-change-functions)
;; Mmmm... Forbidden properties...
(add-hook 'after-change-functions 'message-strip-forbidden-properties
nil 'local)
(when (eq message-mail-alias-type 'abbrev)
(if (fboundp 'mail-abbrevs-setup)
(mail-abbrevs-setup)
- (mail-aliases-setup)))
+ (if (fboundp 'mail-aliases-setup) ; warning avoidance
+ (mail-aliases-setup))))