Mercurial > emacs
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 |