1 ;;; message.el --- composing mail and news messages
2 ;; Copyright (C) 1996,97,98,99 Free Software Foundation, Inc.
4 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
5 ;; Keywords: mail, news
7 ;; This file is part of GNU Emacs.
9 ;; GNU Emacs is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs; see the file COPYING. If not, write to the
21 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
26 ;; This mode provides mail-sending facilities from within Emacs. It
27 ;; consists mainly of large chunks of code from the sendmail.el,
28 ;; gnus-msg.el and rnewspost.el files.
32 (eval-when-compile (require 'cl))
38 (if (string-match "XEmacs\\|Lucid" emacs-version)
39 (require 'mail-abbrevs)
40 (require 'mailabbrev))
46 (defgroup message '((user-mail-address custom-variable)
47 (user-full-name custom-variable))
48 "Mail and news message composing."
49 :link '(custom-manual "(message)Top")
53 (put 'user-mail-address 'custom-type 'string)
54 (put 'user-full-name 'custom-type 'string)
56 (defgroup message-various nil
57 "Various Message Variables"
58 :link '(custom-manual "(message)Various Message Variables")
61 (defgroup message-buffers nil
63 :link '(custom-manual "(message)Message Buffers")
66 (defgroup message-sending nil
68 :link '(custom-manual "(message)Sending Variables")
71 (defgroup message-interface nil
73 :link '(custom-manual "(message)Interface")
76 (defgroup message-forwarding nil
78 :link '(custom-manual "(message)Forwarding")
79 :group 'message-interface)
81 (defgroup message-insertion nil
83 :link '(custom-manual "(message)Insertion")
86 (defgroup message-headers nil
88 :link '(custom-manual "(message)Message Headers")
91 (defgroup message-news nil
92 "Composing News Messages"
95 (defgroup message-mail nil
96 "Composing Mail Messages"
99 (defgroup message-faces nil
100 "Faces used for message composing."
104 (defcustom message-directory "~/Mail/"
105 "*Directory from which all other mail file variables are derived."
106 :group 'message-various
109 (defcustom message-max-buffers 10
110 "*How many buffers to keep before starting to kill them off."
111 :group 'message-buffers
114 (defcustom message-send-rename-function nil
115 "Function called to rename the buffer after sending it."
116 :group 'message-buffers
119 (defcustom message-fcc-handler-function 'message-output
120 "*A function called to save outgoing articles.
121 This function will be called with the name of the file to store the
122 article in. The default function is `message-output' which saves in Unix
124 :type '(radio (function-item message-output)
125 (function :tag "Other"))
126 :group 'message-sending)
128 (defcustom message-courtesy-message
129 "The following message is a courtesy copy of an article\nthat has been posted to %s as well.\n\n"
130 "*This is inserted at the start of a mailed copy of a posted message.
131 If the string contains the format spec \"%s\", the Newsgroups
132 the article has been posted to will be inserted there.
133 If this variable is nil, no such courtesy message will be added."
134 :group 'message-sending
137 (defcustom message-ignored-bounced-headers "^\\(Received\\|Return-Path\\):"
138 "*Regexp that matches headers to be removed in resent bounced mail."
139 :group 'message-interface
143 (defcustom message-from-style 'default
144 "*Specifies how \"From\" headers look.
146 If `nil', they contain just the return address like:
148 If `parens', they look like:
149 king@grassland.com (Elvis Parsley)
150 If `angles', they look like:
151 Elvis Parsley <king@grassland.com>
153 Otherwise, most addresses look like `angles', but they look like
154 `parens' if `angles' would need quoting and `parens' would not."
155 :type '(choice (const :tag "simple" nil)
159 :group 'message-headers)
161 (defcustom message-syntax-checks nil
162 ; Guess this one shouldn't be easy to customize...
163 "*Controls what syntax checks should not be performed on outgoing posts.
164 To disable checking of long signatures, for instance, add
165 `(signature . disabled)' to this list.
167 Don't touch this variable unless you really know what you're doing.
169 Checks include subject-cmsg multiple-headers sendsys message-id from
170 long-lines control-chars size new-text redirected-followup signature
171 approved sender empty empty-headers message-id from subject
172 shorten-followup-to existing-newsgroups buffer-file-name unchanged
174 :group 'message-news)
176 (defcustom message-required-news-headers
177 '(From Newsgroups Subject Date Message-ID
178 (optional . Organization) Lines
179 (optional . User-Agent))
180 "*Headers to be generated or prompted for when posting an article.
181 RFC977 and RFC1036 require From, Date, Newsgroups, Subject,
182 Message-ID. Organization, Lines, In-Reply-To, Expires, and
183 User-Agent are optional. If don't you want message to insert some
184 header, remove it from this list."
186 :group 'message-headers
187 :type '(repeat sexp))
189 (defcustom message-required-mail-headers
190 '(From Subject Date (optional . In-Reply-To) Message-ID Lines
191 (optional . User-Agent))
192 "*Headers to be generated or prompted for when mailing a message.
193 RFC822 required that From, Date, To, Subject and Message-ID be
194 included. Organization, Lines and User-Agent are optional."
196 :group 'message-headers
197 :type '(repeat sexp))
199 (defcustom message-deletable-headers '(Message-ID Date Lines)
200 "Headers to be deleted if they already exist and were generated by message previously."
201 :group 'message-headers
204 (defcustom message-ignored-news-headers
205 "^NNTP-Posting-Host:\\|^Xref:\\|^[BGF]cc:\\|^Resent-Fcc:"
206 "*Regexp of headers to be removed unconditionally before posting."
208 :group 'message-headers
211 (defcustom message-ignored-mail-headers "^[GF]cc:\\|^Resent-Fcc:\\|^Xref:"
212 "*Regexp of headers to be removed unconditionally before mailing."
214 :group 'message-headers
217 (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:"
218 "*Header lines matching this regexp will be deleted before posting.
219 It's best to delete old Path and Date headers before posting to avoid
221 :group 'message-interface
224 (defcustom message-subject-re-regexp "^[ \t]*\\([Rr][Ee]:[ \t]*\\)*[ \t]*"
225 "*Regexp matching \"Re: \" in the subject line."
226 :group 'message-various
230 (defcustom message-signature-separator "^-- *$"
231 "Regexp matching the signature separator."
233 :group 'message-various)
235 (defcustom message-elide-ellipsis "\n[...]\n\n"
236 "*The string which is inserted for elided text."
238 :group 'message-various)
240 (defcustom message-interactive nil
241 "Non-nil means when sending a message wait for and display errors.
242 nil means let mailer mail back a message to report errors."
243 :group 'message-sending
247 (defcustom message-generate-new-buffers 'unique
248 "*Non-nil means that a new message buffer will be created whenever `message-setup' is called.
249 If this is a function, call that function with three parameters: The type,
250 the to address and the group name. (Any of these may be nil.) The function
251 should return the new buffer name."
252 :group 'message-buffers
253 :type '(choice (const :tag "off" nil)
254 (const :tag "unique" unique)
255 (const :tag "unsent" unsent)
258 (defcustom message-kill-buffer-on-exit nil
259 "*Non-nil means that the message buffer will be killed after sending a message."
260 :group 'message-buffers
263 (defvar gnus-local-organization)
264 (defcustom message-user-organization
265 (or (and (boundp 'gnus-local-organization)
266 (stringp gnus-local-organization)
267 gnus-local-organization)
268 (getenv "ORGANIZATION")
270 "*String to be used as an Organization header.
271 If t, use `message-user-organization-file'."
272 :group 'message-headers
273 :type '(choice string
274 (const :tag "consult file" t)))
277 (defcustom message-user-organization-file "/usr/lib/news/organization"
278 "*Local news organization file."
280 :group 'message-headers)
282 (defcustom message-make-forward-subject-function
283 'message-forward-subject-author-subject
284 "*A list of functions that are called to generate a subject header for forwarded messages.
285 The subject generated by the previous function is passed into each
288 The provided functions are:
290 * message-forward-subject-author-subject (Source of article (author or
291 newsgroup)), in brackets followed by the subject
292 * message-forward-subject-fwd (Subject of article with 'Fwd:' prepended
294 :group 'message-forwarding
295 :type '(radio (function-item message-forward-subject-author-subject)
296 (function-item message-forward-subject-fwd)))
298 (defcustom message-forward-as-mime t
299 "*If non-nil, forward messages as an inline/rfc822 MIME section. Otherwise, directly inline the old message in the forwarded message."
300 :group 'message-forwarding
303 (defcustom message-wash-forwarded-subjects nil
304 "*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."
305 :group 'message-forwarding
308 (defcustom message-ignored-resent-headers "^Return-receipt\\|^X-Gnus\\|^Gnus-Warning:"
309 "*All headers that match this regexp will be deleted when resending a message."
310 :group 'message-interface
313 (defcustom message-forward-ignored-headers nil
314 "*All headers that match this regexp will be deleted when forwarding a message."
315 :group 'message-forwarding
316 :type '(choice (const :tag "None" nil)
319 (defcustom message-ignored-cited-headers "."
320 "*Delete these headers from the messages you yank."
321 :group 'message-insertion
324 (defcustom message-cancel-message "I am canceling my own article."
325 "Message to be inserted in the cancel message."
326 :group 'message-interface
329 ;; Useful to set in site-init.el
331 (defcustom message-send-mail-function 'message-send-mail-with-sendmail
332 "Function to call to send the current buffer as mail.
333 The headers should be delimited by a line whose contents match the
334 variable `mail-header-separator'.
336 Valid values include `message-send-mail-with-sendmail' (the default),
337 `message-send-mail-with-mh', `message-send-mail-with-qmail' and
339 :type '(radio (function-item message-send-mail-with-sendmail)
340 (function-item message-send-mail-with-mh)
341 (function-item message-send-mail-with-qmail)
342 (function-item smtpmail-send-it)
343 (function :tag "Other"))
344 :group 'message-sending
345 :group 'message-mail)
347 (defcustom message-send-news-function 'message-send-news
348 "Function to call to send the current buffer as news.
349 The headers should be delimited by a line whose contents match the
350 variable `mail-header-separator'."
351 :group 'message-sending
355 (defcustom message-reply-to-function nil
356 "Function that should return a list of headers.
357 This function should pick out addresses from the To, Cc, and From headers
358 and respond with new To and Cc headers."
359 :group 'message-interface
362 (defcustom message-wide-reply-to-function nil
363 "Function that should return a list of headers.
364 This function should pick out addresses from the To, Cc, and From headers
365 and respond with new To and Cc headers."
366 :group 'message-interface
369 (defcustom message-followup-to-function nil
370 "Function that should return a list of headers.
371 This function should pick out addresses from the To, Cc, and From headers
372 and respond with new To and Cc headers."
373 :group 'message-interface
376 (defcustom message-use-followup-to 'ask
377 "*Specifies what to do with Followup-To header.
378 If nil, always ignore the header. If it is t, use its value, but
379 query before using the \"poster\" value. If it is the symbol `ask',
380 always query the user whether to use the value. If it is the symbol
381 `use', always use the value."
382 :group 'message-interface
383 :type '(choice (const :tag "ignore" nil)
387 ;; stuff relating to broken sendmail in MMDF
388 (defcustom message-sendmail-f-is-evil nil
389 "*Non-nil means that \"-f username\" should not be added to the sendmail
390 command line, because it is even more evil than leaving it out."
391 :group 'message-sending
394 ;; qmail-related stuff
395 (defcustom message-qmail-inject-program "/var/qmail/bin/qmail-inject"
396 "Location of the qmail-inject program."
397 :group 'message-sending
400 (defcustom message-qmail-inject-args nil
401 "Arguments passed to qmail-inject programs.
402 This should be a list of strings, one string for each argument.
404 For e.g., if you wish to set the envelope sender address so that bounces
405 go to the right place or to deal with listserv's usage of that address, you
406 might set this variable to '(\"-f\" \"you@some.where\")."
407 :group 'message-sending
408 :type '(repeat string))
410 (defvar message-cater-to-broken-inn t
411 "Non-nil means Gnus should not fold the `References' header.
412 Folding `References' makes ancient versions of INN create incorrect
415 (defvar gnus-post-method)
416 (defvar gnus-select-method)
417 (defcustom message-post-method
418 (cond ((and (boundp 'gnus-post-method)
419 (listp gnus-post-method)
422 ((boundp 'gnus-select-method)
425 "*Method used to post news.
426 Note that when posting from inside Gnus, for instance, this
427 variable isn't used."
429 :group 'message-sending
430 ;; This should be the `gnus-select-method' widget, but that might
431 ;; create a dependence to `gnus.el'.
434 (defcustom message-generate-headers-first nil
435 "*If non-nil, generate all possible headers before composing."
436 :group 'message-headers
439 (defcustom message-setup-hook nil
440 "Normal hook, run each time a new outgoing message is initialized.
441 The function `message-setup' runs this hook."
442 :group 'message-various
445 (defcustom message-cancel-hook nil
446 "Hook run when cancelling articles."
447 :group 'message-various
450 (defcustom message-signature-setup-hook nil
451 "Normal hook, run each time a new outgoing message is initialized.
452 It is run after the headers have been inserted and before
453 the signature is inserted."
454 :group 'message-various
457 (defcustom message-mode-hook nil
458 "Hook run in message mode buffers."
459 :group 'message-various
462 (defcustom message-header-hook nil
463 "Hook run in a message mode buffer narrowed to the headers."
464 :group 'message-various
467 (defcustom message-header-setup-hook nil
468 "Hook called narrowed to the headers when setting up a message buffer."
469 :group 'message-various
473 (defcustom message-citation-line-function 'message-insert-citation-line
474 "*Function called to insert the \"Whomever writes:\" line."
476 :group 'message-insertion)
479 (defcustom message-yank-prefix "> "
480 "*Prefix inserted on the lines of yanked messages."
482 :group 'message-insertion)
484 (defcustom message-indentation-spaces 3
485 "*Number of spaces to insert at the beginning of each cited line.
486 Used by `message-yank-original' via `message-yank-cite'."
487 :group 'message-insertion
491 (defcustom message-cite-function 'message-cite-original
492 "*Function for citing an original message.
493 Predefined functions include `message-cite-original' and
494 `message-cite-original-without-signature'.
495 Note that `message-cite-original' uses `mail-citation-hook' if that is non-nil."
496 :type '(radio (function-item message-cite-original)
497 (function-item message-cite-original-without-signature)
498 (function-item sc-cite-original)
499 (function :tag "Other"))
500 :group 'message-insertion)
503 (defcustom message-indent-citation-function 'message-indent-citation
504 "*Function for modifying a citation just inserted in the mail buffer.
505 This can also be a list of functions. Each function can find the
506 citation between (point) and (mark t). And each function should leave
507 point and mark around the citation text as modified."
509 :group 'message-insertion)
511 (defvar message-abbrevs-loaded nil)
514 (defcustom message-signature t
515 "*String to be inserted at the end of the message buffer.
516 If t, the `message-signature-file' file will be inserted instead.
517 If a function, the result from the function will be used instead.
518 If a form, the result from the form will be used instead."
520 :group 'message-insertion)
523 (defcustom message-signature-file "~/.signature"
524 "*File containing the text inserted at end of message buffer."
526 :group 'message-insertion)
528 (defcustom message-distribution-function nil
529 "*Function called to return a Distribution header."
531 :group 'message-headers
534 (defcustom message-expires 14
535 "Number of days before your article expires."
537 :group 'message-headers
538 :link '(custom-manual "(message)News Headers")
541 (defcustom message-user-path nil
542 "If nil, use the NNTP server name in the Path header.
543 If stringp, use this; if non-nil, use no host name (user name only)."
545 :group 'message-headers
546 :link '(custom-manual "(message)News Headers")
547 :type '(choice (const :tag "nntp" nil)
549 (sexp :tag "none" :format "%t" t)))
551 (defvar message-reply-buffer nil)
552 (defvar message-reply-headers nil)
553 (defvar message-newsreader nil)
554 (defvar message-mailer nil)
555 (defvar message-sent-message-via nil)
556 (defvar message-checksum nil)
557 (defvar message-send-actions nil
558 "A list of actions to be performed upon successful sending of a message.")
559 (defvar message-exit-actions nil
560 "A list of actions to be performed upon exiting after sending a message.")
561 (defvar message-kill-actions nil
562 "A list of actions to be performed before killing a message buffer.")
563 (defvar message-postpone-actions nil
564 "A list of actions to be performed after postponing a message.")
566 (define-widget 'message-header-lines 'text
567 "All header lines must be LFD terminated."