Mercurial > hg > xemacs-beta
comparison lisp/gnus/message.el @ 70:131b0175ea99 r20-0b30
Import from CVS: tag r20-0b30
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:02:59 +0200 |
parents | 8b8b7f3559a2 |
children | 0d2f883870bc |
comparison
equal
deleted
inserted
replaced
69:804d1389bcd6 | 70:131b0175ea99 |
---|---|
1 ;;; message.el --- composing mail and news messages | 1 ;;; message.el --- composing mail and news messages |
2 ;; Copyright (C) 1996,97 Free Software Foundation, Inc. | 2 ;; Copyright (C) 1996 Free Software Foundation, Inc. |
3 | 3 |
4 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no> | 4 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no> |
5 ;; Keywords: mail, news | 5 ;; Keywords: mail, news |
6 | 6 |
7 ;; This file is part of GNU Emacs. | 7 ;; This file is part of GNU Emacs. |
27 ;; consists mainly of large chunks of code from the sendmail.el, | 27 ;; consists mainly of large chunks of code from the sendmail.el, |
28 ;; gnus-msg.el and rnewspost.el files. | 28 ;; gnus-msg.el and rnewspost.el files. |
29 | 29 |
30 ;;; Code: | 30 ;;; Code: |
31 | 31 |
32 (require 'cl) | 32 (eval-when-compile |
33 (require 'cl)) | |
33 (require 'mailheader) | 34 (require 'mailheader) |
34 (require 'rmail) | 35 (require 'rmail) |
35 (require 'nnheader) | 36 (require 'nnheader) |
36 (require 'timezone) | 37 (require 'timezone) |
37 (require 'easymenu) | 38 (require 'easymenu) |
38 (require 'custom) | |
39 (if (string-match "XEmacs\\|Lucid" emacs-version) | 39 (if (string-match "XEmacs\\|Lucid" emacs-version) |
40 (require 'mail-abbrevs) | 40 (require 'mail-abbrevs) |
41 (require 'mailabbrev)) | 41 (require 'mailabbrev)) |
42 | 42 |
43 (defgroup message '((user-mail-address custom-variable) | 43 (defvar message-directory "~/Mail/" |
44 (user-full-name custom-variable)) | 44 "*Directory from which all other mail file variables are derived.") |
45 "Mail and news message composing." | 45 |
46 :link '(custom-manual "(message)Top") | 46 (defvar message-max-buffers 10 |
47 :group 'mail | 47 "*How many buffers to keep before starting to kill them off.") |
48 :group 'news) | 48 |
49 | 49 (defvar message-send-rename-function nil |
50 (put 'user-mail-address 'custom-type 'string) | 50 "Function called to rename the buffer after sending it.") |
51 (put 'user-full-name 'custom-type 'string) | 51 |
52 | 52 ;;;###autoload |
53 (defgroup message-various nil | 53 (defvar message-fcc-handler-function 'rmail-output |
54 "Various Message Variables" | |
55 :link '(custom-manual "(message)Various Message Variables") | |
56 :group 'message) | |
57 | |
58 (defgroup message-buffers nil | |
59 "Message Buffers" | |
60 :link '(custom-manual "(message)Message Buffers") | |
61 :group 'message) | |
62 | |
63 (defgroup message-sending nil | |
64 "Message Sending" | |
65 :link '(custom-manual "(message)Sending Variables") | |
66 :group 'message) | |
67 | |
68 (defgroup message-interface nil | |
69 "Message Interface" | |
70 :link '(custom-manual "(message)Interface") | |
71 :group 'message) | |
72 | |
73 (defgroup message-forwarding nil | |
74 "Message Forwarding" | |
75 :link '(custom-manual "(message)Forwarding") | |
76 :group 'message-interface) | |
77 | |
78 (defgroup message-insertion nil | |
79 "Message Insertion" | |
80 :link '(custom-manual "(message)Insertion") | |
81 :group 'message) | |
82 | |
83 (defgroup message-headers nil | |
84 "Message Headers" | |
85 :link '(custom-manual "(message)Message Headers") | |
86 :group 'message) | |
87 | |
88 (defgroup message-news nil | |
89 "Composing News Messages" | |
90 :group 'message) | |
91 | |
92 (defgroup message-mail nil | |
93 "Composing Mail Messages" | |
94 :group 'message) | |
95 | |
96 (defgroup message-faces nil | |
97 "Faces used for message composing." | |
98 :group 'message | |
99 :group 'faces) | |
100 | |
101 (defcustom message-directory "~/Mail/" | |
102 "*Directory from which all other mail file variables are derived." | |
103 :group 'message-various | |
104 :type 'directory) | |
105 | |
106 (defcustom message-max-buffers 10 | |
107 "*How many buffers to keep before starting to kill them off." | |
108 :group 'message-buffers | |
109 :type 'integer) | |
110 | |
111 (defcustom message-send-rename-function nil | |
112 "Function called to rename the buffer after sending it." | |
113 :group 'message-buffers | |
114 :type 'function) | |
115 | |
116 (defcustom message-fcc-handler-function 'message-output | |
117 "*A function called to save outgoing articles. | 54 "*A function called to save outgoing articles. |
118 This function will be called with the name of the file to store the | 55 This function will be called with the name of the file to store the |
119 article in. The default function is `message-output' which saves in Unix | 56 article in. The default function is `rmail-output' which saves in Unix |
120 mailbox format." | 57 mailbox format.") |
121 :type '(radio (function-item message-output) | 58 |
122 (function :tag "Other")) | 59 ;;;###autoload |
123 :group 'message-sending) | 60 (defvar message-courtesy-message |
124 | 61 "The following message is a courtesy copy of an article\nthat has been posted as well.\n\n" |
125 (defcustom message-courtesy-message | |
126 "The following message is a courtesy copy of an article\nthat has been posted to %s as well.\n\n" | |
127 "*This is inserted at the start of a mailed copy of a posted message. | 62 "*This is inserted at the start of a mailed copy of a posted message. |
128 If the string contains the format spec \"%s\", the Newsgroups | 63 If this variable is nil, no such courtesy message will be added.") |
129 the article has been posted to will be inserted there. | 64 |
130 If this variable is nil, no such courtesy message will be added." | 65 ;;;###autoload |
131 :group 'message-sending | 66 (defvar message-ignored-bounced-headers "^\\(Received\\|Return-Path\\):" |
132 :type 'string) | 67 "*Regexp that matches headers to be removed in resent bounced mail.") |
133 | 68 |
134 (defcustom message-ignored-bounced-headers "^\\(Received\\|Return-Path\\):" | 69 ;;;###autoload |
135 "*Regexp that matches headers to be removed in resent bounced mail." | 70 (defvar message-from-style 'default |
136 :group 'message-interface | |
137 :type 'regexp) | |
138 | |
139 ;;;###autoload | |
140 (defcustom message-from-style 'default | |
141 "*Specifies how \"From\" headers look. | 71 "*Specifies how \"From\" headers look. |
142 | 72 |
143 If `nil', they contain just the return address like: | 73 If `nil', they contain just the return address like: |
144 king@grassland.com | 74 king@grassland.com |
145 If `parens', they look like: | 75 If `parens', they look like: |
146 king@grassland.com (Elvis Parsley) | 76 king@grassland.com (Elvis Parsley) |
147 If `angles', they look like: | 77 If `angles', they look like: |
148 Elvis Parsley <king@grassland.com> | 78 Elvis Parsley <king@grassland.com> |
149 | 79 |
150 Otherwise, most addresses look like `angles', but they look like | 80 Otherwise, most addresses look like `angles', but they look like |
151 `parens' if `angles' would need quoting and `parens' would not." | 81 `parens' if `angles' would need quoting and `parens' would not.") |
152 :type '(choice (const :tag "simple" nil) | 82 |
153 (const parens) | 83 ;;;###autoload |
154 (const angles) | 84 (defvar message-syntax-checks nil |
155 (const default)) | |
156 :group 'message-headers) | |
157 | |
158 (defcustom message-syntax-checks nil | |
159 ;; Guess this one shouldn't be easy to customize... | |
160 "Controls what syntax checks should not be performed on outgoing posts. | 85 "Controls what syntax checks should not be performed on outgoing posts. |
161 To disable checking of long signatures, for instance, add | 86 To disable checking of long signatures, for instance, add |
162 `(signature . disabled)' to this list. | 87 `(signature . disabled)' to this list. |
163 | 88 |
164 Don't touch this variable unless you really know what you're doing. | 89 Don't touch this variable unless you really know what you're doing. |
165 | 90 |
166 Checks include subject-cmsg multiple-headers sendsys message-id from | 91 Checks include subject-cmsg multiple-headers sendsys message-id from |
167 long-lines control-chars size new-text redirected-followup signature | 92 long-lines control-chars size new-text redirected-followup signature |
168 approved sender empty empty-headers message-id from subject | 93 approved sender empty empty-headers message-id from subject.") |
169 shorten-followup-to existing-newsgroups." | 94 |
170 :group 'message-news) | 95 ;;;###autoload |
171 | 96 (defvar message-required-news-headers |
172 (defcustom message-required-news-headers | 97 '(From Newsgroups Subject Date Message-ID |
173 '(From Newsgroups Subject Date Message-ID | 98 (optional . Organization) Lines |
174 (optional . Organization) Lines | |
175 (optional . X-Newsreader)) | 99 (optional . X-Newsreader)) |
176 "Headers to be generated or prompted for when posting an article. | 100 "*Headers to be generated or prompted for when posting an article. |
177 RFC977 and RFC1036 require From, Date, Newsgroups, Subject, | 101 RFC977 and RFC1036 require From, Date, Newsgroups, Subject, |
178 Message-ID. Organization, Lines, In-Reply-To, Expires, and | 102 Message-ID. Organization, Lines, In-Reply-To, Expires, and |
179 X-Newsreader are optional. If don't you want message to insert some | 103 X-Newsreader are optional. If don't you want message to insert some |
180 header, remove it from this list." | 104 header, remove it from this list.") |
181 :group 'message-news | 105 |
182 :group 'message-headers | 106 ;;;###autoload |
183 :type '(repeat sexp)) | 107 (defvar message-required-mail-headers |
184 | |
185 (defcustom message-required-mail-headers | |
186 '(From Subject Date (optional . In-Reply-To) Message-ID Lines | 108 '(From Subject Date (optional . In-Reply-To) Message-ID Lines |
187 (optional . X-Mailer)) | 109 (optional . X-Mailer)) |
188 "Headers to be generated or prompted for when mailing a message. | 110 "*Headers to be generated or prompted for when mailing a message. |
189 RFC822 required that From, Date, To, Subject and Message-ID be | 111 RFC822 required that From, Date, To, Subject and Message-ID be |
190 included. Organization, Lines and X-Mailer are optional." | 112 included. Organization, Lines and X-Mailer are optional.") |
191 :group 'message-mail | 113 |
192 :group 'message-headers | 114 ;;;###autoload |
193 :type '(repeat sexp)) | 115 (defvar message-deletable-headers '(Message-ID Date) |
194 | 116 "*Headers to be deleted if they already exist and were generated by message previously.") |
195 (defcustom message-deletable-headers '(Message-ID Date Lines) | 117 |
196 "Headers to be deleted if they already exist and were generated by message previously." | 118 ;;;###autoload |
197 :group 'message-headers | 119 (defvar message-ignored-news-headers |
198 :type 'sexp) | 120 "^NNTP-Posting-Host:\\|^Xref:\\|^Bcc:\\|^Gcc:\\|^Fcc:" |
199 | 121 "*Regexp of headers to be removed unconditionally before posting.") |
200 (defcustom message-ignored-news-headers | 122 |
201 "^NNTP-Posting-Host:\\|^Xref:\\|^Bcc:\\|^Gcc:\\|^Fcc:\\|^Resent-Fcc:" | 123 ;;;###autoload |
202 "*Regexp of headers to be removed unconditionally before posting." | 124 (defvar message-ignored-mail-headers "^Gcc:\\|^Fcc:" |
203 :group 'message-news | 125 "*Regexp of headers to be removed unconditionally before mailing.") |
204 :group 'message-headers | 126 |
205 :type 'regexp) | 127 ;;;###autoload |
206 | 128 (defvar message-ignored-supersedes-headers "^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|^Received:\\|^X-From-Line:\\|Return-Path:\\|^Supersedes:" |
207 (defcustom message-ignored-mail-headers "^Gcc:\\|^Fcc:\\|^Resent-Fcc:" | |
208 "*Regexp of headers to be removed unconditionally before mailing." | |
209 :group 'message-mail | |
210 :group 'message-headers | |
211 :type 'regexp) | |
212 | |
213 (defcustom message-ignored-supersedes-headers "^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|^Received:\\|^X-From-Line:\\|Return-Path:\\|^Supersedes:" | |
214 "*Header lines matching this regexp will be deleted before posting. | 129 "*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 | 130 It's best to delete old Path and Date headers before posting to avoid |
216 any confusion." | 131 any confusion.") |
217 :group 'message-interface | 132 |
218 :type 'regexp) | 133 ;;;###autoload |
219 | 134 (defvar message-signature-separator "^-- *$" |
220 ;;;###autoload | 135 "Regexp matching the signature separator.") |
221 (defcustom message-signature-separator "^-- *$" | 136 |
222 "Regexp matching the signature separator." | 137 ;;;###autoload |
223 :type 'regexp | 138 (defvar message-interactive nil |
224 :group 'message-various) | |
225 | |
226 (defcustom message-elide-elipsis "\n[...]\n\n" | |
227 "*The string which is inserted for elided text.") | |
228 | |
229 (defcustom message-interactive nil | |
230 "Non-nil means when sending a message wait for and display errors. | 139 "Non-nil means when sending a message wait for and display errors. |
231 nil means let mailer mail back a message to report errors." | 140 nil means let mailer mail back a message to report errors.") |
232 :group 'message-sending | 141 |
233 :group 'message-mail | 142 ;;;###autoload |
234 :type 'boolean) | 143 (defvar message-generate-new-buffers t |
235 | |
236 (defcustom message-generate-new-buffers t | |
237 "*Non-nil means that a new message buffer will be created whenever `mail-setup' is called. | 144 "*Non-nil means that a new message buffer will be created whenever `mail-setup' is called. |
238 If this is a function, call that function with three parameters: The type, | 145 If this is a function, call that function with three parameters: The type, |
239 the to address and the group name. (Any of these may be nil.) The function | 146 the to address and the group name. (Any of these may be nil.) The function |
240 should return the new buffer name." | 147 should return the new buffer name.") |
241 :group 'message-buffers | 148 |
242 :type '(choice (const :tag "off" nil) | 149 ;;;###autoload |
243 (const :tag "on" t) | 150 (defvar message-kill-buffer-on-exit nil |
244 (function fun))) | 151 "*Non-nil means that the message buffer will be killed after sending a message.") |
245 | |
246 (defcustom message-kill-buffer-on-exit nil | |
247 "*Non-nil means that the message buffer will be killed after sending a message." | |
248 :group 'message-buffers | |
249 :type 'boolean) | |
250 | 152 |
251 (defvar gnus-local-organization) | 153 (defvar gnus-local-organization) |
252 (defcustom message-user-organization | 154 (defvar message-user-organization |
253 (or (and (boundp 'gnus-local-organization) | 155 (or (and (boundp 'gnus-local-organization) |
254 (stringp gnus-local-organization) | |
255 gnus-local-organization) | 156 gnus-local-organization) |
256 (getenv "ORGANIZATION") | 157 (getenv "ORGANIZATION") |
257 t) | 158 t) |
258 "*String to be used as an Organization header. | 159 "*String to be used as an Organization header. |
259 If t, use `message-user-organization-file'." | 160 If t, use `message-user-organization-file'.") |
260 :group 'message-headers | 161 |
261 :type '(choice string | 162 ;;;###autoload |
262 (const :tag "consult file" t))) | 163 (defvar message-user-organization-file "/usr/lib/news/organization" |
263 | 164 "*Local news organization file.") |
264 ;;;###autoload | 165 |
265 (defcustom message-user-organization-file "/usr/lib/news/organization" | 166 (defvar message-autosave-directory "~/" |
266 "*Local news organization file." | |
267 :type 'file | |
268 :group 'message-headers) | |
269 | |
270 (defcustom message-autosave-directory "~/" | |
271 ; (concat (file-name-as-directory message-directory) "drafts/") | 167 ; (concat (file-name-as-directory message-directory) "drafts/") |
272 "*Directory where message autosaves buffers. | 168 "*Directory where message autosaves buffers. |
273 If nil, message won't autosave." | 169 If nil, message won't autosave.") |
274 :group 'message-buffers | 170 |
275 :type 'directory) | 171 (defvar message-forward-start-separator |
276 | |
277 (defcustom message-forward-start-separator | |
278 "------- Start of forwarded message -------\n" | 172 "------- Start of forwarded message -------\n" |
279 "*Delimiter inserted before forwarded messages." | 173 "*Delimiter inserted before forwarded messages.") |
280 :group 'message-forwarding | 174 |
281 :type 'string) | 175 (defvar message-forward-end-separator |
282 | |
283 (defcustom message-forward-end-separator | |
284 "------- End of forwarded message -------\n" | 176 "------- End of forwarded message -------\n" |
285 "*Delimiter inserted after forwarded messages." | 177 "*Delimiter inserted after forwarded messages.") |
286 :group 'message-forwarding | 178 |
287 :type 'string) | 179 ;;;###autoload |
288 | 180 (defvar message-signature-before-forwarded-message t |
289 (defcustom message-signature-before-forwarded-message t | 181 "*If non-nil, put the signature before any included forwarded message.") |
290 "*If non-nil, put the signature before any included forwarded message." | 182 |
291 :group 'message-forwarding | 183 ;;;###autoload |
292 :type 'boolean) | 184 (defvar message-included-forward-headers |
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:" | 185 "^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:" |
296 "*Regexp matching headers to be included in forwarded messages." | 186 "*Regexp matching headers to be included in forwarded messages.") |
297 :group 'message-forwarding | 187 |
298 :type 'regexp) | 188 ;;;###autoload |
299 | 189 (defvar message-ignored-resent-headers "^Return-receipt" |
300 (defcustom message-ignored-resent-headers "^Return-receipt" | 190 "*All headers that match this regexp will be deleted when resending a message.") |
301 "*All headers that match this regexp will be deleted when resending a message." | 191 |
302 :group 'message-interface | 192 ;;;###autoload |
303 :type 'regexp) | 193 (defvar message-ignored-cited-headers "." |
304 | 194 "Delete these headers from the messages you yank.") |
305 (defcustom message-ignored-cited-headers "." | |
306 "*Delete these headers from the messages you yank." | |
307 :group 'message-insertion | |
308 :type 'regexp) | |
309 | |
310 (defcustom message-cancel-message "I am canceling my own article." | |
311 "Message to be inserted in the cancel message." | |
312 :group 'message-interface | |
313 :type 'string) | |
314 | 195 |
315 ;; Useful to set in site-init.el | 196 ;; Useful to set in site-init.el |
316 ;;;###autoload | 197 ;;;###autoload |
317 (defcustom message-send-mail-function 'message-send-mail-with-sendmail | 198 (defvar message-send-mail-function 'message-send-mail-with-sendmail |
318 "Function to call to send the current buffer as mail. | 199 "Function to call to send the current buffer as mail. |
319 The headers should be delimited by a line whose contents match the | 200 The headers should be delimited by a line whose contents match the |
320 variable `mail-header-separator'. | 201 variable `mail-header-separator'. |
321 | 202 |
322 Legal values include `message-send-mail-with-sendmail' (the default), | 203 Legal values include `message-send-mail-with-mh' and |
323 `message-send-mail-with-mh' and `message-send-mail-with-qmail'." | 204 `message-send-mail-with-sendmail', which is the default.") |
324 :type '(radio (function-item message-send-mail-with-sendmail) | 205 |
325 (function-item message-send-mail-with-mh) | 206 ;;;###autoload |
326 (function-item message-send-mail-with-qmail) | 207 (defvar message-send-news-function 'message-send-news |
327 (function :tag "Other")) | |
328 :group 'message-sending | |
329 :group 'message-mail) | |
330 | |
331 (defcustom message-send-news-function 'message-send-news | |
332 "Function to call to send the current buffer as news. | 208 "Function to call to send the current buffer as news. |
333 The headers should be delimited by a line whose contents match the | 209 The headers should be delimited by a line whose contents match the |
334 variable `mail-header-separator'." | 210 variable `mail-header-separator'.") |
335 :group 'message-sending | 211 |
336 :group 'message-news | 212 ;;;###autoload |
337 :type 'function) | 213 (defvar message-reply-to-function nil |
338 | |
339 (defcustom message-reply-to-function nil | |
340 "Function that should return a list of headers. | 214 "Function that should return a list of headers. |
341 This function should pick out addresses from the To, Cc, and From headers | 215 This function should pick out addresses from the To, Cc, and From headers |
342 and respond with new To and Cc headers." | 216 and respond with new To and Cc headers.") |
343 :group 'message-interface | 217 |
344 :type 'function) | 218 ;;;###autoload |
345 | 219 (defvar message-wide-reply-to-function nil |
346 (defcustom message-wide-reply-to-function nil | |
347 "Function that should return a list of headers. | 220 "Function that should return a list of headers. |
348 This function should pick out addresses from the To, Cc, and From headers | 221 This function should pick out addresses from the To, Cc, and From headers |
349 and respond with new To and Cc headers." | 222 and respond with new To and Cc headers.") |
350 :group 'message-interface | 223 |
351 :type 'function) | 224 ;;;###autoload |
352 | 225 (defvar message-followup-to-function nil |
353 (defcustom message-followup-to-function nil | |
354 "Function that should return a list of headers. | 226 "Function that should return a list of headers. |
355 This function should pick out addresses from the To, Cc, and From headers | 227 This function should pick out addresses from the To, Cc, and From headers |
356 and respond with new To and Cc headers." | 228 and respond with new To and Cc headers.") |
357 :group 'message-interface | 229 |
358 :type 'function) | 230 ;;;###autoload |
359 | 231 (defvar message-use-followup-to 'ask |
360 (defcustom message-use-followup-to 'ask | |
361 "*Specifies what to do with Followup-To header. | 232 "*Specifies what to do with Followup-To header. |
362 If nil, always ignore the header. If it is t, use its value, but | 233 If nil, ignore the header. If it is t, use its value, but query before |
363 query before using the \"poster\" value. If it is the symbol `ask', | 234 using the \"poster\" value. If it is the symbol `ask', query the user |
364 always query the user whether to use the value. If it is the symbol | 235 whether to ignore the \"poster\" value. If it is the symbol `use', |
365 `use', always use the value." | 236 always use the value.") |
366 :group 'message-interface | |
367 :type '(choice (const :tag "ignore" nil) | |
368 (const use) | |
369 (const ask))) | |
370 | |
371 ;; stuff relating to broken sendmail in MMDF | |
372 (defcustom message-sendmail-f-is-evil nil | |
373 "*Non-nil means that \"-f username\" should not be added to the sendmail | |
374 command line, because it is even more evil than leaving it out." | |
375 :group 'message-sending | |
376 :type 'boolean) | |
377 | |
378 ;; qmail-related stuff | |
379 (defcustom message-qmail-inject-program "/var/qmail/bin/qmail-inject" | |
380 "Location of the qmail-inject program." | |
381 :group 'message-sending | |
382 :type 'file) | |
383 | |
384 (defcustom message-qmail-inject-args nil | |
385 "Arguments passed to qmail-inject programs. | |
386 This should be a list of strings, one string for each argument. | |
387 | |
388 For e.g., if you wish to set the envelope sender address so that bounces | |
389 go to the right place or to deal with listserv's usage of that address, you | |
390 might set this variable to '(\"-f\" \"you@some.where\")." | |
391 :group 'message-sending | |
392 :type '(repeat string)) | |
393 | 237 |
394 (defvar gnus-post-method) | 238 (defvar gnus-post-method) |
395 (defvar gnus-select-method) | 239 (defvar gnus-select-method) |
396 (defcustom message-post-method | 240 ;;;###autoload |
241 (defvar message-post-method | |
397 (cond ((and (boundp 'gnus-post-method) | 242 (cond ((and (boundp 'gnus-post-method) |
398 gnus-post-method) | 243 gnus-post-method) |
399 gnus-post-method) | 244 gnus-post-method) |
400 ((boundp 'gnus-select-method) | 245 ((boundp 'gnus-select-method) |
401 gnus-select-method) | 246 gnus-select-method) |
402 (t '(nnspool ""))) | 247 (t '(nnspool ""))) |
403 "Method used to post news." | 248 "Method used to post news.") |
404 :group 'message-news | 249 |
405 :group 'message-sending | 250 ;;;###autoload |
406 ;; This should be the `gnus-select-method' widget, but that might | 251 (defvar message-generate-headers-first nil |
407 ;; create a dependence to `gnus.el'. | 252 "*If non-nil, generate all possible headers before composing.") |
408 :type 'sexp) | 253 |
409 | 254 (defvar message-setup-hook nil |
410 (defcustom message-generate-headers-first nil | |
411 "*If non-nil, generate all possible headers before composing." | |
412 :group 'message-headers | |
413 :type 'boolean) | |
414 | |
415 (defcustom message-setup-hook nil | |
416 "Normal hook, run each time a new outgoing message is initialized. | 255 "Normal hook, run each time a new outgoing message is initialized. |
417 The function `message-setup' runs this hook." | 256 The function `message-setup' runs this hook.") |
418 :group 'message-various | 257 |
419 :type 'hook) | 258 (defvar message-signature-setup-hook nil |
420 | |
421 (defcustom message-signature-setup-hook nil | |
422 "Normal hook, run each time a new outgoing message is initialized. | 259 "Normal hook, run each time a new outgoing message is initialized. |
423 It is run after the headers have been inserted and before | 260 It is run after the headers have been inserted and before |
424 the signature is inserted." | 261 the signature is inserted.") |
425 :group 'message-various | 262 |
426 :type 'hook) | 263 (defvar message-mode-hook nil |
427 | 264 "Hook run in message mode buffers.") |
428 (defcustom message-mode-hook nil | 265 |
429 "Hook run in message mode buffers." | 266 (defvar message-header-hook nil |
430 :group 'message-various | 267 "Hook run in a message mode buffer narrowed to the headers.") |
431 :type 'hook) | 268 |
432 | 269 (defvar message-header-setup-hook nil |
433 (defcustom message-header-hook nil | 270 "Hook called narrowed to the headers when setting up a message buffer.") |
434 "Hook run in a message mode buffer narrowed to the headers." | 271 |
435 :group 'message-various | 272 ;;;###autoload |
436 :type 'hook) | 273 (defvar message-citation-line-function 'message-insert-citation-line |
437 | 274 "*Function called to insert the \"Whomever writes:\" line.") |
438 (defcustom message-header-setup-hook nil | 275 |
439 "Hook called narrowed to the headers when setting up a message | 276 ;;;###autoload |
440 buffer." | 277 (defvar message-yank-prefix "> " |
441 :group 'message-various | |
442 :type 'hook) | |
443 | |
444 ;;;###autoload | |
445 (defcustom message-citation-line-function 'message-insert-citation-line | |
446 "*Function called to insert the \"Whomever writes:\" line." | |
447 :type 'function | |
448 :group 'message-insertion) | |
449 | |
450 ;;;###autoload | |
451 (defcustom message-yank-prefix "> " | |
452 "*Prefix inserted on the lines of yanked messages. | 278 "*Prefix inserted on the lines of yanked messages. |
453 nil means use indentation." | 279 nil means use indentation.") |
454 :type 'string | 280 |
455 :group 'message-insertion) | 281 (defvar message-indentation-spaces 3 |
456 | |
457 (defcustom message-indentation-spaces 3 | |
458 "*Number of spaces to insert at the beginning of each cited line. | 282 "*Number of spaces to insert at the beginning of each cited line. |
459 Used by `message-yank-original' via `message-yank-cite'." | 283 Used by `message-yank-original' via `message-yank-cite'.") |
460 :group 'message-insertion | 284 |
461 :type 'integer) | 285 ;;;###autoload |
462 | 286 (defvar message-cite-function 'message-cite-original |
463 ;;;###autoload | 287 "*Function for citing an original message.") |
464 (defcustom message-cite-function | 288 |
465 (if (and (boundp 'mail-citation-hook) | 289 ;;;###autoload |
466 mail-citation-hook) | 290 (defvar message-indent-citation-function 'message-indent-citation |
467 mail-citation-hook | |
468 'message-cite-original) | |
469 "*Function for citing an original message." | |
470 :type '(radio (function-item message-cite-original) | |
471 (function-item sc-cite-original) | |
472 (function :tag "Other")) | |
473 :group 'message-insertion) | |
474 | |
475 ;;;###autoload | |
476 (defcustom message-indent-citation-function 'message-indent-citation | |
477 "*Function for modifying a citation just inserted in the mail buffer. | 291 "*Function for modifying a citation just inserted in the mail buffer. |
478 This can also be a list of functions. Each function can find the | 292 This can also be a list of functions. Each function can find the |
479 citation between (point) and (mark t). And each function should leave | 293 citation between (point) and (mark t). And each function should leave |
480 point and mark around the citation text as modified." | 294 point and mark around the citation text as modified.") |
481 :type 'function | |
482 :group 'message-insertion) | |
483 | 295 |
484 (defvar message-abbrevs-loaded nil) | 296 (defvar message-abbrevs-loaded nil) |
485 | 297 |
486 ;;;###autoload | 298 ;;;###autoload |
487 (defcustom message-signature t | 299 (defvar message-signature t |
488 "*String to be inserted at the end of the message buffer. | 300 "*String to be inserted at the end of the message buffer. |
489 If t, the `message-signature-file' file will be inserted instead. | 301 If t, the `message-signature-file' file will be inserted instead. |
490 If a function, the result from the function will be used instead. | 302 If a function, the result from the function will be used instead. |
491 If a form, the result from the form will be used instead." | 303 If a form, the result from the form will be used instead.") |
492 :type 'sexp | 304 |
493 :group 'message-insertion) | 305 ;;;###autoload |
494 | 306 (defvar message-signature-file "~/.signature" |
495 ;;;###autoload | 307 "*File containing the text inserted at end of message. buffer.") |
496 (defcustom message-signature-file "~/.signature" | 308 |
497 "*File containing the text inserted at end of message buffer." | 309 (defvar message-distribution-function nil |
498 :type 'file | 310 "*Function called to return a Distribution header.") |
499 :group 'message-insertion) | 311 |
500 | 312 (defvar message-expires 14 |
501 (defcustom message-distribution-function nil | 313 "*Number of days before your article expires.") |
502 "*Function called to return a Distribution header." | 314 |
503 :group 'message-news | 315 (defvar message-user-path nil |
504 :group 'message-headers | |
505 :type 'function) | |
506 | |
507 (defcustom message-expires 14 | |
508 "Number of days before your article expires." | |
509 :group 'message-news | |
510 :group 'message-headers | |
511 :link '(custom-manual "(message)News Headers") | |
512 :type 'integer) | |
513 | |
514 (defcustom message-user-path nil | |
515 "If nil, use the NNTP server name in the Path header. | 316 "If nil, use the NNTP server name in the Path header. |
516 If stringp, use this; if non-nil, use no host name (user name only)." | 317 If stringp, use this; if non-nil, use no host name (user name only).") |
517 :group 'message-news | |
518 :group 'message-headers | |
519 :link '(custom-manual "(message)News Headers") | |
520 :type '(choice (const :tag "nntp" nil) | |
521 (string :tag "name") | |
522 (sexp :tag "none" :format "%t" t))) | |
523 | 318 |
524 (defvar message-reply-buffer nil) | 319 (defvar message-reply-buffer nil) |
525 (defvar message-reply-headers nil) | 320 (defvar message-reply-headers nil) |
526 (defvar message-newsreader nil) | 321 (defvar message-newsreader nil) |
527 (defvar message-mailer nil) | 322 (defvar message-mailer nil) |
534 (defvar message-kill-actions nil | 329 (defvar message-kill-actions nil |
535 "A list of actions to be performed before killing a message buffer.") | 330 "A list of actions to be performed before killing a message buffer.") |
536 (defvar message-postpone-actions nil | 331 (defvar message-postpone-actions nil |
537 "A list of actions to be performed after postponing a message.") | 332 "A list of actions to be performed after postponing a message.") |
538 | 333 |
539 (defcustom message-default-headers "" | 334 ;;;###autoload |
335 (defvar message-default-headers nil | |
540 "*A string containing header lines to be inserted in outgoing messages. | 336 "*A string containing header lines to be inserted in outgoing messages. |
541 It is inserted before you edit the message, so you can edit or delete | 337 It is inserted before you edit the message, so you can edit or delete |
542 these lines." | 338 these lines.") |
543 :group 'message-headers | 339 |
544 :type 'string) | 340 ;;;###autoload |
545 | 341 (defvar message-default-mail-headers nil |
546 (defcustom message-default-mail-headers "" | 342 "*A string of header lines to be inserted in outgoing mails.") |
547 "*A string of header lines to be inserted in outgoing mails." | 343 |
548 :group 'message-headers | 344 ;;;###autoload |
549 :group 'message-mail | 345 (defvar message-default-news-headers nil |
550 :type 'string) | 346 "*A string of header lines to be inserted in outgoing news articles.") |
551 | |
552 (defcustom message-default-news-headers "" | |
553 "*A string of header lines to be inserted in outgoing news | |
554 articles." | |
555 :group 'message-headers | |
556 :group 'message-news | |
557 :type 'string) | |
558 | 347 |
559 ;; Note: could use /usr/ucb/mail instead of sendmail; | 348 ;; Note: could use /usr/ucb/mail instead of sendmail; |
560 ;; options -t, and -v if not interactive. | 349 ;; options -t, and -v if not interactive. |
561 (defcustom message-mailer-swallows-blank-line | 350 (defvar message-mailer-swallows-blank-line |
562 (if (and (string-match "sparc-sun-sunos\\(\\'\\|[^5]\\)" | 351 (if (and (string-match "sparc-sun-sunos\\(\\'\\|[^5]\\)" |
563 system-configuration) | 352 system-configuration) |
564 (file-readable-p "/etc/sendmail.cf") | 353 (file-readable-p "/etc/sendmail.cf") |
565 (let ((buffer (get-buffer-create " *temp*"))) | 354 (let ((buffer (get-buffer-create " *temp*"))) |
566 (unwind-protect | 355 (unwind-protect |
567 (save-excursion | 356 (save-excursion |
570 (goto-char (point-min)) | 359 (goto-char (point-min)) |
571 (let ((case-fold-search nil)) | 360 (let ((case-fold-search nil)) |
572 (re-search-forward "^OR\\>" nil t))) | 361 (re-search-forward "^OR\\>" nil t))) |
573 (kill-buffer buffer)))) | 362 (kill-buffer buffer)))) |
574 ;; According to RFC822, "The field-name must be composed of printable | 363 ;; According to RFC822, "The field-name must be composed of printable |
575 ;; ASCII characters (i. e., characters that have decimal values between | 364 ;; ASCII characters (i.e. characters that have decimal values between |
576 ;; 33 and 126, except colon)", i. e., any chars except ctl chars, | 365 ;; 33 and 126, except colon)", i.e. any chars except ctl chars, |
577 ;; space, or colon. | 366 ;; space, or colon. |
578 '(looking-at "[ \t]\\|[][!\"#$%&'()*+,-./0-9;<=>?@A-Z\\\\^_`a-z{|}~]+:")) | 367 '(looking-at "[ \t]\\|[][!\"#$%&'()*+,-./0-9;<=>?@A-Z\\\\^_`a-z{|}~]+:")) |
579 "Set this non-nil if the system's mailer runs the header and body together. | 368 "Set this non-nil if the system's mailer runs the header and body together. |
580 \(This problem exists on Sunos 4 when sendmail is run in remote mode.) | 369 \(This problem exists on Sunos 4 when sendmail is run in remote mode.) |
581 The value should be an expression to test whether the problem will | 370 The value should be an expression to test whether the problem will |
582 actually occur." | 371 actually occur.") |
583 :group 'message-sending | 372 |
584 :type 'sexp) | 373 (defvar message-mode-syntax-table |
585 | |
586 (ignore-errors | |
587 (define-mail-user-agent 'message-user-agent | |
588 'message-mail 'message-send-and-exit | |
589 'message-kill-buffer 'message-send-hook)) | |
590 | |
591 (defvar message-mh-deletable-headers '(Message-ID Date Lines Sender) | |
592 "If non-nil, delete the deletable headers before feeding to mh.") | |
593 | |
594 ;;; Internal variables. | |
595 ;;; Well, not really internal. | |
596 | |
597 (defvar message-mode-syntax-table | |
598 (let ((table (copy-syntax-table text-mode-syntax-table))) | 374 (let ((table (copy-syntax-table text-mode-syntax-table))) |
599 (modify-syntax-entry ?% ". " table) | 375 (modify-syntax-entry ?% ". " table) |
600 table) | 376 table) |
601 "Syntax table used while in Message mode.") | 377 "Syntax table used while in Message mode.") |
602 | 378 |
603 (defvar message-mode-abbrev-table text-mode-abbrev-table | 379 (defvar message-mode-abbrev-table text-mode-abbrev-table |
604 "Abbrev table used in Message mode buffers. | 380 "Abbrev table used in Message mode buffers. |
605 Defaults to `text-mode-abbrev-table'.") | 381 Defaults to `text-mode-abbrev-table'.") |
606 (defgroup message-headers nil | |
607 "Message headers." | |
608 :link '(custom-manual "(message)Variables") | |
609 :group 'message) | |
610 | |
611 (defface message-header-to-face | |
612 '((((class color) | |
613 (background dark)) | |
614 (:foreground "green2" :bold t)) | |
615 (((class color) | |
616 (background light)) | |
617 (:foreground "MidnightBlue" :bold t)) | |
618 (t | |
619 (:bold t :italic t))) | |
620 "Face used for displaying From headers." | |
621 :group 'message-faces) | |
622 | |
623 (defface message-header-cc-face | |
624 '((((class color) | |
625 (background dark)) | |
626 (:foreground "green4" :bold t)) | |
627 (((class color) | |
628 (background light)) | |
629 (:foreground "MidnightBlue")) | |
630 (t | |
631 (:bold t))) | |
632 "Face used for displaying Cc headers." | |
633 :group 'message-faces) | |
634 | |
635 (defface message-header-subject-face | |
636 '((((class color) | |
637 (background dark)) | |
638 (:foreground "green3")) | |
639 (((class color) | |
640 (background light)) | |
641 (:foreground "navy blue" :bold t)) | |
642 (t | |
643 (:bold t))) | |
644 "Face used for displaying subject headers." | |
645 :group 'message-faces) | |
646 | |
647 (defface message-header-newsgroups-face | |
648 '((((class color) | |
649 (background dark)) | |
650 (:foreground "yellow" :bold t :italic t)) | |
651 (((class color) | |
652 (background light)) | |
653 (:foreground "blue4" :bold t :italic t)) | |
654 (t | |
655 (:bold t :italic t))) | |
656 "Face used for displaying newsgroups headers." | |
657 :group 'message-faces) | |
658 | |
659 (defface message-header-other-face | |
660 '((((class color) | |
661 (background dark)) | |
662 (:foreground "red4")) | |
663 (((class color) | |
664 (background light)) | |
665 (:foreground "steel blue")) | |
666 (t | |
667 (:bold t :italic t))) | |
668 "Face used for displaying newsgroups headers." | |
669 :group 'message-faces) | |
670 | |
671 (defface message-header-name-face | |
672 '((((class color) | |
673 (background dark)) | |
674 (:foreground "DarkGreen")) | |
675 (((class color) | |
676 (background light)) | |
677 (:foreground "cornflower blue")) | |
678 (t | |
679 (:bold t))) | |
680 "Face used for displaying header names." | |
681 :group 'message-faces) | |
682 | |
683 (defface message-header-xheader-face | |
684 '((((class color) | |
685 (background dark)) | |
686 (:foreground "blue")) | |
687 (((class color) | |
688 (background light)) | |
689 (:foreground "blue")) | |
690 (t | |
691 (:bold t))) | |
692 "Face used for displaying X-Header headers." | |
693 :group 'message-faces) | |
694 | |
695 (defface message-separator-face | |
696 '((((class color) | |
697 (background dark)) | |
698 (:foreground "blue4")) | |
699 (((class color) | |
700 (background light)) | |
701 (:foreground "brown")) | |
702 (t | |
703 (:bold t))) | |
704 "Face used for displaying the separator." | |
705 :group 'message-faces) | |
706 | |
707 (defface message-cited-text-face | |
708 '((((class color) | |
709 (background dark)) | |
710 (:foreground "red")) | |
711 (((class color) | |
712 (background light)) | |
713 (:foreground "red")) | |
714 (t | |
715 (:bold t))) | |
716 "Face used for displaying cited text names." | |
717 :group 'message-faces) | |
718 | 382 |
719 (defvar message-font-lock-keywords | 383 (defvar message-font-lock-keywords |
720 (let* ((cite-prefix "A-Za-z") | 384 (let* ((cite-prefix "A-Za-z") (cite-suffix (concat cite-prefix "0-9_.@-"))) |
721 (cite-suffix (concat cite-prefix "0-9_.@-")) | 385 (list '("^To:" . font-lock-function-name-face) |
722 (content "[ \t]*\\(.+\\(\n[ \t].*\\)*\\)")) | 386 '("^[GBF]?[Cc][Cc]:\\|^Reply-To:" . font-lock-keyword-face) |
723 `((,(concat "^\\(To:\\)" content) | 387 '("^\\(Subject:\\)[ \t]*\\(.+\\)?" |
724 (1 'message-header-name-face) | 388 (1 font-lock-comment-face) (2 font-lock-type-face nil t)) |
725 (2 'message-header-to-face nil t)) | 389 (list (concat "^\\(" (regexp-quote mail-header-separator) "\\)$") |
726 (,(concat "^\\(^[GBF]?[Cc][Cc]:\\|^Reply-To:\\)" content) | 390 1 'font-lock-comment-face) |
727 (1 'message-header-name-face) | 391 (cons (concat "^[ \t]*" |
728 (2 'message-header-cc-face nil t)) | 392 "\\([" cite-prefix "]+[" cite-suffix "]*\\)?" |
729 (,(concat "^\\(Subject:\\)" content) | 393 "[>|}].*") |
730 (1 'message-header-name-face) | 394 'font-lock-reference-face) |
731 (2 'message-header-subject-face nil t)) | 395 '("^\\(X-[A-Za-z0-9-]+\\|In-reply-to\\):.*" |
732 (,(concat "^\\(Newsgroups:\\|Followup-to:\\)" content) | 396 . font-lock-string-face))) |
733 (1 'message-header-name-face) | |
734 (2 'message-header-newsgroups-face nil t)) | |
735 (,(concat "^\\([^: \n\t]+:\\)" content) | |
736 (1 'message-header-name-face) | |
737 (2 'message-header-other-face nil t)) | |
738 (,(concat "^\\(X-[A-Za-z0-9-]+\\|In-Reply-To\\):" content) | |
739 (1 'message-header-name-face) | |
740 (2 'message-header-name-face)) | |
741 (,(concat "^\\(" (regexp-quote mail-header-separator) "\\)$") | |
742 1 'message-separator-face) | |
743 (,(concat "^[ \t]*" | |
744 "\\([" cite-prefix "]+[" cite-suffix "]*\\)?" | |
745 "[>|}].*") | |
746 (0 'message-cited-text-face)))) | |
747 "Additional expressions to highlight in Message mode.") | 397 "Additional expressions to highlight in Message mode.") |
748 | 398 |
749 (defvar message-face-alist | 399 (defvar message-face-alist |
750 '((bold . bold-region) | 400 '((bold . bold-region) |
751 (underline . underline-region) | 401 (underline . underline-region) |
752 (default . (lambda (b e) | 402 (default . (lambda (b e) |
753 (unbold-region b e) | 403 (unbold-region b e) |
754 (ununderline-region b e)))) | 404 (ununderline-region b e)))) |
755 "Alist of mail and news faces for facemenu. | 405 "Alist of mail and news faces for facemenu. |
756 The cdr of ech entry is a function for applying the face to a region.") | 406 The cdr of ech entry is a function for applying the face to a region.") |
757 | 407 |
758 (defcustom message-send-hook nil | 408 (defvar message-send-hook nil |
759 "Hook run before sending messages." | 409 "Hook run before sending messages.") |
760 :group 'message-various | 410 |
761 :options '(ispell-message) | 411 (defvar message-sent-hook nil |
762 :type 'hook) | 412 "Hook run after sending messages.") |
763 | |
764 (defcustom message-send-mail-hook nil | |
765 "Hook run before sending mail messages." | |
766 :group 'message-various | |
767 :type 'hook) | |
768 | |
769 (defcustom message-send-news-hook nil | |
770 "Hook run before sending news messages." | |
771 :group 'message-various | |
772 :type 'hook) | |
773 | |
774 (defcustom message-sent-hook nil | |
775 "Hook run after sending messages." | |
776 :group 'message-various | |
777 :type 'hook) | |
778 | 413 |
779 ;;; Internal variables. | 414 ;;; Internal variables. |
780 | 415 |
781 (defvar message-buffer-list nil) | 416 (defvar message-buffer-list nil) |
782 (defvar message-this-is-news nil) | |
783 (defvar message-this-is-mail nil) | |
784 | |
785 ;; Byte-compiler warning | |
786 (defvar gnus-active-hashtb) | |
787 (defvar gnus-read-active-file) | |
788 | 417 |
789 ;;; Regexp matching the delimiter of messages in UNIX mail format | 418 ;;; Regexp matching the delimiter of messages in UNIX mail format |
790 ;;; (UNIX From lines), minus the initial ^. | 419 ;;; (UNIX From lines), minus the initial ^. |
791 (defvar message-unix-mail-delimiter | 420 (defvar message-unix-mail-delimiter |
792 (let ((time-zone-regexp | 421 (let ((time-zone-regexp |
793 (concat "\\([A-Z]?[A-Z]?[A-Z][A-Z]\\( DST\\)?" | 422 (concat "\\([A-Z]?[A-Z]?[A-Z][A-Z]\\( DST\\)?" |
794 "\\|[-+]?[0-9][0-9][0-9][0-9]" | 423 "\\|[-+]?[0-9][0-9][0-9][0-9]" |
795 "\\|" | 424 "\\|" |
833 "^ *--+ +begin message +--+ *$\\|" | 462 "^ *--+ +begin message +--+ *$\\|" |
834 "^ *---+ +Original message follows +---+ *$\\|" | 463 "^ *---+ +Original message follows +---+ *$\\|" |
835 "^|? *---+ +Message text follows: +---+ *|?$") | 464 "^|? *---+ +Message text follows: +---+ *|?$") |
836 "A regexp that matches the separator before the text of a failed message.") | 465 "A regexp that matches the separator before the text of a failed message.") |
837 | 466 |
838 (defvar message-header-format-alist | 467 (defvar message-header-format-alist |
839 `((Newsgroups) | 468 `((Newsgroups) |
840 (To . message-fill-address) | 469 (To . message-fill-address) |
841 (Cc . message-fill-address) | 470 (Cc . message-fill-address) |
842 (Subject) | 471 (Subject) |
843 (In-Reply-To) | 472 (In-Reply-To) |
844 (Fcc) | 473 (Fcc) |
845 (Bcc) | 474 (Bcc) |
847 (Organization) | 476 (Organization) |
848 (Distribution) | 477 (Distribution) |
849 (Lines) | 478 (Lines) |
850 (Expires) | 479 (Expires) |
851 (Message-ID) | 480 (Message-ID) |
852 (References) | 481 (References . message-fill-header) |
853 (X-Mailer) | 482 (X-Mailer) |
854 (X-Newsreader)) | 483 (X-Newsreader)) |
855 "Alist used for formatting headers.") | 484 "Alist used for formatting headers.") |
856 | 485 |
857 (eval-and-compile | 486 (eval-and-compile |
858 (autoload 'message-setup-toolbar "messagexmas") | 487 (autoload 'message-setup-toolbar "messagexmas") |
859 (autoload 'mh-send-letter "mh-comp") | 488 (autoload 'mh-send-letter "mh-comp")) |
860 (autoload 'gnus-point-at-eol "gnus-util") | |
861 (autoload 'gnus-point-at-bol "gnus-util") | |
862 (autoload 'gnus-output-to-mail "gnus-util") | |
863 (autoload 'gnus-output-to-rmail "gnus-util") | |
864 (autoload 'mail-abbrev-in-expansion-header-p "mailabbrev")) | |
865 | 489 |
866 | 490 |
867 | 491 |
868 ;;; | 492 ;;; |
869 ;;; Utility functions. | 493 ;;; Utility functions. |
870 ;;; | 494 ;;; |
871 | 495 |
872 (defmacro message-y-or-n-p (question show &rest text) | 496 (defun message-point-at-bol () |
873 "Ask QUESTION, displaying the rest of the arguments in a temp. buffer if SHOW" | 497 "Return point at the beginning of the line." |
874 `(message-talkative-question 'y-or-n-p ,question ,show ,@text)) | 498 (let ((p (point))) |
499 (beginning-of-line) | |
500 (prog1 | |
501 (point) | |
502 (goto-char p)))) | |
503 | |
504 (defun message-point-at-eol () | |
505 "Return point at the end of the line." | |
506 (let ((p (point))) | |
507 (end-of-line) | |
508 (prog1 | |
509 (point) | |
510 (goto-char p)))) | |
875 | 511 |
876 ;; Delete the current line (and the next N lines.); | 512 ;; Delete the current line (and the next N lines.); |
877 (defmacro message-delete-line (&optional n) | 513 (defmacro message-delete-line (&optional n) |
878 `(delete-region (progn (beginning-of-line) (point)) | 514 `(delete-region (progn (beginning-of-line) (point)) |
879 (progn (forward-line ,(or n 1)) (point)))) | 515 (progn (forward-line ,(or n 1)) (point)))) |
880 | 516 |
881 (defun message-tokenize-header (header &optional separator) | 517 (defun message-tokenize-header (header &optional separator) |
882 "Split HEADER into a list of header elements. | 518 "Split HEADER into a list of header elements. |
883 \",\" is used as the separator." | 519 \",\" is used as the separator." |
884 (if (not header) | 520 (let ((regexp (format "[%s]+" (or separator ","))) |
885 nil | 521 (beg 1) |
886 (let ((regexp (format "[%s]+" (or separator ","))) | 522 (first t) |
887 (beg 1) | 523 quoted elems) |
888 (first t) | 524 (save-excursion |
889 quoted elems paren) | 525 (message-set-work-buffer) |
890 (save-excursion | 526 (insert header) |
891 (message-set-work-buffer) | |
892 (insert header) | |
893 (goto-char (point-min)) | |
894 (while (not (eobp)) | |
895 (if first | |
896 (setq first nil) | |
897 (forward-char 1)) | |
898 (cond ((and (> (point) beg) | |
899 (or (eobp) | |
900 (and (looking-at regexp) | |
901 (not quoted) | |
902 (not paren)))) | |
903 (push (buffer-substring beg (point)) elems) | |
904 (setq beg (match-end 0))) | |
905 ((= (following-char) ?\") | |
906 (setq quoted (not quoted))) | |
907 ((and (= (following-char) ?\() | |
908 (not quoted)) | |
909 (setq paren t)) | |
910 ((and (= (following-char) ?\)) | |
911 (not quoted)) | |
912 (setq paren nil)))) | |
913 (nreverse elems))))) | |
914 | |
915 (defun message-mail-file-mbox-p (file) | |
916 "Say whether FILE looks like a Unix mbox file." | |
917 (when (and (file-exists-p file) | |
918 (file-readable-p file) | |
919 (file-regular-p file)) | |
920 (nnheader-temp-write nil | |
921 (nnheader-insert-file-contents file) | |
922 (goto-char (point-min)) | 527 (goto-char (point-min)) |
923 (looking-at message-unix-mail-delimiter)))) | 528 (while (not (eobp)) |
924 | 529 (if first |
925 (defun message-fetch-field (header &optional not-all) | 530 (setq first nil) |
531 (forward-char 1)) | |
532 (cond ((and (> (point) beg) | |
533 (or (eobp) | |
534 (and (looking-at regexp) | |
535 (not quoted)))) | |
536 (push (buffer-substring beg (point)) elems) | |
537 (setq beg (match-end 0))) | |
538 ((= (following-char) ?\") | |
539 (setq quoted (not quoted))))) | |
540 (nreverse elems)))) | |
541 | |
542 (defun message-fetch-field (header) | |
926 "The same as `mail-fetch-field', only remove all newlines." | 543 "The same as `mail-fetch-field', only remove all newlines." |
927 (let ((value (mail-fetch-field header nil (not not-all)))) | 544 (let ((value (mail-fetch-field header))) |
928 (when value | 545 (when value |
929 (nnheader-replace-chars-in-string value ?\n ? )))) | 546 (nnheader-replace-chars-in-string value ?\n ? )))) |
930 | 547 |
931 (defun message-fetch-reply-field (header) | 548 (defun message-fetch-reply-field (header) |
932 "Fetch FIELD from the message we're replying to." | 549 "Fetch FIELD from the message we're replying to." |
1011 (point-max))) | 628 (point-max))) |
1012 (goto-char (point-min))) | 629 (goto-char (point-min))) |
1013 | 630 |
1014 (defun message-news-p () | 631 (defun message-news-p () |
1015 "Say whether the current buffer contains a news message." | 632 "Say whether the current buffer contains a news message." |
1016 (or message-this-is-news | 633 (save-excursion |
1017 (save-excursion | 634 (save-restriction |
1018 (save-restriction | 635 (message-narrow-to-headers) |
1019 (message-narrow-to-headers) | 636 (message-fetch-field "newsgroups")))) |
1020 (message-fetch-field "newsgroups"))))) | |
1021 | 637 |
1022 (defun message-mail-p () | 638 (defun message-mail-p () |
1023 "Say whether the current buffer contains a mail message." | 639 "Say whether the current buffer contains a mail message." |
1024 (or message-this-is-mail | 640 (save-excursion |
1025 (save-excursion | 641 (save-restriction |
1026 (save-restriction | 642 (message-narrow-to-headers) |
1027 (message-narrow-to-headers) | 643 (or (message-fetch-field "to") |
1028 (or (message-fetch-field "to") | 644 (message-fetch-field "cc") |
1029 (message-fetch-field "cc") | 645 (message-fetch-field "bcc"))))) |
1030 (message-fetch-field "bcc")))))) | |
1031 | 646 |
1032 (defun message-next-header () | 647 (defun message-next-header () |
1033 "Go to the beginning of the next header." | 648 "Go to the beginning of the next header." |
1034 (beginning-of-line) | 649 (beginning-of-line) |
1035 (or (eobp) (forward-char 1)) | 650 (or (eobp) (forward-char 1)) |
1036 (not (if (re-search-forward "^[^ \t]" nil t) | 651 (not (if (re-search-forward "^[^ \t]" nil t) |
1037 (beginning-of-line) | 652 (beginning-of-line) |
1038 (goto-char (point-max))))) | 653 (goto-char (point-max))))) |
1039 | 654 |
1040 (defun message-sort-headers-1 () | 655 (defun message-sort-headers-1 () |
1041 "Sort the buffer as headers using `message-rank' text props." | 656 "Sort the buffer as headers using `message-rank' text props." |
1042 (goto-char (point-min)) | 657 (goto-char (point-min)) |
1043 (sort-subr | 658 (sort-subr |
1044 nil 'message-next-header | 659 nil 'message-next-header |
1045 (lambda () | 660 (lambda () |
1046 (message-next-header) | 661 (message-next-header) |
1047 (unless (bobp) | 662 (unless (bobp) |
1048 (forward-char -1))) | 663 (forward-char -1))) |
1049 (lambda () | 664 (lambda () |
1050 (or (get-text-property (point) 'message-rank) | 665 (or (get-text-property (point) 'message-rank) |
1051 10000)))) | 666 0)))) |
1052 | 667 |
1053 (defun message-sort-headers () | 668 (defun message-sort-headers () |
1054 "Sort the headers of the current message according to `message-header-format-alist'." | 669 "Sort the headers of the current message according to `message-header-format-alist'." |
1055 (interactive) | 670 (interactive) |
1056 (save-excursion | 671 (save-excursion |
1099 (define-key message-mode-map "\C-c\C-b" 'message-goto-body) | 714 (define-key message-mode-map "\C-c\C-b" 'message-goto-body) |
1100 (define-key message-mode-map "\C-c\C-i" 'message-goto-signature) | 715 (define-key message-mode-map "\C-c\C-i" 'message-goto-signature) |
1101 | 716 |
1102 (define-key message-mode-map "\C-c\C-t" 'message-insert-to) | 717 (define-key message-mode-map "\C-c\C-t" 'message-insert-to) |
1103 (define-key message-mode-map "\C-c\C-n" 'message-insert-newsgroups) | 718 (define-key message-mode-map "\C-c\C-n" 'message-insert-newsgroups) |
1104 | 719 |
1105 (define-key message-mode-map "\C-c\C-y" 'message-yank-original) | 720 (define-key message-mode-map "\C-c\C-y" 'message-yank-original) |
1106 (define-key message-mode-map "\C-c\C-q" 'message-fill-yanked-message) | 721 (define-key message-mode-map "\C-c\C-q" 'message-fill-yanked-message) |
1107 (define-key message-mode-map "\C-c\C-w" 'message-insert-signature) | 722 (define-key message-mode-map "\C-c\C-w" 'message-insert-signature) |
1108 (define-key message-mode-map "\C-c\C-r" 'message-caesar-buffer-body) | 723 (define-key message-mode-map "\C-c\C-r" 'message-caesar-buffer-body) |
1109 (define-key message-mode-map "\C-c\C-o" 'message-sort-headers) | 724 (define-key message-mode-map "\C-c\C-o" 'message-sort-headers) |
1112 (define-key message-mode-map "\C-c\C-c" 'message-send-and-exit) | 727 (define-key message-mode-map "\C-c\C-c" 'message-send-and-exit) |
1113 (define-key message-mode-map "\C-c\C-s" 'message-send) | 728 (define-key message-mode-map "\C-c\C-s" 'message-send) |
1114 (define-key message-mode-map "\C-c\C-k" 'message-kill-buffer) | 729 (define-key message-mode-map "\C-c\C-k" 'message-kill-buffer) |
1115 (define-key message-mode-map "\C-c\C-d" 'message-dont-send) | 730 (define-key message-mode-map "\C-c\C-d" 'message-dont-send) |
1116 | 731 |
1117 (define-key message-mode-map "\C-c\C-e" 'message-elide-region) | |
1118 | |
1119 (define-key message-mode-map "\t" 'message-tab)) | 732 (define-key message-mode-map "\t" 'message-tab)) |
1120 | 733 |
1121 (easy-menu-define | 734 (easy-menu-define message-mode-menu message-mode-map |
1122 message-mode-menu message-mode-map "Message Menu." | 735 "Message Menu." |
1123 '("Message" | 736 '("Message" |
1124 ["Sort Headers" message-sort-headers t] | 737 "Go to Field:" |
1125 ["Yank Original" message-yank-original t] | 738 "----" |
1126 ["Fill Yanked Message" message-fill-yanked-message t] | 739 ["To" message-goto-to t] |
1127 ["Insert Signature" message-insert-signature t] | 740 ["Subject" message-goto-subject t] |
1128 ["Caesar (rot13) Message" message-caesar-buffer-body t] | 741 ["Cc" message-goto-cc t] |
1129 ["Caesar (rot13) Region" message-caesar-region (mark t)] | 742 ["Reply-to" message-goto-reply-to t] |
1130 ["Elide Region" message-elide-region (mark t)] | 743 ["Summary" message-goto-summary t] |
1131 ["Rename buffer" message-rename-buffer t] | 744 ["Keywords" message-goto-keywords t] |
1132 ["Spellcheck" ispell-message t] | 745 ["Newsgroups" message-goto-newsgroups t] |
1133 "----" | 746 ["Followup-To" message-goto-followup-to t] |
1134 ["Send Message" message-send-and-exit t] | 747 ["Distribution" message-goto-distribution t] |
1135 ["Abort Message" message-dont-send t])) | 748 ["Body" message-goto-body t] |
1136 | 749 ["Signature" message-goto-signature t] |
1137 (easy-menu-define | 750 "----" |
1138 message-mode-field-menu message-mode-map "" | 751 "Miscellaneous Commands:" |
1139 '("Field" | 752 "----" |
1140 ["Fetch To" message-insert-to t] | 753 ["Sort Headers" message-sort-headers t] |
1141 ["Fetch Newsgroups" message-insert-newsgroups t] | 754 ["Yank Original" message-yank-original t] |
1142 "----" | 755 ["Fill Yanked Message" message-fill-yanked-message t] |
1143 ["To" message-goto-to t] | 756 ["Insert Signature" message-insert-signature t] |
1144 ["Subject" message-goto-subject t] | 757 ["Caesar (rot13) Message" message-caesar-buffer-body t] |
1145 ["Cc" message-goto-cc t] | 758 ["Rename buffer" message-rename-buffer t] |
1146 ["Reply-To" message-goto-reply-to t] | 759 ["Spellcheck" ispell-message t] |
1147 ["Summary" message-goto-summary t] | 760 "----" |
1148 ["Keywords" message-goto-keywords t] | 761 ["Send Message" message-send-and-exit t] |
1149 ["Newsgroups" message-goto-newsgroups t] | 762 ["Abort Message" message-dont-send t])) |
1150 ["Followup-To" message-goto-followup-to t] | |
1151 ["Distribution" message-goto-distribution t] | |
1152 ["Body" message-goto-body t] | |
1153 ["Signature" message-goto-signature t])) | |
1154 | 763 |
1155 (defvar facemenu-add-face-function) | 764 (defvar facemenu-add-face-function) |
1156 (defvar facemenu-remove-face-function) | 765 (defvar facemenu-remove-face-function) |
1157 | 766 |
1158 ;;;###autoload | 767 ;;;###autoload |
1161 Like Text Mode but with these additional commands: | 770 Like Text Mode but with these additional commands: |
1162 C-c C-s message-send (send the message) C-c C-c message-send-and-exit | 771 C-c C-s message-send (send the message) C-c C-c message-send-and-exit |
1163 C-c C-f move to a header field (and create it if there isn't): | 772 C-c C-f move to a header field (and create it if there isn't): |
1164 C-c C-f C-t move to To C-c C-f C-s move to Subject | 773 C-c C-f C-t move to To C-c C-f C-s move to Subject |
1165 C-c C-f C-c move to Cc C-c C-f C-b move to Bcc | 774 C-c C-f C-c move to Cc C-c C-f C-b move to Bcc |
1166 C-c C-f C-w move to Fcc C-c C-f C-r move to Reply-To | 775 C-c C-f C-f move to Fcc C-c C-f C-r move to Reply-To |
1167 C-c C-f C-u move to Summary C-c C-f C-n move to Newsgroups | 776 C-c C-f C-u move to Summary C-c C-f C-n move to Newsgroups |
1168 C-c C-f C-k move to Keywords C-c C-f C-d move to Distribution | 777 C-c C-f C-k move to Keywords C-c C-f C-d move to Distribution |
1169 C-c C-f C-f move to Followup-To | 778 C-c C-f C-o move to Followup-To |
1170 C-c C-t message-insert-to (add a To header to a news followup) | 779 C-c C-t message-insert-to (add a To header to a news followup) |
1171 C-c C-n message-insert-newsgroups (add a Newsgroup header to a news reply) | 780 C-c C-n message-insert-newsgroups (add a Newsgroup header to a news reply) |
1172 C-c C-b message-goto-body (move to beginning of message text). | 781 C-c C-b message-goto-body (move to beginning of message text). |
1173 C-c C-i message-goto-signature (move to the beginning of the signature). | 782 C-c C-i message-goto-signature (move to the beginning of the signature). |
1174 C-c C-w message-insert-signature (insert `message-signature-file' file). | 783 C-c C-w message-insert-signature (insert `message-signature-file' file). |
1175 C-c C-y message-yank-original (insert current message, if any). | 784 C-c C-y message-yank-original (insert current message, if any). |
1176 C-c C-q message-fill-yanked-message (fill what was yanked). | 785 C-c C-q message-fill-yanked-message (fill what was yanked). |
1177 C-c C-e message-elide-region (elide the text between point and mark). | 786 C-c C-r message-ceasar-buffer-body (rot13 the message body)." |
1178 C-c C-r message-caesar-buffer-body (rot13 the message body)." | |
1179 (interactive) | 787 (interactive) |
1180 (kill-all-local-variables) | 788 (kill-all-local-variables) |
1181 (make-local-variable 'message-reply-buffer) | 789 (make-local-variable 'message-reply-buffer) |
1182 (setq message-reply-buffer nil) | 790 (setq message-reply-buffer nil) |
1183 (set (make-local-variable 'message-send-actions) nil) | 791 (make-local-variable 'message-send-actions) |
1184 (set (make-local-variable 'message-exit-actions) nil) | 792 (make-local-variable 'message-exit-actions) |
1185 (set (make-local-variable 'message-kill-actions) nil) | 793 (make-local-variable 'message-kill-actions) |
1186 (set (make-local-variable 'message-postpone-actions) nil) | 794 (make-local-variable 'message-postpone-actions) |
1187 (set-syntax-table message-mode-syntax-table) | 795 (set-syntax-table message-mode-syntax-table) |
1188 (use-local-map message-mode-map) | 796 (use-local-map message-mode-map) |
1189 (setq local-abbrev-table message-mode-abbrev-table) | 797 (setq local-abbrev-table message-mode-abbrev-table) |
1190 (setq major-mode 'message-mode) | 798 (setq major-mode 'message-mode) |
1191 (setq mode-name "Message") | 799 (setq mode-name "Message") |
1224 ;;(when (fboundp 'mail-hist-define-keys) | 832 ;;(when (fboundp 'mail-hist-define-keys) |
1225 ;; (mail-hist-define-keys)) | 833 ;; (mail-hist-define-keys)) |
1226 (when (string-match "XEmacs\\|Lucid" emacs-version) | 834 (when (string-match "XEmacs\\|Lucid" emacs-version) |
1227 (message-setup-toolbar)) | 835 (message-setup-toolbar)) |
1228 (easy-menu-add message-mode-menu message-mode-map) | 836 (easy-menu-add message-mode-menu message-mode-map) |
1229 (easy-menu-add message-mode-field-menu message-mode-map) | |
1230 ;; Allow mail alias things. | 837 ;; Allow mail alias things. |
1231 (if (fboundp 'mail-abbrevs-setup) | 838 (if (fboundp 'mail-abbrevs-setup) |
1232 (mail-abbrevs-setup) | 839 (mail-abbrevs-setup) |
1233 (funcall (intern "mail-aliases-setup"))) | 840 (funcall (intern "mail-aliases-setup"))) |
1234 (run-hooks 'text-mode-hook 'message-mode-hook)) | 841 (run-hooks 'text-mode-hook 'message-mode-hook)) |
1305 | 912 |
1306 (defun message-goto-signature () | 913 (defun message-goto-signature () |
1307 "Move point to the beginning of the message signature." | 914 "Move point to the beginning of the message signature." |
1308 (interactive) | 915 (interactive) |
1309 (goto-char (point-min)) | 916 (goto-char (point-min)) |
1310 (if (re-search-forward message-signature-separator nil t) | 917 (or (re-search-forward message-signature-separator nil t) |
1311 (forward-line 1) | 918 (goto-char (point-max)))) |
1312 (goto-char (point-max)))) | |
1313 | 919 |
1314 | 920 |
1315 | 921 |
1316 (defun message-insert-to () | 922 (defun message-insert-to () |
1317 "Insert a To header that points to the author of the article being replied to." | 923 "Insert a To header that points to the author of the article being replied to." |
1318 (interactive) | 924 (interactive) |
1319 (let ((co (message-fetch-field "courtesy-copies-to"))) | |
1320 (when (and co | |
1321 (equal (downcase co) "never")) | |
1322 (error "The user has requested not to have copies sent via mail"))) | |
1323 (when (and (message-position-on-field "To") | 925 (when (and (message-position-on-field "To") |
1324 (mail-fetch-field "to") | 926 (mail-fetch-field "to") |
1325 (not (string-match "\\` *\\'" (mail-fetch-field "to")))) | 927 (not (string-match "\\` *\\'" (mail-fetch-field "to")))) |
1326 (insert ", ")) | 928 (insert ", ")) |
1327 (insert (or (message-fetch-reply-field "reply-to") | 929 (insert (or (message-fetch-reply-field "reply-to") |
1341 ;;; Various commands | 943 ;;; Various commands |
1342 | 944 |
1343 (defun message-insert-signature (&optional force) | 945 (defun message-insert-signature (&optional force) |
1344 "Insert a signature. See documentation for the `message-signature' variable." | 946 "Insert a signature. See documentation for the `message-signature' variable." |
1345 (interactive (list 0)) | 947 (interactive (list 0)) |
1346 (let* ((signature | 948 (let* ((signature |
1347 (cond | 949 (cond ((and (null message-signature) |
1348 ((and (null message-signature) | 950 (eq force 0)) |
1349 (eq force 0)) | 951 (save-excursion |
1350 (save-excursion | 952 (goto-char (point-max)) |
1351 (goto-char (point-max)) | 953 (not (re-search-backward |
1352 (not (re-search-backward | 954 message-signature-separator nil t)))) |
1353 message-signature-separator nil t)))) | 955 ((and (null message-signature) |
1354 ((and (null message-signature) | 956 force) |
1355 force) | 957 t) |
1356 t) | 958 ((message-functionp message-signature) |
1357 ((message-functionp message-signature) | 959 (funcall message-signature)) |
1358 (funcall message-signature)) | 960 ((listp message-signature) |
1359 ((listp message-signature) | 961 (eval message-signature)) |
1360 (eval message-signature)) | 962 (t message-signature))) |
1361 (t message-signature))) | |
1362 (signature | 963 (signature |
1363 (cond ((stringp signature) | 964 (cond ((stringp signature) |
1364 signature) | 965 signature) |
1365 ((and (eq t signature) | 966 ((and (eq t signature) |
1366 message-signature-file | 967 message-signature-file |
1367 (file-exists-p message-signature-file)) | 968 (file-exists-p message-signature-file)) |
1368 signature)))) | 969 signature)))) |
1369 (when signature | 970 (when signature |
971 ;; Insert the signature. | |
1370 (goto-char (point-max)) | 972 (goto-char (point-max)) |
1371 ;; Insert the signature. | |
1372 (unless (bolp) | 973 (unless (bolp) |
1373 (insert "\n")) | 974 (insert "\n")) |
1374 (insert "\n-- \n") | 975 (insert "\n-- \n") |
1375 (if (eq signature t) | 976 (if (eq signature t) |
1376 (insert-file-contents message-signature-file) | 977 (insert-file-contents message-signature-file) |
1377 (insert signature)) | 978 (insert signature)) |
1378 (goto-char (point-max)) | 979 (goto-char (point-max)) |
1379 (or (bolp) (insert "\n"))))) | 980 (or (bolp) (insert "\n"))))) |
1380 | 981 |
1381 (defun message-elide-region (b e) | |
1382 "Elide the text between point and mark. An ellipsis (from | |
1383 message-elide-elipsis) will be inserted where the text was killed." | |
1384 (interactive "r") | |
1385 (kill-region b e) | |
1386 (unless (bolp) | |
1387 (insert "\n")) | |
1388 (insert message-elide-elipsis)) | |
1389 | |
1390 (defvar message-caesar-translation-table nil) | 982 (defvar message-caesar-translation-table nil) |
1391 | 983 |
1392 (defun message-caesar-region (b e &optional n) | 984 (defun message-caesar-region (b e &optional n) |
1393 "Caesar rotation of region by N, default 13, for decrypting netnews." | 985 "Caesar rotation of region by N, default 13, for decrypting netnews." |
1394 (interactive | 986 (interactive |
1402 (unless (or (zerop n) ; no action needed for a rot of 0 | 994 (unless (or (zerop n) ; no action needed for a rot of 0 |
1403 (= b e)) ; no region to rotate | 995 (= b e)) ; no region to rotate |
1404 ;; We build the table, if necessary. | 996 ;; We build the table, if necessary. |
1405 (when (or (not message-caesar-translation-table) | 997 (when (or (not message-caesar-translation-table) |
1406 (/= (aref message-caesar-translation-table ?a) (+ ?a n))) | 998 (/= (aref message-caesar-translation-table ?a) (+ ?a n))) |
1407 (setq message-caesar-translation-table | 999 (let ((i -1) |
1408 (message-make-caesar-translation-table n))) | 1000 (table (make-string 256 0))) |
1409 ;; Then we translate the region. Do it this way to retain | 1001 (while (< (incf i) 256) |
1002 (aset table i i)) | |
1003 (setq table | |
1004 (concat | |
1005 (substring table 0 ?A) | |
1006 (substring table (+ ?A n) (+ ?A n (- 26 n))) | |
1007 (substring table ?A (+ ?A n)) | |
1008 (substring table (+ ?A 26) ?a) | |
1009 (substring table (+ ?a n) (+ ?a n (- 26 n))) | |
1010 (substring table ?a (+ ?a n)) | |
1011 (substring table (+ ?a 26) 255))) | |
1012 (setq message-caesar-translation-table table))) | |
1013 ;; Then we translate the region. Do it this way to retain | |
1410 ;; text properties. | 1014 ;; text properties. |
1411 (while (< b e) | 1015 (while (< b e) |
1412 (subst-char-in-region | 1016 (subst-char-in-region |
1413 b (1+ b) (char-after b) | 1017 b (1+ b) (char-after b) |
1414 (aref message-caesar-translation-table (char-after b))) | 1018 (aref message-caesar-translation-table (char-after b))) |
1415 (incf b)))) | 1019 (incf b)))) |
1416 | |
1417 (defun message-make-caesar-translation-table (n) | |
1418 "Create a rot table with offset N." | |
1419 (let ((i -1) | |
1420 (table (make-string 256 0))) | |
1421 (while (< (incf i) 256) | |
1422 (aset table i i)) | |
1423 (concat | |
1424 (substring table 0 ?A) | |
1425 (substring table (+ ?A n) (+ ?A n (- 26 n))) | |
1426 (substring table ?A (+ ?A n)) | |
1427 (substring table (+ ?A 26) ?a) | |
1428 (substring table (+ ?a n) (+ ?a n (- 26 n))) | |
1429 (substring table ?a (+ ?a n)) | |
1430 (substring table (+ ?a 26) 255)))) | |
1431 | 1020 |
1432 (defun message-caesar-buffer-body (&optional rotnum) | 1021 (defun message-caesar-buffer-body (&optional rotnum) |
1433 "Caesar rotates all letters in the current buffer by 13 places. | 1022 "Caesar rotates all letters in the current buffer by 13 places. |
1434 Used to encode/decode possibly offensive messages (commonly in net.jokes). | 1023 Used to encode/decode possibly offensive messages (commonly in net.jokes). |
1435 With prefix arg, specifies the number of places to rotate each letter forward. | 1024 With prefix arg, specifies the number of places to rotate each letter forward. |
1441 (save-restriction | 1030 (save-restriction |
1442 (when (message-goto-body) | 1031 (when (message-goto-body) |
1443 (narrow-to-region (point) (point-max))) | 1032 (narrow-to-region (point) (point-max))) |
1444 (message-caesar-region (point-min) (point-max) rotnum)))) | 1033 (message-caesar-region (point-min) (point-max) rotnum)))) |
1445 | 1034 |
1446 (defun message-pipe-buffer-body (program) | |
1447 "Pipe the message body in the current buffer through PROGRAM." | |
1448 (save-excursion | |
1449 (save-restriction | |
1450 (when (message-goto-body) | |
1451 (narrow-to-region (point) (point-max))) | |
1452 (let ((body (buffer-substring (point-min) (point-max)))) | |
1453 (unless (equal 0 (call-process-region | |
1454 (point-min) (point-max) program t t)) | |
1455 (insert body) | |
1456 (message "%s failed." program)))))) | |
1457 | |
1458 (defun message-rename-buffer (&optional enter-string) | 1035 (defun message-rename-buffer (&optional enter-string) |
1459 "Rename the *message* buffer to \"*message* RECIPIENT\". | 1036 "Rename the *message* buffer to \"*message* RECIPIENT\". |
1460 If the function is run with a prefix, it will ask for a new buffer | 1037 If the function is run with a prefix, it will ask for a new buffer |
1461 name, rather than giving an automatic name." | 1038 name, rather than giving an automatic name." |
1462 (interactive "Pbuffer name: ") | 1039 (interactive "Pbuffer name: ") |
1463 (save-excursion | 1040 (save-excursion |
1464 (save-restriction | 1041 (save-restriction |
1465 (goto-char (point-min)) | 1042 (goto-char (point-min)) |
1466 (narrow-to-region (point) | 1043 (narrow-to-region (point) |
1467 (search-forward mail-header-separator nil 'end)) | 1044 (search-forward mail-header-separator nil 'end)) |
1468 (let* ((mail-to (or | 1045 (let* ((mail-to (if (message-news-p) (message-fetch-field "Newsgroups") |
1469 (if (message-news-p) (message-fetch-field "Newsgroups") | 1046 (message-fetch-field "To"))) |
1470 (message-fetch-field "To")) | |
1471 "")) | |
1472 (mail-trimmed-to | 1047 (mail-trimmed-to |
1473 (if (string-match "," mail-to) | 1048 (if (string-match "," mail-to) |
1474 (concat (substring mail-to 0 (match-beginning 0)) ", ...") | 1049 (concat (substring mail-to 0 (match-beginning 0)) ", ...") |
1475 mail-to)) | 1050 mail-to)) |
1476 (name-default (concat "*message* " mail-trimmed-to)) | 1051 (name-default (concat "*message* " mail-trimmed-to)) |
1477 (name (if enter-string | 1052 (name (if enter-string |
1478 (read-string "New buffer name: " name-default) | 1053 (read-string "New buffer name: " name-default) |
1479 name-default)) | 1054 name-default))) |
1480 (default-directory | 1055 (rename-buffer name t) |
1481 (file-name-as-directory message-autosave-directory))) | 1056 (setq buffer-auto-save-file-name |
1482 (rename-buffer name t))))) | 1057 (format "%s%s" |
1058 (file-name-as-directory message-autosave-directory) | |
1059 (file-name-nondirectory buffer-auto-save-file-name))))))) | |
1483 | 1060 |
1484 (defun message-fill-yanked-message (&optional justifyp) | 1061 (defun message-fill-yanked-message (&optional justifyp) |
1485 "Fill the paragraphs of a message yanked into this one. | 1062 "Fill the paragraphs of a message yanked into this one. |
1486 Numeric argument means justify as well." | 1063 Numeric argument means justify as well." |
1487 (interactive "P") | 1064 (interactive "P") |
1500 However, if `message-yank-prefix' is non-nil, insert that prefix on each line." | 1077 However, if `message-yank-prefix' is non-nil, insert that prefix on each line." |
1501 (let ((start (point))) | 1078 (let ((start (point))) |
1502 ;; Remove unwanted headers. | 1079 ;; Remove unwanted headers. |
1503 (when message-ignored-cited-headers | 1080 (when message-ignored-cited-headers |
1504 (save-restriction | 1081 (save-restriction |
1505 (narrow-to-region | 1082 (narrow-to-region |
1506 (goto-char start) | 1083 (goto-char start) |
1507 (if (search-forward "\n\n" nil t) | 1084 (if (search-forward "\n\n" nil t) |
1508 (1- (point)) | 1085 (1- (point)) |
1509 (point))) | 1086 (point))) |
1510 (message-remove-header message-ignored-cited-headers t) | 1087 (message-remove-header message-ignored-cited-headers t))) |
1511 (goto-char (point-max)))) | |
1512 ;; Delete blank lines at the start of the buffer. | |
1513 (while (and (point-min) | |
1514 (eolp) | |
1515 (not (eobp))) | |
1516 (message-delete-line)) | |
1517 ;; Delete blank lines at the end of the buffer. | |
1518 (goto-char (point-max)) | |
1519 (unless (eolp) | |
1520 (insert "\n")) | |
1521 (while (and (zerop (forward-line -1)) | |
1522 (looking-at "$")) | |
1523 (message-delete-line)) | |
1524 ;; Do the indentation. | 1088 ;; Do the indentation. |
1525 (if (null message-yank-prefix) | 1089 (if (null message-yank-prefix) |
1526 (indent-rigidly start (mark t) message-indentation-spaces) | 1090 (indent-rigidly start (mark t) message-indentation-spaces) |
1527 (save-excursion | 1091 (save-excursion |
1528 (goto-char start) | 1092 (goto-char start) |
1529 (while (< (point) (mark t)) | 1093 (while (< (point) (mark t)) |
1530 (insert message-yank-prefix) | 1094 (insert message-yank-prefix) |
1531 (forward-line 1)))) | 1095 (forward-line 1))) |
1532 (goto-char start))) | 1096 (goto-char start)))) |
1533 | 1097 |
1534 (defun message-yank-original (&optional arg) | 1098 (defun message-yank-original (&optional arg) |
1535 "Insert the message being replied to, if any. | 1099 "Insert the message being replied to, if any. |
1536 Puts point before the text and mark after. | 1100 Puts point before the text and mark after. |
1537 Normally indents each nonblank line ARG spaces (default 3). However, | 1101 Normally indents each nonblank line ARG spaces (default 3). However, |
1552 (unless (bolp) | 1116 (unless (bolp) |
1553 (insert ?\n)) | 1117 (insert ?\n)) |
1554 (unless modified | 1118 (unless modified |
1555 (setq message-checksum (cons (message-checksum) (buffer-size))))))) | 1119 (setq message-checksum (cons (message-checksum) (buffer-size))))))) |
1556 | 1120 |
1557 (defun message-cite-original () | 1121 (defun message-cite-original () |
1558 "Cite function in the standard Message manner." | |
1559 (let ((start (point)) | 1122 (let ((start (point)) |
1560 (functions | 1123 (functions |
1561 (when message-indent-citation-function | 1124 (when message-indent-citation-function |
1562 (if (listp message-indent-citation-function) | 1125 (if (listp message-indent-citation-function) |
1563 message-indent-citation-function | 1126 message-indent-citation-function |
1564 (list message-indent-citation-function))))) | 1127 (list message-indent-citation-function))))) |
1565 (goto-char start) | 1128 (goto-char start) |
1579 (let ((case-fold-search t)) | 1142 (let ((case-fold-search t)) |
1580 (save-restriction | 1143 (save-restriction |
1581 (narrow-to-region | 1144 (narrow-to-region |
1582 (goto-char (point-min)) | 1145 (goto-char (point-min)) |
1583 (progn | 1146 (progn |
1584 (re-search-forward | 1147 (re-search-forward |
1585 (concat "^" (regexp-quote mail-header-separator) "$")) | 1148 (concat "^" (regexp-quote mail-header-separator) "$")) |
1586 (match-beginning 0))) | 1149 (match-beginning 0))) |
1587 (goto-char (point-min)) | 1150 (goto-char (point-min)) |
1588 (if (re-search-forward (concat "^" (regexp-quote header) ":") nil t) | 1151 (if (re-search-forward (concat "^" (regexp-quote header) ":") nil t) |
1589 (progn | 1152 (progn |
1590 (re-search-forward "^[^ \t]" nil 'move) | 1153 (re-search-forward "^[^ \t]" nil 'move) |
1591 (beginning-of-line) | 1154 (beginning-of-line) |
1592 (skip-chars-backward "\n") | 1155 (skip-chars-backward "\n") |
1593 t) | 1156 t) |
1594 (while (and afters | 1157 (while (and afters |
1595 (not (re-search-forward | 1158 (not (re-search-forward |
1596 (concat "^" (regexp-quote (car afters)) ":") | 1159 (concat "^" (regexp-quote (car afters)) ":") |
1597 nil t))) | 1160 nil t))) |
1598 (pop afters)) | 1161 (pop afters)) |
1599 (when afters | 1162 (when afters |
1600 (re-search-forward "^[^ \t]" nil 'move) | 1163 (re-search-forward "^[^ \t]" nil 'move) |
1607 "Remove the signature from the text between point and mark. | 1170 "Remove the signature from the text between point and mark. |
1608 The text will also be indented the normal way." | 1171 The text will also be indented the normal way." |
1609 (save-excursion | 1172 (save-excursion |
1610 (let ((start (point)) | 1173 (let ((start (point)) |
1611 mark) | 1174 mark) |
1612 (if (not (re-search-forward message-signature-separator (mark t) t)) | 1175 (if (not (re-search-forward message-signature-separator (mark t) t)) |
1613 ;; No signature here, so we just indent the cited text. | 1176 ;; No signature here, so we just indent the cited text. |
1614 (message-indent-citation) | |
1615 ;; Find the last non-empty line. | |
1616 (forward-line -1) | |
1617 (while (looking-at "[ \t]*$") | |
1618 (forward-line -1)) | |
1619 (forward-line 1) | |
1620 (setq mark (set-marker (make-marker) (point))) | |
1621 (goto-char start) | |
1622 (message-indent-citation) | 1177 (message-indent-citation) |
1623 ;; Enable undoing the deletion. | 1178 ;; Find the last non-empty line. |
1624 (undo-boundary) | 1179 (forward-line -1) |
1625 (delete-region mark (mark t)) | 1180 (while (looking-at "[ \t]*$") |
1626 (set-marker mark nil))))) | 1181 (forward-line -1)) |
1182 (forward-line 1) | |
1183 (setq mark (set-marker (make-marker) (point))) | |
1184 (goto-char start) | |
1185 (message-indent-citation) | |
1186 ;; Enable undoing the deletion. | |
1187 (undo-boundary) | |
1188 (delete-region mark (mark t)) | |
1189 (set-marker mark nil))))) | |
1627 | 1190 |
1628 | 1191 |
1629 | 1192 |
1630 ;;; | 1193 ;;; |
1631 ;;; Sending messages | 1194 ;;; Sending messages |
1646 (message-do-actions actions)))) | 1209 (message-do-actions actions)))) |
1647 | 1210 |
1648 (defun message-dont-send () | 1211 (defun message-dont-send () |
1649 "Don't send the message you have been editing." | 1212 "Don't send the message you have been editing." |
1650 (interactive) | 1213 (interactive) |
1651 (let ((actions message-postpone-actions)) | 1214 (message-bury (current-buffer)) |
1652 (message-bury (current-buffer)) | 1215 (message-do-actions message-postpone-actions)) |
1653 (message-do-actions actions))) | |
1654 | 1216 |
1655 (defun message-kill-buffer () | 1217 (defun message-kill-buffer () |
1656 "Kill the current buffer." | 1218 "Kill the current buffer." |
1657 (interactive) | 1219 (interactive) |
1658 (when (or (not (buffer-modified-p)) | 1220 (let ((actions message-kill-actions)) |
1659 (yes-or-no-p "Message modified; kill anyway? ")) | 1221 (kill-buffer (current-buffer)) |
1660 (let ((actions message-kill-actions)) | 1222 (message-do-actions actions))) |
1661 (kill-buffer (current-buffer)) | |
1662 (message-do-actions actions)))) | |
1663 | 1223 |
1664 (defun message-bury (buffer) | 1224 (defun message-bury (buffer) |
1665 "Bury this mail buffer." | 1225 "Bury this mail buffer." |
1666 (let ((newbuf (other-buffer buffer))) | 1226 (let ((newbuf (other-buffer buffer))) |
1667 (bury-buffer buffer) | 1227 (bury-buffer buffer) |
1733 | 1293 |
1734 (defun message-do-actions (actions) | 1294 (defun message-do-actions (actions) |
1735 "Perform all actions in ACTIONS." | 1295 "Perform all actions in ACTIONS." |
1736 ;; Now perform actions on successful sending. | 1296 ;; Now perform actions on successful sending. |
1737 (while actions | 1297 (while actions |
1738 (ignore-errors | 1298 (condition-case nil |
1739 (cond | 1299 (cond |
1740 ;; A simple function. | 1300 ;; A simple function. |
1741 ((message-functionp (car actions)) | 1301 ((message-functionp (car actions)) |
1742 (funcall (car actions))) | 1302 (funcall (car actions))) |
1743 ;; Something to be evaled. | 1303 ;; Something to be evaled. |
1744 (t | 1304 (t |
1745 (eval (car actions))))) | 1305 (eval (car actions)))) |
1306 (error)) | |
1746 (pop actions))) | 1307 (pop actions))) |
1747 | 1308 |
1748 (defun message-send-mail (&optional arg) | 1309 (defun message-send-mail (&optional arg) |
1749 (require 'mail-utils) | 1310 (require 'mail-utils) |
1750 (let ((tembuf (message-generate-new-buffer-clone-locals " message temp")) | 1311 (let ((tembuf (generate-new-buffer " message temp")) |
1751 (case-fold-search nil) | 1312 (case-fold-search nil) |
1752 (news (message-news-p)) | 1313 (news (message-news-p)) |
1753 (mailbuf (current-buffer))) | 1314 (mailbuf (current-buffer))) |
1754 (save-restriction | 1315 (save-restriction |
1755 (message-narrow-to-headers) | 1316 (message-narrow-to-headers) |
1762 (unwind-protect | 1323 (unwind-protect |
1763 (save-excursion | 1324 (save-excursion |
1764 (set-buffer tembuf) | 1325 (set-buffer tembuf) |
1765 (erase-buffer) | 1326 (erase-buffer) |
1766 ;; Avoid copying text props. | 1327 ;; Avoid copying text props. |
1767 (insert (format | 1328 (insert (format |
1768 "%s" (save-excursion | 1329 "%s" (save-excursion |
1769 (set-buffer mailbuf) | 1330 (set-buffer mailbuf) |
1770 (buffer-string)))) | 1331 (buffer-string)))) |
1771 ;; Remove some headers. | 1332 ;; Remove some headers. |
1772 (save-restriction | 1333 (save-restriction |
1801 (re-search-forward | 1362 (re-search-forward |
1802 (concat "^" (regexp-quote mail-header-separator) "\n")) | 1363 (concat "^" (regexp-quote mail-header-separator) "\n")) |
1803 (replace-match "\n") | 1364 (replace-match "\n") |
1804 (backward-char 1) | 1365 (backward-char 1) |
1805 (setq delimline (point-marker)) | 1366 (setq delimline (point-marker)) |
1806 (run-hooks 'message-send-mail-hook) | |
1807 ;; Insert an extra newline if we need it to work around | 1367 ;; Insert an extra newline if we need it to work around |
1808 ;; Sun's bug that swallows newlines. | 1368 ;; Sun's bug that swallows newlines. |
1809 (goto-char (1+ delimline)) | 1369 (goto-char (1+ delimline)) |
1810 (when (eval message-mailer-swallows-blank-line) | 1370 (when (eval message-mailer-swallows-blank-line) |
1811 (newline)) | 1371 (newline)) |
1820 sendmail-program | 1380 sendmail-program |
1821 "/usr/lib/sendmail") | 1381 "/usr/lib/sendmail") |
1822 nil errbuf nil "-oi") | 1382 nil errbuf nil "-oi") |
1823 ;; Always specify who from, | 1383 ;; Always specify who from, |
1824 ;; since some systems have broken sendmails. | 1384 ;; since some systems have broken sendmails. |
1825 ;; But some systems are more broken with -f, so | 1385 (list "-f" (user-login-name)) |
1826 ;; we'll let users override this. | |
1827 (if (null message-sendmail-f-is-evil) | |
1828 (list "-f" (user-login-name))) | |
1829 ;; These mean "report errors by mail" | 1386 ;; These mean "report errors by mail" |
1830 ;; and "deliver in background". | 1387 ;; and "deliver in background". |
1831 (if (null message-interactive) '("-oem" "-odb")) | 1388 (if (null message-interactive) '("-oem" "-odb")) |
1832 ;; Get the addresses from the message | 1389 ;; Get the addresses from the message |
1833 ;; unless this is a resend. | 1390 ;; unless this is a resend. |
1847 (error "Sending...failed to %s" | 1404 (error "Sending...failed to %s" |
1848 (buffer-substring (point-min) (point-max))))) | 1405 (buffer-substring (point-min) (point-max))))) |
1849 (when (bufferp errbuf) | 1406 (when (bufferp errbuf) |
1850 (kill-buffer errbuf))))) | 1407 (kill-buffer errbuf))))) |
1851 | 1408 |
1852 (defun message-send-mail-with-qmail () | |
1853 "Pass the prepared message buffer to qmail-inject. | |
1854 Refer to the documentation for the variable `message-send-mail-function' | |
1855 to find out how to use this." | |
1856 ;; replace the header delimiter with a blank line | |
1857 (goto-char (point-min)) | |
1858 (re-search-forward | |
1859 (concat "^" (regexp-quote mail-header-separator) "\n")) | |
1860 (replace-match "\n") | |
1861 (run-hooks 'message-send-mail-hook) | |
1862 ;; send the message | |
1863 (case | |
1864 (apply | |
1865 'call-process-region 1 (point-max) message-qmail-inject-program | |
1866 nil nil nil | |
1867 ;; qmail-inject's default behaviour is to look for addresses on the | |
1868 ;; command line; if there're none, it scans the headers. | |
1869 ;; yes, it does The Right Thing w.r.t. Resent-To and it's kin. | |
1870 ;; | |
1871 ;; in general, ALL of qmail-inject's defaults are perfect for simply | |
1872 ;; reading a formatted (i. e., at least a To: or Resent-To header) | |
1873 ;; message from stdin. | |
1874 ;; | |
1875 ;; qmail also has the advantage of not having been raped by | |
1876 ;; various vendors, so we don't have to allow for that, either -- | |
1877 ;; compare this with message-send-mail-with-sendmail and weep | |
1878 ;; for sendmail's lost innocence. | |
1879 ;; | |
1880 ;; all this is way cool coz it lets us keep the arguments entirely | |
1881 ;; free for -inject-arguments -- a big win for the user and for us | |
1882 ;; since we don't have to play that double-guessing game and the user | |
1883 ;; gets full control (no gestapo'ish -f's, for instance). --sj | |
1884 message-qmail-inject-args) | |
1885 ;; qmail-inject doesn't say anything on it's stdout/stderr, | |
1886 ;; we have to look at the retval instead | |
1887 (0 nil) | |
1888 (1 (error "qmail-inject reported permanent failure.")) | |
1889 (111 (error "qmail-inject reported transient failure.")) | |
1890 ;; should never happen | |
1891 (t (error "qmail-inject reported unknown failure.")))) | |
1892 | |
1893 (defun message-send-mail-with-mh () | 1409 (defun message-send-mail-with-mh () |
1894 "Send the prepared message buffer with mh." | 1410 "Send the prepared message buffer with mh." |
1895 (let ((mh-previous-window-config nil) | 1411 (let ((mh-previous-window-config nil) |
1896 (name (make-temp-name | 1412 (name (make-temp-name |
1897 (concat (file-name-as-directory | 1413 (concat (file-name-as-directory message-autosave-directory) |
1898 (expand-file-name message-autosave-directory)) | |
1899 "msg.")))) | 1414 "msg.")))) |
1900 (setq buffer-file-name name) | 1415 (setq buffer-file-name name) |
1901 ;; MH wants to generate these headers itself. | 1416 (mh-send-letter) |
1902 (when message-mh-deletable-headers | 1417 (condition-case () |
1903 (let ((headers message-mh-deletable-headers)) | 1418 (delete-file name) |
1904 (while headers | 1419 (error nil)))) |
1905 (goto-char (point-min)) | |
1906 (and (re-search-forward | |
1907 (concat "^" (symbol-name (car headers)) ": *") nil t) | |
1908 (message-delete-line)) | |
1909 (pop headers)))) | |
1910 (run-hooks 'message-send-mail-hook) | |
1911 ;; Pass it on to mh. | |
1912 (mh-send-letter))) | |
1913 | 1420 |
1914 (defun message-send-news (&optional arg) | 1421 (defun message-send-news (&optional arg) |
1915 (let ((tembuf (message-generate-new-buffer-clone-locals " *message temp*")) | 1422 (let ((tembuf (generate-new-buffer " *message temp*")) |
1916 (case-fold-search nil) | 1423 (case-fold-search nil) |
1917 (method (if (message-functionp message-post-method) | 1424 (method (if (message-functionp message-post-method) |
1918 (funcall message-post-method arg) | 1425 (funcall message-post-method arg) |
1919 message-post-method)) | 1426 message-post-method)) |
1920 (messbuf (current-buffer)) | 1427 (messbuf (current-buffer)) |
1929 ;; Insert some headers. | 1436 ;; Insert some headers. |
1930 (message-generate-headers message-required-news-headers) | 1437 (message-generate-headers message-required-news-headers) |
1931 ;; Let the user do all of the above. | 1438 ;; Let the user do all of the above. |
1932 (run-hooks 'message-header-hook)) | 1439 (run-hooks 'message-header-hook)) |
1933 (message-cleanup-headers) | 1440 (message-cleanup-headers) |
1934 (if (not (message-check-news-syntax)) | 1441 (when (message-check-news-syntax) |
1935 (progn | |
1936 ;;(message "Posting not performed") | |
1937 nil) | |
1938 (unwind-protect | 1442 (unwind-protect |
1939 (save-excursion | 1443 (save-excursion |
1940 (set-buffer tembuf) | 1444 (set-buffer tembuf) |
1941 (buffer-disable-undo (current-buffer)) | 1445 (buffer-disable-undo (current-buffer)) |
1942 (erase-buffer) | 1446 (erase-buffer) |
1943 ;; Avoid copying text props. | 1447 ;; Avoid copying text props. |
1944 (insert (format | 1448 (insert (format |
1945 "%s" (save-excursion | 1449 "%s" (save-excursion |
1946 (set-buffer messbuf) | 1450 (set-buffer messbuf) |
1947 (buffer-string)))) | 1451 (buffer-string)))) |
1948 ;; Remove some headers. | 1452 ;; Remove some headers. |
1949 (save-restriction | 1453 (save-restriction |
1950 (message-narrow-to-headers) | 1454 (message-narrow-to-headers) |
1951 ;; Remove some headers. | 1455 ;; Remove some headers. |
1952 (message-remove-header message-ignored-news-headers t)) | 1456 (message-remove-header message-ignored-news-headers t)) |
1953 (goto-char (point-max)) | 1457 (goto-char (point-max)) |
1954 ;; require one newline at the end. | 1458 ;; require one newline at the end. |
1955 (or (= (preceding-char) ?\n) | 1459 (or (= (preceding-char) ?\n) |
1956 (insert ?\n)) | 1460 (insert ?\n)) |
1957 (let ((case-fold-search t)) | 1461 (let ((case-fold-search t)) |
1958 ;; Remove the delimiter. | 1462 ;; Remove the delimeter. |
1959 (goto-char (point-min)) | 1463 (goto-char (point-min)) |
1960 (re-search-forward | 1464 (re-search-forward |
1961 (concat "^" (regexp-quote mail-header-separator) "\n")) | 1465 (concat "^" (regexp-quote mail-header-separator) "\n")) |
1962 (replace-match "\n") | 1466 (replace-match "\n") |
1963 (backward-char 1)) | 1467 (backward-char 1)) |
1964 (run-hooks 'message-send-news-hook) | |
1965 (require (car method)) | 1468 (require (car method)) |
1966 (funcall (intern (format "%s-open-server" (car method))) | 1469 (funcall (intern (format "%s-open-server" (car method))) |
1967 (cadr method) (cddr method)) | 1470 (cadr method) (cddr method)) |
1968 (setq result | 1471 (setq result |
1969 (funcall (intern (format "%s-request-post" (car method)))))) | 1472 (funcall (intern (format "%s-request-post" (car method)))))) |
1977 | 1480 |
1978 ;;; | 1481 ;;; |
1979 ;;; Header generation & syntax checking. | 1482 ;;; Header generation & syntax checking. |
1980 ;;; | 1483 ;;; |
1981 | 1484 |
1982 (defmacro message-check (type &rest forms) | 1485 (defun message-check-news-syntax () |
1983 "Eval FORMS if TYPE is to be checked." | 1486 "Check the syntax of the message." |
1984 `(or (message-check-element ,type) | 1487 (and |
1488 ;; We narrow to the headers and check them first. | |
1489 (save-excursion | |
1490 (save-restriction | |
1491 (message-narrow-to-headers) | |
1492 (and | |
1493 ;; Check for commands in Subject. | |
1494 (or | |
1495 (message-check-element 'subject-cmsg) | |
1496 (save-excursion | |
1497 (if (string-match "^cmsg " (message-fetch-field "subject")) | |
1498 (y-or-n-p | |
1499 "The control code \"cmsg \" is in the subject. Really post? ") | |
1500 t))) | |
1501 ;; Check for multiple identical headers. | |
1502 (or (message-check-element 'multiple-headers) | |
1503 (save-excursion | |
1504 (let (found) | |
1505 (while (and (not found) | |
1506 (re-search-forward "^[^ \t:]+: " nil t)) | |
1507 (save-excursion | |
1508 (or (re-search-forward | |
1509 (concat "^" (setq found | |
1510 (buffer-substring | |
1511 (match-beginning 0) | |
1512 (- (match-end 0) 2)))) | |
1513 nil t) | |
1514 (setq found nil)))) | |
1515 (if found | |
1516 (y-or-n-p | |
1517 (format "Multiple %s headers. Really post? " found)) | |
1518 t)))) | |
1519 ;; Check for Version and Sendsys. | |
1520 (or (message-check-element 'sendsys) | |
1521 (save-excursion | |
1522 (if (re-search-forward "^Sendsys:\\|^Version:" nil t) | |
1523 (y-or-n-p | |
1524 (format "The article contains a %s command. Really post? " | |
1525 (buffer-substring (match-beginning 0) | |
1526 (1- (match-end 0))))) | |
1527 t))) | |
1528 ;; See whether we can shorten Followup-To. | |
1529 (or (message-check-element 'shorten-followup-to) | |
1530 (let ((newsgroups (message-fetch-field "newsgroups")) | |
1531 (followup-to (message-fetch-field "followup-to")) | |
1532 to) | |
1533 (when (and newsgroups (string-match "," newsgroups) | |
1534 (not followup-to) | |
1535 (not | |
1536 (zerop | |
1537 (length | |
1538 (setq to (completing-read | |
1539 "Followups to: (default all groups) " | |
1540 (mapcar (lambda (g) (list g)) | |
1541 (cons "poster" | |
1542 (message-tokenize-header | |
1543 newsgroups))))))))) | |
1544 (goto-char (point-min)) | |
1545 (insert "Followup-To: " to "\n")) | |
1546 t)) | |
1547 ;; Check "Shoot me". | |
1548 (or (message-check-element 'shoot) | |
1549 (save-excursion | |
1550 (if (re-search-forward | |
1551 "Message-ID.*.i-have-a-misconfigured-system-so-shoot-me" | |
1552 nil t) | |
1553 (y-or-n-p | |
1554 "You appear to have a misconfigured system. Really post? ") | |
1555 t))) | |
1556 ;; Check for Approved. | |
1557 (or (message-check-element 'approved) | |
1558 (save-excursion | |
1559 (if (re-search-forward "^Approved:" nil t) | |
1560 (y-or-n-p | |
1561 "The article contains an Approved header. Really post? ") | |
1562 t))) | |
1563 ;; Check the Message-Id header. | |
1564 (or (message-check-element 'message-id) | |
1565 (save-excursion | |
1566 (let* ((case-fold-search t) | |
1567 (message-id (message-fetch-field "message-id"))) | |
1568 (or (not message-id) | |
1569 (and (string-match "@" message-id) | |
1570 (string-match "@[^\\.]*\\." message-id)) | |
1571 (y-or-n-p | |
1572 (format | |
1573 "The Message-ID looks strange: \"%s\". Really post? " | |
1574 message-id)))))) | |
1575 ;; Check the Subject header. | |
1576 (or | |
1577 (message-check-element 'subject) | |
1578 (save-excursion | |
1579 (let* ((case-fold-search t) | |
1580 (subject (message-fetch-field "subject"))) | |
1581 (or | |
1582 (and subject | |
1583 (not (string-match "\\`[ \t]*\\'" subject))) | |
1584 (progn | |
1585 (message | |
1586 "The subject field is empty or missing. Posting is denied.") | |
1587 nil))))) | |
1588 ;; Check the Newsgroups & Followup-To headers. | |
1589 (or | |
1590 (message-check-element 'existing-newsgroups) | |
1591 (let* ((case-fold-search t) | |
1592 (newsgroups (message-fetch-field "newsgroups")) | |
1593 (followup-to (message-fetch-field "followup-to")) | |
1594 (groups (message-tokenize-header | |
1595 (if followup-to | |
1596 (concat newsgroups "," followup-to) | |
1597 newsgroups))) | |
1598 (hashtb (and (boundp 'gnus-active-hashtb) | |
1599 gnus-active-hashtb)) | |
1600 errors) | |
1601 (if (not hashtb) | |
1602 t | |
1603 (while groups | |
1604 (when (and (not (boundp (intern (car groups) hashtb))) | |
1605 (not (equal (car groups) "poster"))) | |
1606 (push (car groups) errors)) | |
1607 (pop groups)) | |
1608 (if (not errors) | |
1609 t | |
1610 (y-or-n-p | |
1611 (format | |
1612 "Really post to %s unknown group%s: %s " | |
1613 (if (= (length errors) 1) "this" "these") | |
1614 (if (= (length errors) 1) "" "s") | |
1615 (mapconcat 'identity errors ", "))))))) | |
1616 ;; Check the Newsgroups & Followup-To headers for syntax errors. | |
1617 (or | |
1618 (message-check-element 'valid-newsgroups) | |
1619 (let ((case-fold-search t) | |
1620 (headers '("Newsgroups" "Followup-To")) | |
1621 header error) | |
1622 (while (and headers (not error)) | |
1623 (when (setq header (mail-fetch-field (car headers))) | |
1624 (if (or | |
1625 (not | |
1626 (string-match | |
1627 "\\`\\([-+_&.a-zA-Z0-9]+\\)?\\(,[-.a-zA-Z0-9]+\\)*\\'" | |
1628 header)) | |
1629 (memq | |
1630 nil (mapcar | |
1631 (lambda (g) | |
1632 (not (string-match "\\.\\'\\|\\.\\." g))) | |
1633 (message-tokenize-header header ",")))) | |
1634 (setq error t))) | |
1635 (unless error | |
1636 (pop headers))) | |
1637 (if (not error) | |
1638 t | |
1639 (y-or-n-p | |
1640 (format "The %s header looks odd: \"%s\". Really post? " | |
1641 (car headers) header))))) | |
1642 ;; Check the From header. | |
1643 (or | |
1644 (save-excursion | |
1645 (let* ((case-fold-search t) | |
1646 (from (message-fetch-field "from"))) | |
1647 (cond | |
1648 ((not from) | |
1649 (message "There is no From line. Posting is denied.") | |
1650 nil) | |
1651 ((not (string-match "@[^\\.]*\\." from)) | |
1652 (message | |
1653 "Denied posting -- the From looks strange: \"%s\"." from) | |
1654 nil) | |
1655 ((string-match "@[^@]*@" from) | |
1656 (message | |
1657 "Denied posting -- two \"@\"'s in the From header: %s." from) | |
1658 nil) | |
1659 ((string-match "(.*).*(.*)" from) | |
1660 (message | |
1661 "Denied posting -- the From header looks strange: \"%s\"." | |
1662 from) | |
1663 nil) | |
1664 (t t)))))))) | |
1665 ;; Check for long lines. | |
1666 (or (message-check-element 'long-lines) | |
1985 (save-excursion | 1667 (save-excursion |
1986 ,@forms))) | 1668 (goto-char (point-min)) |
1987 | 1669 (re-search-forward |
1988 (put 'message-check 'lisp-indent-function 1) | 1670 (concat "^" (regexp-quote mail-header-separator) "$")) |
1989 (put 'message-check 'edebug-form-spec '(form body)) | 1671 (while (and |
1672 (progn | |
1673 (end-of-line) | |
1674 (< (current-column) 80)) | |
1675 (zerop (forward-line 1)))) | |
1676 (or (bolp) | |
1677 (eobp) | |
1678 (y-or-n-p | |
1679 "You have lines longer than 79 characters. Really post? ")))) | |
1680 ;; Check whether the article is empty. | |
1681 (or (message-check-element 'empty) | |
1682 (save-excursion | |
1683 (goto-char (point-min)) | |
1684 (re-search-forward | |
1685 (concat "^" (regexp-quote mail-header-separator) "$")) | |
1686 (forward-line 1) | |
1687 (let ((b (point))) | |
1688 (goto-char (point-max)) | |
1689 (re-search-backward message-signature-separator nil t) | |
1690 (beginning-of-line) | |
1691 (or (re-search-backward "[^ \n\t]" b t) | |
1692 (y-or-n-p "Empty article. Really post? "))))) | |
1693 ;; Check for control characters. | |
1694 (or (message-check-element 'control-chars) | |
1695 (save-excursion | |
1696 (if (re-search-forward "[\000-\007\013\015-\037\200-\237]" nil t) | |
1697 (y-or-n-p | |
1698 "The article contains control characters. Really post? ") | |
1699 t))) | |
1700 ;; Check excessive size. | |
1701 (or (message-check-element 'size) | |
1702 (if (> (buffer-size) 60000) | |
1703 (y-or-n-p | |
1704 (format "The article is %d octets long. Really post? " | |
1705 (buffer-size))) | |
1706 t)) | |
1707 ;; Check whether any new text has been added. | |
1708 (or (message-check-element 'new-text) | |
1709 (not message-checksum) | |
1710 (not (and (eq (message-checksum) (car message-checksum)) | |
1711 (eq (buffer-size) (cdr message-checksum)))) | |
1712 (y-or-n-p | |
1713 "It looks like no new text has been added. Really post? ")) | |
1714 ;; Check the length of the signature. | |
1715 (or | |
1716 (message-check-element 'signature) | |
1717 (progn | |
1718 (goto-char (point-max)) | |
1719 (if (or (not (re-search-backward message-signature-separator nil t)) | |
1720 (search-forward message-forward-end-separator nil t)) | |
1721 t | |
1722 (if (> (count-lines (point) (point-max)) 5) | |
1723 (y-or-n-p | |
1724 (format | |
1725 "Your .sig is %d lines; it should be max 4. Really post? " | |
1726 (count-lines (point) (point-max)))) | |
1727 t)))))) | |
1990 | 1728 |
1991 (defun message-check-element (type) | 1729 (defun message-check-element (type) |
1992 "Returns non-nil if this type is not to be checked." | 1730 "Returns non-nil if this type is not to be checked." |
1993 (if (eq message-syntax-checks 'dont-check-for-anything-just-trust-me) | 1731 (if (eq message-syntax-checks 'dont-check-for-anything-just-trust-me) |
1994 t | 1732 t |
1995 (let ((able (assq type message-syntax-checks))) | 1733 (let ((able (assq type message-syntax-checks))) |
1996 (and (consp able) | 1734 (and (consp able) |
1997 (eq (cdr able) 'disabled))))) | 1735 (eq (cdr able) 'disabled))))) |
1998 | |
1999 (defun message-check-news-syntax () | |
2000 "Check the syntax of the message." | |
2001 (save-excursion | |
2002 (save-restriction | |
2003 (widen) | |
2004 (and | |
2005 ;; We narrow to the headers and check them first. | |
2006 (save-excursion | |
2007 (save-restriction | |
2008 (message-narrow-to-headers) | |
2009 (message-check-news-header-syntax))) | |
2010 ;; Check the body. | |
2011 (message-check-news-body-syntax))))) | |
2012 | |
2013 (defun message-check-news-header-syntax () | |
2014 (and | |
2015 ;; Check for commands in Subject. | |
2016 (message-check 'subject-cmsg | |
2017 (if (string-match "^cmsg " (message-fetch-field "subject")) | |
2018 (y-or-n-p | |
2019 "The control code \"cmsg\" is in the subject. Really post? ") | |
2020 t)) | |
2021 ;; Check for multiple identical headers. | |
2022 (message-check 'multiple-headers | |
2023 (let (found) | |
2024 (while (and (not found) | |
2025 (re-search-forward "^[^ \t:]+: " nil t)) | |
2026 (save-excursion | |
2027 (or (re-search-forward | |
2028 (concat "^" | |
2029 (regexp-quote | |
2030 (setq found | |
2031 (buffer-substring | |
2032 (match-beginning 0) (- (match-end 0) 2)))) | |
2033 ":") | |
2034 nil t) | |
2035 (setq found nil)))) | |
2036 (if found | |
2037 (y-or-n-p (format "Multiple %s headers. Really post? " found)) | |
2038 t))) | |
2039 ;; Check for Version and Sendsys. | |
2040 (message-check 'sendsys | |
2041 (if (re-search-forward "^Sendsys:\\|^Version:" nil t) | |
2042 (y-or-n-p | |
2043 (format "The article contains a %s command. Really post? " | |
2044 (buffer-substring (match-beginning 0) | |
2045 (1- (match-end 0))))) | |
2046 t)) | |
2047 ;; See whether we can shorten Followup-To. | |
2048 (message-check 'shorten-followup-to | |
2049 (let ((newsgroups (message-fetch-field "newsgroups")) | |
2050 (followup-to (message-fetch-field "followup-to")) | |
2051 to) | |
2052 (when (and newsgroups | |
2053 (string-match "," newsgroups) | |
2054 (not followup-to) | |
2055 (not | |
2056 (zerop | |
2057 (length | |
2058 (setq to (completing-read | |
2059 "Followups to: (default all groups) " | |
2060 (mapcar (lambda (g) (list g)) | |
2061 (cons "poster" | |
2062 (message-tokenize-header | |
2063 newsgroups))))))))) | |
2064 (goto-char (point-min)) | |
2065 (insert "Followup-To: " to "\n")) | |
2066 t)) | |
2067 ;; Check "Shoot me". | |
2068 (message-check 'shoot | |
2069 (if (re-search-forward | |
2070 "Message-ID.*.i-did-not-set--mail-host-address--so-shoot-me" nil t) | |
2071 (y-or-n-p "You appear to have a misconfigured system. Really post? ") | |
2072 t)) | |
2073 ;; Check for Approved. | |
2074 (message-check 'approved | |
2075 (if (re-search-forward "^Approved:" nil t) | |
2076 (y-or-n-p "The article contains an Approved header. Really post? ") | |
2077 t)) | |
2078 ;; Check the Message-ID header. | |
2079 (message-check 'message-id | |
2080 (let* ((case-fold-search t) | |
2081 (message-id (message-fetch-field "message-id" t))) | |
2082 (or (not message-id) | |
2083 (and (string-match "@" message-id) | |
2084 (string-match "@[^\\.]*\\." message-id)) | |
2085 (y-or-n-p | |
2086 (format "The Message-ID looks strange: \"%s\". Really post? " | |
2087 message-id))))) | |
2088 ;; Check the Subject header. | |
2089 (message-check 'subject | |
2090 (let* ((case-fold-search t) | |
2091 (subject (message-fetch-field "subject"))) | |
2092 (or | |
2093 (and subject | |
2094 (not (string-match "\\`[ \t]*\\'" subject))) | |
2095 (ignore | |
2096 (message | |
2097 "The subject field is empty or missing. Posting is denied."))))) | |
2098 ;; Check the Newsgroups & Followup-To headers. | |
2099 (message-check 'existing-newsgroups | |
2100 (let* ((case-fold-search t) | |
2101 (newsgroups (message-fetch-field "newsgroups")) | |
2102 (followup-to (message-fetch-field "followup-to")) | |
2103 (groups (message-tokenize-header | |
2104 (if followup-to | |
2105 (concat newsgroups "," followup-to) | |
2106 newsgroups))) | |
2107 (hashtb (and (boundp 'gnus-active-hashtb) | |
2108 gnus-active-hashtb)) | |
2109 errors) | |
2110 (if (or (not hashtb) | |
2111 (not (boundp 'gnus-read-active-file)) | |
2112 (not gnus-read-active-file) | |
2113 (eq gnus-read-active-file 'some)) | |
2114 t | |
2115 (while groups | |
2116 (when (and (not (boundp (intern (car groups) hashtb))) | |
2117 (not (equal (car groups) "poster"))) | |
2118 (push (car groups) errors)) | |
2119 (pop groups)) | |
2120 (if (not errors) | |
2121 t | |
2122 (y-or-n-p | |
2123 (format | |
2124 "Really post to %s unknown group%s: %s " | |
2125 (if (= (length errors) 1) "this" "these") | |
2126 (if (= (length errors) 1) "" "s") | |
2127 (mapconcat 'identity errors ", "))))))) | |
2128 ;; Check the Newsgroups & Followup-To headers for syntax errors. | |
2129 (message-check 'valid-newsgroups | |
2130 (let ((case-fold-search t) | |
2131 (headers '("Newsgroups" "Followup-To")) | |
2132 header error) | |
2133 (while (and headers (not error)) | |
2134 (when (setq header (mail-fetch-field (car headers))) | |
2135 (if (or | |
2136 (not | |
2137 (string-match | |
2138 "\\`\\([-+_&.a-zA-Z0-9]+\\)?\\(,[-+_&.a-zA-Z0-9]+\\)*\\'" | |
2139 header)) | |
2140 (memq | |
2141 nil (mapcar | |
2142 (lambda (g) | |
2143 (not (string-match "\\.\\'\\|\\.\\." g))) | |
2144 (message-tokenize-header header ",")))) | |
2145 (setq error t))) | |
2146 (unless error | |
2147 (pop headers))) | |
2148 (if (not error) | |
2149 t | |
2150 (y-or-n-p | |
2151 (format "The %s header looks odd: \"%s\". Really post? " | |
2152 (car headers) header))))) | |
2153 ;; Check the From header. | |
2154 (message-check 'from | |
2155 (let* ((case-fold-search t) | |
2156 (from (message-fetch-field "from")) | |
2157 (ad (nth 1 (mail-extract-address-components from)))) | |
2158 (cond | |
2159 ((not from) | |
2160 (message "There is no From line. Posting is denied.") | |
2161 nil) | |
2162 ((or (not (string-match "@[^\\.]*\\." ad)) ;larsi@ifi | |
2163 (string-match "\\.\\." ad) ;larsi@ifi..uio | |
2164 (string-match "@\\." ad) ;larsi@.ifi.uio | |
2165 (string-match "\\.$" ad) ;larsi@ifi.uio. | |
2166 (not (string-match "^[^@]+@[^@]+$" ad)) ;larsi.ifi.uio | |
2167 (string-match "(.*).*(.*)" from)) ;(lars) (lars) | |
2168 (message | |
2169 "Denied posting -- the From looks strange: \"%s\"." from) | |
2170 nil) | |
2171 (t t)))))) | |
2172 | |
2173 (defun message-check-news-body-syntax () | |
2174 (and | |
2175 ;; Check for long lines. | |
2176 (message-check 'long-lines | |
2177 (goto-char (point-min)) | |
2178 (re-search-forward | |
2179 (concat "^" (regexp-quote mail-header-separator) "$")) | |
2180 (while (and | |
2181 (progn | |
2182 (end-of-line) | |
2183 (< (current-column) 80)) | |
2184 (zerop (forward-line 1)))) | |
2185 (or (bolp) | |
2186 (eobp) | |
2187 (y-or-n-p | |
2188 "You have lines longer than 79 characters. Really post? "))) | |
2189 ;; Check whether the article is empty. | |
2190 (message-check 'empty | |
2191 (goto-char (point-min)) | |
2192 (re-search-forward | |
2193 (concat "^" (regexp-quote mail-header-separator) "$")) | |
2194 (forward-line 1) | |
2195 (let ((b (point))) | |
2196 (goto-char (point-max)) | |
2197 (re-search-backward message-signature-separator nil t) | |
2198 (beginning-of-line) | |
2199 (or (re-search-backward "[^ \n\t]" b t) | |
2200 (y-or-n-p "Empty article. Really post? ")))) | |
2201 ;; Check for control characters. | |
2202 (message-check 'control-chars | |
2203 (if (re-search-forward "[\000-\007\013\015-\037\200-\237]" nil t) | |
2204 (y-or-n-p | |
2205 "The article contains control characters. Really post? ") | |
2206 t)) | |
2207 ;; Check excessive size. | |
2208 (message-check 'size | |
2209 (if (> (buffer-size) 60000) | |
2210 (y-or-n-p | |
2211 (format "The article is %d octets long. Really post? " | |
2212 (buffer-size))) | |
2213 t)) | |
2214 ;; Check whether any new text has been added. | |
2215 (message-check 'new-text | |
2216 (or | |
2217 (not message-checksum) | |
2218 (not (and (eq (message-checksum) (car message-checksum)) | |
2219 (eq (buffer-size) (cdr message-checksum)))) | |
2220 (y-or-n-p | |
2221 "It looks like no new text has been added. Really post? "))) | |
2222 ;; Check the length of the signature. | |
2223 (message-check 'signature | |
2224 (goto-char (point-max)) | |
2225 (if (or (not (re-search-backward message-signature-separator nil t)) | |
2226 (search-forward message-forward-end-separator nil t)) | |
2227 t | |
2228 (if (> (count-lines (point) (point-max)) 5) | |
2229 (y-or-n-p | |
2230 (format | |
2231 "Your .sig is %d lines; it should be max 4. Really post? " | |
2232 (1- (count-lines (point) (point-max))))) | |
2233 t))))) | |
2234 | 1736 |
2235 (defun message-checksum () | 1737 (defun message-checksum () |
2236 "Return a \"checksum\" for the current buffer." | 1738 "Return a \"checksum\" for the current buffer." |
2237 (let ((sum 0)) | 1739 (let ((sum 0)) |
2238 (save-excursion | 1740 (save-excursion |
2280 (funcall message-fcc-handler-function file) | 1782 (funcall message-fcc-handler-function file) |
2281 (if (and (file-readable-p file) (mail-file-babyl-p file)) | 1783 (if (and (file-readable-p file) (mail-file-babyl-p file)) |
2282 (rmail-output file 1 nil t) | 1784 (rmail-output file 1 nil t) |
2283 (let ((mail-use-rfc822 t)) | 1785 (let ((mail-use-rfc822 t)) |
2284 (rmail-output file 1 t t)))))) | 1786 (rmail-output file 1 t t)))))) |
2285 | |
2286 (kill-buffer (current-buffer))))) | 1787 (kill-buffer (current-buffer))))) |
2287 | |
2288 (defun message-output (filename) | |
2289 "Append this article to Unix/babyl mail file.." | |
2290 (if (and (file-readable-p filename) | |
2291 (mail-file-babyl-p filename)) | |
2292 (gnus-output-to-rmail filename t) | |
2293 (gnus-output-to-mail filename t))) | |
2294 | 1788 |
2295 (defun message-cleanup-headers () | 1789 (defun message-cleanup-headers () |
2296 "Do various automatic cleanups of the headers." | 1790 "Do various automatic cleanups of the headers." |
2297 ;; Remove empty lines in the header. | 1791 ;; Remove empty lines in the header. |
2298 (save-restriction | 1792 (save-restriction |
2324 (replace-match "" t t))))) | 1818 (replace-match "" t t))))) |
2325 | 1819 |
2326 (defun message-make-date () | 1820 (defun message-make-date () |
2327 "Make a valid data header." | 1821 "Make a valid data header." |
2328 (let ((now (current-time))) | 1822 (let ((now (current-time))) |
2329 (timezone-make-date-arpa-standard | 1823 (timezone-make-date-arpa-standard |
2330 (current-time-string now) (current-time-zone now)))) | 1824 (current-time-string now) (current-time-zone now)))) |
2331 | 1825 |
2332 (defun message-make-message-id () | 1826 (defun message-make-message-id () |
2333 "Make a unique Message-ID." | 1827 "Make a unique Message-ID." |
2334 (concat "<" (message-unique-id) | 1828 (concat "<" (message-unique-id) |
2335 (let ((psubject (save-excursion (message-fetch-field "subject")))) | 1829 (let ((psubject (save-excursion (message-fetch-field "subject")))) |
2336 (if (and message-reply-headers | 1830 (if (and message-reply-headers |
2337 (mail-header-references message-reply-headers) | 1831 (mail-header-references message-reply-headers) |
2338 (mail-header-subject message-reply-headers) | 1832 (mail-header-subject message-reply-headers) |
2339 psubject | 1833 psubject |
2340 (mail-header-subject message-reply-headers) | 1834 (mail-header-subject message-reply-headers) |
2341 (not (string= | 1835 (not (string= |
2342 (message-strip-subject-re | 1836 (message-strip-subject-re |
2343 (mail-header-subject message-reply-headers)) | 1837 (mail-header-subject message-reply-headers)) |
2344 (message-strip-subject-re psubject)))) | 1838 (message-strip-subject-re psubject)))) |
2345 "_-_" "")) | 1839 "_-_" "")) |
2346 "@" (message-make-fqdn) ">")) | 1840 "@" (message-make-fqdn) ">")) |
2365 (let ((user (downcase (user-login-name)))) | 1859 (let ((user (downcase (user-login-name)))) |
2366 (while (string-match "[^a-z0-9_]" user) | 1860 (while (string-match "[^a-z0-9_]" user) |
2367 (aset user (match-beginning 0) ?_)) | 1861 (aset user (match-beginning 0) ?_)) |
2368 user) | 1862 user) |
2369 (message-number-base36 (user-uid) -1)) | 1863 (message-number-base36 (user-uid) -1)) |
2370 (message-number-base36 (+ (car tm) | 1864 (message-number-base36 (+ (car tm) |
2371 (lsh (% message-unique-id-char 25) 16)) 4) | 1865 (lsh (% message-unique-id-char 25) 16)) 4) |
2372 (message-number-base36 (+ (nth 1 tm) | 1866 (message-number-base36 (+ (nth 1 tm) |
2373 (lsh (/ message-unique-id-char 25) 16)) 4) | 1867 (lsh (/ message-unique-id-char 25) 16)) 4) |
2374 ;; Append the newsreader name, because while the generated | 1868 ;; Append the newsreader name, because while the generated |
2375 ;; ID is unique to this newsreader, other newsreaders might | 1869 ;; ID is unique to this newsreader, other newsreaders might |
2376 ;; otherwise generate the same ID via another algorithm. | 1870 ;; otherwise generate the same ID via another algorithm. |
2377 ".fsf"))) | 1871 ".fsf"))) |
2378 | 1872 |
2379 (defun message-number-base36 (num len) | 1873 (defun message-number-base36 (num len) |
2380 (if (if (< len 0) | 1874 (if (if (< len 0) (<= num 0) (= len 0)) |
2381 (<= num 0) | |
2382 (= len 0)) | |
2383 "" | 1875 "" |
2384 (concat (message-number-base36 (/ num 36) (1- len)) | 1876 (concat (message-number-base36 (/ num 36) (1- len)) |
2385 (char-to-string (aref "zyxwvutsrqponmlkjihgfedcba9876543210" | 1877 (char-to-string (aref "zyxwvutsrqponmlkjihgfedcba9876543210" |
2386 (% num 36)))))) | 1878 (% num 36)))))) |
2387 | 1879 |
2388 (defun message-make-organization () | 1880 (defun message-make-organization () |
2389 "Make an Organization header." | 1881 "Make an Organization header." |
2390 (let* ((organization | 1882 (let* ((organization |
2391 (or (getenv "ORGANIZATION") | 1883 (or (getenv "ORGANIZATION") |
2392 (when message-user-organization | 1884 (when message-user-organization |
2393 (if (message-functionp message-user-organization) | 1885 (if (message-functionp message-user-organization) |
2394 (funcall message-user-organization) | 1886 (funcall message-user-organization) |
2395 message-user-organization))))) | 1887 message-user-organization))))) |
2411 "Count the number of lines and return numeric string." | 1903 "Count the number of lines and return numeric string." |
2412 (save-excursion | 1904 (save-excursion |
2413 (save-restriction | 1905 (save-restriction |
2414 (widen) | 1906 (widen) |
2415 (goto-char (point-min)) | 1907 (goto-char (point-min)) |
2416 (re-search-forward | 1908 (re-search-forward |
2417 (concat "^" (regexp-quote mail-header-separator) "$")) | 1909 (concat "^" (regexp-quote mail-header-separator) "$")) |
2418 (forward-line 1) | 1910 (forward-line 1) |
2419 (int-to-string (count-lines (point) (point-max)))))) | 1911 (int-to-string (count-lines (point) (point-max)))))) |
2420 | 1912 |
2421 (defun message-make-in-reply-to () | 1913 (defun message-make-in-reply-to () |
2422 "Return the In-Reply-To header for this message." | 1914 "Return the In-Reply-To header for this message." |
2423 (when message-reply-headers | 1915 (when message-reply-headers |
2424 (let ((from (mail-header-from message-reply-headers)) | 1916 (let ((from (mail-header-from message-reply-headers)) |
2425 (date (mail-header-date message-reply-headers))) | 1917 (date (mail-header-date message-reply-headers))) |
2426 (when from | 1918 (when from |
2427 (let ((stop-pos | 1919 (let ((stop-pos |
2428 (string-match " *at \\| *@ \\| *(\\| *<" from))) | 1920 (string-match " *at \\| *@ \\| *(\\| *<" from))) |
2429 (concat (if stop-pos (substring from 0 stop-pos) from) | 1921 (concat (if stop-pos (substring from 0 stop-pos) from) |
2430 "'s message of " | 1922 "'s message of " |
2431 (if (or (not date) (string= date "")) | 1923 (if (or (not date) (string= date "")) |
2432 "(unknown date)" date))))))) | 1924 "(unknown date)" date))))))) |
2433 | 1925 |
2434 (defun message-make-distribution () | 1926 (defun message-make-distribution () |
2435 "Make a Distribution header." | 1927 "Make a Distribution header." |
2444 (future (* 1.0 message-expires 60 60 24))) | 1936 (future (* 1.0 message-expires 60 60 24))) |
2445 ;; Add the future to current. | 1937 ;; Add the future to current. |
2446 (setcar current (+ (car current) (round (/ future (expt 2 16))))) | 1938 (setcar current (+ (car current) (round (/ future (expt 2 16))))) |
2447 (setcar (cdr current) (+ (nth 1 current) (% (round future) (expt 2 16)))) | 1939 (setcar (cdr current) (+ (nth 1 current) (% (round future) (expt 2 16)))) |
2448 ;; Return the date in the future in UT. | 1940 ;; Return the date in the future in UT. |
2449 (timezone-make-date-arpa-standard | 1941 (timezone-make-date-arpa-standard |
2450 (current-time-string current) (current-time-zone current) '(0 "UT")))) | 1942 (current-time-string current) (current-time-zone current) '(0 "UT")))) |
2451 | 1943 |
2452 (defun message-make-path () | 1944 (defun message-make-path () |
2453 "Return uucp path." | 1945 "Return uucp path." |
2454 (let ((login-name (user-login-name))) | 1946 (let ((login-name (user-login-name))) |
2459 (concat message-user-path "!" login-name)) | 1951 (concat message-user-path "!" login-name)) |
2460 (t login-name)))) | 1952 (t login-name)))) |
2461 | 1953 |
2462 (defun message-make-from () | 1954 (defun message-make-from () |
2463 "Make a From header." | 1955 "Make a From header." |
2464 (let* ((style message-from-style) | 1956 (let* ((login (message-make-address)) |
2465 (login (message-make-address)) | 1957 (fullname |
2466 (fullname | |
2467 (or (and (boundp 'user-full-name) | 1958 (or (and (boundp 'user-full-name) |
2468 user-full-name) | 1959 user-full-name) |
2469 (user-full-name)))) | 1960 (user-full-name)))) |
2470 (when (string= fullname "&") | 1961 (when (string= fullname "&") |
2471 (setq fullname (user-login-name))) | 1962 (setq fullname (user-login-name))) |
2472 (save-excursion | 1963 (save-excursion |
2473 (message-set-work-buffer) | 1964 (message-set-work-buffer) |
2474 (cond | 1965 (cond |
2475 ((or (null style) | 1966 ((or (null message-from-style) |
2476 (equal fullname "")) | 1967 (equal fullname "")) |
2477 (insert login)) | 1968 (insert login)) |
2478 ((or (eq style 'angles) | 1969 ((or (eq message-from-style 'angles) |
2479 (and (not (eq style 'parens)) | 1970 (and (not (eq message-from-style 'parens)) |
2480 ;; Use angles if no quoting is needed, or if parens would | 1971 ;; Use angles if no quoting is needed, or if parens would |
2481 ;; need quoting too. | 1972 ;; need quoting too. |
2482 (or (not (string-match "[^- !#-'*+/-9=?A-Z^-~]" fullname)) | 1973 (or (not (string-match "[^- !#-'*+/-9=?A-Z^-~]" fullname)) |
2483 (let ((tmp (concat fullname nil))) | 1974 (let ((tmp (concat fullname nil))) |
2484 (while (string-match "([^()]*)" tmp) | 1975 (while (string-match "([^()]*)" tmp) |
2508 (while (re-search-forward "[()\\]" nil 1) | 1999 (while (re-search-forward "[()\\]" nil 1) |
2509 (replace-match "\\\\\\&" t)) | 2000 (replace-match "\\\\\\&" t)) |
2510 ;; ... then undo escaping of matching parentheses, | 2001 ;; ... then undo escaping of matching parentheses, |
2511 ;; including matching nested parentheses. | 2002 ;; including matching nested parentheses. |
2512 (goto-char fullname-start) | 2003 (goto-char fullname-start) |
2513 (while (re-search-forward | 2004 (while (re-search-forward |
2514 "\\(\\=\\|[^\\]\\(\\\\\\\\\\)*\\)\\\\(\\(\\([^\\]\\|\\\\\\\\\\)*\\)\\\\)" | 2005 "\\(\\=\\|[^\\]\\(\\\\\\\\\\)*\\)\\\\(\\(\\([^\\]\\|\\\\\\\\\\)*\\)\\\\)" |
2515 nil 1) | 2006 nil 1) |
2516 (replace-match "\\1(\\3)" t) | 2007 (replace-match "\\1(\\3)" t) |
2517 (goto-char fullname-start))) | 2008 (goto-char fullname-start))) |
2518 (insert ")"))) | 2009 (insert ")"))) |
2519 (buffer-string)))) | 2010 (buffer-string)))) |
2520 | 2011 |
2521 (defun message-make-sender () | 2012 (defun message-make-sender () |
2522 "Return the \"real\" user address. | 2013 "Return the \"real\" user address. |
2523 This function tries to ignore all user modifications, and | 2014 This function tries to ignore all user modifications, and |
2524 give as trustworthy answer as possible." | 2015 give as trustworthy answer as possible." |
2525 (concat (user-login-name) "@" (system-name))) | 2016 (concat (user-login-name) "@" (system-name))) |
2526 | 2017 |
2527 (defun message-make-address () | 2018 (defun message-make-address () |
2528 "Make the address of the user." | 2019 "Make the address of the user." |
2530 (concat (user-login-name) "@" (message-make-domain)))) | 2021 (concat (user-login-name) "@" (message-make-domain)))) |
2531 | 2022 |
2532 (defun message-user-mail-address () | 2023 (defun message-user-mail-address () |
2533 "Return the pertinent part of `user-mail-address'." | 2024 "Return the pertinent part of `user-mail-address'." |
2534 (when user-mail-address | 2025 (when user-mail-address |
2535 (if (string-match " " user-mail-address) | 2026 (nth 1 (mail-extract-address-components user-mail-address)))) |
2536 (nth 1 (mail-extract-address-components user-mail-address)) | |
2537 user-mail-address))) | |
2538 | 2027 |
2539 (defun message-make-fqdn () | 2028 (defun message-make-fqdn () |
2540 "Return user's fully qualified domain name." | 2029 "Return user's fully qualified domain name." |
2541 (let ((system-name (system-name)) | 2030 (let ((system-name (system-name)) |
2542 (user-mail (message-user-mail-address))) | 2031 (user-mail (message-user-mail-address))) |
2543 (cond | 2032 (cond |
2544 ((string-match "[^.]\\.[^.]" system-name) | 2033 ((string-match "[^.]\\.[^.]" system-name) |
2545 ;; `system-name' returned the right result. | 2034 ;; `system-name' returned the right result. |
2546 system-name) | 2035 system-name) |
2547 ;; Try `mail-host-address'. | 2036 ;; Try `mail-host-address'. |
2548 ((and (boundp 'mail-host-address) | 2037 ((and (boundp 'mail-host-address) |
2553 ((and (string-match "\\." user-mail) | 2042 ((and (string-match "\\." user-mail) |
2554 (string-match "@\\(.*\\)\\'" user-mail)) | 2043 (string-match "@\\(.*\\)\\'" user-mail)) |
2555 (match-string 1 user-mail)) | 2044 (match-string 1 user-mail)) |
2556 ;; Default to this bogus thing. | 2045 ;; Default to this bogus thing. |
2557 (t | 2046 (t |
2558 (concat system-name ".i-did-not-set--mail-host-address--so-shoot-me"))))) | 2047 (concat system-name ".i-have-a-misconfigured-system-so-shoot-me"))))) |
2559 | 2048 |
2560 (defun message-make-host-name () | 2049 (defun message-make-host-name () |
2561 "Return the name of the host." | 2050 "Return the name of the host." |
2562 (let ((fqdn (message-make-fqdn))) | 2051 (let ((fqdn (message-make-fqdn))) |
2563 (string-match "^[^.]+\\." fqdn) | 2052 (string-match "^[^.]+\\." fqdn) |
2592 header value elem) | 2081 header value elem) |
2593 ;; First we remove any old generated headers. | 2082 ;; First we remove any old generated headers. |
2594 (let ((headers message-deletable-headers)) | 2083 (let ((headers message-deletable-headers)) |
2595 (while headers | 2084 (while headers |
2596 (goto-char (point-min)) | 2085 (goto-char (point-min)) |
2597 (and (re-search-forward | 2086 (and (re-search-forward |
2598 (concat "^" (symbol-name (car headers)) ": *") nil t) | 2087 (concat "^" (symbol-name (car headers)) ": *") nil t) |
2599 (get-text-property (1+ (match-beginning 0)) 'message-deletable) | 2088 (get-text-property (1+ (match-beginning 0)) 'message-deletable) |
2600 (message-delete-line)) | 2089 (message-delete-line)) |
2601 (pop headers))) | 2090 (pop headers))) |
2602 ;; Go through all the required headers and see if they are in the | 2091 ;; Go through all the required headers and see if they are in the |
2603 ;; articles already. If they are not, or are empty, they are | 2092 ;; articles already. If they are not, or are empty, they are |
2604 ;; inserted automatically - except for Subject, Newsgroups and | 2093 ;; inserted automatically - except for Subject, Newsgroups and |
2605 ;; Distribution. | 2094 ;; Distribution. |
2606 (while headers | 2095 (while headers |
2607 (goto-char (point-min)) | 2096 (goto-char (point-min)) |
2608 (setq elem (pop headers)) | 2097 (setq elem (pop headers)) |
2609 (if (consp elem) | 2098 (if (consp elem) |
2610 (if (eq (car elem) 'optional) | 2099 (if (eq (car elem) 'optional) |
2611 (setq header (cdr elem)) | 2100 (setq header (cdr elem)) |
2612 (setq header (car elem))) | 2101 (setq header (car elem))) |
2613 (setq header elem)) | 2102 (setq header elem)) |
2614 (when (or (not (re-search-forward | 2103 (when (or (not (re-search-forward |
2615 (concat "^" (downcase (symbol-name header)) ":") | 2104 (concat "^" (downcase (symbol-name header)) ":") |
2616 nil t)) | 2105 nil t)) |
2617 (progn | 2106 (progn |
2618 ;; The header was found. We insert a space after the | 2107 ;; The header was found. We insert a space after the |
2619 ;; colon, if there is none. | 2108 ;; colon, if there is none. |
2620 (if (/= (following-char) ? ) (insert " ") (forward-char 1)) | 2109 (if (/= (following-char) ? ) (insert " ") (forward-char 1)) |
2621 ;; Find out whether the header is empty... | 2110 ;; Find out whether the header is empty... |
2622 (looking-at "[ \t]*$"))) | 2111 (looking-at "[ \t]*$"))) |
2623 ;; So we find out what value we should insert. | 2112 ;; So we find out what value we should insert. |
2624 (setq value | 2113 (setq value |
2625 (cond | 2114 (cond |
2626 ((and (consp elem) (eq (car elem) 'optional)) | 2115 ((and (consp elem) (eq (car elem) 'optional)) |
2627 ;; This is an optional header. If the cdr of this | 2116 ;; This is an optional header. If the cdr of this |
2628 ;; is something that is nil, then we do not insert | 2117 ;; is something that is nil, then we do not insert |
2629 ;; this header. | 2118 ;; this header. |
2630 (setq header (cdr elem)) | 2119 (setq header (cdr elem)) |
2645 ;; We couldn't generate a value for this header, | 2134 ;; We couldn't generate a value for this header, |
2646 ;; so we just ask the user. | 2135 ;; so we just ask the user. |
2647 (read-from-minibuffer | 2136 (read-from-minibuffer |
2648 (format "Empty header for %s; enter value: " header))))) | 2137 (format "Empty header for %s; enter value: " header))))) |
2649 ;; Finally insert the header. | 2138 ;; Finally insert the header. |
2650 (when (and value | 2139 (when (and value |
2651 (not (equal value ""))) | 2140 (not (equal value ""))) |
2652 (save-excursion | 2141 (save-excursion |
2653 (if (bolp) | 2142 (if (bolp) |
2654 (progn | 2143 (progn |
2655 ;; This header didn't exist, so we insert it. | 2144 ;; This header didn't exist, so we insert it. |
2656 (goto-char (point-max)) | 2145 (goto-char (point-max)) |
2657 (insert (symbol-name header) ": " value "\n") | 2146 (insert (symbol-name header) ": " value "\n") |
2658 (forward-line -1)) | 2147 (forward-line -1)) |
2659 ;; The value of this header was empty, so we clear | 2148 ;; The value of this header was empty, so we clear |
2660 ;; totally and insert the new value. | 2149 ;; totally and insert the new value. |
2661 (delete-region (point) (gnus-point-at-eol)) | 2150 (delete-region (point) (message-point-at-eol)) |
2662 (insert value)) | 2151 (insert value)) |
2663 ;; Add the deletable property to the headers that require it. | 2152 ;; Add the deletable property to the headers that require it. |
2664 (and (memq header message-deletable-headers) | 2153 (and (memq header message-deletable-headers) |
2665 (progn (beginning-of-line) (looking-at "[^:]+: ")) | 2154 (progn (beginning-of-line) (looking-at "[^:]+: ")) |
2666 (add-text-properties | 2155 (add-text-properties |
2667 (point) (match-end 0) | 2156 (point) (match-end 0) |
2668 '(message-deletable t face italic) (current-buffer))))))) | 2157 '(message-deletable t face italic) (current-buffer))))))) |
2669 ;; Insert new Sender if the From is strange. | 2158 ;; Insert new Sender if the From is strange. |
2670 (let ((from (message-fetch-field "from")) | 2159 (let ((from (message-fetch-field "from")) |
2671 (sender (message-fetch-field "sender")) | 2160 (sender (message-fetch-field "sender")) |
2672 (secure-sender (message-make-sender))) | 2161 (secure-sender (message-make-sender))) |
2673 (when (and from | 2162 (when (and from |
2674 (not (message-check-element 'sender)) | 2163 (not (message-check-element 'sender)) |
2675 (not (string= | 2164 (not (string= |
2676 (downcase | 2165 (downcase |
2677 (cadr (mail-extract-address-components from))) | 2166 (cadr (mail-extract-address-components from))) |
2678 (downcase secure-sender))) | 2167 (downcase secure-sender))) |
2679 (or (null sender) | 2168 (or (null sender) |
2680 (not | 2169 (not |
2681 (string= | 2170 (string= |
2682 (downcase | 2171 (downcase |
2683 (cadr (mail-extract-address-components sender))) | 2172 (cadr (mail-extract-address-components sender))) |
2684 (downcase secure-sender))))) | 2173 (downcase secure-sender))))) |
2685 (goto-char (point-min)) | 2174 (goto-char (point-min)) |
2686 ;; Rename any old Sender headers to Original-Sender. | 2175 ;; Rename any old Sender headers to Original-Sender. |
2687 (when (re-search-forward "^\\(Original-\\)*Sender:" nil t) | 2176 (when (re-search-forward "^Sender:" nil t) |
2688 (beginning-of-line) | 2177 (beginning-of-line) |
2689 (insert "Original-") | 2178 (insert "Original-") |
2690 (beginning-of-line)) | 2179 (beginning-of-line)) |
2691 (insert "Sender: " secure-sender "\n")))))) | 2180 (insert "Sender: " secure-sender "\n")))))) |
2692 | 2181 |
2693 (defun message-insert-courtesy-copy () | 2182 (defun message-insert-courtesy-copy () |
2694 "Insert a courtesy message in mail copies of combined messages." | 2183 "Insert a courtesy message in mail copies of combined messages." |
2695 (let (newsgroups) | 2184 (save-excursion |
2696 (save-excursion | 2185 (save-restriction |
2697 (save-restriction | 2186 (message-narrow-to-headers) |
2698 (message-narrow-to-headers) | 2187 (let ((newsgroups (message-fetch-field "newsgroups"))) |
2699 (when (setq newsgroups (message-fetch-field "newsgroups")) | 2188 (when newsgroups |
2700 (goto-char (point-max)) | 2189 (goto-char (point-max)) |
2701 (insert "Posted-To: " newsgroups "\n"))) | 2190 (insert "Posted-To: " newsgroups "\n")))) |
2702 (forward-line 1) | 2191 (forward-line 1) |
2703 (when message-courtesy-message | 2192 (insert message-courtesy-message))) |
2704 (cond | 2193 |
2705 ((string-match "%s" message-courtesy-message) | |
2706 (insert (format message-courtesy-message newsgroups))) | |
2707 (t | |
2708 (insert message-courtesy-message))))))) | |
2709 | |
2710 ;;; | 2194 ;;; |
2711 ;;; Setting up a message buffer | 2195 ;;; Setting up a message buffer |
2712 ;;; | 2196 ;;; |
2713 | 2197 |
2714 (defun message-fill-address (header value) | 2198 (defun message-fill-address (header value) |
2763 (goto-char (point-max))))) | 2247 (goto-char (point-max))))) |
2764 | 2248 |
2765 (defun message-position-point () | 2249 (defun message-position-point () |
2766 "Move point to where the user probably wants to find it." | 2250 "Move point to where the user probably wants to find it." |
2767 (message-narrow-to-headers) | 2251 (message-narrow-to-headers) |
2768 (cond | 2252 (cond |
2769 ((re-search-forward "^[^:]+:[ \t]*$" nil t) | 2253 ((re-search-forward "^[^:]+:[ \t]*$" nil t) |
2770 (search-backward ":" ) | 2254 (search-backward ":" ) |
2771 (widen) | 2255 (widen) |
2772 (forward-char 1) | 2256 (forward-char 1) |
2773 (if (= (following-char) ? ) | 2257 (if (= (following-char) ? ) |
2782 (sit-for 0))) | 2266 (sit-for 0))) |
2783 | 2267 |
2784 (defun message-buffer-name (type &optional to group) | 2268 (defun message-buffer-name (type &optional to group) |
2785 "Return a new (unique) buffer name based on TYPE and TO." | 2269 "Return a new (unique) buffer name based on TYPE and TO." |
2786 (cond | 2270 (cond |
2787 ;; Check whether `message-generate-new-buffers' is a function, | 2271 ;; Check whether `message-generate-new-buffers' is a function, |
2788 ;; and if so, call it. | 2272 ;; and if so, call it. |
2789 ((message-functionp message-generate-new-buffers) | 2273 ((message-functionp message-generate-new-buffers) |
2790 (funcall message-generate-new-buffers type to group)) | 2274 (funcall message-generate-new-buffers type to group)) |
2791 ;; Generate a new buffer name The Message Way. | 2275 ;; Generate a new buffer name The Message Way. |
2792 (message-generate-new-buffers | 2276 (message-generate-new-buffers |
2822 "Kill old message buffers." | 2306 "Kill old message buffers." |
2823 ;; We might have sent this buffer already. Delete it from the | 2307 ;; We might have sent this buffer already. Delete it from the |
2824 ;; list of buffers. | 2308 ;; list of buffers. |
2825 (setq message-buffer-list (delq (current-buffer) message-buffer-list)) | 2309 (setq message-buffer-list (delq (current-buffer) message-buffer-list)) |
2826 (while (and message-max-buffers | 2310 (while (and message-max-buffers |
2827 message-buffer-list | |
2828 (>= (length message-buffer-list) message-max-buffers)) | 2311 (>= (length message-buffer-list) message-max-buffers)) |
2829 ;; Kill the oldest buffer -- unless it has been changed. | 2312 ;; Kill the oldest buffer -- unless it has been changed. |
2830 (let ((buffer (pop message-buffer-list))) | 2313 (let ((buffer (pop message-buffer-list))) |
2831 (when (and (buffer-name buffer) | 2314 (when (and (buffer-name buffer) |
2832 (not (buffer-modified-p buffer))) | 2315 (not (buffer-modified-p buffer))) |
2833 (kill-buffer buffer)))) | 2316 (kill-buffer buffer)))) |
2834 ;; Rename the buffer. | 2317 ;; Rename the buffer. |
2835 (if message-send-rename-function | 2318 (if message-send-rename-function |
2836 (funcall message-send-rename-function) | 2319 (funcall message-send-rename-function) |
2837 (when (string-match "\\`\\*" (buffer-name)) | 2320 (when (string-match "\\`\\*" (buffer-name)) |
2838 (rename-buffer | 2321 (rename-buffer |
2839 (concat "*sent " (substring (buffer-name) (match-end 0))) t))) | 2322 (concat "*sent " (substring (buffer-name) (match-end 0))) t))) |
2840 ;; Push the current buffer onto the list. | 2323 ;; Push the current buffer onto the list. |
2841 (when message-max-buffers | 2324 (when message-max-buffers |
2842 (setq message-buffer-list | 2325 (setq message-buffer-list |
2843 (nconc message-buffer-list (list (current-buffer)))))) | 2326 (nconc message-buffer-list (list (current-buffer)))))) |
2844 | 2327 |
2845 (defvar mc-modes-alist) | 2328 (defvar mc-modes-alist) |
2846 (defun message-setup (headers &optional replybuffer actions) | 2329 (defun message-setup (headers &optional replybuffer actions) |
2847 (when (and (boundp 'mc-modes-alist) | 2330 (when (and (boundp 'mc-modes-alist) |
2852 (when actions | 2335 (when actions |
2853 (setq message-send-actions actions)) | 2336 (setq message-send-actions actions)) |
2854 (setq message-reply-buffer replybuffer) | 2337 (setq message-reply-buffer replybuffer) |
2855 (goto-char (point-min)) | 2338 (goto-char (point-min)) |
2856 ;; Insert all the headers. | 2339 ;; Insert all the headers. |
2857 (mail-header-format | 2340 (mail-header-format |
2858 (let ((h headers) | 2341 (let ((h headers) |
2859 (alist message-header-format-alist)) | 2342 (alist message-header-format-alist)) |
2860 (while h | 2343 (while h |
2861 (unless (assq (caar h) message-header-format-alist) | 2344 (unless (assq (caar h) message-header-format-alist) |
2862 (push (list (caar h)) alist)) | 2345 (push (list (caar h)) alist)) |
2904 "Associate the message buffer with a file in the drafts directory." | 2387 "Associate the message buffer with a file in the drafts directory." |
2905 (when message-autosave-directory | 2388 (when message-autosave-directory |
2906 (unless (file-exists-p message-autosave-directory) | 2389 (unless (file-exists-p message-autosave-directory) |
2907 (make-directory message-autosave-directory t)) | 2390 (make-directory message-autosave-directory t)) |
2908 (let ((name (make-temp-name | 2391 (let ((name (make-temp-name |
2909 (expand-file-name | 2392 (concat (file-name-as-directory message-autosave-directory) |
2910 (concat (file-name-as-directory message-autosave-directory) | 2393 "msg.")))) |
2911 "msg."))))) | |
2912 (setq buffer-auto-save-file-name | 2394 (setq buffer-auto-save-file-name |
2913 (save-excursion | 2395 (save-excursion |
2914 (prog1 | 2396 (prog1 |
2915 (progn | 2397 (progn |
2916 (set-buffer (get-buffer-create " *draft tmp*")) | 2398 (set-buffer (get-buffer-create " *draft tmp*")) |
2924 ;;; | 2406 ;;; |
2925 ;;; Commands for interfacing with message | 2407 ;;; Commands for interfacing with message |
2926 ;;; | 2408 ;;; |
2927 | 2409 |
2928 ;;;###autoload | 2410 ;;;###autoload |
2929 (defun message-mail (&optional to subject | 2411 (defun message-mail (&optional to subject) |
2930 other-headers continue switch-function | |
2931 yank-action send-actions) | |
2932 "Start editing a mail message to be sent." | 2412 "Start editing a mail message to be sent." |
2933 (interactive) | 2413 (interactive) |
2934 (let ((message-this-is-mail t)) | 2414 (message-pop-to-buffer (message-buffer-name "mail" to)) |
2935 (message-pop-to-buffer (message-buffer-name "mail" to)) | 2415 (message-setup `((To . ,(or to "")) (Subject . ,(or subject ""))))) |
2936 (message-setup | |
2937 (nconc | |
2938 `((To . ,(or to "")) (Subject . ,(or subject ""))) | |
2939 (when other-headers other-headers))))) | |
2940 | 2416 |
2941 ;;;###autoload | 2417 ;;;###autoload |
2942 (defun message-news (&optional newsgroups subject) | 2418 (defun message-news (&optional newsgroups subject) |
2943 "Start editing a news article to be sent." | 2419 "Start editing a news article to be sent." |
2944 (interactive) | 2420 (interactive) |
2945 (let ((message-this-is-news t)) | 2421 (message-pop-to-buffer (message-buffer-name "news" nil newsgroups)) |
2946 (message-pop-to-buffer (message-buffer-name "news" nil newsgroups)) | 2422 (message-setup `((Newsgroups . ,(or newsgroups "")) |
2947 (message-setup `((Newsgroups . ,(or newsgroups "")) | 2423 (Subject . ,(or subject ""))))) |
2948 (Subject . ,(or subject "")))))) | |
2949 | 2424 |
2950 ;;;###autoload | 2425 ;;;###autoload |
2951 (defun message-reply (&optional to-address wide ignore-reply-to) | 2426 (defun message-reply (&optional to-address wide ignore-reply-to) |
2952 "Start editing a reply to the article in the current buffer." | 2427 "Start editing a reply to the article in the current buffer." |
2953 (interactive) | 2428 (interactive) |
2954 (let ((cur (current-buffer)) | 2429 (let ((cur (current-buffer)) |
2955 from subject date reply-to to cc | 2430 from subject date reply-to to cc |
2956 references message-id follow-to | 2431 references message-id follow-to |
2957 (inhibit-point-motion-hooks t) | 2432 (inhibit-point-motion-hooks t) |
2958 mct never-mct gnus-warning) | 2433 mct never-mct gnus-warning) |
2959 (save-restriction | 2434 (save-restriction |
2960 (message-narrow-to-head) | 2435 (narrow-to-region |
2436 (goto-char (point-min)) | |
2437 (if (search-forward "\n\n" nil t) | |
2438 (1- (point)) | |
2439 (point-max))) | |
2961 ;; Allow customizations to have their say. | 2440 ;; Allow customizations to have their say. |
2962 (if (not wide) | 2441 (if (not wide) |
2963 ;; This is a regular reply. | 2442 ;; This is a regular reply. |
2964 (if (message-functionp message-reply-to-function) | 2443 (if (message-functionp message-reply-to-function) |
2965 (setq follow-to (funcall message-reply-to-function))) | 2444 (setq follow-to (funcall message-reply-to-function))) |
2968 (save-excursion | 2447 (save-excursion |
2969 (setq follow-to | 2448 (setq follow-to |
2970 (funcall message-wide-reply-to-function))))) | 2449 (funcall message-wide-reply-to-function))))) |
2971 ;; Find all relevant headers we need. | 2450 ;; Find all relevant headers we need. |
2972 (setq from (message-fetch-field "from") | 2451 (setq from (message-fetch-field "from") |
2973 date (message-fetch-field "date") | 2452 date (message-fetch-field "date") |
2974 subject (or (message-fetch-field "subject") "none") | 2453 subject (or (message-fetch-field "subject") "none") |
2975 to (message-fetch-field "to") | 2454 to (message-fetch-field "to") |
2976 cc (message-fetch-field "cc") | 2455 cc (message-fetch-field "cc") |
2977 mct (message-fetch-field "mail-copies-to") | 2456 mct (message-fetch-field "mail-copies-to") |
2978 reply-to (unless ignore-reply-to (message-fetch-field "reply-to")) | 2457 reply-to (unless ignore-reply-to (message-fetch-field "reply-to")) |
2979 references (message-fetch-field "references") | 2458 references (message-fetch-field "references") |
2980 message-id (message-fetch-field "message-id" t)) | 2459 message-id (message-fetch-field "message-id")) |
2981 ;; Remove any (buggy) Re:'s that are present and make a | 2460 ;; Remove any (buggy) Re:'s that are present and make a |
2982 ;; proper one. | 2461 ;; proper one. |
2983 (when (string-match "^[ \t]*[Rr][Ee]:[ \t]*" subject) | 2462 (when (string-match "^[ \t]*[Rr][Ee]:[ \t]*" subject) |
2984 (setq subject (substring subject (match-end 0)))) | 2463 (setq subject (substring subject (match-end 0)))) |
2985 (setq subject (concat "Re: " subject)) | 2464 (setq subject (concat "Re: " subject)) |
2986 | 2465 |
2987 (when (and (setq gnus-warning (message-fetch-field "gnus-warning")) | 2466 (when (and (setq gnus-warning (message-fetch-field "gnus-warning")) |
2988 (string-match "<[^>]+>" gnus-warning)) | 2467 (string-match "<[^>]+>" gnus-warning)) |
2989 (setq message-id (match-string 0 gnus-warning))) | 2468 (setq message-id (match-string 0 gnus-warning))) |
2990 | 2469 |
2991 ;; Handle special values of Mail-Copies-To. | 2470 ;; Handle special values of Mail-Copies-To. |
2992 (when mct | 2471 (when mct |
2993 (cond ((equal (downcase mct) "never") | 2472 (cond ((equal (downcase mct) "never") |
2994 (setq never-mct t) | 2473 (setq never-mct t) |
2995 (setq mct nil)) | 2474 (setq mct nil)) |
3006 (unless never-mct | 2485 (unless never-mct |
3007 (insert (or reply-to from ""))) | 2486 (insert (or reply-to from ""))) |
3008 (insert (if (bolp) "" ", ") (or to "")) | 2487 (insert (if (bolp) "" ", ") (or to "")) |
3009 (insert (if mct (concat (if (bolp) "" ", ") mct) "")) | 2488 (insert (if mct (concat (if (bolp) "" ", ") mct) "")) |
3010 (insert (if cc (concat (if (bolp) "" ", ") cc) "")) | 2489 (insert (if cc (concat (if (bolp) "" ", ") cc) "")) |
3011 (goto-char (point-min)) | 2490 ;; Remove addresses that match `rmail-dont-reply-to-names'. |
3012 (while (re-search-forward "[ \t]+" nil t) | |
3013 (replace-match " " t t)) | |
3014 ;; Remove addresses that match `rmail-dont-reply-to-names'. | |
3015 (insert (prog1 (rmail-dont-reply-to (buffer-string)) | 2491 (insert (prog1 (rmail-dont-reply-to (buffer-string)) |
3016 (erase-buffer))) | 2492 (erase-buffer))) |
3017 (goto-char (point-min)) | 2493 (goto-char (point-min)) |
3018 ;; Perhaps Mail-Copies-To: never removed the only address? | |
3019 (when (eobp) | |
3020 (insert (or reply-to from ""))) | |
3021 (setq ccalist | 2494 (setq ccalist |
3022 (mapcar | 2495 (mapcar |
3023 (lambda (addr) | 2496 (lambda (addr) |
3024 (cons (mail-strip-quoted-names addr) addr)) | 2497 (cons (mail-strip-quoted-names addr) addr)) |
3025 (message-tokenize-header (buffer-string)))) | 2498 (message-tokenize-header (buffer-string)))) |
3026 (let ((s ccalist)) | 2499 (let ((s ccalist)) |
3027 (while s | 2500 (while s |
3028 (setq ccalist (delq (assoc (car (pop s)) s) ccalist))))) | 2501 (setq ccalist (delq (assoc (car (pop s)) s) ccalist))))) |
3029 (setq follow-to (list (cons 'To (cdr (pop ccalist))))) | 2502 (setq follow-to (list (cons 'To (cdr (pop ccalist))))) |
3030 (when ccalist | 2503 (when ccalist |
3031 (let ((ccs (cons 'Cc (mapconcat | 2504 (push (cons 'Cc |
3032 (lambda (addr) (cdr addr)) ccalist ", ")))) | 2505 (mapconcat (lambda (addr) (cdr addr)) ccalist ", ")) |
3033 (when (string-match "^ +" (cdr ccs)) | 2506 follow-to))))) |
3034 (setcdr ccs (substring (cdr ccs) (match-end 0)))) | |
3035 (push ccs follow-to)))))) | |
3036 (widen)) | 2507 (widen)) |
3037 | 2508 |
3038 (message-pop-to-buffer (message-buffer-name | 2509 (message-pop-to-buffer (message-buffer-name |
3039 (if wide "wide reply" "reply") from | 2510 (if wide "wide reply" "reply") from |
3040 (if wide to-address nil))) | 2511 (if wide to-address nil))) |
3042 (setq message-reply-headers | 2513 (setq message-reply-headers |
3043 (vector 0 subject from date message-id references 0 0 "")) | 2514 (vector 0 subject from date message-id references 0 0 "")) |
3044 | 2515 |
3045 (message-setup | 2516 (message-setup |
3046 `((Subject . ,subject) | 2517 `((Subject . ,subject) |
3047 ,@follow-to | 2518 ,@follow-to |
3048 ,@(if (or references message-id) | 2519 ,@(if (or references message-id) |
3049 `((References . ,(concat (or references "") (and references " ") | 2520 `((References . ,(concat (or references "") (and references " ") |
3050 (or message-id "")))) | 2521 (or message-id "")))) |
3051 nil)) | 2522 nil)) |
3052 cur))) | 2523 cur))) |
3053 | 2524 |
3054 ;;;###autoload | 2525 ;;;###autoload |
3055 (defun message-wide-reply (&optional to-address) | 2526 (defun message-wide-reply (&optional to-address) |
3056 "Make a \"wide\" reply to the message in the current buffer." | |
3057 (interactive) | 2527 (interactive) |
3058 (message-reply to-address t)) | 2528 (message-reply to-address t)) |
3059 | 2529 |
3060 ;;;###autoload | 2530 ;;;###autoload |
3061 (defun message-followup (&optional to-newsgroups) | 2531 (defun message-followup () |
3062 "Follow up to the message in the current buffer. | |
3063 If TO-NEWSGROUPS, use that as the new Newsgroups line." | |
3064 (interactive) | 2532 (interactive) |
3065 (let ((cur (current-buffer)) | 2533 (let ((cur (current-buffer)) |
3066 from subject date reply-to mct | 2534 from subject date reply-to mct |
3067 references message-id follow-to | 2535 references message-id follow-to |
3068 (inhibit-point-motion-hooks t) | 2536 (inhibit-point-motion-hooks t) |
3069 (message-this-is-news t) | 2537 followup-to distribution newsgroups gnus-warning) |
3070 followup-to distribution newsgroups gnus-warning posted-to) | |
3071 (save-restriction | 2538 (save-restriction |
3072 (narrow-to-region | 2539 (narrow-to-region |
3073 (goto-char (point-min)) | 2540 (goto-char (point-min)) |
3074 (if (search-forward "\n\n" nil t) | 2541 (if (search-forward "\n\n" nil t) |
3075 (1- (point)) | 2542 (1- (point)) |
3076 (point-max))) | 2543 (point-max))) |
3077 (when (message-functionp message-followup-to-function) | 2544 (when (message-functionp message-followup-to-function) |
3078 (setq follow-to | 2545 (setq follow-to |
3079 (funcall message-followup-to-function))) | 2546 (funcall message-followup-to-function))) |
3080 (setq from (message-fetch-field "from") | 2547 (setq from (message-fetch-field "from") |
3081 date (message-fetch-field "date") | 2548 date (message-fetch-field "date") |
3082 subject (or (message-fetch-field "subject") "none") | 2549 subject (or (message-fetch-field "subject") "none") |
3083 references (message-fetch-field "references") | 2550 references (message-fetch-field "references") |
3084 message-id (message-fetch-field "message-id" t) | 2551 message-id (message-fetch-field "message-id") |
3085 followup-to (message-fetch-field "followup-to") | 2552 followup-to (message-fetch-field "followup-to") |
3086 newsgroups (message-fetch-field "newsgroups") | 2553 newsgroups (message-fetch-field "newsgroups") |
3087 posted-to (message-fetch-field "posted-to") | |
3088 reply-to (message-fetch-field "reply-to") | 2554 reply-to (message-fetch-field "reply-to") |
3089 distribution (message-fetch-field "distribution") | 2555 distribution (message-fetch-field "distribution") |
3090 mct (message-fetch-field "mail-copies-to")) | 2556 mct (message-fetch-field "mail-copies-to")) |
3091 (when (and (setq gnus-warning (message-fetch-field "gnus-warning")) | 2557 (when (and (setq gnus-warning (message-fetch-field "gnus-warning")) |
3092 (string-match "<[^>]+>" gnus-warning)) | 2558 (string-match "<[^>]+>" gnus-warning)) |
3093 (setq message-id (match-string 0 gnus-warning))) | 2559 (setq message-id (match-string 0 gnus-warning))) |
3094 ;; Remove bogus distribution. | 2560 ;; Remove bogus distribution. |
3095 (when (and (stringp distribution) | 2561 (and (stringp distribution) |
3096 (let ((case-fold-search t)) | 2562 (string-match "world" distribution) |
3097 (string-match "world" distribution))) | 2563 (setq distribution nil)) |
3098 (setq distribution nil)) | |
3099 ;; Remove any (buggy) Re:'s that are present and make a | 2564 ;; Remove any (buggy) Re:'s that are present and make a |
3100 ;; proper one. | 2565 ;; proper one. |
3101 (when (string-match "^[ \t]*[Rr][Ee]:[ \t]*" subject) | 2566 (when (string-match "^[ \t]*[Rr][Ee]:[ \t]*" subject) |
3102 (setq subject (substring subject (match-end 0)))) | 2567 (setq subject (substring subject (match-end 0)))) |
3103 (setq subject (concat "Re: " subject)) | 2568 (setq subject (concat "Re: " subject)) |
3105 | 2570 |
3106 (message-pop-to-buffer (message-buffer-name "followup" from newsgroups)) | 2571 (message-pop-to-buffer (message-buffer-name "followup" from newsgroups)) |
3107 | 2572 |
3108 (message-setup | 2573 (message-setup |
3109 `((Subject . ,subject) | 2574 `((Subject . ,subject) |
3110 ,@(cond | 2575 ,@(cond |
3111 (to-newsgroups | |
3112 (list (cons 'Newsgroups to-newsgroups))) | |
3113 (follow-to follow-to) | 2576 (follow-to follow-to) |
3114 ((and followup-to message-use-followup-to) | 2577 ((and followup-to message-use-followup-to) |
3115 (list | 2578 (list |
3116 (cond | 2579 (cond |
3117 ((equal (downcase followup-to) "poster") | 2580 ((equal (downcase followup-to) "poster") |
3118 (if (or (eq message-use-followup-to 'use) | 2581 (if (or (eq message-use-followup-to 'use) |
3119 (message-y-or-n-p "Obey Followup-To: poster? " t "\ | 2582 (message-y-or-n-p "Obey Followup-To: poster? " t "\ |
3120 You should normally obey the Followup-To: header. | 2583 You should normally obey the Followup-To: header. |
3121 | 2584 |
3122 `Followup-To: poster' sends your response via e-mail instead of news. | 2585 `Followup-To: poster' sends your response via e-mail instead of news. |
3123 | 2586 |
3124 A typical situation where `Followup-To: poster' is used is when the poster | 2587 A typical situation where `Followup-To: poster' is used is when the poster |
3125 does not read the newsgroup, so he wouldn't see any replies sent to it.")) | 2588 does not read the newsgroup, so he wouldn't see any replies sent to it.")) |
3126 (progn | 2589 (cons 'To (or reply-to from "")) |
3127 (setq message-this-is-news nil) | |
3128 (cons 'To (or reply-to from ""))) | |
3129 (cons 'Newsgroups newsgroups))) | 2590 (cons 'Newsgroups newsgroups))) |
3130 (t | 2591 (t |
3131 (if (or (equal followup-to newsgroups) | 2592 (if (or (equal followup-to newsgroups) |
3132 (not (eq message-use-followup-to 'ask)) | 2593 (not (eq message-use-followup-to 'ask)) |
3133 (message-y-or-n-p | 2594 (message-y-or-n-p |
3142 If a message is posted to several newsgroups, Followup-To is often | 2603 If a message is posted to several newsgroups, Followup-To is often |
3143 used to direct the following discussion to one newsgroup only, | 2604 used to direct the following discussion to one newsgroup only, |
3144 because discussions that are spread over several newsgroup tend to | 2605 because discussions that are spread over several newsgroup tend to |
3145 be fragmented and very difficult to follow. | 2606 be fragmented and very difficult to follow. |
3146 | 2607 |
3147 Also, some source/announcement newsgroups are not indented for discussion; | 2608 Also, some source/announcment newsgroups are not indented for discussion; |
3148 responses here are directed to other newsgroups.")) | 2609 responses here are directed to other newsgroups.")) |
3149 (cons 'Newsgroups followup-to) | 2610 (cons 'Newsgroups followup-to) |
3150 (cons 'Newsgroups newsgroups)))))) | 2611 (cons 'Newsgroups newsgroups)))))) |
3151 (posted-to | |
3152 `((Newsgroups . ,posted-to))) | |
3153 (t | 2612 (t |
3154 `((Newsgroups . ,newsgroups)))) | 2613 `((Newsgroups . ,newsgroups)))) |
3155 ,@(and distribution (list (cons 'Distribution distribution))) | 2614 ,@(and distribution (list (cons 'Distribution distribution))) |
3156 ,@(if (or references message-id) | 2615 (References . ,(concat (or references "") (and references " ") |
3157 `((References . ,(concat (or references "") (and references " ") | 2616 (or message-id ""))) |
3158 (or message-id ""))))) | |
3159 ,@(when (and mct | 2617 ,@(when (and mct |
3160 (not (equal (downcase mct) "never"))) | 2618 (not (equal (downcase mct) "never"))) |
3161 (list (cons 'Cc (if (equal (downcase mct) "always") | 2619 (list (cons 'Cc (if (equal (downcase mct) "always") |
3162 (or reply-to from "") | 2620 (or reply-to from "") |
3163 mct))))) | 2621 mct))))) |
3180 ;; Get header info. from original article. | 2638 ;; Get header info. from original article. |
3181 (save-restriction | 2639 (save-restriction |
3182 (message-narrow-to-head) | 2640 (message-narrow-to-head) |
3183 (setq from (message-fetch-field "from") | 2641 (setq from (message-fetch-field "from") |
3184 newsgroups (message-fetch-field "newsgroups") | 2642 newsgroups (message-fetch-field "newsgroups") |
3185 message-id (message-fetch-field "message-id" t) | 2643 message-id (message-fetch-field "message-id") |
3186 distribution (message-fetch-field "distribution"))) | 2644 distribution (message-fetch-field "distribution"))) |
3187 ;; Make sure that this article was written by the user. | 2645 ;; Make sure that this article was written by the user. |
3188 (unless (string-equal | 2646 (unless (string-equal |
3189 (downcase (cadr (mail-extract-address-components from))) | 2647 (downcase (cadr (mail-extract-address-components from))) |
3190 (downcase (message-make-address))) | 2648 (downcase (message-make-address))) |
3199 "Control: cancel " message-id "\n" | 2657 "Control: cancel " message-id "\n" |
3200 (if distribution | 2658 (if distribution |
3201 (concat "Distribution: " distribution "\n") | 2659 (concat "Distribution: " distribution "\n") |
3202 "") | 2660 "") |
3203 mail-header-separator "\n" | 2661 mail-header-separator "\n" |
3204 message-cancel-message) | 2662 "This is a cancel message from " from ".\n") |
3205 (message "Canceling your article...") | 2663 (message "Canceling your article...") |
3206 (let ((message-syntax-checks 'dont-check-for-anything-just-trust-me)) | 2664 (let ((message-syntax-checks 'dont-check-for-anything-just-trust-me)) |
3207 (funcall message-send-news-function)) | 2665 (funcall message-send-news-function)) |
3208 (message "Canceling your article...done") | 2666 (message "Canceling your article...done") |
3209 (kill-buffer buf))))) | 2667 (kill-buffer buf))))) |
3213 "Start composing a message to supersede the current message. | 2671 "Start composing a message to supersede the current message. |
3214 This is done simply by taking the old article and adding a Supersedes | 2672 This is done simply by taking the old article and adding a Supersedes |
3215 header line with the old Message-ID." | 2673 header line with the old Message-ID." |
3216 (interactive) | 2674 (interactive) |
3217 (let ((cur (current-buffer))) | 2675 (let ((cur (current-buffer))) |
3218 ;; Check whether the user owns the article that is to be superseded. | 2676 ;; Check whether the user owns the article that is to be superseded. |
3219 (unless (string-equal | 2677 (unless (string-equal |
3220 (downcase (cadr (mail-extract-address-components | 2678 (downcase (cadr (mail-extract-address-components |
3221 (message-fetch-field "from")))) | 2679 (message-fetch-field "from")))) |
3222 (downcase (message-make-address))) | 2680 (downcase (message-make-address))) |
3223 (error "This article is not yours")) | 2681 (error "This article is not yours")) |
3257 | 2715 |
3258 ;;; Forwarding messages. | 2716 ;;; Forwarding messages. |
3259 | 2717 |
3260 (defun message-make-forward-subject () | 2718 (defun message-make-forward-subject () |
3261 "Return a Subject header suitable for the message in the current buffer." | 2719 "Return a Subject header suitable for the message in the current buffer." |
3262 (save-excursion | 2720 (concat "[" (or (message-fetch-field (if (message-news-p) "newsgroups" "from")) |
3263 (save-restriction | 2721 "(nowhere)") |
3264 (current-buffer) | 2722 "] " (or (message-fetch-field "Subject") ""))) |
3265 (message-narrow-to-head) | |
3266 (concat "[" (or (message-fetch-field | |
3267 (if (message-news-p) "newsgroups" "from")) | |
3268 "(nowhere)") | |
3269 "] " (or (message-fetch-field "Subject") ""))))) | |
3270 | 2723 |
3271 ;;;###autoload | 2724 ;;;###autoload |
3272 (defun message-forward (&optional news) | 2725 (defun message-forward (&optional news) |
3273 "Forward the current message via mail. | 2726 "Forward the current message via mail. |
3274 Optional NEWS will use news to forward instead of mail." | 2727 Optional NEWS will use news to forward instead of mail." |
3275 (interactive "P") | 2728 (interactive "P") |
3276 (let ((cur (current-buffer)) | 2729 (let ((cur (current-buffer)) |
3277 (subject (message-make-forward-subject)) | 2730 (subject (message-make-forward-subject))) |
3278 art-beg) | |
3279 (if news (message-news nil subject) (message-mail nil subject)) | 2731 (if news (message-news nil subject) (message-mail nil subject)) |
3280 ;; Put point where we want it before inserting the forwarded | 2732 ;; Put point where we want it before inserting the forwarded |
3281 ;; message. | 2733 ;; message. |
3282 (if message-signature-before-forwarded-message | 2734 (if message-signature-before-forwarded-message |
3283 (goto-char (point-max)) | 2735 (goto-char (point-max)) |
3284 (message-goto-body)) | 2736 (message-goto-body)) |
3285 ;; Make sure we're at the start of the line. | 2737 ;; Make sure we're at the start of the line. |
3286 (unless (eolp) | 2738 (unless (eolp) |
3287 (insert "\n")) | 2739 (insert "\n")) |
3288 ;; Narrow to the area we are to insert. | 2740 ;; Narrow to the area we are to insert. |
3289 (narrow-to-region (point) (point)) | 2741 (narrow-to-region (point) (point)) |
3290 ;; Insert the separators and the forwarded buffer. | 2742 ;; Insert the separators and the forwarded buffer. |
3291 (insert message-forward-start-separator) | 2743 (insert message-forward-start-separator) |
3292 (setq art-beg (point)) | |
3293 (insert-buffer-substring cur) | 2744 (insert-buffer-substring cur) |
3294 (goto-char (point-max)) | 2745 (goto-char (point-max)) |
3295 (insert message-forward-end-separator) | 2746 (insert message-forward-end-separator) |
3296 (set-text-properties (point-min) (point-max) nil) | 2747 (set-text-properties (point-min) (point-max) nil) |
3297 ;; Remove all unwanted headers. | 2748 ;; Remove all unwanted headers. |
3298 (goto-char art-beg) | 2749 (goto-char (point-min)) |
2750 (forward-line 1) | |
3299 (narrow-to-region (point) (if (search-forward "\n\n" nil t) | 2751 (narrow-to-region (point) (if (search-forward "\n\n" nil t) |
3300 (1- (point)) | 2752 (1- (point)) |
3301 (point))) | 2753 (point))) |
3302 (goto-char (point-min)) | 2754 (goto-char (point-min)) |
3303 (message-remove-header message-included-forward-headers t nil t) | 2755 (message-remove-header message-included-forward-headers t nil t) |
3306 | 2758 |
3307 ;;;###autoload | 2759 ;;;###autoload |
3308 (defun message-resend (address) | 2760 (defun message-resend (address) |
3309 "Resend the current article to ADDRESS." | 2761 "Resend the current article to ADDRESS." |
3310 (interactive "sResend message to: ") | 2762 (interactive "sResend message to: ") |
3311 (message "Resending message to %s..." address) | |
3312 (save-excursion | 2763 (save-excursion |
3313 (let ((cur (current-buffer)) | 2764 (let ((cur (current-buffer)) |
3314 beg) | 2765 beg) |
3315 ;; We first set up a normal mail buffer. | 2766 ;; We first set up a normal mail buffer. |
3316 (set-buffer (get-buffer-create " *message resend*")) | 2767 (set-buffer (get-buffer-create " *message resend*")) |
3340 (insert mail-header-separator) | 2791 (insert mail-header-separator) |
3341 ;; Rename all old ("Also-")Resent headers. | 2792 ;; Rename all old ("Also-")Resent headers. |
3342 (while (re-search-backward "^\\(Also-\\)?Resent-" beg t) | 2793 (while (re-search-backward "^\\(Also-\\)?Resent-" beg t) |
3343 (beginning-of-line) | 2794 (beginning-of-line) |
3344 (insert "Also-")) | 2795 (insert "Also-")) |
3345 ;; Quote any "From " lines at the beginning. | |
3346 (goto-char beg) | |
3347 (when (looking-at "From ") | |
3348 (replace-match "X-From-Line: ")) | |
3349 ;; Send it. | 2796 ;; Send it. |
3350 (message-send-mail) | 2797 (message-send-mail) |
3351 (kill-buffer (current-buffer))) | 2798 (kill-buffer (current-buffer))))) |
3352 (message "Resending message to %s...done" address))) | |
3353 | 2799 |
3354 ;;;###autoload | 2800 ;;;###autoload |
3355 (defun message-bounce () | 2801 (defun message-bounce () |
3356 "Re-mail the current message. | 2802 "Re-mail the current message. |
3357 This only makes sense if the current message is a bounce message than | 2803 This only makes sense if the current message is a bounce message than |
3379 (and (re-search-forward message-unsent-separator nil t) | 2825 (and (re-search-forward message-unsent-separator nil t) |
3380 (forward-line 1)) | 2826 (forward-line 1)) |
3381 (and (search-forward "\n\n" nil t) | 2827 (and (search-forward "\n\n" nil t) |
3382 (re-search-forward "^Return-Path:.*\n" nil t))) | 2828 (re-search-forward "^Return-Path:.*\n" nil t))) |
3383 ;; We remove everything before the bounced mail. | 2829 ;; We remove everything before the bounced mail. |
3384 (delete-region | 2830 (delete-region |
3385 (point-min) | 2831 (point-min) |
3386 (if (re-search-forward "^[^ \n\t]+:" nil t) | 2832 (if (re-search-forward "^[^ \n\t]+:" nil t) |
3387 (match-beginning 0) | 2833 (match-beginning 0) |
3388 (point))) | 2834 (point))) |
3389 (save-restriction | 2835 (save-restriction |
3429 (special-display-buffer-names nil) | 2875 (special-display-buffer-names nil) |
3430 (special-display-regexps nil) | 2876 (special-display-regexps nil) |
3431 (same-window-buffer-names nil) | 2877 (same-window-buffer-names nil) |
3432 (same-window-regexps nil)) | 2878 (same-window-regexps nil)) |
3433 (message-pop-to-buffer (message-buffer-name "news" nil newsgroups))) | 2879 (message-pop-to-buffer (message-buffer-name "news" nil newsgroups))) |
3434 (message-setup `((Newsgroups . ,(or newsgroups "")) | 2880 (message-setup `((Newsgroups . ,(or newsgroups "")) |
3435 (Subject . ,(or subject ""))))) | 2881 (Subject . ,(or subject ""))))) |
3436 | 2882 |
3437 ;;;###autoload | 2883 ;;;###autoload |
3438 (defun message-news-other-frame (&optional newsgroups subject) | 2884 (defun message-news-other-frame (&optional newsgroups subject) |
3439 "Start editing a news article to be sent." | 2885 "Start editing a news article to be sent." |
3442 (special-display-buffer-names nil) | 2888 (special-display-buffer-names nil) |
3443 (special-display-regexps nil) | 2889 (special-display-regexps nil) |
3444 (same-window-buffer-names nil) | 2890 (same-window-buffer-names nil) |
3445 (same-window-regexps nil)) | 2891 (same-window-regexps nil)) |
3446 (message-pop-to-buffer (message-buffer-name "news" nil newsgroups))) | 2892 (message-pop-to-buffer (message-buffer-name "news" nil newsgroups))) |
3447 (message-setup `((Newsgroups . ,(or newsgroups "")) | 2893 (message-setup `((Newsgroups . ,(or newsgroups "")) |
3448 (Subject . ,(or subject ""))))) | 2894 (Subject . ,(or subject ""))))) |
3449 | 2895 |
3450 ;;; underline.el | 2896 ;;; underline.el |
3451 | 2897 |
3452 ;; This code should be moved to underline.el (from which it is stolen). | 2898 ;; This code should be moved to underline.el (from which it is stolen). |
3453 | 2899 |
3454 ;;;###autoload | 2900 ;;;###autoload |
3455 (defun bold-region (start end) | 2901 (defun bold-region (start end) |
3456 "Bold all nonblank characters in the region. | 2902 "Bold all nonblank characters in the region. |
3457 Works by overstriking characters. | 2903 Works by overstriking characters. |
3458 Called from program, takes two arguments START and END | 2904 Called from program, takes two arguments START and END |
3459 which specify the range to operate on." | 2905 which specify the range to operate on." |
3460 (interactive "r") | 2906 (interactive "r") |
3461 (save-excursion | 2907 (save-excursion |
3462 (let ((end1 (make-marker))) | 2908 (let ((end1 (make-marker))) |
3463 (move-marker end1 (max start end)) | 2909 (move-marker end1 (max start end)) |
3464 (goto-char (min start end)) | 2910 (goto-char (min start end)) |
3465 (while (< (point) end1) | 2911 (while (< (point) end1) |
3466 (or (looking-at "[_\^@- ]") | 2912 (or (looking-at "[_\^@- ]") |
3467 (insert (following-char) "\b")) | 2913 (insert (following-char) "\b")) |
3468 (forward-char 1))))) | 2914 (forward-char 1))))) |
3469 | 2915 |
3470 ;;;###autoload | 2916 ;;;###autoload |
3471 (defun unbold-region (start end) | 2917 (defun unbold-region (start end) |
3472 "Remove all boldness (overstruck characters) in the region. | 2918 "Remove all boldness (overstruck characters) in the region. |
3473 Called from program, takes two arguments START and END | 2919 Called from program, takes two arguments START and END |
3474 which specify the range to operate on." | 2920 which specify the range to operate on." |
3475 (interactive "r") | 2921 (interactive "r") |
3476 (save-excursion | 2922 (save-excursion |
3477 (let ((end1 (make-marker))) | 2923 (let ((end1 (make-marker))) |
3478 (move-marker end1 (max start end)) | 2924 (move-marker end1 (max start end)) |
3479 (goto-char (min start end)) | 2925 (goto-char (min start end)) |
3480 (while (re-search-forward "\b" end1 t) | 2926 (while (re-search-forward "\b" end1 t) |
3481 (if (eq (following-char) (char-after (- (point) 2))) | 2927 (if (eq (following-char) (char-after (- (point) 2))) |
3482 (delete-char -2)))))) | 2928 (delete-char -2)))))) |
3483 | 2929 |
3484 (defalias 'message-exchange-point-and-mark 'exchange-point-and-mark) | 2930 (defalias 'message-exchange-point-and-mark 'exchange-point-and-mark) |
3485 | 2931 |
3486 ;; Support for toolbar | 2932 ;; Support for toolbar |
3487 (when (string-match "XEmacs\\|Lucid" emacs-version) | 2933 (when (string-match "XEmacs\\|Lucid" emacs-version) |
3488 (require 'messagexmas)) | 2934 (require 'messagexmas)) |
3489 | 2935 |
3490 ;;; Group name completion. | 2936 ;;; Group name completion. |
3491 | 2937 |
3492 (defvar message-newgroups-header-regexp | 2938 (defvar message-newgroups-header-regexp |
3493 "^\\(Newsgroups\\|Followup-To\\|Posted-To\\|Gcc\\):" | 2939 "^\\(Newsgroups\\|Followup-To\\|Posted-To\\):" |
3494 "Regexp that match headers that lists groups.") | 2940 "Regexp that match headers that lists groups.") |
3495 | 2941 |
3496 (defun message-tab () | 2942 (defun message-tab () |
3497 "Expand group names in Newsgroups and Followup-To headers. | 2943 "Expand group names in Newsgroups and Followup-To headers. |
3498 Do a `tab-to-tab-stop' if not in those headers." | 2944 Do a `tab-to-tab-stop' if not in those headers." |
3502 (message-expand-group) | 2948 (message-expand-group) |
3503 (tab-to-tab-stop))) | 2949 (tab-to-tab-stop))) |
3504 | 2950 |
3505 (defvar gnus-active-hashtb) | 2951 (defvar gnus-active-hashtb) |
3506 (defun message-expand-group () | 2952 (defun message-expand-group () |
3507 (let* ((b (save-excursion | 2953 (let* ((b (save-excursion (skip-chars-backward "^, :\t\n") (point))) |
3508 (save-restriction | |
3509 (narrow-to-region | |
3510 (save-excursion | |
3511 (beginning-of-line) | |
3512 (skip-chars-forward "^:") | |
3513 (1+ (point))) | |
3514 (point)) | |
3515 (skip-chars-backward "^, \t\n") (point)))) | |
3516 (completion-ignore-case t) | 2954 (completion-ignore-case t) |
3517 (string (buffer-substring b (point))) | 2955 (string (buffer-substring b (point))) |
3518 (hashtb (and (boundp 'gnus-active-hashtb) gnus-active-hashtb)) | 2956 (hashtb (and (boundp 'gnus-active-hashtb) gnus-active-hashtb)) |
3519 (completions (all-completions string hashtb)) | 2957 (completions (all-completions string hashtb)) |
3520 (cur (current-buffer)) | 2958 (cur (current-buffer)) |
3521 comp) | 2959 comp) |
3522 (delete-region b (point)) | 2960 (delete-region b (point)) |
3523 (cond | 2961 (cond |
3524 ((= (length completions) 1) | 2962 ((= (length completions) 1) |
3525 (if (string= (car completions) string) | 2963 (if (string= (car completions) string) |
3526 (progn | 2964 (progn |
3527 (insert string) | 2965 (insert string) |
3528 (message "Only matching group")) | 2966 (message "Only matching group")) |
3543 (goto-char (point-min)) | 2981 (goto-char (point-min)) |
3544 (pop-to-buffer cur))))))) | 2982 (pop-to-buffer cur))))))) |
3545 | 2983 |
3546 ;;; Help stuff. | 2984 ;;; Help stuff. |
3547 | 2985 |
2986 (defmacro message-y-or-n-p (question show &rest text) | |
2987 "Ask QUESTION, displaying the rest of the arguments in a temp. buffer if SHOW" | |
2988 `(message-talkative-question 'y-or-n-p ,question ,show ,@text)) | |
2989 | |
3548 (defun message-talkative-question (ask question show &rest text) | 2990 (defun message-talkative-question (ask question show &rest text) |
3549 "Call FUNCTION with argument QUESTION, displaying the rest of the arguments in a temporary buffer if SHOW. | 2991 "Call FUNCTION with argument QUESTION, displaying the rest of the arguments in a temporary buffer if SHOW. |
3550 The following arguments may contain lists of values." | 2992 The following arguments may contain lists of values." |
3551 (if (and show | 2993 (if (and show |
3552 (setq text (message-flatten-list text))) | 2994 (setq text (message-flatten-list text))) |
3553 (save-window-excursion | 2995 (save-window-excursion |
3554 (save-excursion | 2996 (save-excursion |
3557 (mapcar 'princ text) | 2999 (mapcar 'princ text) |
3558 (goto-char (point-min)))) | 3000 (goto-char (point-min)))) |
3559 (funcall ask question)) | 3001 (funcall ask question)) |
3560 (funcall ask question))) | 3002 (funcall ask question))) |
3561 | 3003 |
3562 (defun message-flatten-list (list) | 3004 (defun message-flatten-list (&rest list) |
3563 "Return a new, flat list that contains all elements of LIST. | 3005 (message-flatten-list-1 list)) |
3564 | 3006 |
3565 \(message-flatten-list '(1 (2 3 (4 5 (6))) 7)) | 3007 (defun message-flatten-list-1 (list) |
3566 => (1 2 3 4 5 6 7)" | 3008 (cond ((consp list) |
3567 (cond ((consp list) | 3009 (apply 'append (mapcar 'message-flatten-list-1 list))) |
3568 (apply 'append (mapcar 'message-flatten-list list))) | |
3569 (list | 3010 (list |
3570 (list list)))) | 3011 (list list)))) |
3571 | 3012 |
3572 (defun message-generate-new-buffer-clone-locals (name &optional varstr) | |
3573 "Create and return a buffer with a name based on NAME using generate-new-buffer. | |
3574 Then clone the local variables and values from the old buffer to the | |
3575 new one, cloning only the locals having a substring matching the | |
3576 regexp varstr." | |
3577 (let ((oldlocals (buffer-local-variables))) | |
3578 (save-excursion | |
3579 (set-buffer (generate-new-buffer name)) | |
3580 (mapcar (lambda (dude) | |
3581 (when (and (car dude) | |
3582 (or (not varstr) | |
3583 (string-match varstr (symbol-name (car dude))))) | |
3584 (ignore-errors | |
3585 (set (make-local-variable (car dude)) | |
3586 (cdr dude))))) | |
3587 oldlocals) | |
3588 (current-buffer)))) | |
3589 | |
3590 (run-hooks 'message-load-hook) | 3013 (run-hooks 'message-load-hook) |
3591 | 3014 |
3592 (provide 'message) | 3015 (provide 'message) |
3593 | 3016 |
3594 ;;; message.el ends here | 3017 ;;; message.el ends here |