comparison lisp/gnus/message.el @ 31716:9968f55ad26e

Update to emacs-21-branch of the Gnus CVS repository.
author Gerd Moellmann <gerd@gnu.org>
date Tue, 19 Sep 2000 13:37:09 +0000
parents 15fc6acbae7a
children 352449d35643
comparison
equal deleted inserted replaced
31715:7c896543d225 31716:9968f55ad26e
1 ;;; message.el --- composing mail and news messages 1 ;;; message.el --- composing mail and news messages
2 ;; Copyright (C) 1996,97,98 Free Software Foundation, Inc. 2 ;; Copyright (C) 1996, 1997, 1998, 1999, 2000
3 ;; Free Software Foundation, Inc.
3 4
4 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org> 5 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
5 ;; Keywords: mail, news 6 ;; Keywords: mail, news
6 7
7 ;; This file is part of GNU Emacs. 8 ;; This file is part of GNU Emacs.
27 ;; consists mainly of large chunks of code from the sendmail.el, 28 ;; consists mainly of large chunks of code from the sendmail.el,
28 ;; gnus-msg.el and rnewspost.el files. 29 ;; gnus-msg.el and rnewspost.el files.
29 30
30 ;;; Code: 31 ;;; Code:
31 32
32 (eval-when-compile (require 'cl)) 33 (eval-when-compile
33 34 (require 'cl)
35 (defvar gnus-list-identifiers)) ; gnus-sum is required where necessary
34 (require 'mailheader) 36 (require 'mailheader)
35 (require 'nnheader) 37 (require 'nnheader)
36 (require 'timezone) 38 ;; This is apparently necessary even though things are autoloaded:
37 (require 'easymenu) 39 (if (featurep 'xemacs)
38 (require 'custom) 40 (require 'mail-abbrevs))
39 (if (string-match "XEmacs\\|Lucid" emacs-version) 41 (require 'mail-parse)
40 (require 'mail-abbrevs) 42 (require 'mml)
41 (require 'mailabbrev))
42 43
43 (defgroup message '((user-mail-address custom-variable) 44 (defgroup message '((user-mail-address custom-variable)
44 (user-full-name custom-variable)) 45 (user-full-name custom-variable))
45 "Mail and news message composing." 46 "Mail and news message composing."
46 :link '(custom-manual "(message)Top") 47 :link '(custom-manual "(message)Top")
154 (const angles) 155 (const angles)
155 (const default)) 156 (const default))
156 :group 'message-headers) 157 :group 'message-headers)
157 158
158 (defcustom message-syntax-checks nil 159 (defcustom message-syntax-checks nil
159 ; Guess this one shouldn't be easy to customize... 160 ;; Guess this one shouldn't be easy to customize...
160 "*Controls what syntax checks should not be performed on outgoing posts. 161 "*Controls what syntax checks should not be performed on outgoing posts.
161 To disable checking of long signatures, for instance, add 162 To disable checking of long signatures, for instance, add
162 `(signature . disabled)' to this list. 163 `(signature . disabled)' to this list.
163 164
164 Don't touch this variable unless you really know what you're doing. 165 Don't touch this variable unless you really know what you're doing.
165 166
166 Checks include subject-cmsg multiple-headers sendsys message-id from 167 Checks include subject-cmsg multiple-headers sendsys message-id from
167 long-lines control-chars size new-text redirected-followup signature 168 long-lines control-chars size new-text quoting-style
168 approved sender empty empty-headers message-id from subject 169 redirected-followup signature approved sender empty empty-headers
169 shorten-followup-to existing-newsgroups buffer-file-name unchanged." 170 message-id from subject shorten-followup-to existing-newsgroups
170 :group 'message-news) 171 buffer-file-name unchanged newsgroups."
172 :group 'message-news
173 :type '(repeat sexp))
171 174
172 (defcustom message-required-news-headers 175 (defcustom message-required-news-headers
173 '(From Newsgroups Subject Date Message-ID 176 '(From Newsgroups Subject Date Message-ID
174 (optional . Organization) Lines 177 (optional . Organization) Lines
175 (optional . X-Newsreader)) 178 (optional . User-Agent))
176 "*Headers to be generated or prompted for when posting an article. 179 "*Headers to be generated or prompted for when posting an article.
177 RFC977 and RFC1036 require From, Date, Newsgroups, Subject, 180 RFC977 and RFC1036 require From, Date, Newsgroups, Subject,
178 Message-ID. Organization, Lines, In-Reply-To, Expires, and 181 Message-ID. Organization, Lines, In-Reply-To, Expires, and
179 X-Newsreader are optional. If don't you want message to insert some 182 User-Agent are optional. If don't you want message to insert some
180 header, remove it from this list." 183 header, remove it from this list."
181 :group 'message-news 184 :group 'message-news
182 :group 'message-headers 185 :group 'message-headers
183 :type '(repeat sexp)) 186 :type '(repeat sexp))
184 187
185 (defcustom message-required-mail-headers 188 (defcustom message-required-mail-headers
186 '(From Subject Date (optional . In-Reply-To) Message-ID Lines 189 '(From Subject Date (optional . In-Reply-To) Message-ID Lines
187 (optional . X-Mailer)) 190 (optional . User-Agent))
188 "*Headers to be generated or prompted for when mailing a message. 191 "*Headers to be generated or prompted for when mailing a message.
189 RFC822 required that From, Date, To, Subject and Message-ID be 192 RFC822 required that From, Date, To, Subject and Message-ID be
190 included. Organization, Lines and X-Mailer are optional." 193 included. Organization, Lines and User-Agent are optional."
191 :group 'message-mail 194 :group 'message-mail
192 :group 'message-headers 195 :group 'message-headers
193 :type '(repeat sexp)) 196 :type '(repeat sexp))
194 197
195 (defcustom message-deletable-headers '(Message-ID Date Lines) 198 (defcustom message-deletable-headers '(Message-ID Date Lines)
208 "*Regexp of headers to be removed unconditionally before mailing." 211 "*Regexp of headers to be removed unconditionally before mailing."
209 :group 'message-mail 212 :group 'message-mail
210 :group 'message-headers 213 :group 'message-headers
211 :type 'regexp) 214 :type 'regexp)
212 215
213 (defcustom message-ignored-supersedes-headers "^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|^Received:\\|^X-From-Line:\\|^X-Trace:\\|^X-Complaints-To:\\|Return-Path:\\|^Supersedes:\\|^X-Trace:\\|^X-Complaints-To:\\|^NNTP-Posting-Date:" 216 (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:"
214 "*Header lines matching this regexp will be deleted before posting. 217 "*Header lines matching this regexp will be deleted before posting.
215 It's best to delete old Path and Date headers before posting to avoid 218 It's best to delete old Path and Date headers before posting to avoid
216 any confusion." 219 any confusion."
217 :group 'message-interface 220 :group 'message-interface
218 :type 'regexp) 221 :type 'regexp)
226 (defcustom message-signature-separator "^-- *$" 229 (defcustom message-signature-separator "^-- *$"
227 "Regexp matching the signature separator." 230 "Regexp matching the signature separator."
228 :type 'regexp 231 :type 'regexp
229 :group 'message-various) 232 :group 'message-various)
230 233
231 (defcustom message-elide-elipsis "\n[...]\n\n" 234 (defcustom message-elide-ellipsis "\n[...]\n\n"
232 "*The string which is inserted for elided text." 235 "*The string which is inserted for elided text."
233 :type 'string 236 :type 'string
234 :group 'message-various) 237 :group 'message-various)
235 238
236 (defcustom message-interactive nil 239 (defcustom message-interactive nil
238 nil means let mailer mail back a message to report errors." 241 nil means let mailer mail back a message to report errors."
239 :group 'message-sending 242 :group 'message-sending
240 :group 'message-mail 243 :group 'message-mail
241 :type 'boolean) 244 :type 'boolean)
242 245
243 (defcustom message-generate-new-buffers t 246 (defcustom message-generate-new-buffers 'unique
244 "*Non-nil means that a new message buffer will be created whenever `message-setup' is called. 247 "*Non-nil means that a new message buffer will be created whenever `message-setup' is called.
245 If this is a function, call that function with three parameters: The type, 248 If this is a function, call that function with three parameters: The type,
246 the to address and the group name. (Any of these may be nil.) The function 249 the to address and the group name. (Any of these may be nil.) The function
247 should return the new buffer name." 250 should return the new buffer name."
248 :group 'message-buffers 251 :group 'message-buffers
249 :type '(choice (const :tag "off" nil) 252 :type '(choice (const :tag "off" nil)
250 (const :tag "on" t) 253 (const :tag "unique" unique)
254 (const :tag "unsent" unsent)
251 (function fun))) 255 (function fun)))
252 256
253 (defcustom message-kill-buffer-on-exit nil 257 (defcustom message-kill-buffer-on-exit nil
254 "*Non-nil means that the message buffer will be killed after sending a message." 258 "*Non-nil means that the message buffer will be killed after sending a message."
255 :group 'message-buffers 259 :group 'message-buffers
272 (defcustom message-user-organization-file "/usr/lib/news/organization" 276 (defcustom message-user-organization-file "/usr/lib/news/organization"
273 "*Local news organization file." 277 "*Local news organization file."
274 :type 'file 278 :type 'file
275 :group 'message-headers) 279 :group 'message-headers)
276 280
277 (defcustom message-forward-start-separator
278 "------- Start of forwarded message -------\n"
279 "*Delimiter inserted before forwarded messages."
280 :group 'message-forwarding
281 :type 'string)
282
283 (defcustom message-forward-end-separator
284 "------- End of forwarded message -------\n"
285 "*Delimiter inserted after forwarded messages."
286 :group 'message-forwarding
287 :type 'string)
288
289 (defcustom message-signature-before-forwarded-message t
290 "*If non-nil, put the signature before any included forwarded message."
291 :group 'message-forwarding
292 :type 'boolean)
293
294 (defcustom message-included-forward-headers
295 "^From:\\|^Newsgroups:\\|^Subject:\\|^Date:\\|^Followup-To:\\|^Reply-To:\\|^Organization:\\|^Summary:\\|^Keywords:\\|^To:\\|^Cc:\\|^Posted-To:\\|^Mail-Copies-To:\\|^Apparently-To:\\|^Gnus-Warning:\\|^Resent-\\|^Message-ID:\\|^References:\\|^Content-Transfer-Encoding:\\|^Content-Type:\\|^Mime-Version:"
296 "*Regexp matching headers to be included in forwarded messages."
297 :group 'message-forwarding
298 :type 'regexp)
299
300 (defcustom message-make-forward-subject-function 281 (defcustom message-make-forward-subject-function
301 'message-forward-subject-author-subject 282 'message-forward-subject-author-subject
302 "*A list of functions that are called to generate a subject header for forwarded messages. 283 "*A list of functions that are called to generate a subject header for forwarded messages.
303 The subject generated by the previous function is passed into each 284 The subject generated by the previous function is passed into each
304 successive function. 285 successive function.
305 286
306 The provided functions are: 287 The provided functions are:
307 288
308 * message-forward-subject-author-subject (Source of article (author or 289 * message-forward-subject-author-subject (Source of article (author or
309 newsgroup)), in brackets followed by the subject 290 newsgroup)), in brackets followed by the subject
310 * message-forward-subject-fwd (Subject of article with 'Fwd:' prepended 291 * message-forward-subject-fwd (Subject of article with 'Fwd:' prepended
311 to it." 292 to it."
312 :group 'message-forwarding 293 :group 'message-forwarding
313 :type '(radio (function-item message-forward-subject-author-subject) 294 :type '(radio (function-item message-forward-subject-author-subject)
314 (function-item message-forward-subject-fwd))) 295 (function-item message-forward-subject-fwd)))
296
297 (defcustom message-forward-as-mime t
298 "*If non-nil, forward messages as an inline/rfc822 MIME section. Otherwise, directly inline the old message in the forwarded message."
299 :group 'message-forwarding
300 :type 'boolean)
301
302 (defcustom message-forward-show-mml t
303 "*If non-nil, forward messages are shown as mml. Otherwise, forward messages are unchanged."
304 :group 'message-forwarding
305 :type 'boolean)
306
307 (defcustom message-forward-before-signature t
308 "*If non-nil, put forwarded message before signature, else after."
309 :group 'message-forwarding
310 :type 'boolean)
315 311
316 (defcustom message-wash-forwarded-subjects nil 312 (defcustom message-wash-forwarded-subjects nil
317 "*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." 313 "*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."
318 :group 'message-forwarding 314 :group 'message-forwarding
319 :type 'boolean) 315 :type 'boolean)
320 316
321 (defcustom message-ignored-resent-headers "^Return-receipt" 317 (defcustom message-ignored-resent-headers "^Return-receipt\\|^X-Gnus\\|^Gnus-Warning:"
322 "*All headers that match this regexp will be deleted when resending a message." 318 "*All headers that match this regexp will be deleted when resending a message."
323 :group 'message-interface 319 :group 'message-interface
324 :type 'regexp) 320 :type 'regexp)
321
322 (defcustom message-forward-ignored-headers "^Content-Transfer-Encoding:\\|^X-Gnus"
323 "*All headers that match this regexp will be deleted when forwarding a message."
324 :group 'message-forwarding
325 :type '(choice (const :tag "None" nil)
326 regexp))
325 327
326 (defcustom message-ignored-cited-headers "." 328 (defcustom message-ignored-cited-headers "."
327 "*Delete these headers from the messages you yank." 329 "*Delete these headers from the messages you yank."
328 :group 'message-insertion 330 :group 'message-insertion
329 :type 'regexp) 331 :type 'regexp)
330 332
331 (defcustom message-cancel-message "I am canceling my own article." 333 (defcustom message-cancel-message "I am canceling my own article.\n"
332 "Message to be inserted in the cancel message." 334 "Message to be inserted in the cancel message."
333 :group 'message-interface 335 :group 'message-interface
334 :type 'string) 336 :type 'string)
335 337
336 ;; Useful to set in site-init.el 338 ;; Useful to set in site-init.el
338 (defcustom message-send-mail-function 'message-send-mail-with-sendmail 340 (defcustom message-send-mail-function 'message-send-mail-with-sendmail
339 "Function to call to send the current buffer as mail. 341 "Function to call to send the current buffer as mail.
340 The headers should be delimited by a line whose contents match the 342 The headers should be delimited by a line whose contents match the
341 variable `mail-header-separator'. 343 variable `mail-header-separator'.
342 344
343 Legal values include `message-send-mail-with-sendmail' (the default), 345 Valid values include `message-send-mail-with-sendmail' (the default),
344 `message-send-mail-with-mh', `message-send-mail-with-qmail' and 346 `message-send-mail-with-mh', `message-send-mail-with-qmail' and
345 `smtpmail-send-it'." 347 `smtpmail-send-it'."
346 :type '(radio (function-item message-send-mail-with-sendmail) 348 :type '(radio (function-item message-send-mail-with-sendmail)
347 (function-item message-send-mail-with-mh) 349 (function-item message-send-mail-with-mh)
348 (function-item message-send-mail-with-qmail) 350 (function-item message-send-mail-with-qmail)
389 :group 'message-interface 391 :group 'message-interface
390 :type '(choice (const :tag "ignore" nil) 392 :type '(choice (const :tag "ignore" nil)
391 (const use) 393 (const use)
392 (const ask))) 394 (const ask)))
393 395
394 ;; stuff relating to broken sendmail in MMDF
395 (defcustom message-sendmail-f-is-evil nil 396 (defcustom message-sendmail-f-is-evil nil
396 "*Non-nil means that \"-f username\" should not be added to the sendmail 397 "*Non-nil means that \"-f username\" should not be added to the sendmail command line.
397 command line, because it is even more evil than leaving it out." 398 Doing so would be even more evil than leaving it out."
398 :group 'message-sending 399 :group 'message-sending
399 :type 'boolean) 400 :type 'boolean)
400 401
401 ;; qmail-related stuff 402 ;; qmail-related stuff
402 (defcustom message-qmail-inject-program "/var/qmail/bin/qmail-inject" 403 (defcustom message-qmail-inject-program "/var/qmail/bin/qmail-inject"
411 For e.g., if you wish to set the envelope sender address so that bounces 412 For e.g., if you wish to set the envelope sender address so that bounces
412 go to the right place or to deal with listserv's usage of that address, you 413 go to the right place or to deal with listserv's usage of that address, you
413 might set this variable to '(\"-f\" \"you@some.where\")." 414 might set this variable to '(\"-f\" \"you@some.where\")."
414 :group 'message-sending 415 :group 'message-sending
415 :type '(repeat string)) 416 :type '(repeat string))
417
418 (defvar message-cater-to-broken-inn t
419 "Non-nil means Gnus should not fold the `References' header.
420 Folding `References' makes ancient versions of INN create incorrect
421 NOV lines.")
416 422
417 (defvar gnus-post-method) 423 (defvar gnus-post-method)
418 (defvar gnus-select-method) 424 (defvar gnus-select-method)
419 (defcustom message-post-method 425 (defcustom message-post-method
420 (cond ((and (boundp 'gnus-post-method) 426 (cond ((and (boundp 'gnus-post-method)
442 "Normal hook, run each time a new outgoing message is initialized. 448 "Normal hook, run each time a new outgoing message is initialized.
443 The function `message-setup' runs this hook." 449 The function `message-setup' runs this hook."
444 :group 'message-various 450 :group 'message-various
445 :type 'hook) 451 :type 'hook)
446 452
453 (defcustom message-cancel-hook nil
454 "Hook run when cancelling articles."
455 :group 'message-various
456 :type 'hook)
457
447 (defcustom message-signature-setup-hook nil 458 (defcustom message-signature-setup-hook nil
448 "Normal hook, run each time a new outgoing message is initialized. 459 "Normal hook, run each time a new outgoing message is initialized.
449 It is run after the headers have been inserted and before 460 It is run after the headers have been inserted and before
450 the signature is inserted." 461 the signature is inserted."
451 :group 'message-various 462 :group 'message-various
472 :type 'function 483 :type 'function
473 :group 'message-insertion) 484 :group 'message-insertion)
474 485
475 ;;;###autoload 486 ;;;###autoload
476 (defcustom message-yank-prefix "> " 487 (defcustom message-yank-prefix "> "
477 "*Prefix inserted on the lines of yanked messages. 488 "*Prefix inserted on the lines of yanked messages."
478 nil means use indentation."
479 :type 'string 489 :type 'string
480 :group 'message-insertion) 490 :group 'message-insertion)
481 491
482 (defcustom message-indentation-spaces 3 492 (defcustom message-indentation-spaces 3
483 "*Number of spaces to insert at the beginning of each cited line. 493 "*Number of spaces to insert at the beginning of each cited line.
490 "*Function for citing an original message. 500 "*Function for citing an original message.
491 Predefined functions include `message-cite-original' and 501 Predefined functions include `message-cite-original' and
492 `message-cite-original-without-signature'. 502 `message-cite-original-without-signature'.
493 Note that `message-cite-original' uses `mail-citation-hook' if that is non-nil." 503 Note that `message-cite-original' uses `mail-citation-hook' if that is non-nil."
494 :type '(radio (function-item message-cite-original) 504 :type '(radio (function-item message-cite-original)
505 (function-item message-cite-original-without-signature)
495 (function-item sc-cite-original) 506 (function-item sc-cite-original)
496 (function :tag "Other")) 507 (function :tag "Other"))
497 :group 'message-insertion) 508 :group 'message-insertion)
498 509
499 ;;;###autoload 510 ;;;###autoload
578 :group 'message-headers 589 :group 'message-headers
579 :group 'message-mail 590 :group 'message-mail
580 :type 'message-header-lines) 591 :type 'message-header-lines)
581 592
582 (defcustom message-default-news-headers "" 593 (defcustom message-default-news-headers ""
583 "*A string of header lines to be inserted in outgoing news 594 "*A string of header lines to be inserted in outgoing news articles."
584 articles."
585 :group 'message-headers 595 :group 'message-headers
586 :group 'message-news 596 :group 'message-news
587 :type 'message-header-lines) 597 :type 'message-header-lines)
588 598
589 ;; Note: could use /usr/ucb/mail instead of sendmail; 599 ;; Note: could use /usr/ucb/mail instead of sendmail;
611 The value should be an expression to test whether the problem will 621 The value should be an expression to test whether the problem will
612 actually occur." 622 actually occur."
613 :group 'message-sending 623 :group 'message-sending
614 :type 'sexp) 624 :type 'sexp)
615 625
616 ;; Ignore errors in case this is used in Emacs 19.
617 ;; Don't use ignore-errors because this is copied into loaddefs.el.
618 ;;;###autoload 626 ;;;###autoload
619 (condition-case nil 627 (define-mail-user-agent 'message-user-agent
620 (define-mail-user-agent 'message-user-agent 628 'message-mail 'message-send-and-exit
621 'message-mail 'message-send-and-exit 629 'message-kill-buffer 'message-send-hook)
622 'message-kill-buffer 'message-send-hook)
623 (error nil))
624 630
625 (defvar message-mh-deletable-headers '(Message-ID Date Lines Sender) 631 (defvar message-mh-deletable-headers '(Message-ID Date Lines Sender)
626 "If non-nil, delete the deletable headers before feeding to mh.") 632 "If non-nil, delete the deletable headers before feeding to mh.")
627 633
628 (defvar message-send-method-alist 634 (defvar message-send-method-alist
649 "*Directory where Message auto-saves buffers if Gnus isn't running. 655 "*Directory where Message auto-saves buffers if Gnus isn't running.
650 If nil, Message won't auto-save." 656 If nil, Message won't auto-save."
651 :group 'message-buffers 657 :group 'message-buffers
652 :type 'directory) 658 :type 'directory)
653 659
660 (defcustom message-buffer-naming-style 'unique
661 "*The way new message buffers are named.
662 Valid valued are `unique' and `unsent'."
663 :group 'message-buffers
664 :type '(choice (const :tag "unique" unique)
665 (const :tag "unsent" unsent)))
666
667 (defcustom message-default-charset nil
668 "Default charset used in non-MULE XEmacsen."
669 :group 'message
670 :type 'symbol)
671
672 (defcustom message-dont-reply-to-names
673 (and (boundp 'rmail-dont-reply-to-names) rmail-dont-reply-to-names)
674 "*A regexp specifying names to prune when doing wide replies.
675 A value of nil means exclude your own name only."
676 :group 'message
677 :type '(choice (const :tag "Yourself" nil)
678 regexp))
679
654 ;;; Internal variables. 680 ;;; Internal variables.
655 ;;; Well, not really internal. 681 ;;; Well, not really internal.
656 682
657 (defvar message-mode-syntax-table 683 (defvar message-mode-syntax-table
658 (let ((table (copy-syntax-table text-mode-syntax-table))) 684 (let ((table (copy-syntax-table text-mode-syntax-table)))
659 (modify-syntax-entry ?% ". " table) 685 (modify-syntax-entry ?% ". " table)
686 (modify-syntax-entry ?> ". " table)
687 (modify-syntax-entry ?< ". " table)
660 table) 688 table)
661 "Syntax table used while in Message mode.") 689 "Syntax table used while in Message mode.")
662 690
663 (defvar message-mode-abbrev-table text-mode-abbrev-table 691 (defvar message-mode-abbrev-table text-mode-abbrev-table
664 "Abbrev table used in Message mode buffers. 692 "Abbrev table used in Message mode buffers.
772 (background light)) 800 (background light))
773 (:foreground "red")) 801 (:foreground "red"))
774 (t 802 (t
775 (:bold t))) 803 (:bold t)))
776 "Face used for displaying cited text names." 804 "Face used for displaying cited text names."
805 :group 'message-faces)
806
807 (defface message-mml-face
808 '((((class color)
809 (background dark))
810 (:foreground "ForestGreen"))
811 (((class color)
812 (background light))
813 (:foreground "ForestGreen"))
814 (t
815 (:bold t)))
816 "Face used for displaying MML."
777 :group 'message-faces) 817 :group 'message-faces)
778 818
779 (defvar message-font-lock-keywords 819 (defvar message-font-lock-keywords
780 (let* ((cite-prefix "A-Za-z") 820 (let* ((cite-prefix "A-Za-z")
781 (cite-suffix (concat cite-prefix "0-9_.@-")) 821 (cite-suffix (concat cite-prefix "0-9_.@-"))
804 1 'message-separator-face)) 844 1 'message-separator-face))
805 nil) 845 nil)
806 (,(concat "^[ \t]*" 846 (,(concat "^[ \t]*"
807 "\\([" cite-prefix "]+[" cite-suffix "]*\\)?" 847 "\\([" cite-prefix "]+[" cite-suffix "]*\\)?"
808 "[:>|}].*") 848 "[:>|}].*")
809 (0 'message-cited-text-face)))) 849 (0 'message-cited-text-face))
850 ("<#/?\\(multipart\\|part\\|external\\|mml\\).*>"
851 (0 'message-mml-face))))
810 "Additional expressions to highlight in Message mode.") 852 "Additional expressions to highlight in Message mode.")
811 853
812 ;; XEmacs does it like this. For Emacs, we have to set the 854 ;; XEmacs does it like this. For Emacs, we have to set the
813 ;; `font-lock-defaults' buffer-local variable. 855 ;; `font-lock-defaults' buffer-local variable.
814 (put 'message-mode 'font-lock-defaults '(message-font-lock-keywords t)) 856 (put 'message-mode 'font-lock-defaults '(message-font-lock-keywords t))
844 :type 'hook) 886 :type 'hook)
845 887
846 (defvar message-send-coding-system 'binary 888 (defvar message-send-coding-system 'binary
847 "Coding system to encode outgoing mail.") 889 "Coding system to encode outgoing mail.")
848 890
891 (defvar message-draft-coding-system
892 mm-auto-save-coding-system
893 "Coding system to compose mail.")
894
895 (defcustom message-send-mail-partially-limit 1000000
896 "The limitation of messages sent as message/partial.
897 The lower bound of message size in characters, beyond which the message
898 should be sent in several parts. If it is nil, the size is unlimited."
899 :group 'message-buffers
900 :type '(choice (const :tag "unlimited" nil)
901 (integer 1000000)))
902
849 ;;; Internal variables. 903 ;;; Internal variables.
850 904
851 (defvar message-buffer-list nil) 905 (defvar message-buffer-list nil)
852 (defvar message-this-is-news nil) 906 (defvar message-this-is-news nil)
853 (defvar message-this-is-mail nil) 907 (defvar message-this-is-mail nil)
854 (defvar message-draft-article nil) 908 (defvar message-draft-article nil)
909 (defvar message-mime-part nil)
910 (defvar message-posting-charset nil)
855 911
856 ;; Byte-compiler warning 912 ;; Byte-compiler warning
857 (defvar gnus-active-hashtb) 913 (defvar gnus-active-hashtb)
858 (defvar gnus-read-active-file) 914 (defvar gnus-read-active-file)
859 915
889 ;; The following regexp rejects names whose first characters are 945 ;; The following regexp rejects names whose first characters are
890 ;; obviously bogus, but after that anything goes. 946 ;; obviously bogus, but after that anything goes.
891 "\\([^\0-\b\n-\r\^?].*\\)? " 947 "\\([^\0-\b\n-\r\^?].*\\)? "
892 948
893 ;; The time the message was sent. 949 ;; The time the message was sent.
894 "\\([^\0-\r \^?]+\\) +" ; day of the week 950 "\\([^\0-\r \^?]+\\) +" ; day of the week
895 "\\([^\0-\r \^?]+\\) +" ; month 951 "\\([^\0-\r \^?]+\\) +" ; month
896 "\\([0-3]?[0-9]\\) +" ; day of month 952 "\\([0-3]?[0-9]\\) +" ; day of month
897 "\\([0-2][0-9]:[0-5][0-9]\\(:[0-6][0-9]\\)?\\) *" ; time of day 953 "\\([0-2][0-9]:[0-5][0-9]\\(:[0-6][0-9]\\)?\\) *" ; time of day
898 954
899 ;; Perhaps a time zone, specified by an abbreviation, or by a 955 ;; Perhaps a time zone, specified by an abbreviation, or by a
900 ;; numeric offset. 956 ;; numeric offset.
901 time-zone-regexp 957 time-zone-regexp
902 958
917 "^ *---+ +Returned message +---+ *$\\|" 973 "^ *---+ +Returned message +---+ *$\\|"
918 "^Start of returned message$\\|" 974 "^Start of returned message$\\|"
919 "^ *---+ +Original message +---+ *$\\|" 975 "^ *---+ +Original message +---+ *$\\|"
920 "^ *--+ +begin message +--+ *$\\|" 976 "^ *--+ +begin message +--+ *$\\|"
921 "^ *---+ +Original message follows +---+ *$\\|" 977 "^ *---+ +Original message follows +---+ *$\\|"
978 "^ *---+ +Undelivered message follows +---+ *$\\|"
922 "^|? *---+ +Message text follows: +---+ *|?$") 979 "^|? *---+ +Message text follows: +---+ *|?$")
923 "A regexp that matches the separator before the text of a failed message.") 980 "A regexp that matches the separator before the text of a failed message.")
924 981
925 (defvar message-header-format-alist 982 (defvar message-header-format-alist
926 `((Newsgroups) 983 `((Newsgroups)
935 (Distribution) 992 (Distribution)
936 (Lines) 993 (Lines)
937 (Expires) 994 (Expires)
938 (Message-ID) 995 (Message-ID)
939 (References . message-shorten-references) 996 (References . message-shorten-references)
940 (X-Mailer) 997 (User-Agent))
941 (X-Newsreader))
942 "Alist used for formatting headers.") 998 "Alist used for formatting headers.")
943 999
944 (eval-and-compile 1000 (eval-and-compile
945 (autoload 'message-setup-toolbar "messagexmas") 1001 (autoload 'message-setup-toolbar "messagexmas")
946 (autoload 'mh-new-draft-name "mh-comp") 1002 (autoload 'mh-new-draft-name "mh-comp")
947 (autoload 'mh-send-letter "mh-comp") 1003 (autoload 'mh-send-letter "mh-comp")
948 (autoload 'gnus-point-at-eol "gnus-util") 1004 (autoload 'gnus-point-at-eol "gnus-util")
949 (autoload 'gnus-point-at-bol "gnus-util") 1005 (autoload 'gnus-point-at-bol "gnus-util")
1006 (autoload 'gnus-output-to-rmail "gnus-util")
950 (autoload 'gnus-output-to-mail "gnus-util") 1007 (autoload 'gnus-output-to-mail "gnus-util")
951 (autoload 'gnus-output-to-rmail "gnus-util")
952 (autoload 'mail-abbrev-in-expansion-header-p "mailabbrev") 1008 (autoload 'mail-abbrev-in-expansion-header-p "mailabbrev")
953 (autoload 'nndraft-request-associate-buffer "nndraft") 1009 (autoload 'nndraft-request-associate-buffer "nndraft")
954 (autoload 'nndraft-request-expire-articles "nndraft") 1010 (autoload 'nndraft-request-expire-articles "nndraft")
955 (autoload 'gnus-open-server "gnus-int") 1011 (autoload 'gnus-open-server "gnus-int")
956 (autoload 'gnus-request-post "gnus-int") 1012 (autoload 'gnus-request-post "gnus-int")
957 (autoload 'gnus-alive-p "gnus-util") 1013 (autoload 'gnus-alive-p "gnus-util")
1014 (autoload 'gnus-group-name-charset "gnus-group")
958 (autoload 'rmail-output "rmail")) 1015 (autoload 'rmail-output "rmail"))
959 1016
960 1017
961 1018
962 ;;; 1019 ;;;
970 ;; Delete the current line (and the next N lines.); 1027 ;; Delete the current line (and the next N lines.);
971 (defmacro message-delete-line (&optional n) 1028 (defmacro message-delete-line (&optional n)
972 `(delete-region (progn (beginning-of-line) (point)) 1029 `(delete-region (progn (beginning-of-line) (point))
973 (progn (forward-line ,(or n 1)) (point)))) 1030 (progn (forward-line ,(or n 1)) (point))))
974 1031
1032 (defun message-unquote-tokens (elems)
1033 "Remove double quotes (\") from strings in list."
1034 (mapcar (lambda (item)
1035 (while (string-match "^\\(.*\\)\"\\(.*\\)$" item)
1036 (setq item (concat (match-string 1 item)
1037 (match-string 2 item))))
1038 item)
1039 elems))
1040
975 (defun message-tokenize-header (header &optional separator) 1041 (defun message-tokenize-header (header &optional separator)
976 "Split HEADER into a list of header elements. 1042 "Split HEADER into a list of header elements.
977 \",\" is used as the separator." 1043 SEPARATOR is a string of characters to be used as separators. \",\"
1044 is used by default."
978 (if (not header) 1045 (if (not header)
979 nil 1046 nil
980 (let ((regexp (format "[%s]+" (or separator ","))) 1047 (let ((regexp (format "[%s]+" (or separator ",")))
981 (beg 1) 1048 (beg 1)
982 (first t) 1049 (first t)
994 (and (looking-at regexp) 1061 (and (looking-at regexp)
995 (not quoted) 1062 (not quoted)
996 (not paren)))) 1063 (not paren))))
997 (push (buffer-substring beg (point)) elems) 1064 (push (buffer-substring beg (point)) elems)
998 (setq beg (match-end 0))) 1065 (setq beg (match-end 0)))
999 ((= (following-char) ?\") 1066 ((eq (char-after) ?\")
1000 (setq quoted (not quoted))) 1067 (setq quoted (not quoted)))
1001 ((and (= (following-char) ?\() 1068 ((and (eq (char-after) ?\()
1002 (not quoted)) 1069 (not quoted))
1003 (setq paren t)) 1070 (setq paren t))
1004 ((and (= (following-char) ?\)) 1071 ((and (eq (char-after) ?\))
1005 (not quoted)) 1072 (not quoted))
1006 (setq paren nil)))) 1073 (setq paren nil))))
1007 (nreverse elems))))) 1074 (nreverse elems)))))
1008 1075
1009 (defun message-mail-file-mbox-p (file) 1076 (defun message-mail-file-mbox-p (file)
1010 "Say whether FILE looks like a Unix mbox file." 1077 "Say whether FILE looks like a Unix mbox file."
1011 (when (and (file-exists-p file) 1078 (when (and (file-exists-p file)
1012 (file-readable-p file) 1079 (file-readable-p file)
1013 (file-regular-p file)) 1080 (file-regular-p file))
1014 (nnheader-temp-write nil 1081 (with-temp-buffer
1015 (nnheader-insert-file-contents file) 1082 (nnheader-insert-file-contents file)
1016 (goto-char (point-min)) 1083 (goto-char (point-min))
1017 (looking-at message-unix-mail-delimiter)))) 1084 (looking-at message-unix-mail-delimiter))))
1018 1085
1019 (defun message-fetch-field (header &optional not-all) 1086 (defun message-fetch-field (header &optional not-all)
1020 "The same as `mail-fetch-field', only remove all newlines." 1087 "The same as `mail-fetch-field', only remove all newlines."
1021 (let* ((inhibit-point-motion-hooks t) 1088 (let* ((inhibit-point-motion-hooks t)
1089 (case-fold-search t)
1022 (value (mail-fetch-field header nil (not not-all)))) 1090 (value (mail-fetch-field header nil (not not-all))))
1023 (when value 1091 (when value
1024 (nnheader-replace-chars-in-string value ?\n ? )))) 1092 (while (string-match "\n[\t ]+" value)
1093 (setq value (replace-match " " t t value)))
1094 (set-text-properties 0 (length value) nil value)
1095 value)))
1096
1097 (defun message-narrow-to-field ()
1098 "Narrow the buffer to the header on the current line."
1099 (beginning-of-line)
1100 (narrow-to-region
1101 (point)
1102 (progn
1103 (forward-line 1)
1104 (if (re-search-forward "^[^ \n\t]" nil t)
1105 (progn
1106 (beginning-of-line)
1107 (point))
1108 (point-max))))
1109 (goto-char (point-min)))
1025 1110
1026 (defun message-add-header (&rest headers) 1111 (defun message-add-header (&rest headers)
1027 "Add the HEADERS to the message header, skipping those already present." 1112 "Add the HEADERS to the message header, skipping those already present."
1028 (while headers 1113 (while headers
1029 (let (hclean) 1114 (let (hclean)
1030 (unless (string-match "^\\([^:]+\\):[ \t]*[^ \t]" (car headers)) 1115 (unless (string-match "^\\([^:]+\\):[ \t]*[^ \t]" (car headers))
1031 (error "Invalid header `%s'" (car headers))) 1116 (error "Invalid header `%s'" (car headers)))
1032 (setq hclean (match-string 1 (car headers))) 1117 (setq hclean (match-string 1 (car headers)))
1033 (save-restriction 1118 (save-restriction
1034 (message-narrow-to-headers) 1119 (message-narrow-to-headers)
1035 (unless (re-search-forward (concat "^" (regexp-quote hclean) ":") nil t) 1120 (unless (re-search-forward (concat "^" (regexp-quote hclean) ":") nil t)
1036 (insert (car headers) ?\n)))) 1121 (insert (car headers) ?\n))))
1037 (setq headers (cdr headers)))) 1122 (setq headers (cdr headers))))
1123
1038 1124
1039 (defun message-fetch-reply-field (header) 1125 (defun message-fetch-reply-field (header)
1040 "Fetch FIELD from the message we're replying to." 1126 "Fetch FIELD from the message we're replying to."
1041 (when (and message-reply-buffer 1127 (when (and message-reply-buffer
1042 (buffer-name message-reply-buffer)) 1128 (buffer-name message-reply-buffer))
1049 (progn 1135 (progn
1050 (set-buffer " *message work*") 1136 (set-buffer " *message work*")
1051 (erase-buffer)) 1137 (erase-buffer))
1052 (set-buffer (get-buffer-create " *message work*")) 1138 (set-buffer (get-buffer-create " *message work*"))
1053 (kill-all-local-variables) 1139 (kill-all-local-variables)
1054 (buffer-disable-undo (current-buffer)))) 1140 (mm-enable-multibyte)))
1055 1141
1056 (defun message-functionp (form) 1142 (defun message-functionp (form)
1057 "Return non-nil if FORM is funcallable." 1143 "Return non-nil if FORM is funcallable."
1058 (or (and (symbolp form) (fboundp form)) 1144 (or (and (symbolp form) (fboundp form))
1059 (and (listp form) (eq (car form) 'lambda)) 1145 (and (listp form) (eq (car form) 'lambda))
1060 (byte-code-function-p form))) 1146 (byte-code-function-p form)))
1147
1148 (defun message-strip-list-identifiers (subject)
1149 "Remove list identifiers in `gnus-list-identifiers'."
1150 (require 'gnus-sum) ; for gnus-list-identifiers
1151 (let ((regexp (if (stringp gnus-list-identifiers)
1152 gnus-list-identifiers
1153 (mapconcat 'identity gnus-list-identifiers " *\\|"))))
1154 (if (string-match (concat "\\(\\(\\(Re: +\\)?\\(" regexp
1155 " *\\)\\)+\\(Re: +\\)?\\)") subject)
1156 (concat (substring subject 0 (match-beginning 1))
1157 (or (match-string 3 subject)
1158 (match-string 5 subject))
1159 (substring subject
1160 (match-end 1)))
1161 subject)))
1061 1162
1062 (defun message-strip-subject-re (subject) 1163 (defun message-strip-subject-re (subject)
1063 "Remove \"Re:\" from subject lines." 1164 "Remove \"Re:\" from subject lines."
1064 (if (string-match message-subject-re-regexp subject) 1165 (if (string-match message-subject-re-regexp subject)
1065 (substring subject (match-end 0)) 1166 (substring subject (match-end 0))
1094 (goto-char (match-beginning 0)) 1195 (goto-char (match-beginning 0))
1095 (point-max))))) 1196 (point-max)))))
1096 (forward-line 1) 1197 (forward-line 1)
1097 (if (re-search-forward "^[^ \t]" nil t) 1198 (if (re-search-forward "^[^ \t]" nil t)
1098 (goto-char (match-beginning 0)) 1199 (goto-char (match-beginning 0))
1099 (point-max)))) 1200 (goto-char (point-max)))))
1100 number)) 1201 number))
1202
1203 (defun message-remove-first-header (header)
1204 "Remove the first instance of HEADER if there is more than one."
1205 (let ((count 0)
1206 (regexp (concat "^" (regexp-quote header) ":")))
1207 (save-excursion
1208 (goto-char (point-min))
1209 (while (re-search-forward regexp nil t)
1210 (incf count)))
1211 (while (> count 1)
1212 (message-remove-header header nil t)
1213 (decf count))))
1101 1214
1102 (defun message-narrow-to-headers () 1215 (defun message-narrow-to-headers ()
1103 "Narrow the buffer to the head of the message." 1216 "Narrow the buffer to the head of the message."
1104 (widen) 1217 (widen)
1105 (narrow-to-region 1218 (narrow-to-region
1109 (match-beginning 0) 1222 (match-beginning 0)
1110 (point-max))) 1223 (point-max)))
1111 (goto-char (point-min))) 1224 (goto-char (point-min)))
1112 1225
1113 (defun message-narrow-to-head () 1226 (defun message-narrow-to-head ()
1114 "Narrow the buffer to the head of the message." 1227 "Narrow the buffer to the head of the message.
1228 Point is left at the beginning of the narrowed-to region."
1115 (widen) 1229 (widen)
1116 (narrow-to-region 1230 (narrow-to-region
1117 (goto-char (point-min)) 1231 (goto-char (point-min))
1118 (if (search-forward "\n\n" nil 1) 1232 (if (search-forward "\n\n" nil 1)
1119 (1- (point)) 1233 (1- (point))
1120 (point-max))) 1234 (point-max)))
1235 (goto-char (point-min)))
1236
1237 (defun message-narrow-to-headers-or-head ()
1238 "Narrow the buffer to the head of the message."
1239 (widen)
1240 (narrow-to-region
1241 (goto-char (point-min))
1242 (cond
1243 ((re-search-forward
1244 (concat "^" (regexp-quote mail-header-separator) "\n") nil t)
1245 (match-beginning 0))
1246 ((search-forward "\n\n" nil t)
1247 (1- (point)))
1248 (t
1249 (point-max))))
1121 (goto-char (point-min))) 1250 (goto-char (point-min)))
1122 1251
1123 (defun message-news-p () 1252 (defun message-news-p ()
1124 "Say whether the current buffer contains a news message." 1253 "Say whether the current buffer contains a news message."
1125 (and (not message-this-is-mail) 1254 (and (not message-this-is-mail)
1150 (goto-char (point-max))))) 1279 (goto-char (point-max)))))
1151 1280
1152 (defun message-sort-headers-1 () 1281 (defun message-sort-headers-1 ()
1153 "Sort the buffer as headers using `message-rank' text props." 1282 "Sort the buffer as headers using `message-rank' text props."
1154 (goto-char (point-min)) 1283 (goto-char (point-min))
1284 (require 'sort)
1155 (sort-subr 1285 (sort-subr
1156 nil 'message-next-header 1286 nil 'message-next-header
1157 (lambda () 1287 (lambda ()
1158 (message-next-header) 1288 (message-next-header)
1159 (unless (bobp) 1289 (unless (bobp)
1192 ;;; Set up keymap. 1322 ;;; Set up keymap.
1193 1323
1194 (defvar message-mode-map nil) 1324 (defvar message-mode-map nil)
1195 1325
1196 (unless message-mode-map 1326 (unless message-mode-map
1197 (setq message-mode-map (copy-keymap text-mode-map)) 1327 (setq message-mode-map (make-keymap))
1328 (set-keymap-parent message-mode-map text-mode-map)
1198 (define-key message-mode-map "\C-c?" 'describe-mode) 1329 (define-key message-mode-map "\C-c?" 'describe-mode)
1199 1330
1200 (define-key message-mode-map "\C-c\C-f\C-t" 'message-goto-to) 1331 (define-key message-mode-map "\C-c\C-f\C-t" 'message-goto-to)
1201 (define-key message-mode-map "\C-c\C-f\C-b" 'message-goto-bcc) 1332 (define-key message-mode-map "\C-c\C-f\C-b" 'message-goto-bcc)
1202 (define-key message-mode-map "\C-c\C-f\C-w" 'message-goto-fcc) 1333 (define-key message-mode-map "\C-c\C-f\C-w" 'message-goto-fcc)
1213 1344
1214 (define-key message-mode-map "\C-c\C-t" 'message-insert-to) 1345 (define-key message-mode-map "\C-c\C-t" 'message-insert-to)
1215 (define-key message-mode-map "\C-c\C-n" 'message-insert-newsgroups) 1346 (define-key message-mode-map "\C-c\C-n" 'message-insert-newsgroups)
1216 1347
1217 (define-key message-mode-map "\C-c\C-y" 'message-yank-original) 1348 (define-key message-mode-map "\C-c\C-y" 'message-yank-original)
1349 (define-key message-mode-map "\C-c\M-\C-y" 'message-yank-buffer)
1218 (define-key message-mode-map "\C-c\C-q" 'message-fill-yanked-message) 1350 (define-key message-mode-map "\C-c\C-q" 'message-fill-yanked-message)
1219 (define-key message-mode-map "\C-c\C-w" 'message-insert-signature) 1351 (define-key message-mode-map "\C-c\C-w" 'message-insert-signature)
1352 (define-key message-mode-map "\C-c\M-h" 'message-insert-headers)
1220 (define-key message-mode-map "\C-c\C-r" 'message-caesar-buffer-body) 1353 (define-key message-mode-map "\C-c\C-r" 'message-caesar-buffer-body)
1221 (define-key message-mode-map "\C-c\C-o" 'message-sort-headers) 1354 (define-key message-mode-map "\C-c\C-o" 'message-sort-headers)
1222 (define-key message-mode-map "\C-c\M-r" 'message-rename-buffer) 1355 (define-key message-mode-map "\C-c\M-r" 'message-rename-buffer)
1223 1356
1224 (define-key message-mode-map "\C-c\C-c" 'message-send-and-exit) 1357 (define-key message-mode-map "\C-c\C-c" 'message-send-and-exit)
1228 1361
1229 (define-key message-mode-map "\C-c\C-e" 'message-elide-region) 1362 (define-key message-mode-map "\C-c\C-e" 'message-elide-region)
1230 (define-key message-mode-map "\C-c\C-v" 'message-delete-not-region) 1363 (define-key message-mode-map "\C-c\C-v" 'message-delete-not-region)
1231 (define-key message-mode-map "\C-c\C-z" 'message-kill-to-signature) 1364 (define-key message-mode-map "\C-c\C-z" 'message-kill-to-signature)
1232 (define-key message-mode-map "\M-\r" 'message-newline-and-reformat) 1365 (define-key message-mode-map "\M-\r" 'message-newline-and-reformat)
1366
1367 (define-key message-mode-map "\C-c\C-a" 'mml-attach-file)
1233 1368
1234 (define-key message-mode-map "\t" 'message-tab)) 1369 (define-key message-mode-map "\t" 'message-tab))
1235 1370
1236 (easy-menu-define 1371 (easy-menu-define
1237 message-mode-menu message-mode-map "Message Menu." 1372 message-mode-menu message-mode-map "Message Menu."
1246 ["Delete Outside Region" message-delete-not-region (mark t)] 1381 ["Delete Outside Region" message-delete-not-region (mark t)]
1247 ["Kill To Signature" message-kill-to-signature t] 1382 ["Kill To Signature" message-kill-to-signature t]
1248 ["Newline and Reformat" message-newline-and-reformat t] 1383 ["Newline and Reformat" message-newline-and-reformat t]
1249 ["Rename buffer" message-rename-buffer t] 1384 ["Rename buffer" message-rename-buffer t]
1250 ["Spellcheck" ispell-message t] 1385 ["Spellcheck" ispell-message t]
1386 ["Attach file as MIME" mml-attach-file t]
1251 "----" 1387 "----"
1252 ["Send Message" message-send-and-exit t] 1388 ["Send Message" message-send-and-exit t]
1253 ["Abort Message" message-dont-send t] 1389 ["Abort Message" message-dont-send t]
1254 ["Kill Message" message-kill-buffer t])) 1390 ["Kill Message" message-kill-buffer t]))
1255 1391
1277 ;;;###autoload 1413 ;;;###autoload
1278 (defun message-mode () 1414 (defun message-mode ()
1279 "Major mode for editing mail and news to be sent. 1415 "Major mode for editing mail and news to be sent.
1280 Like Text Mode but with these additional commands: 1416 Like Text Mode but with these additional commands:
1281 C-c C-s message-send (send the message) C-c C-c message-send-and-exit 1417 C-c C-s message-send (send the message) C-c C-c message-send-and-exit
1418 C-c C-d Pospone sending the message C-c C-k Kill the message
1282 C-c C-f move to a header field (and create it if there isn't): 1419 C-c C-f move to a header field (and create it if there isn't):
1283 C-c C-f C-t move to To C-c C-f C-s move to Subject 1420 C-c C-f C-t move to To C-c C-f C-s move to Subject
1284 C-c C-f C-c move to Cc C-c C-f C-b move to Bcc 1421 C-c C-f C-c move to Cc C-c C-f C-b move to Bcc
1285 C-c C-f C-w move to Fcc C-c C-f C-r move to Reply-To 1422 C-c C-f C-w move to Fcc C-c C-f C-r move to Reply-To
1286 C-c C-f C-u move to Summary C-c C-f C-n move to Newsgroups 1423 C-c C-f C-u move to Summary C-c C-f C-n move to Newsgroups
1292 C-c C-i message-goto-signature (move to the beginning of the signature). 1429 C-c C-i message-goto-signature (move to the beginning of the signature).
1293 C-c C-w message-insert-signature (insert `message-signature-file' file). 1430 C-c C-w message-insert-signature (insert `message-signature-file' file).
1294 C-c C-y message-yank-original (insert current message, if any). 1431 C-c C-y message-yank-original (insert current message, if any).
1295 C-c C-q message-fill-yanked-message (fill what was yanked). 1432 C-c C-q message-fill-yanked-message (fill what was yanked).
1296 C-c C-e message-elide-region (elide the text between point and mark). 1433 C-c C-e message-elide-region (elide the text between point and mark).
1434 C-c C-v message-delete-not-region (remove the text outside the region).
1297 C-c C-z message-kill-to-signature (kill the text up to the signature). 1435 C-c C-z message-kill-to-signature (kill the text up to the signature).
1298 C-c C-r message-caesar-buffer-body (rot13 the message body)." 1436 C-c C-r message-caesar-buffer-body (rot13 the message body).
1437 C-c C-a mml-attach-file (attach a file as MIME).
1438 M-RET message-newline-and-reformat (break the line and reformat)."
1299 (interactive) 1439 (interactive)
1440 (if (local-variable-p 'mml-buffer-list (current-buffer))
1441 (mml-destroy-buffers))
1300 (kill-all-local-variables) 1442 (kill-all-local-variables)
1301 (make-local-variable 'message-reply-buffer) 1443 (set (make-local-variable 'message-reply-buffer) nil)
1302 (setq message-reply-buffer nil)
1303 (make-local-variable 'message-send-actions) 1444 (make-local-variable 'message-send-actions)
1304 (make-local-variable 'message-exit-actions) 1445 (make-local-variable 'message-exit-actions)
1305 (make-local-variable 'message-kill-actions) 1446 (make-local-variable 'message-kill-actions)
1306 (make-local-variable 'message-postpone-actions) 1447 (make-local-variable 'message-postpone-actions)
1307 (make-local-variable 'message-draft-article) 1448 (make-local-variable 'message-draft-article)
1326 (make-local-variable 'paragraph-start) 1467 (make-local-variable 'paragraph-start)
1327 ;; `-- ' precedes the signature. `-----' appears at the start of the 1468 ;; `-- ' precedes the signature. `-----' appears at the start of the
1328 ;; lines that delimit forwarded messages. 1469 ;; lines that delimit forwarded messages.
1329 ;; Lines containing just >= 3 dashes, perhaps after whitespace, 1470 ;; Lines containing just >= 3 dashes, perhaps after whitespace,
1330 ;; are also sometimes used and should be separators. 1471 ;; are also sometimes used and should be separators.
1331 (setq paragraph-start (concat (regexp-quote mail-header-separator) 1472 (setq paragraph-start
1332 "$\\|[ \t]*[a-z0-9A-Z]*>+[ \t]*$\\|[ \t]*$\\|" 1473 (concat (regexp-quote mail-header-separator)
1333 "-- $\\|---+$\\|" 1474 "$\\|[ \t]*[a-z0-9A-Z]*>+[ \t]*$\\|[ \t]*$\\|"
1334 page-delimiter)) 1475 "-- $\\|---+$\\|"
1476 page-delimiter
1477 ;;!!! Uhm... shurely this can't be right?
1478 "[> " (regexp-quote message-yank-prefix) "]+$"))
1335 (setq paragraph-separate paragraph-start) 1479 (setq paragraph-separate paragraph-start)
1336 (make-local-variable 'message-reply-headers) 1480 (make-local-variable 'message-reply-headers)
1337 (setq message-reply-headers nil) 1481 (setq message-reply-headers nil)
1338 (make-local-variable 'message-newsreader) 1482 (make-local-variable 'message-newsreader)
1339 (make-local-variable 'message-mailer) 1483 (make-local-variable 'message-mailer)
1340 (make-local-variable 'message-post-method) 1484 (make-local-variable 'message-post-method)
1341 (make-local-variable 'message-sent-message-via) 1485 (set (make-local-variable 'message-sent-message-via) nil)
1342 (setq message-sent-message-via nil) 1486 (set (make-local-variable 'message-checksum) nil)
1343 (make-local-variable 'message-checksum) 1487 (set (make-local-variable 'message-mime-part) 0)
1344 (setq message-checksum nil)
1345 ;;(when (fboundp 'mail-hist-define-keys) 1488 ;;(when (fboundp 'mail-hist-define-keys)
1346 ;; (mail-hist-define-keys)) 1489 ;; (mail-hist-define-keys))
1347 (when (string-match "XEmacs\\|Lucid" emacs-version) 1490 (if (featurep 'xemacs)
1348 (message-setup-toolbar)) 1491 (message-setup-toolbar)
1492 (set (make-local-variable 'font-lock-defaults)
1493 '(message-font-lock-keywords t)))
1349 (easy-menu-add message-mode-menu message-mode-map) 1494 (easy-menu-add message-mode-menu message-mode-map)
1350 (easy-menu-add message-mode-field-menu message-mode-map) 1495 (easy-menu-add message-mode-field-menu message-mode-map)
1351 (make-local-variable 'adaptive-fill-regexp)
1352 (setq adaptive-fill-regexp
1353 (concat "[ \t]*[-a-z0-9A-Z]*>+[ \t]*\\|" adaptive-fill-regexp))
1354 (make-local-variable 'adaptive-fill-first-line-regexp)
1355 (setq adaptive-fill-first-line-regexp
1356 (concat "[ \t]*[-a-z0-9A-Z]*>+[ \t]*\\|"
1357 adaptive-fill-first-line-regexp))
1358 ;; Allow mail alias things. 1496 ;; Allow mail alias things.
1359 (when (eq message-mail-alias-type 'abbrev) 1497 (when (eq message-mail-alias-type 'abbrev)
1360 (if (fboundp 'mail-abbrevs-setup) 1498 (if (fboundp 'mail-abbrevs-setup)
1361 (mail-abbrevs-setup) 1499 (mail-abbrevs-setup)
1362 (mail-aliases-setup))) 1500 (mail-aliases-setup)))
1363 (message-set-auto-save-file-name) 1501 (message-set-auto-save-file-name)
1364 (unless (string-match "XEmacs" emacs-version)
1365 (set (make-local-variable 'font-lock-defaults)
1366 '(message-font-lock-keywords t)))
1367 (make-local-variable 'adaptive-fill-regexp) 1502 (make-local-variable 'adaptive-fill-regexp)
1368 (setq adaptive-fill-regexp 1503 (setq adaptive-fill-regexp
1369 (concat "[ \t]*[-a-z0-9A-Z]*>+[ \t]*\\|" adaptive-fill-regexp)) 1504 (concat "[ \t]*[-a-z0-9A-Z]*\\(>[ \t]*\\)+[ \t]*\\|" adaptive-fill-regexp))
1370 (unless (boundp 'adaptive-fill-first-line-regexp) 1505 (unless (boundp 'adaptive-fill-first-line-regexp)
1371 (setq adaptive-fill-first-line-regexp nil)) 1506 (setq adaptive-fill-first-line-regexp nil))
1372 (make-local-variable 'adaptive-fill-first-line-regexp) 1507 (make-local-variable 'adaptive-fill-first-line-regexp)
1373 (setq adaptive-fill-first-line-regexp 1508 (setq adaptive-fill-first-line-regexp
1374 (concat "[ \t]*[-a-z0-9A-Z]*>+[ \t]*\\|" 1509 (concat "[ \t]*[-a-z0-9A-Z]*\\(>[ \t]*\\)+[ \t]*\\|"
1375 adaptive-fill-first-line-regexp)) 1510 adaptive-fill-first-line-regexp))
1511 (make-local-variable 'auto-fill-inhibit-regexp)
1512 (setq auto-fill-inhibit-regexp "^[A-Z][^: \n\t]+:")
1513 (mm-enable-multibyte)
1514 (make-local-variable 'indent-tabs-mode) ;Turn off tabs for indentation.
1515 (setq indent-tabs-mode nil)
1516 (mml-mode)
1376 (run-hooks 'text-mode-hook 'message-mode-hook)) 1517 (run-hooks 'text-mode-hook 'message-mode-hook))
1377 1518
1378 1519
1379 1520
1380 ;;; 1521 ;;;
1441 (defun message-goto-body () 1582 (defun message-goto-body ()
1442 "Move point to the beginning of the message body." 1583 "Move point to the beginning of the message body."
1443 (interactive) 1584 (interactive)
1444 (if (looking-at "[ \t]*\n") (expand-abbrev)) 1585 (if (looking-at "[ \t]*\n") (expand-abbrev))
1445 (goto-char (point-min)) 1586 (goto-char (point-min))
1446 (search-forward (concat "\n" mail-header-separator "\n") nil t)) 1587 (or (search-forward (concat "\n" mail-header-separator "\n") nil t)
1588 (search-forward "\n\n" nil t)))
1447 1589
1448 (defun message-goto-eoh () 1590 (defun message-goto-eoh ()
1449 "Move point to the end of the headers." 1591 "Move point to the end of the headers."
1450 (interactive) 1592 (interactive)
1451 (message-goto-body) 1593 (message-goto-body)
1452 (forward-line -2)) 1594 (forward-line -1))
1453 1595
1454 (defun message-goto-signature () 1596 (defun message-goto-signature ()
1455 "Move point to the beginning of the message signature. 1597 "Move point to the beginning of the message signature.
1456 If there is no signature in the article, go to the end and 1598 If there is no signature in the article, go to the end and
1457 return nil." 1599 return nil."
1471 With the prefix argument FORCE, insert the header anyway." 1613 With the prefix argument FORCE, insert the header anyway."
1472 (interactive "P") 1614 (interactive "P")
1473 (let ((co (message-fetch-reply-field "mail-copies-to"))) 1615 (let ((co (message-fetch-reply-field "mail-copies-to")))
1474 (when (and (null force) 1616 (when (and (null force)
1475 co 1617 co
1476 (equal (downcase co) "never")) 1618 (or (equal (downcase co) "never")
1619 (equal (downcase co) "nobody")))
1477 (error "The user has requested not to have copies sent via mail"))) 1620 (error "The user has requested not to have copies sent via mail")))
1478 (when (and (message-position-on-field "To") 1621 (when (and (message-position-on-field "To")
1479 (mail-fetch-field "to") 1622 (mail-fetch-field "to")
1480 (not (string-match "\\` *\\'" (mail-fetch-field "to")))) 1623 (not (string-match "\\` *\\'" (mail-fetch-field "to"))))
1481 (insert ", ")) 1624 (insert ", "))
1482 (insert (or (message-fetch-reply-field "reply-to") 1625 (insert (or (message-fetch-reply-field "reply-to")
1483 (message-fetch-reply-field "from") ""))) 1626 (message-fetch-reply-field "from") "")))
1627
1628 (defun message-widen-reply ()
1629 "Widen the reply to include maximum recipients."
1630 (interactive)
1631 (let ((follow-to
1632 (and message-reply-buffer
1633 (buffer-name message-reply-buffer)
1634 (save-excursion
1635 (set-buffer message-reply-buffer)
1636 (message-get-reply-headers t)))))
1637 (save-excursion
1638 (save-restriction
1639 (message-narrow-to-headers)
1640 (dolist (elem follow-to)
1641 (message-remove-header (symbol-name (car elem)))
1642 (goto-char (point-min))
1643 (insert (symbol-name (car elem)) ": "
1644 (cdr elem) "\n"))))))
1484 1645
1485 (defun message-insert-newsgroups () 1646 (defun message-insert-newsgroups ()
1486 "Insert the Newsgroups header from the article being replied to." 1647 "Insert the Newsgroups header from the article being replied to."
1487 (interactive) 1648 (interactive)
1488 (when (and (message-position-on-field "Newsgroups") 1649 (when (and (message-position-on-field "Newsgroups")
1524 (insert "\n")))) 1685 (insert "\n"))))
1525 1686
1526 (defun message-newline-and-reformat () 1687 (defun message-newline-and-reformat ()
1527 "Insert four newlines, and then reformat if inside quoted text." 1688 "Insert four newlines, and then reformat if inside quoted text."
1528 (interactive) 1689 (interactive)
1529 (let ((point (point)) 1690 (let ((prefix "[]>»|:}+ \t]*")
1530 quoted) 1691 (supercite-thing "[-._a-zA-Z0-9]*[>]+[ \t]*")
1531 (save-excursion 1692 quoted point)
1532 (beginning-of-line) 1693 (unless (bolp)
1533 (setq quoted (looking-at (regexp-quote message-yank-prefix)))) 1694 (save-excursion
1534 (insert "\n\n\n\n") 1695 (beginning-of-line)
1696 (when (looking-at (concat prefix
1697 supercite-thing))
1698 (setq quoted (match-string 0))))
1699 (insert "\n"))
1700 (setq point (point))
1701 (insert "\n\n\n")
1702 (delete-region (point) (re-search-forward "[ \t]*"))
1535 (when quoted 1703 (when quoted
1536 (insert message-yank-prefix)) 1704 (insert quoted))
1537 (fill-paragraph nil) 1705 (fill-paragraph nil)
1538 (goto-char point) 1706 (goto-char point)
1539 (forward-line 2))) 1707 (forward-line 1)))
1540 1708
1541 (defun message-insert-signature (&optional force) 1709 (defun message-insert-signature (&optional force)
1542 "Insert a signature. See documentation for the `message-signature' variable." 1710 "Insert a signature. See documentation for the `message-signature' variable."
1543 (interactive (list 0)) 1711 (interactive (list 0))
1544 (let* ((signature 1712 (let* ((signature
1545 (cond 1713 (cond
1546 ((and (null message-signature) 1714 ((and (null message-signature)
1547 (eq force 0)) 1715 (eq force 0))
1548 (save-excursion 1716 (save-excursion
1549 (goto-char (point-max)) 1717 (goto-char (point-max))
1550 (not (re-search-backward 1718 (not (re-search-backward message-signature-separator nil t))))
1551 message-signature-separator nil t))))
1552 ((and (null message-signature) 1719 ((and (null message-signature)
1553 force) 1720 force)
1554 t) 1721 t)
1555 ((message-functionp message-signature) 1722 ((message-functionp message-signature)
1556 (funcall message-signature)) 1723 (funcall message-signature))
1576 (goto-char (point-max)) 1743 (goto-char (point-max))
1577 (or (bolp) (insert "\n"))))) 1744 (or (bolp) (insert "\n")))))
1578 1745
1579 (defun message-elide-region (b e) 1746 (defun message-elide-region (b e)
1580 "Elide the text between point and mark. 1747 "Elide the text between point and mark.
1581 An ellipsis (from `message-elide-elipsis') will be inserted where the 1748 An ellipsis (from `message-elide-ellipsis') will be inserted where the
1582 text was killed." 1749 text was killed."
1583 (interactive "r") 1750 (interactive "r")
1584 (kill-region b e) 1751 (kill-region b e)
1585 (unless (bolp) 1752 (insert message-elide-ellipsis))
1586 (insert "\n"))
1587 (insert message-elide-elipsis))
1588 1753
1589 (defvar message-caesar-translation-table nil) 1754 (defvar message-caesar-translation-table nil)
1590 1755
1591 (defun message-caesar-region (b e &optional n) 1756 (defun message-caesar-region (b e &optional n)
1592 "Caesar rotation of region by N, default 13, for decrypting netnews." 1757 "Caesar rotation of region by N, default 13, for decrypting netnews."
1601 (unless (or (zerop n) ; no action needed for a rot of 0 1766 (unless (or (zerop n) ; no action needed for a rot of 0
1602 (= b e)) ; no region to rotate 1767 (= b e)) ; no region to rotate
1603 ;; We build the table, if necessary. 1768 ;; We build the table, if necessary.
1604 (when (or (not message-caesar-translation-table) 1769 (when (or (not message-caesar-translation-table)
1605 (/= (aref message-caesar-translation-table ?a) (+ ?a n))) 1770 (/= (aref message-caesar-translation-table ?a) (+ ?a n)))
1606 (setq message-caesar-translation-table 1771 (setq message-caesar-translation-table
1607 (message-make-caesar-translation-table n))) 1772 (message-make-caesar-translation-table n)))
1608 ;; Then we translate the region. Do it this way to retain 1773 (translate-region b e message-caesar-translation-table)))
1609 ;; text properties.
1610 (while (< b e)
1611 (subst-char-in-region
1612 b (1+ b) (char-after b)
1613 (aref message-caesar-translation-table (char-after b)))
1614 (incf b))))
1615 1774
1616 (defun message-make-caesar-translation-table (n) 1775 (defun message-make-caesar-translation-table (n)
1617 "Create a rot table with offset N." 1776 "Create a rot table with offset N."
1618 (let ((i -1) 1777 (let ((i -1)
1619 (table (make-string 256 0))) 1778 (table (make-string 256 0)))
1646 "Pipe the message body in the current buffer through PROGRAM." 1805 "Pipe the message body in the current buffer through PROGRAM."
1647 (save-excursion 1806 (save-excursion
1648 (save-restriction 1807 (save-restriction
1649 (when (message-goto-body) 1808 (when (message-goto-body)
1650 (narrow-to-region (point) (point-max))) 1809 (narrow-to-region (point) (point-max)))
1651 (let ((body (buffer-substring (point-min) (point-max)))) 1810 (shell-command-on-region
1652 (unless (equal 0 (call-process-region 1811 (point-min) (point-max) program nil t))))
1653 (point-min) (point-max) program t t))
1654 (insert body)
1655 (message "%s failed." program))))))
1656 1812
1657 (defun message-rename-buffer (&optional enter-string) 1813 (defun message-rename-buffer (&optional enter-string)
1658 "Rename the *message* buffer to \"*message* RECIPIENT\". 1814 "Rename the *message* buffer to \"*message* RECIPIENT\".
1659 If the function is run with a prefix, it will ask for a new buffer 1815 If the function is run with a prefix, it will ask for a new buffer
1660 name, rather than giving an automatic name." 1816 name, rather than giving an automatic name."
1684 (interactive "P") 1840 (interactive "P")
1685 (save-excursion 1841 (save-excursion
1686 (goto-char (point-min)) 1842 (goto-char (point-min))
1687 (search-forward (concat "\n" mail-header-separator "\n") nil t) 1843 (search-forward (concat "\n" mail-header-separator "\n") nil t)
1688 (let ((fill-prefix message-yank-prefix)) 1844 (let ((fill-prefix message-yank-prefix))
1689 (fill-individual-paragraphs (point) (point-max) justifyp 1845 (fill-individual-paragraphs (point) (point-max) justifyp))))
1690 mail-citation-prefix-regexp))))
1691 1846
1692 (defun message-indent-citation () 1847 (defun message-indent-citation ()
1693 "Modify text just inserted from a message to be cited. 1848 "Modify text just inserted from a message to be cited.
1694 The inserted text should be the region. 1849 The inserted text should be the region.
1695 When this function returns, the region is again around the modified text. 1850 When this function returns, the region is again around the modified text.
1756 (unless (bolp) 1911 (unless (bolp)
1757 (insert ?\n)) 1912 (insert ?\n))
1758 (unless modified 1913 (unless modified
1759 (setq message-checksum (message-checksum)))))) 1914 (setq message-checksum (message-checksum))))))
1760 1915
1916 (defun message-yank-buffer (buffer)
1917 "Insert BUFFER into the current buffer and quote it."
1918 (interactive "bYank buffer: ")
1919 (let ((message-reply-buffer buffer))
1920 (save-window-excursion
1921 (message-yank-original))))
1922
1923 (defun message-buffers ()
1924 "Return a list of active message buffers."
1925 (let (buffers)
1926 (save-excursion
1927 (dolist (buffer (buffer-list t))
1928 (set-buffer buffer)
1929 (when (and (eq major-mode 'message-mode)
1930 (null message-sent-message-via))
1931 (push (buffer-name buffer) buffers))))
1932 (nreverse buffers)))
1933
1761 (defun message-cite-original-without-signature () 1934 (defun message-cite-original-without-signature ()
1762 "Cite function in the standard Message manner." 1935 "Cite function in the standard Message manner."
1763 (let ((start (point)) 1936 (let ((start (point))
1764 (end (mark t)) 1937 (end (mark t))
1765 (functions 1938 (functions
1766 (when message-indent-citation-function 1939 (when message-indent-citation-function
1767 (if (listp message-indent-citation-function) 1940 (if (listp message-indent-citation-function)
1768 message-indent-citation-function 1941 message-indent-citation-function
1769 (list message-indent-citation-function))))) 1942 (list message-indent-citation-function)))))
1943 (mml-quote-region start end)
1944 ;; Allow undoing.
1945 (undo-boundary)
1770 (goto-char end) 1946 (goto-char end)
1771 (when (re-search-backward "^-- $" start t) 1947 (when (re-search-backward message-signature-separator start t)
1772 ;; Also peel off any blank lines before the signature. 1948 ;; Also peel off any blank lines before the signature.
1773 (forward-line -1) 1949 (forward-line -1)
1774 (while (looking-at "^[ \t]*$") 1950 (while (looking-at "^[ \t]*$")
1775 (forward-line -1)) 1951 (forward-line -1))
1776 (forward-line 1) 1952 (forward-line 1)
1781 (when message-citation-line-function 1957 (when message-citation-line-function
1782 (unless (bolp) 1958 (unless (bolp)
1783 (insert "\n")) 1959 (insert "\n"))
1784 (funcall message-citation-line-function)))) 1960 (funcall message-citation-line-function))))
1785 1961
1786 (defvar mail-citation-hook) ;Compiler directive 1962 (defvar mail-citation-hook) ;Compiler directive
1787 (defun message-cite-original () 1963 (defun message-cite-original ()
1788 "Cite function in the standard Message manner." 1964 "Cite function in the standard Message manner."
1789 (if (and (boundp 'mail-citation-hook) 1965 (if (and (boundp 'mail-citation-hook)
1790 mail-citation-hook) 1966 mail-citation-hook)
1791 (run-hooks 'mail-citation-hook) 1967 (run-hooks 'mail-citation-hook)
1792 (let ((start (point)) 1968 (let ((start (point))
1793 (functions 1969 (end (mark t))
1794 (when message-indent-citation-function 1970 (functions
1795 (if (listp message-indent-citation-function) 1971 (when message-indent-citation-function
1796 message-indent-citation-function 1972 (if (listp message-indent-citation-function)
1797 (list message-indent-citation-function))))) 1973 message-indent-citation-function
1974 (list message-indent-citation-function)))))
1975 (mml-quote-region start end)
1798 (goto-char start) 1976 (goto-char start)
1799 (while functions 1977 (while functions
1800 (funcall (pop functions))) 1978 (funcall (pop functions)))
1801 (when message-citation-line-function 1979 (when message-citation-line-function
1802 (unless (bolp) 1980 (unless (bolp)
1803 (insert "\n")) 1981 (insert "\n"))
1804 (funcall message-citation-line-function))))) 1982 (funcall message-citation-line-function)))))
1805 1983
1806 (defun message-insert-citation-line () 1984 (defun message-insert-citation-line ()
1807 "Function that inserts a simple citation line." 1985 "Function that inserts a simple citation line."
1808 (when message-reply-headers 1986 (when message-reply-headers
1809 (insert (mail-header-from message-reply-headers) " writes:\n\n"))) 1987 (insert (mail-header-from message-reply-headers) " writes:\n\n")))
1908 (delete-frame (selected-frame)) 2086 (delete-frame (selected-frame))
1909 (switch-to-buffer newbuf)))) 2087 (switch-to-buffer newbuf))))
1910 2088
1911 (defun message-send (&optional arg) 2089 (defun message-send (&optional arg)
1912 "Send the message in the current buffer. 2090 "Send the message in the current buffer.
1913 If `message-interactive' is non-nil, wait for success indication 2091 If `message-interactive' is non-nil, wait for success indication or
1914 or error messages, and inform user. 2092 error messages, and inform user.
1915 Otherwise any failure is reported in a message back to 2093 Otherwise any failure is reported in a message back to the user from
1916 the user from the mailer." 2094 the mailer.
2095 The usage of ARG is defined by the instance that called Message.
2096 It should typically alter the sending method in some way or other."
1917 (interactive "P") 2097 (interactive "P")
1918 ;; Disabled test. 2098 ;; Make it possible to undo the coming changes.
1919 (when (or (buffer-modified-p) 2099 (undo-boundary)
1920 (message-check-element 'unchanged) 2100 (let ((inhibit-read-only t))
1921 (y-or-n-p "No changes in the buffer; really send? ")) 2101 (put-text-property (point-min) (point-max) 'read-only nil))
1922 ;; Make it possible to undo the coming changes. 2102 (message-fix-before-sending)
1923 (undo-boundary) 2103 (run-hooks 'message-send-hook)
1924 (let ((inhibit-read-only t)) 2104 (message "Sending...")
1925 (put-text-property (point-min) (point-max) 'read-only nil)) 2105 (let ((alist message-send-method-alist)
1926 (message-fix-before-sending) 2106 (success t)
1927 (run-hooks 'message-send-hook) 2107 elem sent)
1928 (message "Sending...") 2108 (while (and success
1929 (let ((alist message-send-method-alist) 2109 (setq elem (pop alist)))
1930 (success t) 2110 (when (or (not (funcall (cadr elem)))
1931 elem sent) 2111 (and (or (not (memq (car elem)
1932 (while (and success 2112 message-sent-message-via))
1933 (setq elem (pop alist))) 2113 (y-or-n-p
1934 (when (and (or (not (funcall (cadr elem))) 2114 (format
1935 (and (or (not (memq (car elem) 2115 "Already sent message via %s; resend? "
1936 message-sent-message-via)) 2116 (car elem))))
1937 (y-or-n-p 2117 (setq success (funcall (caddr elem) arg))))
1938 (format 2118 (setq sent t)))
1939 "Already sent message via %s; resend? " 2119 (unless (or sent (not success))
1940 (car elem)))) 2120 (error "No methods specified to send by"))
1941 (setq success (funcall (caddr elem) arg))))) 2121 (when (and success sent)
1942 (setq sent t))) 2122 (message-do-fcc)
1943 (when (and success sent) 2123 (save-excursion
1944 (message-do-fcc) 2124 (run-hooks 'message-sent-hook))
1945 ;;(when (fboundp 'mail-hist-put-headers-into-history) 2125 (message "Sending...done")
1946 ;; (mail-hist-put-headers-into-history)) 2126 ;; Mark the buffer as unmodified and delete auto-save.
1947 (run-hooks 'message-sent-hook) 2127 (set-buffer-modified-p nil)
1948 (message "Sending...done") 2128 (delete-auto-save-file-if-necessary t)
1949 ;; Mark the buffer as unmodified and delete auto-save. 2129 (message-disassociate-draft)
1950 (set-buffer-modified-p nil) 2130 ;; Delete other mail buffers and stuff.
1951 (delete-auto-save-file-if-necessary t) 2131 (message-do-send-housekeeping)
1952 (message-disassociate-draft) 2132 (message-do-actions message-send-actions)
1953 ;; Delete other mail buffers and stuff. 2133 ;; Return success.
1954 (message-do-send-housekeeping) 2134 t)))
1955 (message-do-actions message-send-actions)
1956 ;; Return success.
1957 t))))
1958 2135
1959 (defun message-send-via-mail (arg) 2136 (defun message-send-via-mail (arg)
1960 "Send the current message via mail." 2137 "Send the current message via mail."
1961 (message-send-mail arg)) 2138 (message-send-mail arg))
1962 2139
1963 (defun message-send-via-news (arg) 2140 (defun message-send-via-news (arg)
1964 "Send the current message via news." 2141 "Send the current message via news."
1965 (funcall message-send-news-function arg)) 2142 (funcall message-send-news-function arg))
2143
2144 (defmacro message-check (type &rest forms)
2145 "Eval FORMS if TYPE is to be checked."
2146 `(or (message-check-element ,type)
2147 (save-excursion
2148 ,@forms)))
2149
2150 (put 'message-check 'lisp-indent-function 1)
2151 (put 'message-check 'edebug-form-spec '(form body))
1966 2152
1967 (defun message-fix-before-sending () 2153 (defun message-fix-before-sending ()
1968 "Do various things to make the message nice before sending it." 2154 "Do various things to make the message nice before sending it."
1969 ;; Make sure there's a newline at the end of the message. 2155 ;; Make sure there's a newline at the end of the message.
1970 (goto-char (point-max)) 2156 (goto-char (point-max))
1971 (unless (bolp) 2157 (unless (bolp)
1972 (insert "\n")) 2158 (insert "\n"))
1973 ;; Make all invisible text visible. 2159 ;; Delete all invisible text.
1974 ;;(when (text-property-any (point-min) (point-max) 'invisible t) 2160 (message-check 'invisible-text
1975 ;; (put-text-property (point-min) (point-max) 'invisible nil) 2161 (when (text-property-any (point-min) (point-max) 'invisible t)
1976 ;; (unless (yes-or-no-p "Invisible text found and made visible; continue posting?") 2162 (put-text-property (point-min) (point-max) 'invisible nil)
1977 ;; (error "Invisible text found and made visible"))) 2163 (unless (yes-or-no-p
1978 ) 2164 "Invisible text found and made visible; continue posting? ")
2165 (error "Invisible text found and made visible")))))
1979 2166
1980 (defun message-add-action (action &rest types) 2167 (defun message-add-action (action &rest types)
1981 "Add ACTION to be performed when doing an exit of type TYPES." 2168 "Add ACTION to be performed when doing an exit of type TYPES."
1982 (let (var) 2169 (let (var)
1983 (while types 2170 (while types
1996 ;; Something to be evaled. 2183 ;; Something to be evaled.
1997 (t 2184 (t
1998 (eval (car actions))))) 2185 (eval (car actions)))))
1999 (pop actions))) 2186 (pop actions)))
2000 2187
2188 (defun message-send-mail-partially ()
2189 "Sendmail as message/partial."
2190 (let ((p (goto-char (point-min)))
2191 (tembuf (message-generate-new-buffer-clone-locals " message temp"))
2192 (curbuf (current-buffer))
2193 (id (message-make-message-id)) (n 1)
2194 plist total header required-mail-headers)
2195 (while (not (eobp))
2196 (if (< (point-max) (+ p message-send-mail-partially-limit))
2197 (goto-char (point-max))
2198 (goto-char (+ p message-send-mail-partially-limit))
2199 (beginning-of-line)
2200 (if (<= (point) p) (forward-line 1))) ;; In case of bad message.
2201 (push p plist)
2202 (setq p (point)))
2203 (setq total (length plist))
2204 (push (point-max) plist)
2205 (setq plist (nreverse plist))
2206 (unwind-protect
2207 (save-excursion
2208 (setq p (pop plist))
2209 (while plist
2210 (set-buffer curbuf)
2211 (copy-to-buffer tembuf p (car plist))
2212 (set-buffer tembuf)
2213 (goto-char (point-min))
2214 (if header
2215 (progn
2216 (goto-char (point-min))
2217 (narrow-to-region (point) (point))
2218 (insert header))
2219 (message-goto-eoh)
2220 (setq header (buffer-substring (point-min) (point)))
2221 (goto-char (point-min))
2222 (narrow-to-region (point) (point))
2223 (insert header)
2224 (message-remove-header "Mime-Version")
2225 (message-remove-header "Content-Type")
2226 (message-remove-header "Content-Transfer-Encoding")
2227 (message-remove-header "Message-ID")
2228 (message-remove-header "Lines")
2229 (goto-char (point-max))
2230 (insert "Mime-Version: 1.0\n")
2231 (setq header (buffer-substring (point-min) (point-max))))
2232 (goto-char (point-max))
2233 (insert (format "Content-Type: message/partial; id=\"%s\"; number=%d; total=%d\n"
2234 id n total))
2235 (let ((mail-header-separator ""))
2236 (when (memq 'Message-ID message-required-mail-headers)
2237 (insert "Message-ID: " (message-make-message-id) "\n"))
2238 (when (memq 'Lines message-required-mail-headers)
2239 (let ((mail-header-separator ""))
2240 (insert "Lines: " (message-make-lines) "\n")))
2241 (message-goto-subject)
2242 (end-of-line)
2243 (insert (format " (%d/%d)" n total))
2244 (goto-char (point-max))
2245 (insert "\n")
2246 (widen)
2247 (mm-with-unibyte-current-buffer
2248 (funcall message-send-mail-function)))
2249 (setq n (+ n 1))
2250 (setq p (pop plist))
2251 (erase-buffer)))
2252 (kill-buffer tembuf))))
2253
2001 (defun message-send-mail (&optional arg) 2254 (defun message-send-mail (&optional arg)
2002 (require 'mail-utils) 2255 (require 'mail-utils)
2003 (let ((tembuf (message-generate-new-buffer-clone-locals " message temp")) 2256 (let* ((tembuf (message-generate-new-buffer-clone-locals " message temp"))
2004 (case-fold-search nil) 2257 (case-fold-search nil)
2005 (news (message-news-p)) 2258 (news (message-news-p))
2006 (mailbuf (current-buffer))) 2259 (mailbuf (current-buffer))
2260 (message-this-is-mail t)
2261 (message-posting-charset
2262 (if (fboundp 'gnus-setup-posting-charset)
2263 (gnus-setup-posting-charset nil)
2264 message-posting-charset)))
2007 (save-restriction 2265 (save-restriction
2008 (message-narrow-to-headers) 2266 (message-narrow-to-headers)
2009 ;; Insert some headers. 2267 ;; Insert some headers.
2010 (let ((message-deletable-headers 2268 (let ((message-deletable-headers
2011 (if news nil message-deletable-headers))) 2269 (if news nil message-deletable-headers)))
2020 (insert (format 2278 (insert (format
2021 "%s" (save-excursion 2279 "%s" (save-excursion
2022 (set-buffer mailbuf) 2280 (set-buffer mailbuf)
2023 (buffer-string)))) 2281 (buffer-string))))
2024 ;; Remove some headers. 2282 ;; Remove some headers.
2283 (message-encode-message-body)
2025 (save-restriction 2284 (save-restriction
2026 (message-narrow-to-headers) 2285 (message-narrow-to-headers)
2286 ;; We (re)generate the Lines header.
2287 (when (memq 'Lines message-required-mail-headers)
2288 (message-generate-headers '(Lines)))
2027 ;; Remove some headers. 2289 ;; Remove some headers.
2028 (message-remove-header message-ignored-mail-headers t)) 2290 (message-remove-header message-ignored-mail-headers t)
2291 (let ((mail-parse-charset message-default-charset))
2292 (mail-encode-encoded-word-buffer)))
2029 (goto-char (point-max)) 2293 (goto-char (point-max))
2030 ;; require one newline at the end. 2294 ;; require one newline at the end.
2031 (or (= (preceding-char) ?\n) 2295 (or (= (preceding-char) ?\n)
2032 (insert ?\n)) 2296 (insert ?\n))
2033 (when (and news 2297 (when
2298 (save-restriction
2299 (message-narrow-to-headers)
2300 (and news
2034 (or (message-fetch-field "cc") 2301 (or (message-fetch-field "cc")
2035 (message-fetch-field "to"))) 2302 (message-fetch-field "to"))
2303 (string= "text/plain"
2304 (car
2305 (mail-header-parse-content-type
2306 (message-fetch-field "content-type"))))))
2036 (message-insert-courtesy-copy)) 2307 (message-insert-courtesy-copy))
2037 (funcall message-send-mail-function)) 2308 (if (or (not message-send-mail-partially-limit)
2309 (< (point-max) message-send-mail-partially-limit)
2310 (not (y-or-n-p "The message size is too large, should it be sent partially?")))
2311 (mm-with-unibyte-current-buffer
2312 (funcall message-send-mail-function))
2313 (message-send-mail-partially)))
2038 (kill-buffer tembuf)) 2314 (kill-buffer tembuf))
2039 (set-buffer mailbuf) 2315 (set-buffer mailbuf)
2040 (push 'mail message-sent-message-via))) 2316 (push 'mail message-sent-message-via)))
2041 2317
2042 (defun message-send-mail-with-sendmail () 2318 (defun message-send-mail-with-sendmail ()
2043 "Send off the prepared buffer with sendmail." 2319 "Send off the prepared buffer with sendmail."
2044 (let ((errbuf (if message-interactive 2320 (let ((errbuf (if message-interactive
2045 (generate-new-buffer " sendmail errors") 2321 (message-generate-new-buffer-clone-locals
2322 " sendmail errors")
2046 0)) 2323 0))
2047 resend-to-addresses delimline) 2324 resend-to-addresses delimline)
2048 (let ((case-fold-search t)) 2325 (let ((case-fold-search t))
2049 (save-restriction 2326 (save-restriction
2050 (message-narrow-to-headers) 2327 (message-narrow-to-headers)
2065 (when message-interactive 2342 (when message-interactive
2066 (save-excursion 2343 (save-excursion
2067 (set-buffer errbuf) 2344 (set-buffer errbuf)
2068 (erase-buffer)))) 2345 (erase-buffer))))
2069 (let ((default-directory "/") 2346 (let ((default-directory "/")
2070 (coding-system-for-write message-send-coding-system)) 2347 (coding-system-for-write message-send-coding-system))
2071 (apply 'call-process-region 2348 (apply 'call-process-region
2072 (append (list (point-min) (point-max) 2349 (append (list (point-min) (point-max)
2073 (if (boundp 'sendmail-program) 2350 (if (boundp 'sendmail-program)
2074 sendmail-program 2351 sendmail-program
2075 "/usr/lib/sendmail") 2352 "/usr/lib/sendmail")
2077 ;; Always specify who from, 2354 ;; Always specify who from,
2078 ;; since some systems have broken sendmails. 2355 ;; since some systems have broken sendmails.
2079 ;; But some systems are more broken with -f, so 2356 ;; But some systems are more broken with -f, so
2080 ;; we'll let users override this. 2357 ;; we'll let users override this.
2081 (if (null message-sendmail-f-is-evil) 2358 (if (null message-sendmail-f-is-evil)
2082 (list "-f" (user-login-name))) 2359 (list "-f" (message-make-address)))
2083 ;; These mean "report errors by mail" 2360 ;; These mean "report errors by mail"
2084 ;; and "deliver in background". 2361 ;; and "deliver in background".
2085 (if (null message-interactive) '("-oem" "-odb")) 2362 (if (null message-interactive) '("-oem" "-odb"))
2086 ;; Get the addresses from the message 2363 ;; Get the addresses from the message
2087 ;; unless this is a resend. 2364 ;; unless this is a resend.
2162 (run-hooks 'message-send-mail-hook) 2439 (run-hooks 'message-send-mail-hook)
2163 ;; Pass it on to mh. 2440 ;; Pass it on to mh.
2164 (mh-send-letter))) 2441 (mh-send-letter)))
2165 2442
2166 (defun message-send-news (&optional arg) 2443 (defun message-send-news (&optional arg)
2167 (let ((tembuf (message-generate-new-buffer-clone-locals " *message temp*")) 2444 (let* ((tembuf (message-generate-new-buffer-clone-locals " *message temp*"))
2168 (case-fold-search nil) 2445 (case-fold-search nil)
2169 (method (if (message-functionp message-post-method) 2446 (method (if (message-functionp message-post-method)
2170 (funcall message-post-method arg) 2447 (funcall message-post-method arg)
2171 message-post-method)) 2448 message-post-method))
2172 (messbuf (current-buffer)) 2449 (group-name-charset (gnus-group-name-charset method ""))
2173 (message-syntax-checks 2450 (rfc2047-header-encoding-alist
2174 (if arg 2451 (if group-name-charset
2175 (cons '(existing-newsgroups . disabled) 2452 (cons (cons "Newsgroups" group-name-charset)
2176 message-syntax-checks) 2453 rfc2047-header-encoding-alist)
2177 message-syntax-checks)) 2454 rfc2047-header-encoding-alist))
2178 result) 2455 (messbuf (current-buffer))
2179 (save-restriction 2456 (message-syntax-checks
2180 (message-narrow-to-headers) 2457 (if arg
2181 ;; Insert some headers. 2458 (cons '(existing-newsgroups . disabled)
2182 (message-generate-headers message-required-news-headers) 2459 message-syntax-checks)
2183 ;; Let the user do all of the above. 2460 message-syntax-checks))
2184 (run-hooks 'message-header-hook)) 2461 (message-this-is-news t)
2185 (message-cleanup-headers) 2462 (message-posting-charset (gnus-setup-posting-charset
2186 (if (not (message-check-news-syntax)) 2463 (save-restriction
2187 (progn 2464 (message-narrow-to-headers-or-head)
2188 ;;(message "Posting not performed") 2465 (message-fetch-field "Newsgroups"))))
2189 nil) 2466 result)
2190 (unwind-protect 2467 (if (not (message-check-news-body-syntax))
2191 (save-excursion 2468 nil
2192 (set-buffer tembuf) 2469 (save-restriction
2193 (buffer-disable-undo (current-buffer)) 2470 (message-narrow-to-headers)
2194 (erase-buffer) 2471 ;; Insert some headers.
2195 ;; Avoid copying text props. 2472 (message-generate-headers message-required-news-headers)
2196 (insert (format 2473 ;; Let the user do all of the above.
2197 "%s" (save-excursion 2474 (run-hooks 'message-header-hook))
2198 (set-buffer messbuf) 2475 (if group-name-charset
2199 (buffer-string)))) 2476 (setq message-syntax-checks
2200 ;; Remove some headers. 2477 (cons '(valid-newsgroups . disabled)
2201 (save-restriction 2478 message-syntax-checks)))
2202 (message-narrow-to-headers) 2479 (message-cleanup-headers)
2480 (if (not (message-check-news-syntax))
2481 nil
2482 (unwind-protect
2483 (save-excursion
2484 (set-buffer tembuf)
2485 (buffer-disable-undo)
2486 (erase-buffer)
2487 ;; Avoid copying text props.
2488 (insert (format
2489 "%s" (save-excursion
2490 (set-buffer messbuf)
2491 (buffer-string))))
2492 (message-encode-message-body)
2203 ;; Remove some headers. 2493 ;; Remove some headers.
2204 (message-remove-header message-ignored-news-headers t)) 2494 (save-restriction
2205 (goto-char (point-max)) 2495 (message-narrow-to-headers)
2206 ;; require one newline at the end. 2496 ;; We (re)generate the Lines header.
2207 (or (= (preceding-char) ?\n) 2497 (when (memq 'Lines message-required-mail-headers)
2208 (insert ?\n)) 2498 (message-generate-headers '(Lines)))
2209 (let ((case-fold-search t)) 2499 ;; Remove some headers.
2210 ;; Remove the delimiter. 2500 (message-remove-header message-ignored-news-headers t)
2211 (goto-char (point-min)) 2501 (let ((mail-parse-charset message-default-charset))
2212 (re-search-forward 2502 (mail-encode-encoded-word-buffer)))
2213 (concat "^" (regexp-quote mail-header-separator) "\n")) 2503 (goto-char (point-max))
2214 (replace-match "\n") 2504 ;; require one newline at the end.
2215 (backward-char 1)) 2505 (or (= (preceding-char) ?\n)
2216 (run-hooks 'message-send-news-hook) 2506 (insert ?\n))
2217 ;;(require (car method)) 2507 (let ((case-fold-search t))
2218 ;;(funcall (intern (format "%s-open-server" (car method))) 2508 ;; Remove the delimiter.
2219 ;;(cadr method) (cddr method)) 2509 (goto-char (point-min))
2220 ;;(setq result 2510 (re-search-forward
2221 ;; (funcall (intern (format "%s-request-post" (car method))) 2511 (concat "^" (regexp-quote mail-header-separator) "\n"))
2222 ;; (cadr method))) 2512 (replace-match "\n")
2223 (gnus-open-server method) 2513 (backward-char 1))
2224 (setq result (gnus-request-post method))) 2514 (run-hooks 'message-send-news-hook)
2225 (kill-buffer tembuf)) 2515 (gnus-open-server method)
2226 (set-buffer messbuf) 2516 (setq result (let ((mail-header-separator ""))
2227 (if result 2517 (gnus-request-post method))))
2228 (push 'news message-sent-message-via) 2518 (kill-buffer tembuf))
2229 (message "Couldn't send message via news: %s" 2519 (set-buffer messbuf)
2230 (nnheader-get-report (car method))) 2520 (if result
2231 nil)))) 2521 (push 'news message-sent-message-via)
2522 (message "Couldn't send message via news: %s"
2523 (nnheader-get-report (car method)))
2524 nil)))))
2232 2525
2233 ;;; 2526 ;;;
2234 ;;; Header generation & syntax checking. 2527 ;;; Header generation & syntax checking.
2235 ;;; 2528 ;;;
2236
2237 (defmacro message-check (type &rest forms)
2238 "Eval FORMS if TYPE is to be checked."
2239 `(or (message-check-element ,type)
2240 (save-excursion
2241 ,@forms)))
2242
2243 (put 'message-check 'lisp-indent-function 1)
2244 (put 'message-check 'edebug-form-spec '(form body))
2245 2529
2246 (defun message-check-element (type) 2530 (defun message-check-element (type)
2247 "Returns non-nil if this type is not to be checked." 2531 "Returns non-nil if this type is not to be checked."
2248 (if (eq message-syntax-checks 'dont-check-for-anything-just-trust-me) 2532 (if (eq message-syntax-checks 'dont-check-for-anything-just-trust-me)
2249 t 2533 t
2254 (defun message-check-news-syntax () 2538 (defun message-check-news-syntax ()
2255 "Check the syntax of the message." 2539 "Check the syntax of the message."
2256 (save-excursion 2540 (save-excursion
2257 (save-restriction 2541 (save-restriction
2258 (widen) 2542 (widen)
2259 (and 2543 ;; We narrow to the headers and check them first.
2260 ;; We narrow to the headers and check them first. 2544 (save-excursion
2261 (save-excursion 2545 (save-restriction
2262 (save-restriction 2546 (message-narrow-to-headers)
2263 (message-narrow-to-headers) 2547 (message-check-news-header-syntax))))))
2264 (message-check-news-header-syntax)))
2265 ;; Check the body.
2266 (message-check-news-body-syntax)))))
2267 2548
2268 (defun message-check-news-header-syntax () 2549 (defun message-check-news-header-syntax ()
2269 (and 2550 (and
2551 ;; Check Newsgroups header.
2552 (message-check 'newsgroups
2553 (let ((group (message-fetch-field "newsgroups")))
2554 (or
2555 (and group
2556 (not (string-match "\\`[ \t]*\\'" group)))
2557 (ignore
2558 (message
2559 "The newsgroups field is empty or missing. Posting is denied.")))))
2270 ;; Check the Subject header. 2560 ;; Check the Subject header.
2271 (message-check 'subject 2561 (message-check 'subject
2272 (let* ((case-fold-search t) 2562 (let* ((case-fold-search t)
2273 (subject (message-fetch-field "subject"))) 2563 (subject (message-fetch-field "subject")))
2274 (or 2564 (or
2427 (format "Group %s is repeated in headers. Really post? " error))))) 2717 (format "Group %s is repeated in headers. Really post? " error)))))
2428 ;; Check the From header. 2718 ;; Check the From header.
2429 (message-check 'from 2719 (message-check 'from
2430 (let* ((case-fold-search t) 2720 (let* ((case-fold-search t)
2431 (from (message-fetch-field "from")) 2721 (from (message-fetch-field "from"))
2432 (ad (nth 1 (mail-extract-address-components from)))) 2722 ad)
2433 (cond 2723 (cond
2434 ((not from) 2724 ((not from)
2435 (message "There is no From line. Posting is denied.") 2725 (message "There is no From line. Posting is denied.")
2436 nil) 2726 nil)
2437 ((or (not (string-match "@[^\\.]*\\." ad)) ;larsi@ifi 2727 ((or (not (string-match
2728 "@[^\\.]*\\."
2729 (setq ad (nth 1 (mail-extract-address-components
2730 from))))) ;larsi@ifi
2438 (string-match "\\.\\." ad) ;larsi@ifi..uio 2731 (string-match "\\.\\." ad) ;larsi@ifi..uio
2439 (string-match "@\\." ad) ;larsi@.ifi.uio 2732 (string-match "@\\." ad) ;larsi@.ifi.uio
2440 (string-match "\\.$" ad) ;larsi@ifi.uio. 2733 (string-match "\\.$" ad) ;larsi@ifi.uio.
2441 (not (string-match "^[^@]+@[^@]+$" ad)) ;larsi.ifi.uio 2734 (not (string-match "^[^@]+@[^@]+$" ad)) ;larsi.ifi.uio
2442 (string-match "(.*).*(.*)" from)) ;(lars) (lars) 2735 (string-match "(.*).*(.*)" from)) ;(lars) (lars)
2473 (beginning-of-line) 2766 (beginning-of-line)
2474 (or (re-search-backward "[^ \n\t]" b t) 2767 (or (re-search-backward "[^ \n\t]" b t)
2475 (y-or-n-p "Empty article. Really post? ")))) 2768 (y-or-n-p "Empty article. Really post? "))))
2476 ;; Check for control characters. 2769 ;; Check for control characters.
2477 (message-check 'control-chars 2770 (message-check 'control-chars
2478 (if (re-search-forward "[\000-\007\013\015-\037\200-\237]" nil t) 2771 (if (re-search-forward "[\000-\007\013\015-\032\034-\037\200-\237]" nil t)
2479 (y-or-n-p 2772 (y-or-n-p
2480 "The article contains control characters. Really post? ") 2773 "The article contains control characters. Really post? ")
2481 t)) 2774 t))
2482 ;; Check excessive size. 2775 ;; Check excessive size.
2483 (message-check 'size 2776 (message-check 'size
2494 (y-or-n-p 2787 (y-or-n-p
2495 "It looks like no new text has been added. Really post? "))) 2788 "It looks like no new text has been added. Really post? ")))
2496 ;; Check the length of the signature. 2789 ;; Check the length of the signature.
2497 (message-check 'signature 2790 (message-check 'signature
2498 (goto-char (point-max)) 2791 (goto-char (point-max))
2499 (if (or (not (re-search-backward message-signature-separator nil t)) 2792 (if (> (count-lines (point) (point-max)) 5)
2500 (search-forward message-forward-end-separator nil t)) 2793 (y-or-n-p
2501 t 2794 (format
2502 (if (> (count-lines (point) (point-max)) 5) 2795 "Your .sig is %d lines; it should be max 4. Really post? "
2503 (y-or-n-p 2796 (1- (count-lines (point) (point-max)))))
2504 (format 2797 t))
2505 "Your .sig is %d lines; it should be max 4. Really post? " 2798 ;; Ensure that text follows last quoted portion.
2506 (1- (count-lines (point) (point-max))))) 2799 (message-check 'quoting-style
2507 t))))) 2800 (goto-char (point-max))
2801 (let ((no-problem t))
2802 (when (search-backward-regexp "^>[^\n]*\n>" nil t)
2803 (setq no-problem nil)
2804 (while (not (eobp))
2805 (when (and (not (eolp)) (looking-at "[^> \t]"))
2806 (setq no-problem t))
2807 (forward-line)))
2808 (if no-problem
2809 t
2810 (y-or-n-p "Your text should follow quoted text. Really post? "))))))
2508 2811
2509 (defun message-checksum () 2812 (defun message-checksum ()
2510 "Return a \"checksum\" for the current buffer." 2813 "Return a \"checksum\" for the current buffer."
2511 (let ((sum 0)) 2814 (let ((sum 0))
2512 (save-excursion 2815 (save-excursion
2514 (re-search-forward 2817 (re-search-forward
2515 (concat "^" (regexp-quote mail-header-separator) "$")) 2818 (concat "^" (regexp-quote mail-header-separator) "$"))
2516 (while (not (eobp)) 2819 (while (not (eobp))
2517 (when (not (looking-at "[ \t\n]")) 2820 (when (not (looking-at "[ \t\n]"))
2518 (setq sum (logxor (ash sum 1) (if (natnump sum) 0 1) 2821 (setq sum (logxor (ash sum 1) (if (natnump sum) 0 1)
2519 (following-char)))) 2822 (char-after))))
2520 (forward-char 1))) 2823 (forward-char 1)))
2521 sum)) 2824 sum))
2522 2825
2523 (defun message-do-fcc () 2826 (defun message-do-fcc ()
2524 "Process Fcc headers in the current buffer." 2827 "Process Fcc headers in the current buffer."
2525 (let ((case-fold-search t) 2828 (let ((case-fold-search t)
2526 (buf (current-buffer)) 2829 (buf (current-buffer))
2527 list file) 2830 list file)
2528 (save-excursion 2831 (save-excursion
2529 (set-buffer (get-buffer-create " *message temp*")) 2832 (set-buffer (get-buffer-create " *message temp*"))
2530 (buffer-disable-undo (current-buffer))
2531 (erase-buffer) 2833 (erase-buffer)
2532 (insert-buffer-substring buf) 2834 (insert-buffer-substring buf)
2533 (save-restriction 2835 (save-restriction
2534 (message-narrow-to-headers) 2836 (message-narrow-to-headers)
2535 (while (setq file (message-fetch-field "fcc")) 2837 (while (setq file (message-fetch-field "fcc"))
2536 (push file list) 2838 (push file list)
2537 (message-remove-header "fcc" nil t))) 2839 (message-remove-header "fcc" nil t)))
2840 (message-encode-message-body)
2841 (save-restriction
2842 (message-narrow-to-headers)
2843 (let ((mail-parse-charset message-default-charset)
2844 (rfc2047-header-encoding-alist
2845 (cons '("Newsgroups" . default)
2846 rfc2047-header-encoding-alist)))
2847 (mail-encode-encoded-word-buffer)))
2538 (goto-char (point-min)) 2848 (goto-char (point-min))
2539 (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$")) 2849 (when (re-search-forward
2540 (replace-match "" t t) 2850 (concat "^" (regexp-quote mail-header-separator) "$")
2851 nil t)
2852 (replace-match "" t t ))
2541 ;; Process FCC operations. 2853 ;; Process FCC operations.
2542 (while list 2854 (while list
2543 (setq file (pop list)) 2855 (setq file (pop list))
2544 (if (string-match "^[ \t]*|[ \t]*\\(.*\\)[ \t]*$" file) 2856 (if (string-match "^[ \t]*|[ \t]*\\(.*\\)[ \t]*$" file)
2545 ;; Pipe the article to the program in question. 2857 ;; Pipe the article to the program in question.
2555 (funcall message-fcc-handler-function file) 2867 (funcall message-fcc-handler-function file)
2556 (if (and (file-readable-p file) (mail-file-babyl-p file)) 2868 (if (and (file-readable-p file) (mail-file-babyl-p file))
2557 (rmail-output file 1 nil t) 2869 (rmail-output file 1 nil t)
2558 (let ((mail-use-rfc822 t)) 2870 (let ((mail-use-rfc822 t))
2559 (rmail-output file 1 t t)))))) 2871 (rmail-output file 1 t t))))))
2560
2561 (kill-buffer (current-buffer))))) 2872 (kill-buffer (current-buffer)))))
2562 2873
2563 (defun message-output (filename) 2874 (defun message-output (filename)
2564 "Append this article to Unix/babyl mail file.." 2875 "Append this article to Unix/babyl mail file.."
2565 (if (and (file-readable-p filename) 2876 (if (and (file-readable-p filename)
2597 (goto-char (point-min)) 2908 (goto-char (point-min))
2598 ;; Remove trailing commas. 2909 ;; Remove trailing commas.
2599 (when (re-search-forward ",+$" nil t) 2910 (when (re-search-forward ",+$" nil t)
2600 (replace-match "" t t)))))) 2911 (replace-match "" t t))))))
2601 2912
2602 (defun message-make-date () 2913 (defun message-make-date (&optional now)
2603 "Make a valid data header." 2914 "Make a valid data header.
2604 (let ((now (current-time))) 2915 If NOW, use that time instead."
2605 (timezone-make-date-arpa-standard 2916 (let* ((now (or now (current-time)))
2606 (current-time-string now) (current-time-zone now)))) 2917 (zone (nth 8 (decode-time now)))
2918 (sign "+"))
2919 (when (< zone 0)
2920 (setq sign "-")
2921 (setq zone (- zone)))
2922 (concat
2923 (format-time-string "%d" now)
2924 ;; The month name of the %b spec is locale-specific. Pfff.
2925 (format " %s "
2926 (capitalize (car (rassoc (nth 4 (decode-time now))
2927 parse-time-months))))
2928 (format-time-string "%Y %H:%M:%S " now)
2929 ;; We do all of this because XEmacs doesn't have the %z spec.
2930 (format "%s%02d%02d" sign (/ zone 3600) (/ (% zone 3600) 60)))))
2607 2931
2608 (defun message-make-message-id () 2932 (defun message-make-message-id ()
2609 "Make a unique Message-ID." 2933 "Make a unique Message-ID."
2610 (concat "<" (message-unique-id) 2934 (concat "<" (message-unique-id)
2611 (let ((psubject (save-excursion (message-fetch-field "subject"))) 2935 (let ((psubject (save-excursion (message-fetch-field "subject")))
2668 2992
2669 (defun message-make-organization () 2993 (defun message-make-organization ()
2670 "Make an Organization header." 2994 "Make an Organization header."
2671 (let* ((organization 2995 (let* ((organization
2672 (when message-user-organization 2996 (when message-user-organization
2673 (if (message-functionp message-user-organization) 2997 (if (message-functionp message-user-organization)
2674 (funcall message-user-organization) 2998 (funcall message-user-organization)
2675 message-user-organization)))) 2999 message-user-organization))))
2676 (save-excursion 3000 (save-excursion
2677 (message-set-work-buffer) 3001 (message-set-work-buffer)
2678 (cond ((stringp organization) 3002 (cond ((stringp organization)
2679 (insert organization)) 3003 (insert organization))
2680 ((and (eq t organization) 3004 ((and (eq t organization)
2726 (let ((current (current-time)) 3050 (let ((current (current-time))
2727 (future (* 1.0 message-expires 60 60 24))) 3051 (future (* 1.0 message-expires 60 60 24)))
2728 ;; Add the future to current. 3052 ;; Add the future to current.
2729 (setcar current (+ (car current) (round (/ future (expt 2 16))))) 3053 (setcar current (+ (car current) (round (/ future (expt 2 16)))))
2730 (setcar (cdr current) (+ (nth 1 current) (% (round future) (expt 2 16)))) 3054 (setcar (cdr current) (+ (nth 1 current) (% (round future) (expt 2 16))))
2731 ;; Return the date in the future in UT. 3055 (message-make-date current)))
2732 (timezone-make-date-arpa-standard
2733 (current-time-string current) (current-time-zone current) '(0 "UT"))))
2734 3056
2735 (defun message-make-path () 3057 (defun message-make-path ()
2736 "Return uucp path." 3058 "Return uucp path."
2737 (let ((login-name (user-login-name))) 3059 (let ((login-name (user-login-name)))
2738 (cond ((null message-user-path) 3060 (cond ((null message-user-path)
2866 (Newsgroups nil) 3188 (Newsgroups nil)
2867 (In-Reply-To (message-make-in-reply-to)) 3189 (In-Reply-To (message-make-in-reply-to))
2868 (To nil) 3190 (To nil)
2869 (Distribution (message-make-distribution)) 3191 (Distribution (message-make-distribution))
2870 (Lines (message-make-lines)) 3192 (Lines (message-make-lines))
2871 (X-Newsreader message-newsreader) 3193 (User-Agent message-newsreader)
2872 (X-Mailer (and (not (message-fetch-field "X-Newsreader"))
2873 message-mailer))
2874 (Expires (message-make-expires)) 3194 (Expires (message-make-expires))
2875 (case-fold-search t) 3195 (case-fold-search t)
2876 header value elem) 3196 header value elem)
2877 ;; First we remove any old generated headers. 3197 ;; First we remove any old generated headers.
2878 (let ((headers message-deletable-headers)) 3198 (let ((headers message-deletable-headers))
2907 ":") 3227 ":")
2908 nil t)) 3228 nil t))
2909 (progn 3229 (progn
2910 ;; The header was found. We insert a space after the 3230 ;; The header was found. We insert a space after the
2911 ;; colon, if there is none. 3231 ;; colon, if there is none.
2912 (if (/= (following-char) ? ) (insert " ") (forward-char 1)) 3232 (if (/= (char-after) ? ) (insert " ") (forward-char 1))
2913 ;; Find out whether the header is empty... 3233 ;; Find out whether the header is empty...
2914 (looking-at "[ \t]*$"))) 3234 (looking-at "[ \t]*\n[^ \t]")))
2915 ;; So we find out what value we should insert. 3235 ;; So we find out what value we should insert.
2916 (setq value 3236 (setq value
2917 (cond 3237 (cond
2918 ((and (consp elem) (eq (car elem) 'optional)) 3238 ((and (consp elem) (eq (car elem) 'optional))
2919 ;; This is an optional header. If the cdr of this 3239 ;; This is an optional header. If the cdr of this
2931 (and (fboundp (cdr elem)) (funcall (cdr elem))))) 3251 (and (fboundp (cdr elem)) (funcall (cdr elem)))))
2932 ((and (boundp header) (symbol-value header)) 3252 ((and (boundp header) (symbol-value header))
2933 ;; The element is a symbol. We insert the value 3253 ;; The element is a symbol. We insert the value
2934 ;; of this symbol, if any. 3254 ;; of this symbol, if any.
2935 (symbol-value header)) 3255 (symbol-value header))
2936 (t 3256 ((not (message-check-element header))
2937 ;; We couldn't generate a value for this header, 3257 ;; We couldn't generate a value for this header,
2938 ;; so we just ask the user. 3258 ;; so we just ask the user.
2939 (read-from-minibuffer 3259 (read-from-minibuffer
2940 (format "Empty header for %s; enter value: " header))))) 3260 (format "Empty header for %s; enter value: " header)))))
2941 ;; Finally insert the header. 3261 ;; Finally insert the header.
3016 (narrow-to-region (point-min) (1- (point-max))) 3336 (narrow-to-region (point-min) (1- (point-max)))
3017 (let (quoted last) 3337 (let (quoted last)
3018 (goto-char (point-min)) 3338 (goto-char (point-min))
3019 (while (not (eobp)) 3339 (while (not (eobp))
3020 (skip-chars-forward "^,\"" (point-max)) 3340 (skip-chars-forward "^,\"" (point-max))
3021 (if (or (= (following-char) ?,) 3341 (if (or (eq (char-after) ?,)
3022 (eobp)) 3342 (eobp))
3023 (when (not quoted) 3343 (when (not quoted)
3024 (if (and (> (current-column) 78) 3344 (if (and (> (current-column) 78)
3025 last) 3345 last)
3026 (progn 3346 (progn
3036 (widen) 3356 (widen)
3037 (forward-line 1))) 3357 (forward-line 1)))
3038 3358
3039 (defun message-fill-header (header value) 3359 (defun message-fill-header (header value)
3040 (let ((begin (point)) 3360 (let ((begin (point))
3041 (fill-column 990) 3361 (fill-column 78)
3042 (fill-prefix "\t")) 3362 (fill-prefix "\t"))
3043 (insert (capitalize (symbol-name header)) 3363 (insert (capitalize (symbol-name header))
3044 ": " 3364 ": "
3045 (if (consp value) (car value) value) 3365 (if (consp value) (car value) value)
3046 "\n") 3366 "\n")
3055 (re-search-forward ":" nil t) 3375 (re-search-forward ":" nil t)
3056 (when (looking-at "\n[ \t]+") 3376 (when (looking-at "\n[ \t]+")
3057 (replace-match " " t t)) 3377 (replace-match " " t t))
3058 (goto-char (point-max))))) 3378 (goto-char (point-max)))))
3059 3379
3380 (defun message-shorten-1 (list cut surplus)
3381 ;; Cut SURPLUS elements out of LIST, beginning with CUTth one.
3382 (setcdr (nthcdr (- cut 2) list)
3383 (nthcdr (+ (- cut 2) surplus 1) list)))
3384
3060 (defun message-shorten-references (header references) 3385 (defun message-shorten-references (header references)
3061 "Limit REFERENCES to be shorter than 988 characters." 3386 "Trim REFERENCES to be less than 31 Message-ID long, and fold them.
3062 (let ((max 988) 3387 If folding is disallowed, also check that the REFERENCES are less
3063 (cut 4) 3388 than 988 characters long, and if they are not, trim them until they are."
3389 (let ((maxcount 31)
3390 (count 0)
3391 (cut 6)
3064 refs) 3392 refs)
3065 (nnheader-temp-write nil 3393 (with-temp-buffer
3066 (insert references) 3394 (insert references)
3067 (goto-char (point-min)) 3395 (goto-char (point-min))
3396 ;; Cons a list of valid references.
3068 (while (re-search-forward "<[^>]+>" nil t) 3397 (while (re-search-forward "<[^>]+>" nil t)
3069 (push (match-string 0) refs)) 3398 (push (match-string 0) refs))
3070 (setq refs (nreverse refs)) 3399 (setq refs (nreverse refs)
3071 (while (> (length (mapconcat 'identity refs " ")) max) 3400 count (length refs)))
3072 (when (< (length refs) (1+ cut)) 3401
3073 (decf cut)) 3402 ;; If the list has more than MAXCOUNT elements, trim it by
3074 (setcdr (nthcdr cut refs) (cddr (nthcdr cut refs))))) 3403 ;; removing the CUTth element and the required number of
3075 (insert (capitalize (symbol-name header)) ": " 3404 ;; elements that follow.
3076 (mapconcat 'identity refs " ") "\n"))) 3405 (when (> count maxcount)
3406 (let ((surplus (- count maxcount)))
3407 (message-shorten-1 refs cut surplus)
3408 (decf count surplus)))
3409
3410 ;; If folding is disallowed, make sure the total length (including
3411 ;; the spaces between) will be less than MAXSIZE characters.
3412 ;;
3413 ;; Only disallow folding for News messages. At this point the headers
3414 ;; have not been generated, thus we use message-this-is-news directly.
3415 (when (and message-this-is-news message-cater-to-broken-inn)
3416 (let ((maxsize 988)
3417 (totalsize (+ (apply #'+ (mapcar #'length refs))
3418 (1- count)))
3419 (surplus 0)
3420 (ptr (nthcdr (1- cut) refs)))
3421 ;; Decide how many elements to cut off...
3422 (while (> totalsize maxsize)
3423 (decf totalsize (1+ (length (car ptr))))
3424 (incf surplus)
3425 (setq ptr (cdr ptr)))
3426 ;; ...and do it.
3427 (when (> surplus 0)
3428 (message-shorten-1 refs cut surplus))))
3429
3430 ;; Finally, collect the references back into a string and insert
3431 ;; it into the buffer.
3432 (let ((refstring (mapconcat #'identity refs " ")))
3433 (if (and message-this-is-news message-cater-to-broken-inn)
3434 (insert (capitalize (symbol-name header)) ": "
3435 refstring "\n")
3436 (message-fill-header header refstring)))))
3077 3437
3078 (defun message-position-point () 3438 (defun message-position-point ()
3079 "Move point to where the user probably wants to find it." 3439 "Move point to where the user probably wants to find it."
3080 (message-narrow-to-headers) 3440 (message-narrow-to-headers)
3081 (cond 3441 (cond
3082 ((re-search-forward "^[^:]+:[ \t]*$" nil t) 3442 ((re-search-forward "^[^:]+:[ \t]*$" nil t)
3083 (search-backward ":" ) 3443 (search-backward ":" )
3084 (widen) 3444 (widen)
3085 (forward-char 1) 3445 (forward-char 1)
3086 (if (= (following-char) ? ) 3446 (if (eq (char-after) ? )
3087 (forward-char 1) 3447 (forward-char 1)
3088 (insert " "))) 3448 (insert " ")))
3089 (t 3449 (t
3090 (goto-char (point-max)) 3450 (goto-char (point-max))
3091 (widen) 3451 (widen)
3095 (sit-for 0))) 3455 (sit-for 0)))
3096 3456
3097 (defun message-buffer-name (type &optional to group) 3457 (defun message-buffer-name (type &optional to group)
3098 "Return a new (unique) buffer name based on TYPE and TO." 3458 "Return a new (unique) buffer name based on TYPE and TO."
3099 (cond 3459 (cond
3460 ;; Generate a new buffer name The Message Way.
3461 ((eq message-generate-new-buffers 'unique)
3462 (generate-new-buffer-name
3463 (concat "*" type
3464 (if to
3465 (concat " to "
3466 (or (car (mail-extract-address-components to))
3467 to) "")
3468 "")
3469 (if (and group (not (string= group ""))) (concat " on " group) "")
3470 "*")))
3100 ;; Check whether `message-generate-new-buffers' is a function, 3471 ;; Check whether `message-generate-new-buffers' is a function,
3101 ;; and if so, call it. 3472 ;; and if so, call it.
3102 ((message-functionp message-generate-new-buffers) 3473 ((message-functionp message-generate-new-buffers)
3103 (funcall message-generate-new-buffers type to group)) 3474 (funcall message-generate-new-buffers type to group))
3104 ;; Generate a new buffer name The Message Way. 3475 ((eq message-generate-new-buffers 'unsent)
3105 (message-generate-new-buffers
3106 (generate-new-buffer-name 3476 (generate-new-buffer-name
3107 (concat "*" type 3477 (concat "*unsent " type
3108 (if to 3478 (if to
3109 (concat " to " 3479 (concat " to "
3110 (or (car (mail-extract-address-components to)) 3480 (or (car (mail-extract-address-components to))
3111 to) "") 3481 to) "")
3112 "") 3482 "")
3145 (not (buffer-modified-p buffer))) 3515 (not (buffer-modified-p buffer)))
3146 (kill-buffer buffer)))) 3516 (kill-buffer buffer))))
3147 ;; Rename the buffer. 3517 ;; Rename the buffer.
3148 (if message-send-rename-function 3518 (if message-send-rename-function
3149 (funcall message-send-rename-function) 3519 (funcall message-send-rename-function)
3150 (when (string-match "\\`\\*" (buffer-name)) 3520 (when (string-match "\\`\\*\\(unsent \\)?" (buffer-name))
3151 (rename-buffer 3521 (rename-buffer
3152 (concat "*sent " (substring (buffer-name) (match-end 0))) t))) 3522 (concat "*sent " (substring (buffer-name) (match-end 0))) t)))
3153 ;; Push the current buffer onto the list. 3523 ;; Push the current buffer onto the list.
3154 (when message-max-buffers 3524 (when message-max-buffers
3155 (setq message-buffer-list 3525 (setq message-buffer-list
3223 (setq message-draft-article 3593 (setq message-draft-article
3224 (nndraft-request-associate-buffer "drafts")) 3594 (nndraft-request-associate-buffer "drafts"))
3225 (setq buffer-file-name (expand-file-name "*message*" 3595 (setq buffer-file-name (expand-file-name "*message*"
3226 message-auto-save-directory)) 3596 message-auto-save-directory))
3227 (setq buffer-auto-save-file-name (make-auto-save-file-name))) 3597 (setq buffer-auto-save-file-name (make-auto-save-file-name)))
3228 (clear-visited-file-modtime))) 3598 (clear-visited-file-modtime)
3599 (setq buffer-file-coding-system message-draft-coding-system)))
3229 3600
3230 (defun message-disassociate-draft () 3601 (defun message-disassociate-draft ()
3231 "Disassociate the message buffer from the drafts directory." 3602 "Disassociate the message buffer from the drafts directory."
3232 (when message-draft-article 3603 (when message-draft-article
3233 (nndraft-request-expire-articles 3604 (nndraft-request-expire-articles
3234 (list message-draft-article) "drafts" nil t))) 3605 (list message-draft-article) "drafts" nil t)))
3606
3607 (defun message-insert-headers ()
3608 "Generate the headers for the article."
3609 (interactive)
3610 (save-excursion
3611 (save-restriction
3612 (message-narrow-to-headers)
3613 (when (message-news-p)
3614 (message-generate-headers
3615 (delq 'Lines
3616 (delq 'Subject
3617 (copy-sequence message-required-news-headers)))))
3618 (when (message-mail-p)
3619 (message-generate-headers
3620 (delq 'Lines
3621 (delq 'Subject
3622 (copy-sequence message-required-mail-headers))))))))
3235 3623
3236 3624
3237 3625
3238 ;;; 3626 ;;;
3239 ;;; Commands for interfacing with message 3627 ;;; Commands for interfacing with message
3260 (let ((message-this-is-news t)) 3648 (let ((message-this-is-news t))
3261 (message-pop-to-buffer (message-buffer-name "news" nil newsgroups)) 3649 (message-pop-to-buffer (message-buffer-name "news" nil newsgroups))
3262 (message-setup `((Newsgroups . ,(or newsgroups "")) 3650 (message-setup `((Newsgroups . ,(or newsgroups ""))
3263 (Subject . ,(or subject "")))))) 3651 (Subject . ,(or subject ""))))))
3264 3652
3653 (defun message-get-reply-headers (wide &optional to-address)
3654 (let (follow-to mct never-mct from to cc reply-to ccalist)
3655 ;; Find all relevant headers we need.
3656 (setq from (message-fetch-field "from")
3657 to (message-fetch-field "to")
3658 cc (message-fetch-field "cc")
3659 mct (message-fetch-field "mail-copies-to")
3660 reply-to (message-fetch-field "reply-to"))
3661
3662 ;; Handle special values of Mail-Copies-To.
3663 (when mct
3664 (cond ((or (equal (downcase mct) "never")
3665 (equal (downcase mct) "nobody"))
3666 (setq never-mct t)
3667 (setq mct nil))
3668 ((or (equal (downcase mct) "always")
3669 (equal (downcase mct) "poster"))
3670 (setq mct (or reply-to from)))))
3671
3672 (if (or (not wide)
3673 to-address)
3674 (progn
3675 (setq follow-to (list (cons 'To (or to-address reply-to from))))
3676 (when (and wide mct)
3677 (push (cons 'Cc mct) follow-to)))
3678 (let (ccalist)
3679 (save-excursion
3680 (message-set-work-buffer)
3681 (unless never-mct
3682 (insert (or reply-to from "")))
3683 (insert (if to (concat (if (bolp) "" ", ") to "") ""))
3684 (insert (if mct (concat (if (bolp) "" ", ") mct) ""))
3685 (insert (if cc (concat (if (bolp) "" ", ") cc) ""))
3686 (goto-char (point-min))
3687 (while (re-search-forward "[ \t]+" nil t)
3688 (replace-match " " t t))
3689 ;; Remove addresses that match `rmail-dont-reply-to-names'.
3690 (let ((rmail-dont-reply-to-names message-dont-reply-to-names))
3691 (insert (prog1 (rmail-dont-reply-to (buffer-string))
3692 (erase-buffer))))
3693 (goto-char (point-min))
3694 ;; Perhaps "Mail-Copies-To: never" removed the only address?
3695 (when (eobp)
3696 (insert (or reply-to from "")))
3697 (setq ccalist
3698 (mapcar
3699 (lambda (addr)
3700 (cons (mail-strip-quoted-names addr) addr))
3701 (message-tokenize-header (buffer-string))))
3702 (let ((s ccalist))
3703 (while s
3704 (setq ccalist (delq (assoc (car (pop s)) s) ccalist)))))
3705 (setq follow-to (list (cons 'To (cdr (pop ccalist)))))
3706 (when ccalist
3707 (let ((ccs (cons 'Cc (mapconcat
3708 (lambda (addr) (cdr addr)) ccalist ", "))))
3709 (when (string-match "^ +" (cdr ccs))
3710 (setcdr ccs (substring (cdr ccs) (match-end 0))))
3711 (push ccs follow-to)))))
3712 follow-to))
3713
3714
3265 ;;;###autoload 3715 ;;;###autoload
3266 (defun message-reply (&optional to-address wide) 3716 (defun message-reply (&optional to-address wide)
3267 "Start editing a reply to the article in the current buffer." 3717 "Start editing a reply to the article in the current buffer."
3268 (interactive) 3718 (interactive)
3719 (require 'gnus-sum) ; for gnus-list-identifiers
3269 (let ((cur (current-buffer)) 3720 (let ((cur (current-buffer))
3270 from subject date reply-to to cc 3721 from subject date reply-to to cc
3271 references message-id follow-to 3722 references message-id follow-to
3272 (inhibit-point-motion-hooks t) 3723 (inhibit-point-motion-hooks t)
3273 mct never-mct gnus-warning) 3724 (message-this-is-mail t)
3725 gnus-warning)
3274 (save-restriction 3726 (save-restriction
3275 (message-narrow-to-head) 3727 (message-narrow-to-head)
3276 ;; Allow customizations to have their say. 3728 ;; Allow customizations to have their say.
3277 (if (not wide) 3729 (if (not wide)
3278 ;; This is a regular reply. 3730 ;; This is a regular reply.
3281 ;; This is a followup. 3733 ;; This is a followup.
3282 (if (message-functionp message-wide-reply-to-function) 3734 (if (message-functionp message-wide-reply-to-function)
3283 (save-excursion 3735 (save-excursion
3284 (setq follow-to 3736 (setq follow-to
3285 (funcall message-wide-reply-to-function))))) 3737 (funcall message-wide-reply-to-function)))))
3286 ;; Find all relevant headers we need. 3738 (setq message-id (message-fetch-field "message-id" t)
3287 (setq from (message-fetch-field "from") 3739 references (message-fetch-field "references")
3288 date (message-fetch-field "date") 3740 date (message-fetch-field "date")
3289 subject (or (message-fetch-field "subject") "none") 3741 from (message-fetch-field "from")
3290 to (message-fetch-field "to") 3742 subject (or (message-fetch-field "subject") "none"))
3291 cc (message-fetch-field "cc") 3743 (if gnus-list-identifiers
3292 mct (message-fetch-field "mail-copies-to") 3744 (setq subject (message-strip-list-identifiers subject)))
3293 reply-to (message-fetch-field "reply-to") 3745 (setq subject (concat "Re: " (message-strip-subject-re subject)))
3294 references (message-fetch-field "references") 3746
3295 message-id (message-fetch-field "message-id" t)) 3747 (when (and (setq gnus-warning (message-fetch-field "gnus-warning"))
3296 ;; Remove any (buggy) Re:'s that are present and make a 3748 (string-match "<[^>]+>" gnus-warning))
3297 ;; proper one. 3749 (setq message-id (match-string 0 gnus-warning)))
3298 (when (string-match message-subject-re-regexp subject) 3750
3299 (setq subject (substring subject (match-end 0)))) 3751 (unless follow-to
3300 (setq subject (concat "Re: " subject)) 3752 (setq follow-to (message-get-reply-headers wide to-address))))
3301 3753
3302 (when (and (setq gnus-warning (message-fetch-field "gnus-warning")) 3754 (message-pop-to-buffer
3303 (string-match "<[^>]+>" gnus-warning)) 3755 (message-buffer-name
3304 (setq message-id (match-string 0 gnus-warning))) 3756 (if wide "wide reply" "reply") from
3305 3757 (if wide to-address nil)))
3306 ;; Handle special values of Mail-Copies-To.
3307 (when mct
3308 (cond ((equal (downcase mct) "never")
3309 (setq never-mct t)
3310 (setq mct nil))
3311 ((equal (downcase mct) "always")
3312 (setq mct (or reply-to from)))))
3313
3314 (unless follow-to
3315 (if (or (not wide)
3316 to-address)
3317 (progn
3318 (setq follow-to (list (cons 'To (or to-address reply-to from))))
3319 (when (and wide mct)
3320 (push (cons 'Cc mct) follow-to)))
3321 (let (ccalist)
3322 (save-excursion
3323 (message-set-work-buffer)
3324 (unless never-mct
3325 (insert (or reply-to from "")))
3326 (insert (if to (concat (if (bolp) "" ", ") to "") ""))
3327 (insert (if mct (concat (if (bolp) "" ", ") mct) ""))
3328 (insert (if cc (concat (if (bolp) "" ", ") cc) ""))
3329 (goto-char (point-min))
3330 (while (re-search-forward "[ \t]+" nil t)
3331 (replace-match " " t t))
3332 ;; Remove addresses that match `rmail-dont-reply-to-names'.
3333 (insert (prog1 (rmail-dont-reply-to (buffer-string))
3334 (erase-buffer)))
3335 (goto-char (point-min))
3336 ;; Perhaps Mail-Copies-To: never removed the only address?
3337 (when (eobp)
3338 (insert (or reply-to from "")))
3339 (setq ccalist
3340 (mapcar
3341 (lambda (addr)
3342 (cons (mail-strip-quoted-names addr) addr))
3343 (message-tokenize-header (buffer-string))))
3344 (let ((s ccalist))
3345 (while s
3346 (setq ccalist (delq (assoc (car (pop s)) s) ccalist)))))
3347 (setq follow-to (list (cons 'To (cdr (pop ccalist)))))
3348 (when ccalist
3349 (let ((ccs (cons 'Cc (mapconcat
3350 (lambda (addr) (cdr addr)) ccalist ", "))))
3351 (when (string-match "^ +" (cdr ccs))
3352 (setcdr ccs (substring (cdr ccs) (match-end 0))))
3353 (push ccs follow-to))))))
3354 (widen))
3355
3356 (message-pop-to-buffer (message-buffer-name
3357 (if wide "wide reply" "reply") from
3358 (if wide to-address nil)))
3359 3758
3360 (setq message-reply-headers 3759 (setq message-reply-headers
3361 (vector 0 subject from date message-id references 0 0 "")) 3760 (vector 0 subject from date message-id references 0 0 ""))
3362 3761
3363 (message-setup 3762 (message-setup
3378 ;;;###autoload 3777 ;;;###autoload
3379 (defun message-followup (&optional to-newsgroups) 3778 (defun message-followup (&optional to-newsgroups)
3380 "Follow up to the message in the current buffer. 3779 "Follow up to the message in the current buffer.
3381 If TO-NEWSGROUPS, use that as the new Newsgroups line." 3780 If TO-NEWSGROUPS, use that as the new Newsgroups line."
3382 (interactive) 3781 (interactive)
3782 (require 'gnus-sum) ; for gnus-list-identifiers
3383 (let ((cur (current-buffer)) 3783 (let ((cur (current-buffer))
3384 from subject date reply-to mct 3784 from subject date reply-to mct
3385 references message-id follow-to 3785 references message-id follow-to
3386 (inhibit-point-motion-hooks t) 3786 (inhibit-point-motion-hooks t)
3387 (message-this-is-news t) 3787 (message-this-is-news t)
3412 ;; Remove bogus distribution. 3812 ;; Remove bogus distribution.
3413 (when (and (stringp distribution) 3813 (when (and (stringp distribution)
3414 (let ((case-fold-search t)) 3814 (let ((case-fold-search t))
3415 (string-match "world" distribution))) 3815 (string-match "world" distribution)))
3416 (setq distribution nil)) 3816 (setq distribution nil))
3417 ;; Remove any (buggy) Re:'s that are present and make a 3817 (if gnus-list-identifiers
3418 ;; proper one. 3818 (setq subject (message-strip-list-identifiers subject)))
3419 (when (string-match message-subject-re-regexp subject) 3819 (setq subject (concat "Re: " (message-strip-subject-re subject)))
3420 (setq subject (substring subject (match-end 0))))
3421 (setq subject (concat "Re: " subject))
3422 (widen)) 3820 (widen))
3423 3821
3424 (message-pop-to-buffer (message-buffer-name "followup" from newsgroups)) 3822 (message-pop-to-buffer (message-buffer-name "followup" from newsgroups))
3425 3823
3426 (message-setup 3824 (message-setup
3473 ,@(and distribution (list (cons 'Distribution distribution))) 3871 ,@(and distribution (list (cons 'Distribution distribution)))
3474 ,@(if (or references message-id) 3872 ,@(if (or references message-id)
3475 `((References . ,(concat (or references "") (and references " ") 3873 `((References . ,(concat (or references "") (and references " ")
3476 (or message-id ""))))) 3874 (or message-id "")))))
3477 ,@(when (and mct 3875 ,@(when (and mct
3478 (not (equal (downcase mct) "never"))) 3876 (not (or (equal (downcase mct) "never")
3479 (list (cons 'Cc (if (equal (downcase mct) "always") 3877 (equal (downcase mct) "nobody"))))
3878 (list (cons 'Cc (if (or (equal (downcase mct) "always")
3879 (equal (downcase mct) "poster"))
3480 (or reply-to from "") 3880 (or reply-to from "")
3481 mct))))) 3881 mct)))))
3482 3882
3483 cur) 3883 cur)
3484 3884
3485 (setq message-reply-headers 3885 (setq message-reply-headers
3486 (vector 0 subject from date message-id references 0 0 "")))) 3886 (vector 0 subject from date message-id references 0 0 ""))))
3487 3887
3488 3888
3489 ;;;###autoload 3889 ;;;###autoload
3490 (defun message-cancel-news () 3890 (defun message-cancel-news (&optional arg)
3491 "Cancel an article you posted." 3891 "Cancel an article you posted.
3492 (interactive) 3892 If ARG, allow editing of the cancellation message."
3893 (interactive "P")
3493 (unless (message-news-p) 3894 (unless (message-news-p)
3494 (error "This is not a news article; canceling is impossible")) 3895 (error "This is not a news article; canceling is impossible"))
3495 (when (yes-or-no-p "Do you really want to cancel this article? ") 3896 (when (yes-or-no-p "Do you really want to cancel this article? ")
3496 (let (from newsgroups message-id distribution buf sender) 3897 (let (from newsgroups message-id distribution buf sender)
3497 (save-excursion 3898 (save-excursion
3498 ;; Get header info. from original article. 3899 ;; Get header info from original article.
3499 (save-restriction 3900 (save-restriction
3500 (message-narrow-to-head) 3901 (message-narrow-to-head)
3501 (setq from (message-fetch-field "from") 3902 (setq from (message-fetch-field "from")
3502 sender (message-fetch-field "sender") 3903 sender (message-fetch-field "sender")
3503 newsgroups (message-fetch-field "newsgroups") 3904 newsgroups (message-fetch-field "newsgroups")
3512 (downcase (cadr (mail-extract-address-components from))) 3913 (downcase (cadr (mail-extract-address-components from)))
3513 (downcase (cadr (mail-extract-address-components 3914 (downcase (cadr (mail-extract-address-components
3514 (message-make-from)))))) 3915 (message-make-from))))))
3515 (error "This article is not yours")) 3916 (error "This article is not yours"))
3516 ;; Make control message. 3917 ;; Make control message.
3517 (setq buf (set-buffer (get-buffer-create " *message cancel*"))) 3918 (if arg
3518 (buffer-disable-undo (current-buffer)) 3919 (message-news)
3920 (setq buf (set-buffer (get-buffer-create " *message cancel*"))))
3519 (erase-buffer) 3921 (erase-buffer)
3520 (insert "Newsgroups: " newsgroups "\n" 3922 (insert "Newsgroups: " newsgroups "\n"
3521 "From: " (message-make-from) "\n" 3923 "From: " from "\n"
3522 "Subject: cmsg cancel " message-id "\n" 3924 "Subject: cmsg cancel " message-id "\n"
3523 "Control: cancel " message-id "\n" 3925 "Control: cancel " message-id "\n"
3524 (if distribution 3926 (if distribution
3525 (concat "Distribution: " distribution "\n") 3927 (concat "Distribution: " distribution "\n")
3526 "") 3928 "")
3527 mail-header-separator "\n" 3929 mail-header-separator "\n"
3528 message-cancel-message) 3930 message-cancel-message)
3529 (message "Canceling your article...") 3931 (run-hooks 'message-cancel-hook)
3530 (if (let ((message-syntax-checks 3932 (unless arg
3531 'dont-check-for-anything-just-trust-me)) 3933 (message "Canceling your article...")
3532 (funcall message-send-news-function)) 3934 (if (let ((message-syntax-checks
3533 (message "Canceling your article...done")) 3935 'dont-check-for-anything-just-trust-me))
3534 (kill-buffer buf))))) 3936 (funcall message-send-news-function))
3937 (message "Canceling your article...done"))
3938 (kill-buffer buf))))))
3535 3939
3536 ;;;###autoload 3940 ;;;###autoload
3537 (defun message-supersede () 3941 (defun message-supersede ()
3538 "Start composing a message to supersede the current message. 3942 "Start composing a message to supersede the current message.
3539 This is done simply by taking the old article and adding a Supersedes 3943 This is done simply by taking the old article and adding a Supersedes
3553 (message-make-from)))))) 3957 (message-make-from))))))
3554 (error "This article is not yours")) 3958 (error "This article is not yours"))
3555 ;; Get a normal message buffer. 3959 ;; Get a normal message buffer.
3556 (message-pop-to-buffer (message-buffer-name "supersede")) 3960 (message-pop-to-buffer (message-buffer-name "supersede"))
3557 (insert-buffer-substring cur) 3961 (insert-buffer-substring cur)
3962 (mime-to-mml)
3558 (message-narrow-to-head) 3963 (message-narrow-to-head)
3559 ;; Remove unwanted headers. 3964 ;; Remove unwanted headers.
3560 (when message-ignored-supersedes-headers 3965 (when message-ignored-supersedes-headers
3561 (message-remove-header message-ignored-supersedes-headers t)) 3966 (message-remove-header message-ignored-supersedes-headers t))
3562 (goto-char (point-min)) 3967 (goto-char (point-min))
3574 (interactive) 3979 (interactive)
3575 (let ((file-name (make-auto-save-file-name))) 3980 (let ((file-name (make-auto-save-file-name)))
3576 (cond ((save-window-excursion 3981 (cond ((save-window-excursion
3577 (if (not (eq system-type 'vax-vms)) 3982 (if (not (eq system-type 'vax-vms))
3578 (with-output-to-temp-buffer "*Directory*" 3983 (with-output-to-temp-buffer "*Directory*"
3984 (with-current-buffer standard-output
3985 (fundamental-mode)) ; for Emacs 20.4+
3579 (buffer-disable-undo standard-output) 3986 (buffer-disable-undo standard-output)
3580 (let ((default-directory "/")) 3987 (let ((default-directory "/"))
3581 (call-process 3988 (call-process
3582 "ls" nil standard-output nil "-l" file-name)))) 3989 "ls" nil standard-output nil "-l" file-name))))
3583 (yes-or-no-p (format "Recover auto save file %s? " file-name))) 3990 (yes-or-no-p (format "Recover auto save file %s? " file-name)))
3588 3995
3589 ;;; Washing Subject: 3996 ;;; Washing Subject:
3590 3997
3591 (defun message-wash-subject (subject) 3998 (defun message-wash-subject (subject)
3592 "Remove junk like \"Re:\", \"(fwd)\", etc. that was added to the subject by previous forwarders, replyers, etc." 3999 "Remove junk like \"Re:\", \"(fwd)\", etc. that was added to the subject by previous forwarders, replyers, etc."
3593 (nnheader-temp-write nil 4000 (with-temp-buffer
3594 (insert-string subject) 4001 (insert-string subject)
3595 (goto-char (point-min)) 4002 (goto-char (point-min))
3596 ;; strip Re/Fwd stuff off the beginning 4003 ;; strip Re/Fwd stuff off the beginning
3597 (while (re-search-forward 4004 (while (re-search-forward
3598 "\\([Rr][Ee]:\\|[Ff][Ww][Dd]\\(\\[[0-9]*\\]\\)?:\\|[Ff][Ww]:\\)" nil t) 4005 "\\([Rr][Ee]:\\|[Ff][Ww][Dd]\\(\\[[0-9]*\\]\\)?:\\|[Ff][Ww]:\\)" nil t)
3659 (setq subject (funcall (car funcs) subject))) 4066 (setq subject (funcall (car funcs) subject)))
3660 (setq funcs (cdr funcs))) 4067 (setq funcs (cdr funcs)))
3661 subject)))) 4068 subject))))
3662 4069
3663 ;;;###autoload 4070 ;;;###autoload
3664 (defun message-forward (&optional news) 4071 (defun message-forward (&optional news digest)
3665 "Forward the current message via mail. 4072 "Forward the current message via mail.
3666 Optional NEWS will use news to forward instead of mail." 4073 Optional NEWS will use news to forward instead of mail.
4074 Optional DIGEST will use digest to forward."
3667 (interactive "P") 4075 (interactive "P")
3668 (let ((cur (current-buffer)) 4076 (let* ((cur (current-buffer))
3669 (subject (message-make-forward-subject)) 4077 (subject (if message-forward-show-mml
3670 art-beg) 4078 (message-make-forward-subject)
3671 (if news (message-news nil subject) (message-mail nil subject)) 4079 (mail-decode-encoded-word-string
4080 (message-make-forward-subject))))
4081 art-beg)
4082 (if news
4083 (message-news nil subject)
4084 (message-mail nil subject))
3672 ;; Put point where we want it before inserting the forwarded 4085 ;; Put point where we want it before inserting the forwarded
3673 ;; message. 4086 ;; message.
3674 (if message-signature-before-forwarded-message 4087 (if message-forward-before-signature
3675 (goto-char (point-max)) 4088 (message-goto-body)
3676 (message-goto-body)) 4089 (goto-char (point-max)))
3677 ;; Make sure we're at the start of the line. 4090 (if message-forward-as-mime
3678 (unless (eolp) 4091 (if digest
3679 (insert "\n")) 4092 (insert "\n<#multipart type=digest>\n")
3680 ;; Narrow to the area we are to insert. 4093 (if message-forward-show-mml
3681 (narrow-to-region (point) (point)) 4094 (insert "\n\n<#mml type=message/rfc822 disposition=inline>\n")
3682 ;; Insert the separators and the forwarded buffer. 4095 (insert "\n\n<#part type=message/rfc822 disposition=inline raw=t>\n")))
3683 (insert message-forward-start-separator) 4096 (insert "\n-------------------- Start of forwarded message --------------------\n"))
3684 (setq art-beg (point)) 4097 (let ((b (point)) e)
3685 (insert-buffer-substring cur) 4098 (if digest
3686 (goto-char (point-max)) 4099 (if message-forward-as-mime
3687 (insert message-forward-end-separator) 4100 (insert-buffer-substring cur)
3688 (set-text-properties (point-min) (point-max) nil) 4101 (mml-insert-buffer cur))
3689 ;; Remove all unwanted headers. 4102 (if message-forward-show-mml
3690 (goto-char art-beg) 4103 (insert-buffer-substring cur)
3691 (narrow-to-region (point) (if (search-forward "\n\n" nil t) 4104 (mm-with-unibyte-current-buffer
3692 (1- (point)) 4105 (mml-insert-buffer cur))))
3693 (point))) 4106 (setq e (point))
3694 (goto-char (point-min)) 4107 (if message-forward-as-mime
3695 (message-remove-header message-included-forward-headers t nil t) 4108 (if digest
3696 (widen) 4109 (insert "<#/multipart>\n")
4110 (if message-forward-show-mml
4111 (insert "<#/mml>\n")
4112 (insert "<#/part>\n")))
4113 (insert "\n-------------------- End of forwarded message --------------------\n"))
4114 (if (and digest message-forward-as-mime)
4115 (save-restriction
4116 (narrow-to-region b e)
4117 (goto-char b)
4118 (narrow-to-region (point)
4119 (or (search-forward "\n\n" nil t) (point)))
4120 (delete-region (point-min) (point-max)))
4121 (when (and (not current-prefix-arg)
4122 message-forward-ignored-headers)
4123 (save-restriction
4124 (narrow-to-region b e)
4125 (goto-char b)
4126 (narrow-to-region (point)
4127 (or (search-forward "\n\n" nil t) (point)))
4128 (message-remove-header message-forward-ignored-headers t)))))
3697 (message-position-point))) 4129 (message-position-point)))
3698 4130
3699 ;;;###autoload 4131 ;;;###autoload
3700 (defun message-resend (address) 4132 (defun message-resend (address)
3701 "Resend the current article to ADDRESS." 4133 "Resend the current article to ADDRESS."
3702 (interactive "sResend message to: ") 4134 (interactive
4135 (list (message-read-from-minibuffer "Resend message to: ")))
3703 (message "Resending message to %s..." address) 4136 (message "Resending message to %s..." address)
3704 (save-excursion 4137 (save-excursion
3705 (let ((cur (current-buffer)) 4138 (let ((cur (current-buffer))
3706 beg) 4139 beg)
3707 ;; We first set up a normal mail buffer. 4140 ;; We first set up a normal mail buffer.
3708 (set-buffer (get-buffer-create " *message resend*")) 4141 (set-buffer (get-buffer-create " *message resend*"))
3709 (buffer-disable-undo (current-buffer))
3710 (erase-buffer) 4142 (erase-buffer)
3711 (message-setup `((To . ,address))) 4143 (message-setup `((To . ,address)))
3712 ;; Insert our usual headers. 4144 ;; Insert our usual headers.
3713 (message-generate-headers '(From Date To)) 4145 (message-generate-headers '(From Date To))
3714 (message-narrow-to-headers) 4146 (message-narrow-to-headers)
3737 ;; Quote any "From " lines at the beginning. 4169 ;; Quote any "From " lines at the beginning.
3738 (goto-char beg) 4170 (goto-char beg)
3739 (when (looking-at "From ") 4171 (when (looking-at "From ")
3740 (replace-match "X-From-Line: ")) 4172 (replace-match "X-From-Line: "))
3741 ;; Send it. 4173 ;; Send it.
3742 (message-send-mail) 4174 (let ((message-inhibit-body-encoding t)
4175 message-required-mail-headers)
4176 (message-send-mail))
3743 (kill-buffer (current-buffer))) 4177 (kill-buffer (current-buffer)))
3744 (message "Resending message to %s...done" address))) 4178 (message "Resending message to %s...done" address)))
3745 4179
3746 ;;;###autoload 4180 ;;;###autoload
3747 (defun message-bounce () 4181 (defun message-bounce ()
3748 "Re-mail the current message. 4182 "Re-mail the current message.
3749 This only makes sense if the current message is a bounce message than 4183 This only makes sense if the current message is a bounce message that
3750 contains some mail you have written which has been bounced back to 4184 contains some mail you have written which has been bounced back to
3751 you." 4185 you."
3752 (interactive) 4186 (interactive)
3753 (let ((cur (current-buffer)) 4187 (let ((handles (mm-dissect-buffer t))
3754 boundary) 4188 boundary)
3755 (message-pop-to-buffer (message-buffer-name "bounce")) 4189 (message-pop-to-buffer (message-buffer-name "bounce"))
3756 (insert-buffer-substring cur) 4190 (if (stringp (car handles))
3757 (undo-boundary) 4191 ;; This is a MIME bounce.
3758 (message-narrow-to-head) 4192 (mm-insert-part (car (last handles)))
3759 (if (and (message-fetch-field "Mime-Version") 4193 ;; This is a non-MIME bounce, so we try to remove things
3760 (setq boundary (message-fetch-field "Content-Type"))) 4194 ;; manually.
3761 (if (string-match "boundary=\"\\([^\"]+\\)\"" boundary) 4195 (mm-insert-part handles)
3762 (setq boundary (concat (match-string 1 boundary) " *\n" 4196 (undo-boundary)
3763 "Content-Type: message/rfc822")) 4197 (goto-char (point-min))
3764 (setq boundary nil))) 4198 (search-forward "\n\n" nil t)
3765 (widen) 4199 (or (and (re-search-forward message-unsent-separator nil t)
3766 (goto-char (point-min)) 4200 (forward-line 1))
3767 (search-forward "\n\n" nil t) 4201 (re-search-forward "^Return-Path:.*\n" nil t))
3768 (or (and boundary 4202 ;; We remove everything before the bounced mail.
3769 (re-search-forward boundary nil t) 4203 (delete-region
3770 (forward-line 2)) 4204 (point-min)
3771 (and (re-search-forward message-unsent-separator nil t) 4205 (if (re-search-forward "^[^ \n\t]+:" nil t)
3772 (forward-line 1)) 4206 (match-beginning 0)
3773 (re-search-forward "^Return-Path:.*\n" nil t)) 4207 (point))))
3774 ;; We remove everything before the bounced mail. 4208 (mm-enable-multibyte)
3775 (delete-region 4209 (mime-to-mml)
3776 (point-min)
3777 (if (re-search-forward "^[^ \n\t]+:" nil t)
3778 (match-beginning 0)
3779 (point)))
3780 (save-restriction 4210 (save-restriction
3781 (message-narrow-to-head) 4211 (message-narrow-to-head)
3782 (message-remove-header message-ignored-bounced-headers t) 4212 (message-remove-header message-ignored-bounced-headers t)
3783 (goto-char (point-max)) 4213 (goto-char (point-max))
3784 (insert mail-header-separator)) 4214 (insert mail-header-separator))
3857 (let ((end1 (make-marker))) 4287 (let ((end1 (make-marker)))
3858 (move-marker end1 (max start end)) 4288 (move-marker end1 (max start end))
3859 (goto-char (min start end)) 4289 (goto-char (min start end))
3860 (while (< (point) end1) 4290 (while (< (point) end1)
3861 (or (looking-at "[_\^@- ]") 4291 (or (looking-at "[_\^@- ]")
3862 (insert (following-char) "\b")) 4292 (insert (char-after) "\b"))
3863 (forward-char 1))))) 4293 (forward-char 1)))))
3864 4294
3865 ;;;###autoload 4295 ;;;###autoload
3866 (defun unbold-region (start end) 4296 (defun unbold-region (start end)
3867 "Remove all boldness (overstruck characters) in the region. 4297 "Remove all boldness (overstruck characters) in the region.
3871 (save-excursion 4301 (save-excursion
3872 (let ((end1 (make-marker))) 4302 (let ((end1 (make-marker)))
3873 (move-marker end1 (max start end)) 4303 (move-marker end1 (max start end))
3874 (goto-char (min start end)) 4304 (goto-char (min start end))
3875 (while (re-search-forward "\b" end1 t) 4305 (while (re-search-forward "\b" end1 t)
3876 (if (eq (following-char) (char-after (- (point) 2))) 4306 (if (eq (char-after) (char-after (- (point) 2)))
3877 (delete-char -2)))))) 4307 (delete-char -2))))))
3878 4308
3879 (defalias 'message-exchange-point-and-mark 'exchange-point-and-mark) 4309 (defalias 'message-exchange-point-and-mark 'exchange-point-and-mark)
3880 4310
3881 ;; Support for toolbar 4311 ;; Support for toolbar
3930 (insert string) 4360 (insert string)
3931 (if (not comp) 4361 (if (not comp)
3932 (message "No matching groups") 4362 (message "No matching groups")
3933 (save-selected-window 4363 (save-selected-window
3934 (pop-to-buffer "*Completions*") 4364 (pop-to-buffer "*Completions*")
3935 (buffer-disable-undo (current-buffer)) 4365 (buffer-disable-undo)
3936 (let ((buffer-read-only nil)) 4366 (let ((buffer-read-only nil))
3937 (erase-buffer) 4367 (erase-buffer)
3938 (let ((standard-output (current-buffer))) 4368 (let ((standard-output (current-buffer)))
3939 (display-completion-list (sort completions 'string<))) 4369 (display-completion-list (sort completions 'string<)))
3940 (goto-char (point-min)) 4370 (goto-char (point-min))
3950 (setq text (message-flatten-list text))) 4380 (setq text (message-flatten-list text)))
3951 (save-window-excursion 4381 (save-window-excursion
3952 (save-excursion 4382 (save-excursion
3953 (with-output-to-temp-buffer " *MESSAGE information message*" 4383 (with-output-to-temp-buffer " *MESSAGE information message*"
3954 (set-buffer " *MESSAGE information message*") 4384 (set-buffer " *MESSAGE information message*")
4385 (fundamental-mode) ; for Emacs 20.4+
3955 (mapcar 'princ text) 4386 (mapcar 'princ text)
3956 (goto-char (point-min)))) 4387 (goto-char (point-min))))
3957 (funcall ask question)) 4388 (funcall ask question))
3958 (funcall ask question))) 4389 (funcall ask question)))
3959 4390
3973 new one, cloning only the locals having a substring matching the 4404 new one, cloning only the locals having a substring matching the
3974 regexp varstr." 4405 regexp varstr."
3975 (let ((oldbuf (current-buffer))) 4406 (let ((oldbuf (current-buffer)))
3976 (save-excursion 4407 (save-excursion
3977 (set-buffer (generate-new-buffer name)) 4408 (set-buffer (generate-new-buffer name))
3978 (message-clone-locals oldbuf) 4409 (message-clone-locals oldbuf varstr)
3979 (current-buffer)))) 4410 (current-buffer))))
3980 4411
3981 (defun message-clone-locals (buffer) 4412 (defun message-clone-locals (buffer &optional varstr)
3982 "Clone the local variables from BUFFER to the current buffer." 4413 "Clone the local variables from BUFFER to the current buffer."
3983 (let ((locals (save-excursion 4414 (let ((locals (save-excursion
3984 (set-buffer buffer) 4415 (set-buffer buffer)
3985 (buffer-local-variables))) 4416 (buffer-local-variables)))
3986 (regexp "^gnus\\|^nn\\|^message")) 4417 (regexp "^gnus\\|^nn\\|^message\\|^user-mail-address"))
3987 (mapcar 4418 (mapcar
3988 (lambda (local) 4419 (lambda (local)
3989 (when (and (consp local) 4420 (when (and (consp local)
3990 (car local) 4421 (car local)
3991 (string-match regexp (symbol-name (car local)))) 4422 (string-match regexp (symbol-name (car local)))
4423 (or (null varstr)
4424 (string-match varstr (symbol-name (car local)))))
3992 (ignore-errors 4425 (ignore-errors
3993 (set (make-local-variable (car local)) 4426 (set (make-local-variable (car local))
3994 (cdr local))))) 4427 (cdr local)))))
3995 locals))) 4428 locals)))
3996 4429
3997 ;;; Miscellaneous functions 4430 ;;; Miscellaneous functions
3998 4431
3999 ;; stolen (and renamed) from nnheader.el 4432 ;; stolen (and renamed) from nnheader.el
4000 (defun message-replace-chars-in-string (string from to) 4433 (if (fboundp 'subst-char-in-string)
4001 "Replace characters in STRING from FROM to TO." 4434 (defsubst message-replace-chars-in-string (string from to)
4002 (let ((string (substring string 0)) ;Copy string. 4435 (subst-char-in-string from to string))
4003 (len (length string)) 4436 (defun message-replace-chars-in-string (string from to)
4004 (idx 0)) 4437 "Replace characters in STRING from FROM to TO."
4005 ;; Replace all occurrences of FROM with TO. 4438 (let ((string (substring string 0)) ;Copy string.
4006 (while (< idx len) 4439 (len (length string))
4007 (when (= (aref string idx) from) 4440 (idx 0))
4008 (aset string idx to)) 4441 ;; Replace all occurrences of FROM with TO.
4009 (setq idx (1+ idx))) 4442 (while (< idx len)
4010 string)) 4443 (when (= (aref string idx) from)
4444 (aset string idx to))
4445 (setq idx (1+ idx)))
4446 string)))
4447
4448 ;;;
4449 ;;; MIME functions
4450 ;;;
4451
4452 (defvar message-inhibit-body-encoding nil)
4453
4454 (defun message-encode-message-body ()
4455 (unless message-inhibit-body-encoding
4456 (let ((mail-parse-charset (or mail-parse-charset
4457 message-default-charset))
4458 (case-fold-search t)
4459 lines content-type-p)
4460 (message-goto-body)
4461 (save-restriction
4462 (narrow-to-region (point) (point-max))
4463 (let ((new (mml-generate-mime)))
4464 (when new
4465 (delete-region (point-min) (point-max))
4466 (insert new)
4467 (goto-char (point-min))
4468 (if (eq (aref new 0) ?\n)
4469 (delete-char 1)
4470 (search-forward "\n\n")
4471 (setq lines (buffer-substring (point-min) (1- (point))))
4472 (delete-region (point-min) (point))))))
4473 (save-restriction
4474 (message-narrow-to-headers-or-head)
4475 (message-remove-header "Mime-Version")
4476 (goto-char (point-max))
4477 (insert "MIME-Version: 1.0\n")
4478 (when lines
4479 (insert lines))
4480 (setq content-type-p
4481 (re-search-backward "^Content-Type:" nil t)))
4482 (save-restriction
4483 (message-narrow-to-headers-or-head)
4484 (message-remove-first-header "Content-Type")
4485 (message-remove-first-header "Content-Transfer-Encoding"))
4486 ;; We always make sure that the message has a Content-Type header.
4487 ;; This is because some broken MTAs and MUAs get awfully confused
4488 ;; when confronted with a message with a MIME-Version header and
4489 ;; without a Content-Type header. For instance, Solaris'
4490 ;; /usr/bin/mail.
4491 (unless content-type-p
4492 (goto-char (point-min))
4493 (re-search-forward "^MIME-Version:")
4494 (forward-line 1)
4495 (insert "Content-Type: text/plain; charset=us-ascii\n")))))
4496
4497 (defun message-read-from-minibuffer (prompt)
4498 "Read from the minibuffer while providing abbrev expansion."
4499 (if (fboundp 'mail-abbrevs-setup)
4500 (let ((mail-abbrev-mode-regexp "")
4501 (minibuffer-setup-hook 'mail-abbrevs-setup))
4502 (read-from-minibuffer prompt))
4503 (let ((minibuffer-setup-hook 'mail-abbrev-minibuffer-setup-hook))
4504 (read-string prompt))))
4505
4506 (provide 'message)
4011 4507
4012 (run-hooks 'message-load-hook) 4508 (run-hooks 'message-load-hook)
4013 4509
4014 (provide 'message) 4510 ;; Local Variables:
4511 ;; coding: iso-8859-1
4512 ;; End:
4015 4513
4016 ;;; message.el ends here 4514 ;;; message.el ends here