comparison lisp/gnus/message.el @ 98:0d2f883870bc r20-1b1

Import from CVS: tag r20-1b1
author cvs
date Mon, 13 Aug 2007 09:13:56 +0200
parents 131b0175ea99
children 4be1180a9e89
comparison
equal deleted inserted replaced
97:498bf5da1c90 98:0d2f883870bc
1 ;;; message.el --- composing mail and news messages 1 ;;; message.el --- composing mail and news messages
2 ;; Copyright (C) 1996 Free Software Foundation, Inc. 2 ;; Copyright (C) 1996,97 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.
34 (require 'mailheader) 34 (require 'mailheader)
35 (require 'rmail) 35 (require 'rmail)
36 (require 'nnheader) 36 (require 'nnheader)
37 (require 'timezone) 37 (require 'timezone)
38 (require 'easymenu) 38 (require 'easymenu)
39 (require 'custom)
39 (if (string-match "XEmacs\\|Lucid" emacs-version) 40 (if (string-match "XEmacs\\|Lucid" emacs-version)
40 (require 'mail-abbrevs) 41 (require 'mail-abbrevs)
41 (require 'mailabbrev)) 42 (require 'mailabbrev))
42 43
43 (defvar message-directory "~/Mail/" 44 (defgroup message '((user-mail-address custom-variable)
44 "*Directory from which all other mail file variables are derived.") 45 (user-full-name custom-variable))
45 46 "Mail and news message composing."
46 (defvar message-max-buffers 10 47 :link '(custom-manual "(message)Top")
47 "*How many buffers to keep before starting to kill them off.") 48 :group 'emacs)
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)
52
53 (defgroup message-various nil
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 (defcustom message-directory "~/Mail/"
97 "*Directory from which all other mail file variables are derived."
98 :group 'message-various
99 :type 'directory)
100
101 (defcustom message-max-buffers 10
102 "*How many buffers to keep before starting to kill them off."
103 :group 'message-buffers
104 :type 'integer)
105
106 (defcustom message-send-rename-function nil
107 "Function called to rename the buffer after sending it."
108 :group 'message-buffers
109 :type 'function)
51 110
52 ;;;###autoload 111 ;;;###autoload
53 (defvar message-fcc-handler-function 'rmail-output 112 (defcustom message-fcc-handler-function 'message-output
54 "*A function called to save outgoing articles. 113 "*A function called to save outgoing articles.
55 This function will be called with the name of the file to store the 114 This function will be called with the name of the file to store the
56 article in. The default function is `rmail-output' which saves in Unix 115 article in. The default function is `message-output' which saves in Unix
57 mailbox format.") 116 mailbox format."
117 :type '(radio (function-item message-output)
118 (function :tag "Other"))
119 :group 'message-sending)
120
121 (defcustom message-courtesy-message
122 "The following message is a courtesy copy of an article\nthat has been posted to %s as well.\n\n"
123 "*This is inserted at the start of a mailed copy of a posted message.
124 If the string contains the format spec \"%s\", the Newsgroups
125 the article has been posted to will be inserted there.
126 If this variable is nil, no such courtesy message will be added."
127 :group 'message-sending
128 :type 'string)
129
130 (defcustom message-ignored-bounced-headers "^\\(Received\\|Return-Path\\):"
131 "*Regexp that matches headers to be removed in resent bounced mail."
132 :group 'message-interface
133 :type 'regexp)
58 134
59 ;;;###autoload 135 ;;;###autoload
60 (defvar message-courtesy-message 136 (defcustom message-from-style 'default
61 "The following message is a courtesy copy of an article\nthat has been posted as well.\n\n"
62 "*This is inserted at the start of a mailed copy of a posted message.
63 If this variable is nil, no such courtesy message will be added.")
64
65 ;;;###autoload
66 (defvar message-ignored-bounced-headers "^\\(Received\\|Return-Path\\):"
67 "*Regexp that matches headers to be removed in resent bounced mail.")
68
69 ;;;###autoload
70 (defvar message-from-style 'default
71 "*Specifies how \"From\" headers look. 137 "*Specifies how \"From\" headers look.
72 138
73 If `nil', they contain just the return address like: 139 If `nil', they contain just the return address like:
74 king@grassland.com 140 king@grassland.com
75 If `parens', they look like: 141 If `parens', they look like:
76 king@grassland.com (Elvis Parsley) 142 king@grassland.com (Elvis Parsley)
77 If `angles', they look like: 143 If `angles', they look like:
78 Elvis Parsley <king@grassland.com> 144 Elvis Parsley <king@grassland.com>
79 145
80 Otherwise, most addresses look like `angles', but they look like 146 Otherwise, most addresses look like `angles', but they look like
81 `parens' if `angles' would need quoting and `parens' would not.") 147 `parens' if `angles' would need quoting and `parens' would not."
82 148 :type '(choice (const :tag "simple" nil)
83 ;;;###autoload 149 (const parens)
84 (defvar message-syntax-checks nil 150 (const angles)
151 (const default))
152 :group 'message-headers)
153
154 (defcustom message-syntax-checks nil
155 ;; Guess this one shouldn't be easy to customize...
85 "Controls what syntax checks should not be performed on outgoing posts. 156 "Controls what syntax checks should not be performed on outgoing posts.
86 To disable checking of long signatures, for instance, add 157 To disable checking of long signatures, for instance, add
87 `(signature . disabled)' to this list. 158 `(signature . disabled)' to this list.
88 159
89 Don't touch this variable unless you really know what you're doing. 160 Don't touch this variable unless you really know what you're doing.
90 161
91 Checks include subject-cmsg multiple-headers sendsys message-id from 162 Checks include subject-cmsg multiple-headers sendsys message-id from
92 long-lines control-chars size new-text redirected-followup signature 163 long-lines control-chars size new-text redirected-followup signature
93 approved sender empty empty-headers message-id from subject.") 164 approved sender empty empty-headers message-id from subject
94 165 shorten-followup-to existing-newsgroups."
95 ;;;###autoload 166 :group 'message-news)
96 (defvar message-required-news-headers 167
168 (defcustom message-required-news-headers
97 '(From Newsgroups Subject Date Message-ID 169 '(From Newsgroups Subject Date Message-ID
98 (optional . Organization) Lines 170 (optional . Organization) Lines
99 (optional . X-Newsreader)) 171 (optional . X-Newsreader))
100 "*Headers to be generated or prompted for when posting an article. 172 "Headers to be generated or prompted for when posting an article.
101 RFC977 and RFC1036 require From, Date, Newsgroups, Subject, 173 RFC977 and RFC1036 require From, Date, Newsgroups, Subject,
102 Message-ID. Organization, Lines, In-Reply-To, Expires, and 174 Message-ID. Organization, Lines, In-Reply-To, Expires, and
103 X-Newsreader are optional. If don't you want message to insert some 175 X-Newsreader are optional. If don't you want message to insert some
104 header, remove it from this list.") 176 header, remove it from this list."
105 177 :group 'message-news
106 ;;;###autoload 178 :group 'message-headers
107 (defvar message-required-mail-headers 179 :type '(repeat sexp))
180
181 (defcustom message-required-mail-headers
108 '(From Subject Date (optional . In-Reply-To) Message-ID Lines 182 '(From Subject Date (optional . In-Reply-To) Message-ID Lines
109 (optional . X-Mailer)) 183 (optional . X-Mailer))
110 "*Headers to be generated or prompted for when mailing a message. 184 "Headers to be generated or prompted for when mailing a message.
111 RFC822 required that From, Date, To, Subject and Message-ID be 185 RFC822 required that From, Date, To, Subject and Message-ID be
112 included. Organization, Lines and X-Mailer are optional.") 186 included. Organization, Lines and X-Mailer are optional."
113 187 :group 'message-mail
114 ;;;###autoload 188 :group 'message-headers
115 (defvar message-deletable-headers '(Message-ID Date) 189 :type '(repeat sexp))
116 "*Headers to be deleted if they already exist and were generated by message previously.") 190
117 191 (defcustom message-deletable-headers '(Message-ID Date Lines)
118 ;;;###autoload 192 "Headers to be deleted if they already exist and were generated by message previously."
119 (defvar message-ignored-news-headers 193 :group 'message-headers
120 "^NNTP-Posting-Host:\\|^Xref:\\|^Bcc:\\|^Gcc:\\|^Fcc:" 194 :type 'sexp)
121 "*Regexp of headers to be removed unconditionally before posting.") 195
122 196 (defcustom message-ignored-news-headers
123 ;;;###autoload 197 "^NNTP-Posting-Host:\\|^Xref:\\|^Bcc:\\|^Gcc:\\|^Fcc:\\|^Resent-Fcc:"
124 (defvar message-ignored-mail-headers "^Gcc:\\|^Fcc:" 198 "*Regexp of headers to be removed unconditionally before posting."
125 "*Regexp of headers to be removed unconditionally before mailing.") 199 :group 'message-news
126 200 :group 'message-headers
127 ;;;###autoload 201 :type 'regexp)
128 (defvar message-ignored-supersedes-headers "^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|^Received:\\|^X-From-Line:\\|Return-Path:\\|^Supersedes:" 202
203 (defcustom message-ignored-mail-headers "^Gcc:\\|^Fcc:\\|^Resent-Fcc:"
204 "*Regexp of headers to be removed unconditionally before mailing."
205 :group 'message-mail
206 :group 'message-headers
207 :type 'regexp)
208
209 (defcustom message-ignored-supersedes-headers "^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|^Received:\\|^X-From-Line:\\|Return-Path:\\|^Supersedes:"
129 "*Header lines matching this regexp will be deleted before posting. 210 "*Header lines matching this regexp will be deleted before posting.
130 It's best to delete old Path and Date headers before posting to avoid 211 It's best to delete old Path and Date headers before posting to avoid
131 any confusion.") 212 any confusion."
213 :group 'message-interface
214 :type 'regexp)
132 215
133 ;;;###autoload 216 ;;;###autoload
134 (defvar message-signature-separator "^-- *$" 217 (defcustom message-signature-separator "^-- *$"
135 "Regexp matching the signature separator.") 218 "Regexp matching the signature separator."
136 219 :type 'regexp
137 ;;;###autoload 220 :group 'message-various)
138 (defvar message-interactive nil 221
222 (defcustom message-elide-elipsis "\n[...]\n\n"
223 "*The string which is inserted for elided text.")
224
225 (defcustom message-interactive nil
139 "Non-nil means when sending a message wait for and display errors. 226 "Non-nil means when sending a message wait for and display errors.
140 nil means let mailer mail back a message to report errors.") 227 nil means let mailer mail back a message to report errors."
141 228 :group 'message-sending
142 ;;;###autoload 229 :group 'message-mail
143 (defvar message-generate-new-buffers t 230 :type 'boolean)
231
232 (defcustom message-generate-new-buffers t
144 "*Non-nil means that a new message buffer will be created whenever `mail-setup' is called. 233 "*Non-nil means that a new message buffer will be created whenever `mail-setup' is called.
145 If this is a function, call that function with three parameters: The type, 234 If this is a function, call that function with three parameters: The type,
146 the to address and the group name. (Any of these may be nil.) The function 235 the to address and the group name. (Any of these may be nil.) The function
147 should return the new buffer name.") 236 should return the new buffer name."
148 237 :group 'message-buffers
149 ;;;###autoload 238 :type '(choice (const :tag "off" nil)
150 (defvar message-kill-buffer-on-exit nil 239 (const :tag "on" t)
151 "*Non-nil means that the message buffer will be killed after sending a message.") 240 (function fun)))
241
242 (defcustom message-kill-buffer-on-exit nil
243 "*Non-nil means that the message buffer will be killed after sending a message."
244 :group 'message-buffers
245 :type 'boolean)
152 246
153 (defvar gnus-local-organization) 247 (defvar gnus-local-organization)
154 (defvar message-user-organization 248 (defcustom message-user-organization
155 (or (and (boundp 'gnus-local-organization) 249 (or (and (boundp 'gnus-local-organization)
250 (stringp gnus-local-organization)
156 gnus-local-organization) 251 gnus-local-organization)
157 (getenv "ORGANIZATION") 252 (getenv "ORGANIZATION")
158 t) 253 t)
159 "*String to be used as an Organization header. 254 "*String to be used as an Organization header.
160 If t, use `message-user-organization-file'.") 255 If t, use `message-user-organization-file'."
256 :group 'message-headers
257 :type '(choice string
258 (const :tag "consult file" t)))
161 259
162 ;;;###autoload 260 ;;;###autoload
163 (defvar message-user-organization-file "/usr/lib/news/organization" 261 (defcustom message-user-organization-file "/usr/lib/news/organization"
164 "*Local news organization file.") 262 "*Local news organization file."
165 263 :type 'file
166 (defvar message-autosave-directory "~/" 264 :group 'message-headers)
265
266 (defcustom message-autosave-directory "~/"
167 ; (concat (file-name-as-directory message-directory) "drafts/") 267 ; (concat (file-name-as-directory message-directory) "drafts/")
168 "*Directory where message autosaves buffers. 268 "*Directory where message autosaves buffers.
169 If nil, message won't autosave.") 269 If nil, message won't autosave."
170 270 :group 'message-buffers
171 (defvar message-forward-start-separator 271 :type 'directory)
272
273 (defcustom message-forward-start-separator
172 "------- Start of forwarded message -------\n" 274 "------- Start of forwarded message -------\n"
173 "*Delimiter inserted before forwarded messages.") 275 "*Delimiter inserted before forwarded messages."
174 276 :group 'message-forwarding
175 (defvar message-forward-end-separator 277 :type 'string)
278
279 (defcustom message-forward-end-separator
176 "------- End of forwarded message -------\n" 280 "------- End of forwarded message -------\n"
177 "*Delimiter inserted after forwarded messages.") 281 "*Delimiter inserted after forwarded messages."
178 282 :group 'message-forwarding
179 ;;;###autoload 283 :type 'string)
180 (defvar message-signature-before-forwarded-message t 284
181 "*If non-nil, put the signature before any included forwarded message.") 285 (defcustom message-signature-before-forwarded-message t
182 286 "*If non-nil, put the signature before any included forwarded message."
183 ;;;###autoload 287 :group 'message-forwarding
184 (defvar message-included-forward-headers 288 :type 'boolean)
289
290 (defcustom message-included-forward-headers
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:" 291 "^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:"
186 "*Regexp matching headers to be included in forwarded messages.") 292 "*Regexp matching headers to be included in forwarded messages."
187 293 :group 'message-forwarding
188 ;;;###autoload 294 :type 'regexp)
189 (defvar message-ignored-resent-headers "^Return-receipt" 295
190 "*All headers that match this regexp will be deleted when resending a message.") 296 (defcustom message-ignored-resent-headers "^Return-receipt"
191 297 "*All headers that match this regexp will be deleted when resending a message."
192 ;;;###autoload 298 :group 'message-interface
193 (defvar message-ignored-cited-headers "." 299 :type 'regexp)
194 "Delete these headers from the messages you yank.") 300
301 (defcustom message-ignored-cited-headers "."
302 "*Delete these headers from the messages you yank."
303 :group 'message-insertion
304 :type 'regexp)
305
306 (defcustom message-cancel-message "I am canceling my own article."
307 "Message to be inserted in the cancel message."
308 :group 'message-interface
309 :type 'string)
195 310
196 ;; Useful to set in site-init.el 311 ;; Useful to set in site-init.el
197 ;;;###autoload 312 ;;;###autoload
198 (defvar message-send-mail-function 'message-send-mail-with-sendmail 313 (defcustom message-send-mail-function 'message-send-mail-with-sendmail
199 "Function to call to send the current buffer as mail. 314 "Function to call to send the current buffer as mail.
200 The headers should be delimited by a line whose contents match the 315 The headers should be delimited by a line whose contents match the
201 variable `mail-header-separator'. 316 variable `mail-header-separator'.
202 317
203 Legal values include `message-send-mail-with-mh' and 318 Legal values include `message-send-mail-with-sendmail' (the default),
204 `message-send-mail-with-sendmail', which is the default.") 319 `message-send-mail-with-mh' and `message-send-mail-with-qmail'."
205 320 :type '(radio (function-item message-send-mail-with-sendmail)
206 ;;;###autoload 321 (function-item message-send-mail-with-mh)
207 (defvar message-send-news-function 'message-send-news 322 (function-item message-send-mail-with-qmail)
323 (function :tag "Other"))
324 :group 'message-sending
325 :group 'message-mail)
326
327 (defcustom message-send-news-function 'message-send-news
208 "Function to call to send the current buffer as news. 328 "Function to call to send the current buffer as news.
209 The headers should be delimited by a line whose contents match the 329 The headers should be delimited by a line whose contents match the
210 variable `mail-header-separator'.") 330 variable `mail-header-separator'."
211 331 :group 'message-sending
212 ;;;###autoload 332 :group 'message-news
213 (defvar message-reply-to-function nil 333 :type 'function)
334
335 (defcustom message-reply-to-function nil
214 "Function that should return a list of headers. 336 "Function that should return a list of headers.
215 This function should pick out addresses from the To, Cc, and From headers 337 This function should pick out addresses from the To, Cc, and From headers
216 and respond with new To and Cc headers.") 338 and respond with new To and Cc headers."
217 339 :group 'message-interface
218 ;;;###autoload 340 :type 'function)
219 (defvar message-wide-reply-to-function nil 341
342 (defcustom message-wide-reply-to-function nil
220 "Function that should return a list of headers. 343 "Function that should return a list of headers.
221 This function should pick out addresses from the To, Cc, and From headers 344 This function should pick out addresses from the To, Cc, and From headers
222 and respond with new To and Cc headers.") 345 and respond with new To and Cc headers."
223 346 :group 'message-interface
224 ;;;###autoload 347 :type 'function)
225 (defvar message-followup-to-function nil 348
349 (defcustom message-followup-to-function nil
226 "Function that should return a list of headers. 350 "Function that should return a list of headers.
227 This function should pick out addresses from the To, Cc, and From headers 351 This function should pick out addresses from the To, Cc, and From headers
228 and respond with new To and Cc headers.") 352 and respond with new To and Cc headers."
229 353 :group 'message-interface
230 ;;;###autoload 354 :type 'function)
231 (defvar message-use-followup-to 'ask 355
356 (defcustom message-use-followup-to 'ask
232 "*Specifies what to do with Followup-To header. 357 "*Specifies what to do with Followup-To header.
233 If nil, ignore the header. If it is t, use its value, but query before 358 If nil, always ignore the header. If it is t, use its value, but
234 using the \"poster\" value. If it is the symbol `ask', query the user 359 query before using the \"poster\" value. If it is the symbol `ask',
235 whether to ignore the \"poster\" value. If it is the symbol `use', 360 always query the user whether to use the value. If it is the symbol
236 always use the value.") 361 `use', always use the value."
362 :group 'message-interface
363 :type '(choice (const :tag "ignore" nil)
364 (const use)
365 (const ask)))
366
367 ;; stuff relating to broken sendmail in MMDF
368 (defcustom message-sendmail-f-is-evil nil
369 "*Non-nil means that \"-f username\" should not be added to the sendmail
370 command line, because it is even more evil than leaving it out."
371 :group 'message-sending
372 :type 'boolean)
373
374 ;; qmail-related stuff
375 (defcustom message-qmail-inject-program "/var/qmail/bin/qmail-inject"
376 "Location of the qmail-inject program."
377 :group 'message-sending
378 :type 'file)
379
380 (defcustom message-qmail-inject-args nil
381 "Arguments passed to qmail-inject programs.
382 This should be a list of strings, one string for each argument.
383
384 For e.g., if you wish to set the envelope sender address so that bounces
385 go to the right place or to deal with listserv's usage of that address, you
386 might set this variable to '(\"-f\" \"you@some.where\")."
387 :group 'message-sending
388 :type '(repeat string))
237 389
238 (defvar gnus-post-method) 390 (defvar gnus-post-method)
239 (defvar gnus-select-method) 391 (defvar gnus-select-method)
240 ;;;###autoload 392 (defcustom message-post-method
241 (defvar message-post-method
242 (cond ((and (boundp 'gnus-post-method) 393 (cond ((and (boundp 'gnus-post-method)
243 gnus-post-method) 394 gnus-post-method)
244 gnus-post-method) 395 gnus-post-method)
245 ((boundp 'gnus-select-method) 396 ((boundp 'gnus-select-method)
246 gnus-select-method) 397 gnus-select-method)
247 (t '(nnspool ""))) 398 (t '(nnspool "")))
248 "Method used to post news.") 399 "Method used to post news."
249 400 :group 'message-news
250 ;;;###autoload 401 :group 'mesage-sending
251 (defvar message-generate-headers-first nil 402 ;; This should be the `gnus-select-method' widget, but that might
252 "*If non-nil, generate all possible headers before composing.") 403 ;; create a dependence to `gnus.el'.
253 404 :type 'sexp)
254 (defvar message-setup-hook nil 405
406 (defcustom message-generate-headers-first nil
407 "*If non-nil, generate all possible headers before composing."
408 :group 'message-headers
409 :type 'boolean)
410
411 (defcustom message-setup-hook nil
255 "Normal hook, run each time a new outgoing message is initialized. 412 "Normal hook, run each time a new outgoing message is initialized.
256 The function `message-setup' runs this hook.") 413 The function `message-setup' runs this hook."
257 414 :group 'message-various
258 (defvar message-signature-setup-hook nil 415 :type 'hook)
416
417 (defcustom message-signature-setup-hook nil
259 "Normal hook, run each time a new outgoing message is initialized. 418 "Normal hook, run each time a new outgoing message is initialized.
260 It is run after the headers have been inserted and before 419 It is run after the headers have been inserted and before
261 the signature is inserted.") 420 the signature is inserted."
262 421 :group 'message-various
263 (defvar message-mode-hook nil 422 :type 'hook)
264 "Hook run in message mode buffers.") 423
265 424 (defcustom message-mode-hook nil
266 (defvar message-header-hook nil 425 "Hook run in message mode buffers."
267 "Hook run in a message mode buffer narrowed to the headers.") 426 :group 'message-various
268 427 :type 'hook)
269 (defvar message-header-setup-hook nil 428
270 "Hook called narrowed to the headers when setting up a message buffer.") 429 (defcustom message-header-hook nil
430 "Hook run in a message mode buffer narrowed to the headers."
431 :group 'message-various
432 :type 'hook)
433
434 (defcustom message-header-setup-hook nil
435 "Hook called narrowed to the headers when setting up a message
436 buffer."
437 :group 'message-various
438 :type 'hook)
271 439
272 ;;;###autoload 440 ;;;###autoload
273 (defvar message-citation-line-function 'message-insert-citation-line 441 (defcustom message-citation-line-function 'message-insert-citation-line
274 "*Function called to insert the \"Whomever writes:\" line.") 442 "*Function called to insert the \"Whomever writes:\" line."
443 :type 'function
444 :group 'message-insertion)
275 445
276 ;;;###autoload 446 ;;;###autoload
277 (defvar message-yank-prefix "> " 447 (defcustom message-yank-prefix "> "
278 "*Prefix inserted on the lines of yanked messages. 448 "*Prefix inserted on the lines of yanked messages.
279 nil means use indentation.") 449 nil means use indentation."
280 450 :type 'string
281 (defvar message-indentation-spaces 3 451 :group 'message-insertion)
452
453 (defcustom message-indentation-spaces 3
282 "*Number of spaces to insert at the beginning of each cited line. 454 "*Number of spaces to insert at the beginning of each cited line.
283 Used by `message-yank-original' via `message-yank-cite'.") 455 Used by `message-yank-original' via `message-yank-cite'."
456 :group 'message-insertion
457 :type 'integer)
284 458
285 ;;;###autoload 459 ;;;###autoload
286 (defvar message-cite-function 'message-cite-original 460 (defcustom message-cite-function
287 "*Function for citing an original message.") 461 (if (and (boundp 'mail-citation-hook)
462 mail-citation-hook)
463 mail-citation-hook
464 'message-cite-original)
465 "*Function for citing an original message."
466 :type '(radio (function-item message-cite-original)
467 (function-item sc-cite-original)
468 (function :tag "Other"))
469 :group 'message-insertion)
288 470
289 ;;;###autoload 471 ;;;###autoload
290 (defvar message-indent-citation-function 'message-indent-citation 472 (defcustom message-indent-citation-function 'message-indent-citation
291 "*Function for modifying a citation just inserted in the mail buffer. 473 "*Function for modifying a citation just inserted in the mail buffer.
292 This can also be a list of functions. Each function can find the 474 This can also be a list of functions. Each function can find the
293 citation between (point) and (mark t). And each function should leave 475 citation between (point) and (mark t). And each function should leave
294 point and mark around the citation text as modified.") 476 point and mark around the citation text as modified."
477 :type 'function
478 :group 'message-insertion)
295 479
296 (defvar message-abbrevs-loaded nil) 480 (defvar message-abbrevs-loaded nil)
297 481
298 ;;;###autoload 482 ;;;###autoload
299 (defvar message-signature t 483 (defcustom message-signature t
300 "*String to be inserted at the end of the message buffer. 484 "*String to be inserted at the end of the message buffer.
301 If t, the `message-signature-file' file will be inserted instead. 485 If t, the `message-signature-file' file will be inserted instead.
302 If a function, the result from the function will be used instead. 486 If a function, the result from the function will be used instead.
303 If a form, the result from the form will be used instead.") 487 If a form, the result from the form will be used instead."
488 :type 'sexp
489 :group 'message-insertion)
304 490
305 ;;;###autoload 491 ;;;###autoload
306 (defvar message-signature-file "~/.signature" 492 (defcustom message-signature-file "~/.signature"
307 "*File containing the text inserted at end of message. buffer.") 493 "*File containing the text inserted at end of message buffer."
308 494 :type 'file
309 (defvar message-distribution-function nil 495 :group 'message-insertion)
310 "*Function called to return a Distribution header.") 496
311 497 (defcustom message-distribution-function nil
312 (defvar message-expires 14 498 "*Function called to return a Distribution header."
313 "*Number of days before your article expires.") 499 :group 'message-news
314 500 :group 'message-headers
315 (defvar message-user-path nil 501 :type 'function)
502
503 (defcustom message-expires 14
504 "Number of days before your article expires."
505 :group 'message-news
506 :group 'message-headers
507 :link '(custom-manual "(message)News Headers")
508 :type 'integer)
509
510 (defcustom message-user-path nil
316 "If nil, use the NNTP server name in the Path header. 511 "If nil, use the NNTP server name in the Path header.
317 If stringp, use this; if non-nil, use no host name (user name only).") 512 If stringp, use this; if non-nil, use no host name (user name only)."
513 :group 'message-news
514 :group 'message-headers
515 :link '(custom-manual "(message)News Headers")
516 :type '(choice (const :tag "nntp" nil)
517 (string :tag "name")
518 (sexp :tag "none" :format "%t" t)))
318 519
319 (defvar message-reply-buffer nil) 520 (defvar message-reply-buffer nil)
320 (defvar message-reply-headers nil) 521 (defvar message-reply-headers nil)
321 (defvar message-newsreader nil) 522 (defvar message-newsreader nil)
322 (defvar message-mailer nil) 523 (defvar message-mailer nil)
329 (defvar message-kill-actions nil 530 (defvar message-kill-actions nil
330 "A list of actions to be performed before killing a message buffer.") 531 "A list of actions to be performed before killing a message buffer.")
331 (defvar message-postpone-actions nil 532 (defvar message-postpone-actions nil
332 "A list of actions to be performed after postponing a message.") 533 "A list of actions to be performed after postponing a message.")
333 534
334 ;;;###autoload 535 (defcustom message-default-headers ""
335 (defvar message-default-headers nil
336 "*A string containing header lines to be inserted in outgoing messages. 536 "*A string containing header lines to be inserted in outgoing messages.
337 It is inserted before you edit the message, so you can edit or delete 537 It is inserted before you edit the message, so you can edit or delete
338 these lines.") 538 these lines."
339 539 :group 'message-headers
340 ;;;###autoload 540 :type 'string)
341 (defvar message-default-mail-headers nil 541
342 "*A string of header lines to be inserted in outgoing mails.") 542 (defcustom message-default-mail-headers ""
343 543 "*A string of header lines to be inserted in outgoing mails."
344 ;;;###autoload 544 :group 'message-headers
345 (defvar message-default-news-headers nil 545 :group 'message-mail
346 "*A string of header lines to be inserted in outgoing news articles.") 546 :type 'string)
547
548 (defcustom message-default-news-headers ""
549 "*A string of header lines to be inserted in outgoing news
550 articles."
551 :group 'message-headers
552 :group 'message-news
553 :type 'string)
347 554
348 ;; Note: could use /usr/ucb/mail instead of sendmail; 555 ;; Note: could use /usr/ucb/mail instead of sendmail;
349 ;; options -t, and -v if not interactive. 556 ;; options -t, and -v if not interactive.
350 (defvar message-mailer-swallows-blank-line 557 (defcustom message-mailer-swallows-blank-line
351 (if (and (string-match "sparc-sun-sunos\\(\\'\\|[^5]\\)" 558 (if (and (string-match "sparc-sun-sunos\\(\\'\\|[^5]\\)"
352 system-configuration) 559 system-configuration)
353 (file-readable-p "/etc/sendmail.cf") 560 (file-readable-p "/etc/sendmail.cf")
354 (let ((buffer (get-buffer-create " *temp*"))) 561 (let ((buffer (get-buffer-create " *temp*")))
355 (unwind-protect 562 (unwind-protect
359 (goto-char (point-min)) 566 (goto-char (point-min))
360 (let ((case-fold-search nil)) 567 (let ((case-fold-search nil))
361 (re-search-forward "^OR\\>" nil t))) 568 (re-search-forward "^OR\\>" nil t)))
362 (kill-buffer buffer)))) 569 (kill-buffer buffer))))
363 ;; According to RFC822, "The field-name must be composed of printable 570 ;; According to RFC822, "The field-name must be composed of printable
364 ;; ASCII characters (i.e. characters that have decimal values between 571 ;; ASCII characters (i. e., characters that have decimal values between
365 ;; 33 and 126, except colon)", i.e. any chars except ctl chars, 572 ;; 33 and 126, except colon)", i. e., any chars except ctl chars,
366 ;; space, or colon. 573 ;; space, or colon.
367 '(looking-at "[ \t]\\|[][!\"#$%&'()*+,-./0-9;<=>?@A-Z\\\\^_`a-z{|}~]+:")) 574 '(looking-at "[ \t]\\|[][!\"#$%&'()*+,-./0-9;<=>?@A-Z\\\\^_`a-z{|}~]+:"))
368 "Set this non-nil if the system's mailer runs the header and body together. 575 "Set this non-nil if the system's mailer runs the header and body together.
369 \(This problem exists on Sunos 4 when sendmail is run in remote mode.) 576 \(This problem exists on Sunos 4 when sendmail is run in remote mode.)
370 The value should be an expression to test whether the problem will 577 The value should be an expression to test whether the problem will
371 actually occur.") 578 actually occur."
579 :group 'message-sending
580 :type 'sexp)
581
582 (ignore-errors
583 (define-mail-user-agent 'message-user-agent
584 'message-mail 'message-send-and-exit
585 'message-kill-buffer 'message-send-hook))
586
587 (defvar message-mh-deletable-headers '(Message-ID Date Lines Sender)
588 "If non-nil, delete the deletable headers before feeding to mh.")
589
590 ;;; Internal variables.
591 ;;; Well, not really internal.
372 592
373 (defvar message-mode-syntax-table 593 (defvar message-mode-syntax-table
374 (let ((table (copy-syntax-table text-mode-syntax-table))) 594 (let ((table (copy-syntax-table text-mode-syntax-table)))
375 (modify-syntax-entry ?% ". " table) 595 (modify-syntax-entry ?% ". " table)
376 table) 596 table)
390 1 'font-lock-comment-face) 610 1 'font-lock-comment-face)
391 (cons (concat "^[ \t]*" 611 (cons (concat "^[ \t]*"
392 "\\([" cite-prefix "]+[" cite-suffix "]*\\)?" 612 "\\([" cite-prefix "]+[" cite-suffix "]*\\)?"
393 "[>|}].*") 613 "[>|}].*")
394 'font-lock-reference-face) 614 'font-lock-reference-face)
395 '("^\\(X-[A-Za-z0-9-]+\\|In-reply-to\\):.*" 615 '("^\\(X-[A-Za-z0-9-]+\\|In-Reply-To\\):.*"
396 . font-lock-string-face))) 616 . font-lock-string-face)))
397 "Additional expressions to highlight in Message mode.") 617 "Additional expressions to highlight in Message mode.")
398 618
399 (defvar message-face-alist 619 (defvar message-face-alist
400 '((bold . bold-region) 620 '((bold . bold-region)
403 (unbold-region b e) 623 (unbold-region b e)
404 (ununderline-region b e)))) 624 (ununderline-region b e))))
405 "Alist of mail and news faces for facemenu. 625 "Alist of mail and news faces for facemenu.
406 The cdr of ech entry is a function for applying the face to a region.") 626 The cdr of ech entry is a function for applying the face to a region.")
407 627
408 (defvar message-send-hook nil 628 (defcustom message-send-hook nil
409 "Hook run before sending messages.") 629 "Hook run before sending messages."
410 630 :group 'message-various
411 (defvar message-sent-hook nil 631 :options '(ispell-message)
412 "Hook run after sending messages.") 632 :type 'hook)
633
634 (defcustom message-send-mail-hook nil
635 "Hook run before sending mail messages."
636 :group 'message-various
637 :type 'hook)
638
639 (defcustom message-send-news-hook nil
640 "Hook run before sending news messages."
641 :group 'message-various
642 :type 'hook)
643
644 (defcustom message-sent-hook nil
645 "Hook run after sending messages."
646 :group 'message-various
647 :type 'hook)
413 648
414 ;;; Internal variables. 649 ;;; Internal variables.
415 650
416 (defvar message-buffer-list nil) 651 (defvar message-buffer-list nil)
652 (defvar message-this-is-news nil)
653 (defvar message-this-is-mail nil)
654
655 ;; Byte-compiler warning
656 (defvar gnus-active-hashtb)
657 (defvar gnus-read-active-file)
417 658
418 ;;; Regexp matching the delimiter of messages in UNIX mail format 659 ;;; Regexp matching the delimiter of messages in UNIX mail format
419 ;;; (UNIX From lines), minus the initial ^. 660 ;;; (UNIX From lines), minus the initial ^.
420 (defvar message-unix-mail-delimiter 661 (defvar message-unix-mail-delimiter
421 (let ((time-zone-regexp 662 (let ((time-zone-regexp
476 (Organization) 717 (Organization)
477 (Distribution) 718 (Distribution)
478 (Lines) 719 (Lines)
479 (Expires) 720 (Expires)
480 (Message-ID) 721 (Message-ID)
481 (References . message-fill-header) 722 (References)
482 (X-Mailer) 723 (X-Mailer)
483 (X-Newsreader)) 724 (X-Newsreader))
484 "Alist used for formatting headers.") 725 "Alist used for formatting headers.")
485 726
486 (eval-and-compile 727 (eval-and-compile
487 (autoload 'message-setup-toolbar "messagexmas") 728 (autoload 'message-setup-toolbar "messagexmas")
488 (autoload 'mh-send-letter "mh-comp")) 729 (autoload 'mh-send-letter "mh-comp")
730 (autoload 'gnus-output-to-mail "gnus-util")
731 (autoload 'gnus-output-to-rmail "gnus-util"))
489 732
490 733
491 734
492 ;;; 735 ;;;
493 ;;; Utility functions. 736 ;;; Utility functions.
507 (end-of-line) 750 (end-of-line)
508 (prog1 751 (prog1
509 (point) 752 (point)
510 (goto-char p)))) 753 (goto-char p))))
511 754
755 (defmacro message-y-or-n-p (question show &rest text)
756 "Ask QUESTION, displaying the rest of the arguments in a temp. buffer if SHOW"
757 `(message-talkative-question 'y-or-n-p ,question ,show ,@text))
758
512 ;; Delete the current line (and the next N lines.); 759 ;; Delete the current line (and the next N lines.);
513 (defmacro message-delete-line (&optional n) 760 (defmacro message-delete-line (&optional n)
514 `(delete-region (progn (beginning-of-line) (point)) 761 `(delete-region (progn (beginning-of-line) (point))
515 (progn (forward-line ,(or n 1)) (point)))) 762 (progn (forward-line ,(or n 1)) (point))))
516 763
517 (defun message-tokenize-header (header &optional separator) 764 (defun message-tokenize-header (header &optional separator)
518 "Split HEADER into a list of header elements. 765 "Split HEADER into a list of header elements.
519 \",\" is used as the separator." 766 \",\" is used as the separator."
520 (let ((regexp (format "[%s]+" (or separator ","))) 767 (if (not header)
521 (beg 1) 768 nil
522 (first t) 769 (let ((regexp (format "[%s]+" (or separator ",")))
523 quoted elems) 770 (beg 1)
524 (save-excursion 771 (first t)
525 (message-set-work-buffer) 772 quoted elems paren)
526 (insert header) 773 (save-excursion
527 (goto-char (point-min)) 774 (message-set-work-buffer)
528 (while (not (eobp)) 775 (insert header)
529 (if first 776 (goto-char (point-min))
530 (setq first nil) 777 (while (not (eobp))
531 (forward-char 1)) 778 (if first
532 (cond ((and (> (point) beg) 779 (setq first nil)
533 (or (eobp) 780 (forward-char 1))
534 (and (looking-at regexp) 781 (cond ((and (> (point) beg)
535 (not quoted)))) 782 (or (eobp)
536 (push (buffer-substring beg (point)) elems) 783 (and (looking-at regexp)
537 (setq beg (match-end 0))) 784 (not quoted)
538 ((= (following-char) ?\") 785 (not paren))))
539 (setq quoted (not quoted))))) 786 (push (buffer-substring beg (point)) elems)
540 (nreverse elems)))) 787 (setq beg (match-end 0)))
541 788 ((= (following-char) ?\")
542 (defun message-fetch-field (header) 789 (setq quoted (not quoted)))
790 ((and (= (following-char) ?\()
791 (not quoted))
792 (setq paren t))
793 ((and (= (following-char) ?\))
794 (not quoted))
795 (setq paren nil))))
796 (nreverse elems)))))
797
798 (defun message-fetch-field (header &optional not-all)
543 "The same as `mail-fetch-field', only remove all newlines." 799 "The same as `mail-fetch-field', only remove all newlines."
544 (let ((value (mail-fetch-field header))) 800 (let ((value (mail-fetch-field header nil (not not-all))))
545 (when value 801 (when value
546 (nnheader-replace-chars-in-string value ?\n ? )))) 802 (nnheader-replace-chars-in-string value ?\n ? ))))
547 803
548 (defun message-fetch-reply-field (header) 804 (defun message-fetch-reply-field (header)
549 "Fetch FIELD from the message we're replying to." 805 "Fetch FIELD from the message we're replying to."
628 (point-max))) 884 (point-max)))
629 (goto-char (point-min))) 885 (goto-char (point-min)))
630 886
631 (defun message-news-p () 887 (defun message-news-p ()
632 "Say whether the current buffer contains a news message." 888 "Say whether the current buffer contains a news message."
633 (save-excursion 889 (or message-this-is-news
634 (save-restriction 890 (save-excursion
635 (message-narrow-to-headers) 891 (save-restriction
636 (message-fetch-field "newsgroups")))) 892 (message-narrow-to-headers)
893 (message-fetch-field "newsgroups")))))
637 894
638 (defun message-mail-p () 895 (defun message-mail-p ()
639 "Say whether the current buffer contains a mail message." 896 "Say whether the current buffer contains a mail message."
640 (save-excursion 897 (or message-this-is-mail
641 (save-restriction 898 (save-excursion
642 (message-narrow-to-headers) 899 (save-restriction
643 (or (message-fetch-field "to") 900 (message-narrow-to-headers)
644 (message-fetch-field "cc") 901 (or (message-fetch-field "to")
645 (message-fetch-field "bcc"))))) 902 (message-fetch-field "cc")
903 (message-fetch-field "bcc"))))))
646 904
647 (defun message-next-header () 905 (defun message-next-header ()
648 "Go to the beginning of the next header." 906 "Go to the beginning of the next header."
649 (beginning-of-line) 907 (beginning-of-line)
650 (or (eobp) (forward-char 1)) 908 (or (eobp) (forward-char 1))
661 (message-next-header) 919 (message-next-header)
662 (unless (bobp) 920 (unless (bobp)
663 (forward-char -1))) 921 (forward-char -1)))
664 (lambda () 922 (lambda ()
665 (or (get-text-property (point) 'message-rank) 923 (or (get-text-property (point) 'message-rank)
666 0)))) 924 10000))))
667 925
668 (defun message-sort-headers () 926 (defun message-sort-headers ()
669 "Sort the headers of the current message according to `message-header-format-alist'." 927 "Sort the headers of the current message according to `message-header-format-alist'."
670 (interactive) 928 (interactive)
671 (save-excursion 929 (save-excursion
727 (define-key message-mode-map "\C-c\C-c" 'message-send-and-exit) 985 (define-key message-mode-map "\C-c\C-c" 'message-send-and-exit)
728 (define-key message-mode-map "\C-c\C-s" 'message-send) 986 (define-key message-mode-map "\C-c\C-s" 'message-send)
729 (define-key message-mode-map "\C-c\C-k" 'message-kill-buffer) 987 (define-key message-mode-map "\C-c\C-k" 'message-kill-buffer)
730 (define-key message-mode-map "\C-c\C-d" 'message-dont-send) 988 (define-key message-mode-map "\C-c\C-d" 'message-dont-send)
731 989
990 (define-key message-mode-map "\C-c\C-e" 'message-elide-region)
991
732 (define-key message-mode-map "\t" 'message-tab)) 992 (define-key message-mode-map "\t" 'message-tab))
733 993
734 (easy-menu-define message-mode-menu message-mode-map 994 (easy-menu-define
735 "Message Menu." 995 message-mode-menu message-mode-map "Message Menu."
736 '("Message" 996 '("Message"
737 "Go to Field:" 997 ["Sort Headers" message-sort-headers t]
738 "----" 998 ["Yank Original" message-yank-original t]
739 ["To" message-goto-to t] 999 ["Fill Yanked Message" message-fill-yanked-message t]
740 ["Subject" message-goto-subject t] 1000 ["Insert Signature" message-insert-signature t]
741 ["Cc" message-goto-cc t] 1001 ["Caesar (rot13) Message" message-caesar-buffer-body t]
742 ["Reply-to" message-goto-reply-to t] 1002 ["Caesar (rot13) Region" message-caesar-region (mark t)]
743 ["Summary" message-goto-summary t] 1003 ["Elide Region" message-elide-region (mark t)]
744 ["Keywords" message-goto-keywords t] 1004 ["Rename buffer" message-rename-buffer t]
745 ["Newsgroups" message-goto-newsgroups t] 1005 ["Spellcheck" ispell-message t]
746 ["Followup-To" message-goto-followup-to t] 1006 "----"
747 ["Distribution" message-goto-distribution t] 1007 ["Send Message" message-send-and-exit t]
748 ["Body" message-goto-body t] 1008 ["Abort Message" message-dont-send t]))
749 ["Signature" message-goto-signature t] 1009
750 "----" 1010 (easy-menu-define
751 "Miscellaneous Commands:" 1011 message-mode-field-menu message-mode-map ""
752 "----" 1012 '("Field"
753 ["Sort Headers" message-sort-headers t] 1013 ["Fetch To" message-insert-to t]
754 ["Yank Original" message-yank-original t] 1014 ["Fetch Newsgroups" message-insert-newsgroups t]
755 ["Fill Yanked Message" message-fill-yanked-message t] 1015 "----"
756 ["Insert Signature" message-insert-signature t] 1016 ["To" message-goto-to t]
757 ["Caesar (rot13) Message" message-caesar-buffer-body t] 1017 ["Subject" message-goto-subject t]
758 ["Rename buffer" message-rename-buffer t] 1018 ["Cc" message-goto-cc t]
759 ["Spellcheck" ispell-message t] 1019 ["Reply-To" message-goto-reply-to t]
760 "----" 1020 ["Summary" message-goto-summary t]
761 ["Send Message" message-send-and-exit t] 1021 ["Keywords" message-goto-keywords t]
762 ["Abort Message" message-dont-send t])) 1022 ["Newsgroups" message-goto-newsgroups t]
1023 ["Followup-To" message-goto-followup-to t]
1024 ["Distribution" message-goto-distribution t]
1025 ["Body" message-goto-body t]
1026 ["Signature" message-goto-signature t]))
763 1027
764 (defvar facemenu-add-face-function) 1028 (defvar facemenu-add-face-function)
765 (defvar facemenu-remove-face-function) 1029 (defvar facemenu-remove-face-function)
766 1030
767 ;;;###autoload 1031 ;;;###autoload
770 Like Text Mode but with these additional commands: 1034 Like Text Mode but with these additional commands:
771 C-c C-s message-send (send the message) C-c C-c message-send-and-exit 1035 C-c C-s message-send (send the message) C-c C-c message-send-and-exit
772 C-c C-f move to a header field (and create it if there isn't): 1036 C-c C-f move to a header field (and create it if there isn't):
773 C-c C-f C-t move to To C-c C-f C-s move to Subject 1037 C-c C-f C-t move to To C-c C-f C-s move to Subject
774 C-c C-f C-c move to Cc C-c C-f C-b move to Bcc 1038 C-c C-f C-c move to Cc C-c C-f C-b move to Bcc
775 C-c C-f C-f move to Fcc C-c C-f C-r move to Reply-To 1039 C-c C-f C-w move to Fcc C-c C-f C-r move to Reply-To
776 C-c C-f C-u move to Summary C-c C-f C-n move to Newsgroups 1040 C-c C-f C-u move to Summary C-c C-f C-n move to Newsgroups
777 C-c C-f C-k move to Keywords C-c C-f C-d move to Distribution 1041 C-c C-f C-k move to Keywords C-c C-f C-d move to Distribution
778 C-c C-f C-o move to Followup-To 1042 C-c C-f C-f move to Followup-To
779 C-c C-t message-insert-to (add a To header to a news followup) 1043 C-c C-t message-insert-to (add a To header to a news followup)
780 C-c C-n message-insert-newsgroups (add a Newsgroup header to a news reply) 1044 C-c C-n message-insert-newsgroups (add a Newsgroup header to a news reply)
781 C-c C-b message-goto-body (move to beginning of message text). 1045 C-c C-b message-goto-body (move to beginning of message text).
782 C-c C-i message-goto-signature (move to the beginning of the signature). 1046 C-c C-i message-goto-signature (move to the beginning of the signature).
783 C-c C-w message-insert-signature (insert `message-signature-file' file). 1047 C-c C-w message-insert-signature (insert `message-signature-file' file).
784 C-c C-y message-yank-original (insert current message, if any). 1048 C-c C-y message-yank-original (insert current message, if any).
785 C-c C-q message-fill-yanked-message (fill what was yanked). 1049 C-c C-q message-fill-yanked-message (fill what was yanked).
786 C-c C-r message-ceasar-buffer-body (rot13 the message body)." 1050 C-c C-e message-elide-region (elide the text between point and mark).
1051 C-c C-r message-caesar-buffer-body (rot13 the message body)."
787 (interactive) 1052 (interactive)
788 (kill-all-local-variables) 1053 (kill-all-local-variables)
789 (make-local-variable 'message-reply-buffer) 1054 (make-local-variable 'message-reply-buffer)
790 (setq message-reply-buffer nil) 1055 (setq message-reply-buffer nil)
791 (make-local-variable 'message-send-actions) 1056 (set (make-local-variable 'message-send-actions) nil)
792 (make-local-variable 'message-exit-actions) 1057 (set (make-local-variable 'message-exit-actions) nil)
793 (make-local-variable 'message-kill-actions) 1058 (set (make-local-variable 'message-kill-actions) nil)
794 (make-local-variable 'message-postpone-actions) 1059 (set (make-local-variable 'message-postpone-actions) nil)
795 (set-syntax-table message-mode-syntax-table) 1060 (set-syntax-table message-mode-syntax-table)
796 (use-local-map message-mode-map) 1061 (use-local-map message-mode-map)
797 (setq local-abbrev-table message-mode-abbrev-table) 1062 (setq local-abbrev-table message-mode-abbrev-table)
798 (setq major-mode 'message-mode) 1063 (setq major-mode 'message-mode)
799 (setq mode-name "Message") 1064 (setq mode-name "Message")
832 ;;(when (fboundp 'mail-hist-define-keys) 1097 ;;(when (fboundp 'mail-hist-define-keys)
833 ;; (mail-hist-define-keys)) 1098 ;; (mail-hist-define-keys))
834 (when (string-match "XEmacs\\|Lucid" emacs-version) 1099 (when (string-match "XEmacs\\|Lucid" emacs-version)
835 (message-setup-toolbar)) 1100 (message-setup-toolbar))
836 (easy-menu-add message-mode-menu message-mode-map) 1101 (easy-menu-add message-mode-menu message-mode-map)
1102 (easy-menu-add message-mode-field-menu message-mode-map)
837 ;; Allow mail alias things. 1103 ;; Allow mail alias things.
838 (if (fboundp 'mail-abbrevs-setup) 1104 (if (fboundp 'mail-abbrevs-setup)
839 (mail-abbrevs-setup) 1105 (mail-abbrevs-setup)
840 (funcall (intern "mail-aliases-setup"))) 1106 (funcall (intern "mail-aliases-setup")))
841 (run-hooks 'text-mode-hook 'message-mode-hook)) 1107 (run-hooks 'text-mode-hook 'message-mode-hook))
912 1178
913 (defun message-goto-signature () 1179 (defun message-goto-signature ()
914 "Move point to the beginning of the message signature." 1180 "Move point to the beginning of the message signature."
915 (interactive) 1181 (interactive)
916 (goto-char (point-min)) 1182 (goto-char (point-min))
917 (or (re-search-forward message-signature-separator nil t) 1183 (if (re-search-forward message-signature-separator nil t)
918 (goto-char (point-max)))) 1184 (forward-line 1)
1185 (goto-char (point-max))))
919 1186
920 1187
921 1188
922 (defun message-insert-to () 1189 (defun message-insert-to ()
923 "Insert a To header that points to the author of the article being replied to." 1190 "Insert a To header that points to the author of the article being replied to."
924 (interactive) 1191 (interactive)
1192 (let ((co (message-fetch-field "courtesy-copies-to")))
1193 (when (and co
1194 (equal (downcase co) "never"))
1195 (error "The user has requested not to have copies sent via mail")))
925 (when (and (message-position-on-field "To") 1196 (when (and (message-position-on-field "To")
926 (mail-fetch-field "to") 1197 (mail-fetch-field "to")
927 (not (string-match "\\` *\\'" (mail-fetch-field "to")))) 1198 (not (string-match "\\` *\\'" (mail-fetch-field "to"))))
928 (insert ", ")) 1199 (insert ", "))
929 (insert (or (message-fetch-reply-field "reply-to") 1200 (insert (or (message-fetch-reply-field "reply-to")
944 1215
945 (defun message-insert-signature (&optional force) 1216 (defun message-insert-signature (&optional force)
946 "Insert a signature. See documentation for the `message-signature' variable." 1217 "Insert a signature. See documentation for the `message-signature' variable."
947 (interactive (list 0)) 1218 (interactive (list 0))
948 (let* ((signature 1219 (let* ((signature
949 (cond ((and (null message-signature) 1220 (cond
950 (eq force 0)) 1221 ((and (null message-signature)
951 (save-excursion 1222 (eq force 0))
952 (goto-char (point-max)) 1223 (save-excursion
953 (not (re-search-backward 1224 (goto-char (point-max))
954 message-signature-separator nil t)))) 1225 (not (re-search-backward
955 ((and (null message-signature) 1226 message-signature-separator nil t))))
956 force) 1227 ((and (null message-signature)
957 t) 1228 force)
958 ((message-functionp message-signature) 1229 t)
959 (funcall message-signature)) 1230 ((message-functionp message-signature)
960 ((listp message-signature) 1231 (funcall message-signature))
961 (eval message-signature)) 1232 ((listp message-signature)
962 (t message-signature))) 1233 (eval message-signature))
1234 (t message-signature)))
963 (signature 1235 (signature
964 (cond ((stringp signature) 1236 (cond ((stringp signature)
965 signature) 1237 signature)
966 ((and (eq t signature) 1238 ((and (eq t signature)
967 message-signature-file 1239 message-signature-file
968 (file-exists-p message-signature-file)) 1240 (file-exists-p message-signature-file))
969 signature)))) 1241 signature))))
970 (when signature 1242 (when signature
1243 (goto-char (point-max))
971 ;; Insert the signature. 1244 ;; Insert the signature.
972 (goto-char (point-max))
973 (unless (bolp) 1245 (unless (bolp)
974 (insert "\n")) 1246 (insert "\n"))
975 (insert "\n-- \n") 1247 (insert "\n-- \n")
976 (if (eq signature t) 1248 (if (eq signature t)
977 (insert-file-contents message-signature-file) 1249 (insert-file-contents message-signature-file)
978 (insert signature)) 1250 (insert signature))
979 (goto-char (point-max)) 1251 (goto-char (point-max))
980 (or (bolp) (insert "\n"))))) 1252 (or (bolp) (insert "\n")))))
1253
1254 (defun message-elide-region (b e)
1255 "Elide the text between point and mark. An ellipsis (from
1256 message-elide-elipsis) will be inserted where the text was killed."
1257 (interactive "r")
1258 (kill-region b e)
1259 (unless (bolp)
1260 (insert "\n"))
1261 (insert message-elide-elipsis))
981 1262
982 (defvar message-caesar-translation-table nil) 1263 (defvar message-caesar-translation-table nil)
983 1264
984 (defun message-caesar-region (b e &optional n) 1265 (defun message-caesar-region (b e &optional n)
985 "Caesar rotation of region by N, default 13, for decrypting netnews." 1266 "Caesar rotation of region by N, default 13, for decrypting netnews."
1030 (save-restriction 1311 (save-restriction
1031 (when (message-goto-body) 1312 (when (message-goto-body)
1032 (narrow-to-region (point) (point-max))) 1313 (narrow-to-region (point) (point-max)))
1033 (message-caesar-region (point-min) (point-max) rotnum)))) 1314 (message-caesar-region (point-min) (point-max) rotnum))))
1034 1315
1316 (defun message-pipe-buffer-body (program)
1317 "Pipe the message body in the current buffer through PROGRAM."
1318 (save-excursion
1319 (save-restriction
1320 (when (message-goto-body)
1321 (narrow-to-region (point) (point-max)))
1322 (let ((body (buffer-substring (point-min) (point-max))))
1323 (unless (equal 0 (call-process-region
1324 (point-min) (point-max) program t t))
1325 (insert body)
1326 (gnus-message 1 "%s failed." program))))))
1327
1035 (defun message-rename-buffer (&optional enter-string) 1328 (defun message-rename-buffer (&optional enter-string)
1036 "Rename the *message* buffer to \"*message* RECIPIENT\". 1329 "Rename the *message* buffer to \"*message* RECIPIENT\".
1037 If the function is run with a prefix, it will ask for a new buffer 1330 If the function is run with a prefix, it will ask for a new buffer
1038 name, rather than giving an automatic name." 1331 name, rather than giving an automatic name."
1039 (interactive "Pbuffer name: ") 1332 (interactive "Pbuffer name: ")
1040 (save-excursion 1333 (save-excursion
1041 (save-restriction 1334 (save-restriction
1042 (goto-char (point-min)) 1335 (goto-char (point-min))
1043 (narrow-to-region (point) 1336 (narrow-to-region (point)
1044 (search-forward mail-header-separator nil 'end)) 1337 (search-forward mail-header-separator nil 'end))
1045 (let* ((mail-to (if (message-news-p) (message-fetch-field "Newsgroups") 1338 (let* ((mail-to (or
1046 (message-fetch-field "To"))) 1339 (if (message-news-p) (message-fetch-field "Newsgroups")
1340 (message-fetch-field "To"))
1341 ""))
1047 (mail-trimmed-to 1342 (mail-trimmed-to
1048 (if (string-match "," mail-to) 1343 (if (string-match "," mail-to)
1049 (concat (substring mail-to 0 (match-beginning 0)) ", ...") 1344 (concat (substring mail-to 0 (match-beginning 0)) ", ...")
1050 mail-to)) 1345 mail-to))
1051 (name-default (concat "*message* " mail-trimmed-to)) 1346 (name-default (concat "*message* " mail-trimmed-to))
1052 (name (if enter-string 1347 (name (if enter-string
1053 (read-string "New buffer name: " name-default) 1348 (read-string "New buffer name: " name-default)
1054 name-default))) 1349 name-default))
1055 (rename-buffer name t) 1350 (default-directory
1056 (setq buffer-auto-save-file-name 1351 (file-name-as-directory message-autosave-directory)))
1057 (format "%s%s" 1352 (rename-buffer name t)))))
1058 (file-name-as-directory message-autosave-directory)
1059 (file-name-nondirectory buffer-auto-save-file-name)))))))
1060 1353
1061 (defun message-fill-yanked-message (&optional justifyp) 1354 (defun message-fill-yanked-message (&optional justifyp)
1062 "Fill the paragraphs of a message yanked into this one. 1355 "Fill the paragraphs of a message yanked into this one.
1063 Numeric argument means justify as well." 1356 Numeric argument means justify as well."
1064 (interactive "P") 1357 (interactive "P")
1082 (narrow-to-region 1375 (narrow-to-region
1083 (goto-char start) 1376 (goto-char start)
1084 (if (search-forward "\n\n" nil t) 1377 (if (search-forward "\n\n" nil t)
1085 (1- (point)) 1378 (1- (point))
1086 (point))) 1379 (point)))
1087 (message-remove-header message-ignored-cited-headers t))) 1380 (message-remove-header message-ignored-cited-headers t)
1381 (goto-char (point-max))))
1382 ;; Delete blank lines at the start of the buffer.
1383 (while (and (point-min)
1384 (eolp)
1385 (not (eobp)))
1386 (message-delete-line))
1387 ;; Delete blank lines at the end of the buffer.
1388 (goto-char (point-max))
1389 (unless (eolp)
1390 (insert "\n"))
1391 (while (and (zerop (forward-line -1))
1392 (looking-at "$"))
1393 (message-delete-line))
1088 ;; Do the indentation. 1394 ;; Do the indentation.
1089 (if (null message-yank-prefix) 1395 (if (null message-yank-prefix)
1090 (indent-rigidly start (mark t) message-indentation-spaces) 1396 (indent-rigidly start (mark t) message-indentation-spaces)
1091 (save-excursion 1397 (save-excursion
1092 (goto-char start) 1398 (goto-char start)
1093 (while (< (point) (mark t)) 1399 (while (< (point) (mark t))
1094 (insert message-yank-prefix) 1400 (insert message-yank-prefix)
1095 (forward-line 1))) 1401 (forward-line 1))))
1096 (goto-char start)))) 1402 (goto-char start)))
1097 1403
1098 (defun message-yank-original (&optional arg) 1404 (defun message-yank-original (&optional arg)
1099 "Insert the message being replied to, if any. 1405 "Insert the message being replied to, if any.
1100 Puts point before the text and mark after. 1406 Puts point before the text and mark after.
1101 Normally indents each nonblank line ARG spaces (default 3). However, 1407 Normally indents each nonblank line ARG spaces (default 3). However,
1116 (unless (bolp) 1422 (unless (bolp)
1117 (insert ?\n)) 1423 (insert ?\n))
1118 (unless modified 1424 (unless modified
1119 (setq message-checksum (cons (message-checksum) (buffer-size))))))) 1425 (setq message-checksum (cons (message-checksum) (buffer-size)))))))
1120 1426
1121 (defun message-cite-original () 1427 (defun message-cite-original ()
1428 "Cite function in the standard Message manner."
1122 (let ((start (point)) 1429 (let ((start (point))
1123 (functions 1430 (functions
1124 (when message-indent-citation-function 1431 (when message-indent-citation-function
1125 (if (listp message-indent-citation-function) 1432 (if (listp message-indent-citation-function)
1126 message-indent-citation-function 1433 message-indent-citation-function
1170 "Remove the signature from the text between point and mark. 1477 "Remove the signature from the text between point and mark.
1171 The text will also be indented the normal way." 1478 The text will also be indented the normal way."
1172 (save-excursion 1479 (save-excursion
1173 (let ((start (point)) 1480 (let ((start (point))
1174 mark) 1481 mark)
1175 (if (not (re-search-forward message-signature-separator (mark t) t)) 1482 (if (not (re-search-forward message-signature-separator (mark t) t))
1176 ;; No signature here, so we just indent the cited text. 1483 ;; No signature here, so we just indent the cited text.
1484 (message-indent-citation)
1485 ;; Find the last non-empty line.
1486 (forward-line -1)
1487 (while (looking-at "[ \t]*$")
1488 (forward-line -1))
1489 (forward-line 1)
1490 (setq mark (set-marker (make-marker) (point)))
1491 (goto-char start)
1177 (message-indent-citation) 1492 (message-indent-citation)
1178 ;; Find the last non-empty line. 1493 ;; Enable undoing the deletion.
1179 (forward-line -1) 1494 (undo-boundary)
1180 (while (looking-at "[ \t]*$") 1495 (delete-region mark (mark t))
1181 (forward-line -1)) 1496 (set-marker mark nil)))))
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)))))
1190 1497
1191 1498
1192 1499
1193 ;;; 1500 ;;;
1194 ;;; Sending messages 1501 ;;; Sending messages
1209 (message-do-actions actions)))) 1516 (message-do-actions actions))))
1210 1517
1211 (defun message-dont-send () 1518 (defun message-dont-send ()
1212 "Don't send the message you have been editing." 1519 "Don't send the message you have been editing."
1213 (interactive) 1520 (interactive)
1214 (message-bury (current-buffer)) 1521 (let ((actions message-postpone-actions))
1215 (message-do-actions message-postpone-actions)) 1522 (message-bury (current-buffer))
1523 (message-do-actions actions)))
1216 1524
1217 (defun message-kill-buffer () 1525 (defun message-kill-buffer ()
1218 "Kill the current buffer." 1526 "Kill the current buffer."
1219 (interactive) 1527 (interactive)
1220 (let ((actions message-kill-actions)) 1528 (let ((actions message-kill-actions))
1293 1601
1294 (defun message-do-actions (actions) 1602 (defun message-do-actions (actions)
1295 "Perform all actions in ACTIONS." 1603 "Perform all actions in ACTIONS."
1296 ;; Now perform actions on successful sending. 1604 ;; Now perform actions on successful sending.
1297 (while actions 1605 (while actions
1298 (condition-case nil 1606 (ignore-errors
1299 (cond 1607 (cond
1300 ;; A simple function. 1608 ;; A simple function.
1301 ((message-functionp (car actions)) 1609 ((message-functionp (car actions))
1302 (funcall (car actions))) 1610 (funcall (car actions)))
1303 ;; Something to be evaled. 1611 ;; Something to be evaled.
1304 (t 1612 (t
1305 (eval (car actions)))) 1613 (eval (car actions)))))
1306 (error))
1307 (pop actions))) 1614 (pop actions)))
1308 1615
1309 (defun message-send-mail (&optional arg) 1616 (defun message-send-mail (&optional arg)
1310 (require 'mail-utils) 1617 (require 'mail-utils)
1311 (let ((tembuf (generate-new-buffer " message temp")) 1618 (let ((tembuf (message-generate-new-buffer-clone-locals " message temp"))
1312 (case-fold-search nil) 1619 (case-fold-search nil)
1313 (news (message-news-p)) 1620 (news (message-news-p))
1314 (mailbuf (current-buffer))) 1621 (mailbuf (current-buffer)))
1315 (save-restriction 1622 (save-restriction
1316 (message-narrow-to-headers) 1623 (message-narrow-to-headers)
1362 (re-search-forward 1669 (re-search-forward
1363 (concat "^" (regexp-quote mail-header-separator) "\n")) 1670 (concat "^" (regexp-quote mail-header-separator) "\n"))
1364 (replace-match "\n") 1671 (replace-match "\n")
1365 (backward-char 1) 1672 (backward-char 1)
1366 (setq delimline (point-marker)) 1673 (setq delimline (point-marker))
1674 (run-hooks 'message-send-mail-hook)
1367 ;; Insert an extra newline if we need it to work around 1675 ;; Insert an extra newline if we need it to work around
1368 ;; Sun's bug that swallows newlines. 1676 ;; Sun's bug that swallows newlines.
1369 (goto-char (1+ delimline)) 1677 (goto-char (1+ delimline))
1370 (when (eval message-mailer-swallows-blank-line) 1678 (when (eval message-mailer-swallows-blank-line)
1371 (newline)) 1679 (newline))
1380 sendmail-program 1688 sendmail-program
1381 "/usr/lib/sendmail") 1689 "/usr/lib/sendmail")
1382 nil errbuf nil "-oi") 1690 nil errbuf nil "-oi")
1383 ;; Always specify who from, 1691 ;; Always specify who from,
1384 ;; since some systems have broken sendmails. 1692 ;; since some systems have broken sendmails.
1385 (list "-f" (user-login-name)) 1693 ;; But some systems are more broken with -f, so
1694 ;; we'll let users override this.
1695 (if (null message-sendmail-f-is-evil)
1696 (list "-f" (user-login-name)))
1386 ;; These mean "report errors by mail" 1697 ;; These mean "report errors by mail"
1387 ;; and "deliver in background". 1698 ;; and "deliver in background".
1388 (if (null message-interactive) '("-oem" "-odb")) 1699 (if (null message-interactive) '("-oem" "-odb"))
1389 ;; Get the addresses from the message 1700 ;; Get the addresses from the message
1390 ;; unless this is a resend. 1701 ;; unless this is a resend.
1404 (error "Sending...failed to %s" 1715 (error "Sending...failed to %s"
1405 (buffer-substring (point-min) (point-max))))) 1716 (buffer-substring (point-min) (point-max)))))
1406 (when (bufferp errbuf) 1717 (when (bufferp errbuf)
1407 (kill-buffer errbuf))))) 1718 (kill-buffer errbuf)))))
1408 1719
1720 (defun message-send-mail-with-qmail ()
1721 "Pass the prepared message buffer to qmail-inject.
1722 Refer to the documentation for the variable `message-send-mail-function'
1723 to find out how to use this."
1724 ;; replace the header delimiter with a blank line
1725 (goto-char (point-min))
1726 (re-search-forward
1727 (concat "^" (regexp-quote mail-header-separator) "\n"))
1728 (replace-match "\n")
1729 (run-hooks 'message-send-mail-hook)
1730 ;; send the message
1731 (case
1732 (apply
1733 'call-process-region 1 (point-max) message-qmail-inject-program
1734 nil nil nil
1735 ;; qmail-inject's default behaviour is to look for addresses on the
1736 ;; command line; if there're none, it scans the headers.
1737 ;; yes, it does The Right Thing w.r.t. Resent-To and it's kin.
1738 ;;
1739 ;; in general, ALL of qmail-inject's defaults are perfect for simply
1740 ;; reading a formatted (i. e., at least a To: or Resent-To header)
1741 ;; message from stdin.
1742 ;;
1743 ;; qmail also has the advantage of not having been raped by
1744 ;; various vendors, so we don't have to allow for that, either --
1745 ;; compare this with message-send-mail-with-sendmail and weep
1746 ;; for sendmail's lost innocence.
1747 ;;
1748 ;; all this is way cool coz it lets us keep the arguments entirely
1749 ;; free for -inject-arguments -- a big win for the user and for us
1750 ;; since we don't have to play that double-guessing game and the user
1751 ;; gets full control (no gestapo'ish -f's, for instance). --sj
1752 message-qmail-inject-args)
1753 ;; qmail-inject doesn't say anything on it's stdout/stderr,
1754 ;; we have to look at the retval instead
1755 (0 nil)
1756 (1 (error "qmail-inject reported permanent failure."))
1757 (111 (error "qmail-inject reported transient failure."))
1758 ;; should never happen
1759 (t (error "qmail-inject reported unknown failure."))))
1760
1409 (defun message-send-mail-with-mh () 1761 (defun message-send-mail-with-mh ()
1410 "Send the prepared message buffer with mh." 1762 "Send the prepared message buffer with mh."
1411 (let ((mh-previous-window-config nil) 1763 (let ((mh-previous-window-config nil)
1412 (name (make-temp-name 1764 (name (make-temp-name
1413 (concat (file-name-as-directory message-autosave-directory) 1765 (concat (file-name-as-directory
1766 (expand-file-name message-autosave-directory))
1414 "msg.")))) 1767 "msg."))))
1415 (setq buffer-file-name name) 1768 (setq buffer-file-name name)
1416 (mh-send-letter) 1769 ;; MH wants to generate these headers itself.
1417 (condition-case () 1770 (when message-mh-deletable-headers
1418 (delete-file name) 1771 (let ((headers message-mh-deletable-headers))
1419 (error nil)))) 1772 (while headers
1773 (goto-char (point-min))
1774 (and (re-search-forward
1775 (concat "^" (symbol-name (car headers)) ": *") nil t)
1776 (message-delete-line))
1777 (pop headers))))
1778 (run-hooks 'message-send-mail-hook)
1779 ;; Pass it on to mh.
1780 (mh-send-letter)))
1420 1781
1421 (defun message-send-news (&optional arg) 1782 (defun message-send-news (&optional arg)
1422 (let ((tembuf (generate-new-buffer " *message temp*")) 1783 (let ((tembuf (message-generate-new-buffer-clone-locals " *message temp*"))
1423 (case-fold-search nil) 1784 (case-fold-search nil)
1424 (method (if (message-functionp message-post-method) 1785 (method (if (message-functionp message-post-method)
1425 (funcall message-post-method arg) 1786 (funcall message-post-method arg)
1426 message-post-method)) 1787 message-post-method))
1427 (messbuf (current-buffer)) 1788 (messbuf (current-buffer))
1436 ;; Insert some headers. 1797 ;; Insert some headers.
1437 (message-generate-headers message-required-news-headers) 1798 (message-generate-headers message-required-news-headers)
1438 ;; Let the user do all of the above. 1799 ;; Let the user do all of the above.
1439 (run-hooks 'message-header-hook)) 1800 (run-hooks 'message-header-hook))
1440 (message-cleanup-headers) 1801 (message-cleanup-headers)
1441 (when (message-check-news-syntax) 1802 (if (not (message-check-news-syntax))
1803 (progn
1804 ;;(message "Posting not performed")
1805 nil)
1442 (unwind-protect 1806 (unwind-protect
1443 (save-excursion 1807 (save-excursion
1444 (set-buffer tembuf) 1808 (set-buffer tembuf)
1445 (buffer-disable-undo (current-buffer)) 1809 (buffer-disable-undo (current-buffer))
1446 (erase-buffer) 1810 (erase-buffer)
1447 ;; Avoid copying text props. 1811 ;; Avoid copying text props.
1448 (insert (format 1812 (insert (format
1449 "%s" (save-excursion 1813 "%s" (save-excursion
1450 (set-buffer messbuf) 1814 (set-buffer messbuf)
1451 (buffer-string)))) 1815 (buffer-string))))
1452 ;; Remove some headers. 1816 ;; Remove some headers.
1453 (save-restriction 1817 (save-restriction
1454 (message-narrow-to-headers) 1818 (message-narrow-to-headers)
1455 ;; Remove some headers. 1819 ;; Remove some headers.
1456 (message-remove-header message-ignored-news-headers t)) 1820 (message-remove-header message-ignored-news-headers t))
1457 (goto-char (point-max)) 1821 (goto-char (point-max))
1458 ;; require one newline at the end. 1822 ;; require one newline at the end.
1459 (or (= (preceding-char) ?\n) 1823 (or (= (preceding-char) ?\n)
1460 (insert ?\n)) 1824 (insert ?\n))
1461 (let ((case-fold-search t)) 1825 (let ((case-fold-search t))
1462 ;; Remove the delimeter. 1826 ;; Remove the delimiter.
1463 (goto-char (point-min)) 1827 (goto-char (point-min))
1464 (re-search-forward 1828 (re-search-forward
1465 (concat "^" (regexp-quote mail-header-separator) "\n")) 1829 (concat "^" (regexp-quote mail-header-separator) "\n"))
1466 (replace-match "\n") 1830 (replace-match "\n")
1467 (backward-char 1)) 1831 (backward-char 1))
1832 (run-hooks 'message-send-news-hook)
1468 (require (car method)) 1833 (require (car method))
1469 (funcall (intern (format "%s-open-server" (car method))) 1834 (funcall (intern (format "%s-open-server" (car method)))
1470 (cadr method) (cddr method)) 1835 (cadr method) (cddr method))
1471 (setq result 1836 (setq result
1472 (funcall (intern (format "%s-request-post" (car method)))))) 1837 (funcall (intern (format "%s-request-post" (car method))))))
1480 1845
1481 ;;; 1846 ;;;
1482 ;;; Header generation & syntax checking. 1847 ;;; Header generation & syntax checking.
1483 ;;; 1848 ;;;
1484 1849
1485 (defun message-check-news-syntax () 1850 (defmacro message-check (type &rest forms)
1486 "Check the syntax of the message." 1851 "Eval FORMS if TYPE is to be checked."
1487 (and 1852 `(or (message-check-element ,type)
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)
1667 (save-excursion 1853 (save-excursion
1668 (goto-char (point-min)) 1854 ,@forms)))
1669 (re-search-forward 1855
1670 (concat "^" (regexp-quote mail-header-separator) "$")) 1856 (put 'message-check 'lisp-indent-function 1)
1671 (while (and 1857 (put 'message-check 'edebug-form-spec '(form body))
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))))))
1728 1858
1729 (defun message-check-element (type) 1859 (defun message-check-element (type)
1730 "Returns non-nil if this type is not to be checked." 1860 "Returns non-nil if this type is not to be checked."
1731 (if (eq message-syntax-checks 'dont-check-for-anything-just-trust-me) 1861 (if (eq message-syntax-checks 'dont-check-for-anything-just-trust-me)
1732 t 1862 t
1733 (let ((able (assq type message-syntax-checks))) 1863 (let ((able (assq type message-syntax-checks)))
1734 (and (consp able) 1864 (and (consp able)
1735 (eq (cdr able) 'disabled))))) 1865 (eq (cdr able) 'disabled)))))
1866
1867 (defun message-check-news-syntax ()
1868 "Check the syntax of the message."
1869 (save-excursion
1870 (save-restriction
1871 (widen)
1872 (and
1873 ;; We narrow to the headers and check them first.
1874 (save-excursion
1875 (save-restriction
1876 (message-narrow-to-headers)
1877 (message-check-news-header-syntax)))
1878 ;; Check the body.
1879 (message-check-news-body-syntax)))))
1880
1881 (defun message-check-news-header-syntax ()
1882 (and
1883 ;; Check for commands in Subject.
1884 (message-check 'subject-cmsg
1885 (if (string-match "^cmsg " (message-fetch-field "subject"))
1886 (y-or-n-p
1887 "The control code \"cmsg\" is in the subject. Really post? ")
1888 t))
1889 ;; Check for multiple identical headers.
1890 (message-check 'multiple-headers
1891 (let (found)
1892 (while (and (not found)
1893 (re-search-forward "^[^ \t:]+: " nil t))
1894 (save-excursion
1895 (or (re-search-forward
1896 (concat "^"
1897 (regexp-quote
1898 (setq found
1899 (buffer-substring
1900 (match-beginning 0) (- (match-end 0) 2))))
1901 ":")
1902 nil t)
1903 (setq found nil))))
1904 (if found
1905 (y-or-n-p (format "Multiple %s headers. Really post? " found))
1906 t)))
1907 ;; Check for Version and Sendsys.
1908 (message-check 'sendsys
1909 (if (re-search-forward "^Sendsys:\\|^Version:" nil t)
1910 (y-or-n-p
1911 (format "The article contains a %s command. Really post? "
1912 (buffer-substring (match-beginning 0)
1913 (1- (match-end 0)))))
1914 t))
1915 ;; See whether we can shorten Followup-To.
1916 (message-check 'shorten-followup-to
1917 (let ((newsgroups (message-fetch-field "newsgroups"))
1918 (followup-to (message-fetch-field "followup-to"))
1919 to)
1920 (when (and newsgroups
1921 (string-match "," newsgroups)
1922 (not followup-to)
1923 (not
1924 (zerop
1925 (length
1926 (setq to (completing-read
1927 "Followups to: (default all groups) "
1928 (mapcar (lambda (g) (list g))
1929 (cons "poster"
1930 (message-tokenize-header
1931 newsgroups)))))))))
1932 (goto-char (point-min))
1933 (insert "Followup-To: " to "\n"))
1934 t))
1935 ;; Check "Shoot me".
1936 (message-check 'shoot
1937 (if (re-search-forward
1938 "Message-ID.*.i-did-not-set--mail-host-address--so-shoot-me" nil t)
1939 (y-or-n-p "You appear to have a misconfigured system. Really post? ")
1940 t))
1941 ;; Check for Approved.
1942 (message-check 'approved
1943 (if (re-search-forward "^Approved:" nil t)
1944 (y-or-n-p "The article contains an Approved header. Really post? ")
1945 t))
1946 ;; Check the Message-ID header.
1947 (message-check 'message-id
1948 (let* ((case-fold-search t)
1949 (message-id (message-fetch-field "message-id" t)))
1950 (or (not message-id)
1951 (and (string-match "@" message-id)
1952 (string-match "@[^\\.]*\\." message-id))
1953 (y-or-n-p
1954 (format "The Message-ID looks strange: \"%s\". Really post? "
1955 message-id)))))
1956 ;; Check the Subject header.
1957 (message-check 'subject
1958 (let* ((case-fold-search t)
1959 (subject (message-fetch-field "subject")))
1960 (or
1961 (and subject
1962 (not (string-match "\\`[ \t]*\\'" subject)))
1963 (ignore
1964 (message
1965 "The subject field is empty or missing. Posting is denied.")))))
1966 ;; Check the Newsgroups & Followup-To headers.
1967 (message-check 'existing-newsgroups
1968 (let* ((case-fold-search t)
1969 (newsgroups (message-fetch-field "newsgroups"))
1970 (followup-to (message-fetch-field "followup-to"))
1971 (groups (message-tokenize-header
1972 (if followup-to
1973 (concat newsgroups "," followup-to)
1974 newsgroups)))
1975 (hashtb (and (boundp 'gnus-active-hashtb)
1976 gnus-active-hashtb))
1977 errors)
1978 (if (or (not hashtb)
1979 (not (boundp 'gnus-read-active-file))
1980 (not gnus-read-active-file)
1981 (eq gnus-read-active-file 'some))
1982 t
1983 (while groups
1984 (when (and (not (boundp (intern (car groups) hashtb)))
1985 (not (equal (car groups) "poster")))
1986 (push (car groups) errors))
1987 (pop groups))
1988 (if (not errors)
1989 t
1990 (y-or-n-p
1991 (format
1992 "Really post to %s unknown group%s: %s "
1993 (if (= (length errors) 1) "this" "these")
1994 (if (= (length errors) 1) "" "s")
1995 (mapconcat 'identity errors ", ")))))))
1996 ;; Check the Newsgroups & Followup-To headers for syntax errors.
1997 (message-check 'valid-newsgroups
1998 (let ((case-fold-search t)
1999 (headers '("Newsgroups" "Followup-To"))
2000 header error)
2001 (while (and headers (not error))
2002 (when (setq header (mail-fetch-field (car headers)))
2003 (if (or
2004 (not
2005 (string-match
2006 "\\`\\([-+_&.a-zA-Z0-9]+\\)?\\(,[-+_&.a-zA-Z0-9]+\\)*\\'"
2007 header))
2008 (memq
2009 nil (mapcar
2010 (lambda (g)
2011 (not (string-match "\\.\\'\\|\\.\\." g)))
2012 (message-tokenize-header header ","))))
2013 (setq error t)))
2014 (unless error
2015 (pop headers)))
2016 (if (not error)
2017 t
2018 (y-or-n-p
2019 (format "The %s header looks odd: \"%s\". Really post? "
2020 (car headers) header)))))
2021 ;; Check the From header.
2022 (message-check 'from
2023 (let* ((case-fold-search t)
2024 (from (message-fetch-field "from"))
2025 (ad (nth 1 (mail-extract-address-components from))))
2026 (cond
2027 ((not from)
2028 (message "There is no From line. Posting is denied.")
2029 nil)
2030 ((or (not (string-match "@[^\\.]*\\." ad)) ;larsi@ifi
2031 (string-match "\\.\\." ad) ;larsi@ifi..uio
2032 (string-match "@\\." ad) ;larsi@.ifi.uio
2033 (string-match "\\.$" ad) ;larsi@ifi.uio.
2034 (not (string-match "^[^@]+@[^@]+$" ad)) ;larsi.ifi.uio
2035 (string-match "(.*).*(.*)" from)) ;(lars) (lars)
2036 (message
2037 "Denied posting -- the From looks strange: \"%s\"." from)
2038 nil)
2039 (t t))))))
2040
2041 (defun message-check-news-body-syntax ()
2042 (and
2043 ;; Check for long lines.
2044 (message-check 'long-lines
2045 (goto-char (point-min))
2046 (re-search-forward
2047 (concat "^" (regexp-quote mail-header-separator) "$"))
2048 (while (and
2049 (progn
2050 (end-of-line)
2051 (< (current-column) 80))
2052 (zerop (forward-line 1))))
2053 (or (bolp)
2054 (eobp)
2055 (y-or-n-p
2056 "You have lines longer than 79 characters. Really post? ")))
2057 ;; Check whether the article is empty.
2058 (message-check 'empty
2059 (goto-char (point-min))
2060 (re-search-forward
2061 (concat "^" (regexp-quote mail-header-separator) "$"))
2062 (forward-line 1)
2063 (let ((b (point)))
2064 (goto-char (point-max))
2065 (re-search-backward message-signature-separator nil t)
2066 (beginning-of-line)
2067 (or (re-search-backward "[^ \n\t]" b t)
2068 (y-or-n-p "Empty article. Really post? "))))
2069 ;; Check for control characters.
2070 (message-check 'control-chars
2071 (if (re-search-forward "[\000-\007\013\015-\037\200-\237]" nil t)
2072 (y-or-n-p
2073 "The article contains control characters. Really post? ")
2074 t))
2075 ;; Check excessive size.
2076 (message-check 'size
2077 (if (> (buffer-size) 60000)
2078 (y-or-n-p
2079 (format "The article is %d octets long. Really post? "
2080 (buffer-size)))
2081 t))
2082 ;; Check whether any new text has been added.
2083 (message-check 'new-text
2084 (or
2085 (not message-checksum)
2086 (not (and (eq (message-checksum) (car message-checksum))
2087 (eq (buffer-size) (cdr message-checksum))))
2088 (y-or-n-p
2089 "It looks like no new text has been added. Really post? ")))
2090 ;; Check the length of the signature.
2091 (message-check 'signature
2092 (goto-char (point-max))
2093 (if (or (not (re-search-backward message-signature-separator nil t))
2094 (search-forward message-forward-end-separator nil t))
2095 t
2096 (if (> (count-lines (point) (point-max)) 5)
2097 (y-or-n-p
2098 (format
2099 "Your .sig is %d lines; it should be max 4. Really post? "
2100 (1- (count-lines (point) (point-max)))))
2101 t)))))
1736 2102
1737 (defun message-checksum () 2103 (defun message-checksum ()
1738 "Return a \"checksum\" for the current buffer." 2104 "Return a \"checksum\" for the current buffer."
1739 (let ((sum 0)) 2105 (let ((sum 0))
1740 (save-excursion 2106 (save-excursion
1782 (funcall message-fcc-handler-function file) 2148 (funcall message-fcc-handler-function file)
1783 (if (and (file-readable-p file) (mail-file-babyl-p file)) 2149 (if (and (file-readable-p file) (mail-file-babyl-p file))
1784 (rmail-output file 1 nil t) 2150 (rmail-output file 1 nil t)
1785 (let ((mail-use-rfc822 t)) 2151 (let ((mail-use-rfc822 t))
1786 (rmail-output file 1 t t)))))) 2152 (rmail-output file 1 t t))))))
2153
1787 (kill-buffer (current-buffer))))) 2154 (kill-buffer (current-buffer)))))
2155
2156 (defun message-output (filename)
2157 "Append this article to Unix/babyl mail file.."
2158 (if (and (file-readable-p filename)
2159 (mail-file-babyl-p filename))
2160 (gnus-output-to-rmail filename t)
2161 (gnus-output-to-mail filename t)))
1788 2162
1789 (defun message-cleanup-headers () 2163 (defun message-cleanup-headers ()
1790 "Do various automatic cleanups of the headers." 2164 "Do various automatic cleanups of the headers."
1791 ;; Remove empty lines in the header. 2165 ;; Remove empty lines in the header.
1792 (save-restriction 2166 (save-restriction
2001 ;; ... then undo escaping of matching parentheses, 2375 ;; ... then undo escaping of matching parentheses,
2002 ;; including matching nested parentheses. 2376 ;; including matching nested parentheses.
2003 (goto-char fullname-start) 2377 (goto-char fullname-start)
2004 (while (re-search-forward 2378 (while (re-search-forward
2005 "\\(\\=\\|[^\\]\\(\\\\\\\\\\)*\\)\\\\(\\(\\([^\\]\\|\\\\\\\\\\)*\\)\\\\)" 2379 "\\(\\=\\|[^\\]\\(\\\\\\\\\\)*\\)\\\\(\\(\\([^\\]\\|\\\\\\\\\\)*\\)\\\\)"
2006 nil 1) 2380 nil 1)
2007 (replace-match "\\1(\\3)" t) 2381 (replace-match "\\1(\\3)" t)
2008 (goto-char fullname-start))) 2382 (goto-char fullname-start)))
2009 (insert ")"))) 2383 (insert ")")))
2010 (buffer-string)))) 2384 (buffer-string))))
2011 2385
2021 (concat (user-login-name) "@" (message-make-domain)))) 2395 (concat (user-login-name) "@" (message-make-domain))))
2022 2396
2023 (defun message-user-mail-address () 2397 (defun message-user-mail-address ()
2024 "Return the pertinent part of `user-mail-address'." 2398 "Return the pertinent part of `user-mail-address'."
2025 (when user-mail-address 2399 (when user-mail-address
2026 (nth 1 (mail-extract-address-components user-mail-address)))) 2400 (if (string-match " " user-mail-address)
2401 (nth 1 (mail-extract-address-components user-mail-address))
2402 user-mail-address)))
2027 2403
2028 (defun message-make-fqdn () 2404 (defun message-make-fqdn ()
2029 "Return user's fully qualified domain name." 2405 "Return user's fully qualified domain name."
2030 (let ((system-name (system-name)) 2406 (let ((system-name (system-name))
2031 (user-mail (message-user-mail-address))) 2407 (user-mail (message-user-mail-address)))
2042 ((and (string-match "\\." user-mail) 2418 ((and (string-match "\\." user-mail)
2043 (string-match "@\\(.*\\)\\'" user-mail)) 2419 (string-match "@\\(.*\\)\\'" user-mail))
2044 (match-string 1 user-mail)) 2420 (match-string 1 user-mail))
2045 ;; Default to this bogus thing. 2421 ;; Default to this bogus thing.
2046 (t 2422 (t
2047 (concat system-name ".i-have-a-misconfigured-system-so-shoot-me"))))) 2423 (concat system-name ".i-did-not-set--mail-host-address--so-shoot-me")))))
2048 2424
2049 (defun message-make-host-name () 2425 (defun message-make-host-name ()
2050 "Return the name of the host." 2426 "Return the name of the host."
2051 (let ((fqdn (message-make-fqdn))) 2427 (let ((fqdn (message-make-fqdn)))
2052 (string-match "^[^.]+\\." fqdn) 2428 (string-match "^[^.]+\\." fqdn)
2087 (concat "^" (symbol-name (car headers)) ": *") nil t) 2463 (concat "^" (symbol-name (car headers)) ": *") nil t)
2088 (get-text-property (1+ (match-beginning 0)) 'message-deletable) 2464 (get-text-property (1+ (match-beginning 0)) 'message-deletable)
2089 (message-delete-line)) 2465 (message-delete-line))
2090 (pop headers))) 2466 (pop headers)))
2091 ;; Go through all the required headers and see if they are in the 2467 ;; Go through all the required headers and see if they are in the
2092 ;; articles already. If they are not, or are empty, they are 2468 ;; articles already. If they are not, or are empty, they are
2093 ;; inserted automatically - except for Subject, Newsgroups and 2469 ;; inserted automatically - except for Subject, Newsgroups and
2094 ;; Distribution. 2470 ;; Distribution.
2095 (while headers 2471 (while headers
2096 (goto-char (point-min)) 2472 (goto-char (point-min))
2097 (setq elem (pop headers)) 2473 (setq elem (pop headers))
2102 (setq header elem)) 2478 (setq header elem))
2103 (when (or (not (re-search-forward 2479 (when (or (not (re-search-forward
2104 (concat "^" (downcase (symbol-name header)) ":") 2480 (concat "^" (downcase (symbol-name header)) ":")
2105 nil t)) 2481 nil t))
2106 (progn 2482 (progn
2107 ;; The header was found. We insert a space after the 2483 ;; The header was found. We insert a space after the
2108 ;; colon, if there is none. 2484 ;; colon, if there is none.
2109 (if (/= (following-char) ? ) (insert " ") (forward-char 1)) 2485 (if (/= (following-char) ? ) (insert " ") (forward-char 1))
2110 ;; Find out whether the header is empty... 2486 ;; Find out whether the header is empty...
2111 (looking-at "[ \t]*$"))) 2487 (looking-at "[ \t]*$")))
2112 ;; So we find out what value we should insert. 2488 ;; So we find out what value we should insert.
2171 (downcase 2547 (downcase
2172 (cadr (mail-extract-address-components sender))) 2548 (cadr (mail-extract-address-components sender)))
2173 (downcase secure-sender))))) 2549 (downcase secure-sender)))))
2174 (goto-char (point-min)) 2550 (goto-char (point-min))
2175 ;; Rename any old Sender headers to Original-Sender. 2551 ;; Rename any old Sender headers to Original-Sender.
2176 (when (re-search-forward "^Sender:" nil t) 2552 (when (re-search-forward "^\\(Original-\\)*Sender:" nil t)
2177 (beginning-of-line) 2553 (beginning-of-line)
2178 (insert "Original-") 2554 (insert "Original-")
2179 (beginning-of-line)) 2555 (beginning-of-line))
2180 (insert "Sender: " secure-sender "\n")))))) 2556 (insert "Sender: " secure-sender "\n"))))))
2181 2557
2182 (defun message-insert-courtesy-copy () 2558 (defun message-insert-courtesy-copy ()
2183 "Insert a courtesy message in mail copies of combined messages." 2559 "Insert a courtesy message in mail copies of combined messages."
2184 (save-excursion 2560 (let (newsgroups)
2185 (save-restriction 2561 (save-excursion
2186 (message-narrow-to-headers) 2562 (save-restriction
2187 (let ((newsgroups (message-fetch-field "newsgroups"))) 2563 (message-narrow-to-headers)
2188 (when newsgroups 2564 (when (setq newsgroups (message-fetch-field "newsgroups"))
2189 (goto-char (point-max)) 2565 (goto-char (point-max))
2190 (insert "Posted-To: " newsgroups "\n")))) 2566 (insert "Posted-To: " newsgroups "\n")))
2191 (forward-line 1) 2567 (forward-line 1)
2192 (insert message-courtesy-message))) 2568 (when message-courtesy-message
2569 (cond
2570 ((string-match "%s" message-courtesy-message)
2571 (insert (format message-courtesy-message newsgroups)))
2572 (t
2573 (insert message-courtesy-message)))))))
2193 2574
2194 ;;; 2575 ;;;
2195 ;;; Setting up a message buffer 2576 ;;; Setting up a message buffer
2196 ;;; 2577 ;;;
2197 2578
2306 "Kill old message buffers." 2687 "Kill old message buffers."
2307 ;; We might have sent this buffer already. Delete it from the 2688 ;; We might have sent this buffer already. Delete it from the
2308 ;; list of buffers. 2689 ;; list of buffers.
2309 (setq message-buffer-list (delq (current-buffer) message-buffer-list)) 2690 (setq message-buffer-list (delq (current-buffer) message-buffer-list))
2310 (while (and message-max-buffers 2691 (while (and message-max-buffers
2692 message-buffer-list
2311 (>= (length message-buffer-list) message-max-buffers)) 2693 (>= (length message-buffer-list) message-max-buffers))
2312 ;; Kill the oldest buffer -- unless it has been changed. 2694 ;; Kill the oldest buffer -- unless it has been changed.
2313 (let ((buffer (pop message-buffer-list))) 2695 (let ((buffer (pop message-buffer-list)))
2314 (when (and (buffer-name buffer) 2696 (when (and (buffer-name buffer)
2315 (not (buffer-modified-p buffer))) 2697 (not (buffer-modified-p buffer)))
2406 ;;; 2788 ;;;
2407 ;;; Commands for interfacing with message 2789 ;;; Commands for interfacing with message
2408 ;;; 2790 ;;;
2409 2791
2410 ;;;###autoload 2792 ;;;###autoload
2411 (defun message-mail (&optional to subject) 2793 (defun message-mail (&optional to subject
2794 other-headers continue switch-function
2795 yank-action send-actions)
2412 "Start editing a mail message to be sent." 2796 "Start editing a mail message to be sent."
2413 (interactive) 2797 (interactive)
2414 (message-pop-to-buffer (message-buffer-name "mail" to)) 2798 (let ((message-this-is-mail t))
2415 (message-setup `((To . ,(or to "")) (Subject . ,(or subject ""))))) 2799 (message-pop-to-buffer (message-buffer-name "mail" to))
2800 (message-setup
2801 (nconc
2802 `((To . ,(or to "")) (Subject . ,(or subject "")))
2803 (when other-headers (list other-headers))))))
2416 2804
2417 ;;;###autoload 2805 ;;;###autoload
2418 (defun message-news (&optional newsgroups subject) 2806 (defun message-news (&optional newsgroups subject)
2419 "Start editing a news article to be sent." 2807 "Start editing a news article to be sent."
2420 (interactive) 2808 (interactive)
2421 (message-pop-to-buffer (message-buffer-name "news" nil newsgroups)) 2809 (let ((message-this-is-news t))
2422 (message-setup `((Newsgroups . ,(or newsgroups "")) 2810 (message-pop-to-buffer (message-buffer-name "news" nil newsgroups))
2423 (Subject . ,(or subject ""))))) 2811 (message-setup `((Newsgroups . ,(or newsgroups ""))
2812 (Subject . ,(or subject ""))))))
2424 2813
2425 ;;;###autoload 2814 ;;;###autoload
2426 (defun message-reply (&optional to-address wide ignore-reply-to) 2815 (defun message-reply (&optional to-address wide ignore-reply-to)
2427 "Start editing a reply to the article in the current buffer." 2816 "Start editing a reply to the article in the current buffer."
2428 (interactive) 2817 (interactive)
2430 from subject date reply-to to cc 2819 from subject date reply-to to cc
2431 references message-id follow-to 2820 references message-id follow-to
2432 (inhibit-point-motion-hooks t) 2821 (inhibit-point-motion-hooks t)
2433 mct never-mct gnus-warning) 2822 mct never-mct gnus-warning)
2434 (save-restriction 2823 (save-restriction
2435 (narrow-to-region 2824 (message-narrow-to-head)
2436 (goto-char (point-min))
2437 (if (search-forward "\n\n" nil t)
2438 (1- (point))
2439 (point-max)))
2440 ;; Allow customizations to have their say. 2825 ;; Allow customizations to have their say.
2441 (if (not wide) 2826 (if (not wide)
2442 ;; This is a regular reply. 2827 ;; This is a regular reply.
2443 (if (message-functionp message-reply-to-function) 2828 (if (message-functionp message-reply-to-function)
2444 (setq follow-to (funcall message-reply-to-function))) 2829 (setq follow-to (funcall message-reply-to-function)))
2454 to (message-fetch-field "to") 2839 to (message-fetch-field "to")
2455 cc (message-fetch-field "cc") 2840 cc (message-fetch-field "cc")
2456 mct (message-fetch-field "mail-copies-to") 2841 mct (message-fetch-field "mail-copies-to")
2457 reply-to (unless ignore-reply-to (message-fetch-field "reply-to")) 2842 reply-to (unless ignore-reply-to (message-fetch-field "reply-to"))
2458 references (message-fetch-field "references") 2843 references (message-fetch-field "references")
2459 message-id (message-fetch-field "message-id")) 2844 message-id (message-fetch-field "message-id" t))
2460 ;; Remove any (buggy) Re:'s that are present and make a 2845 ;; Remove any (buggy) Re:'s that are present and make a
2461 ;; proper one. 2846 ;; proper one.
2462 (when (string-match "^[ \t]*[Rr][Ee]:[ \t]*" subject) 2847 (when (string-match "^[ \t]*[Rr][Ee]:[ \t]*" subject)
2463 (setq subject (substring subject (match-end 0)))) 2848 (setq subject (substring subject (match-end 0))))
2464 (setq subject (concat "Re: " subject)) 2849 (setq subject (concat "Re: " subject))
2489 (insert (if cc (concat (if (bolp) "" ", ") cc) "")) 2874 (insert (if cc (concat (if (bolp) "" ", ") cc) ""))
2490 ;; Remove addresses that match `rmail-dont-reply-to-names'. 2875 ;; Remove addresses that match `rmail-dont-reply-to-names'.
2491 (insert (prog1 (rmail-dont-reply-to (buffer-string)) 2876 (insert (prog1 (rmail-dont-reply-to (buffer-string))
2492 (erase-buffer))) 2877 (erase-buffer)))
2493 (goto-char (point-min)) 2878 (goto-char (point-min))
2879 ;; Perhaps Mail-Copies-To: never removed the only address?
2880 (when (eobp)
2881 (insert (or reply-to from "")))
2494 (setq ccalist 2882 (setq ccalist
2495 (mapcar 2883 (mapcar
2496 (lambda (addr) 2884 (lambda (addr)
2497 (cons (mail-strip-quoted-names addr) addr)) 2885 (cons (mail-strip-quoted-names addr) addr))
2498 (message-tokenize-header (buffer-string)))) 2886 (message-tokenize-header (buffer-string))))
2499 (let ((s ccalist)) 2887 (let ((s ccalist))
2500 (while s 2888 (while s
2501 (setq ccalist (delq (assoc (car (pop s)) s) ccalist))))) 2889 (setq ccalist (delq (assoc (car (pop s)) s) ccalist)))))
2502 (setq follow-to (list (cons 'To (cdr (pop ccalist))))) 2890 (setq follow-to (list (cons 'To (cdr (pop ccalist)))))
2503 (when ccalist 2891 (when ccalist
2504 (push (cons 'Cc 2892 (let ((ccs (cons 'Cc (mapconcat
2505 (mapconcat (lambda (addr) (cdr addr)) ccalist ", ")) 2893 (lambda (addr) (cdr addr)) ccalist ", "))))
2506 follow-to))))) 2894 (when (string-match "^ +" (cdr ccs))
2895 (setcdr ccs (substring (cdr ccs) (match-end 0))))
2896 (push ccs follow-to))))))
2507 (widen)) 2897 (widen))
2508 2898
2509 (message-pop-to-buffer (message-buffer-name 2899 (message-pop-to-buffer (message-buffer-name
2510 (if wide "wide reply" "reply") from 2900 (if wide "wide reply" "reply") from
2511 (if wide to-address nil))) 2901 (if wide to-address nil)))
2522 nil)) 2912 nil))
2523 cur))) 2913 cur)))
2524 2914
2525 ;;;###autoload 2915 ;;;###autoload
2526 (defun message-wide-reply (&optional to-address) 2916 (defun message-wide-reply (&optional to-address)
2917 "Make a \"wide\" reply to the message in the current buffer."
2527 (interactive) 2918 (interactive)
2528 (message-reply to-address t)) 2919 (message-reply to-address t))
2529 2920
2530 ;;;###autoload 2921 ;;;###autoload
2531 (defun message-followup () 2922 (defun message-followup (&optional to-newsgroups)
2923 "Follow up to the message in the current buffer.
2924 If TO-NEWSGROUPS, use that as the new Newsgroups line."
2532 (interactive) 2925 (interactive)
2533 (let ((cur (current-buffer)) 2926 (let ((cur (current-buffer))
2534 from subject date reply-to mct 2927 from subject date reply-to mct
2535 references message-id follow-to 2928 references message-id follow-to
2536 (inhibit-point-motion-hooks t) 2929 (inhibit-point-motion-hooks t)
2930 (message-this-is-news t)
2537 followup-to distribution newsgroups gnus-warning) 2931 followup-to distribution newsgroups gnus-warning)
2538 (save-restriction 2932 (save-restriction
2539 (narrow-to-region 2933 (narrow-to-region
2540 (goto-char (point-min)) 2934 (goto-char (point-min))
2541 (if (search-forward "\n\n" nil t) 2935 (if (search-forward "\n\n" nil t)
2546 (funcall message-followup-to-function))) 2940 (funcall message-followup-to-function)))
2547 (setq from (message-fetch-field "from") 2941 (setq from (message-fetch-field "from")
2548 date (message-fetch-field "date") 2942 date (message-fetch-field "date")
2549 subject (or (message-fetch-field "subject") "none") 2943 subject (or (message-fetch-field "subject") "none")
2550 references (message-fetch-field "references") 2944 references (message-fetch-field "references")
2551 message-id (message-fetch-field "message-id") 2945 message-id (message-fetch-field "message-id" t)
2552 followup-to (message-fetch-field "followup-to") 2946 followup-to (message-fetch-field "followup-to")
2553 newsgroups (message-fetch-field "newsgroups") 2947 newsgroups (message-fetch-field "newsgroups")
2554 reply-to (message-fetch-field "reply-to") 2948 reply-to (message-fetch-field "reply-to")
2555 distribution (message-fetch-field "distribution") 2949 distribution (message-fetch-field "distribution")
2556 mct (message-fetch-field "mail-copies-to")) 2950 mct (message-fetch-field "mail-copies-to"))
2557 (when (and (setq gnus-warning (message-fetch-field "gnus-warning")) 2951 (when (and (setq gnus-warning (message-fetch-field "gnus-warning"))
2558 (string-match "<[^>]+>" gnus-warning)) 2952 (string-match "<[^>]+>" gnus-warning))
2559 (setq message-id (match-string 0 gnus-warning))) 2953 (setq message-id (match-string 0 gnus-warning)))
2560 ;; Remove bogus distribution. 2954 ;; Remove bogus distribution.
2561 (and (stringp distribution) 2955 (when (and (stringp distribution)
2562 (string-match "world" distribution) 2956 (let ((case-fold-search t))
2563 (setq distribution nil)) 2957 (string-match "world" distribution)))
2958 (setq distribution nil))
2564 ;; Remove any (buggy) Re:'s that are present and make a 2959 ;; Remove any (buggy) Re:'s that are present and make a
2565 ;; proper one. 2960 ;; proper one.
2566 (when (string-match "^[ \t]*[Rr][Ee]:[ \t]*" subject) 2961 (when (string-match "^[ \t]*[Rr][Ee]:[ \t]*" subject)
2567 (setq subject (substring subject (match-end 0)))) 2962 (setq subject (substring subject (match-end 0))))
2568 (setq subject (concat "Re: " subject)) 2963 (setq subject (concat "Re: " subject))
2571 (message-pop-to-buffer (message-buffer-name "followup" from newsgroups)) 2966 (message-pop-to-buffer (message-buffer-name "followup" from newsgroups))
2572 2967
2573 (message-setup 2968 (message-setup
2574 `((Subject . ,subject) 2969 `((Subject . ,subject)
2575 ,@(cond 2970 ,@(cond
2971 (to-newsgroups
2972 (list (cons 'Newsgroups to-newsgroups)))
2576 (follow-to follow-to) 2973 (follow-to follow-to)
2577 ((and followup-to message-use-followup-to) 2974 ((and followup-to message-use-followup-to)
2578 (list 2975 (list
2579 (cond 2976 (cond
2580 ((equal (downcase followup-to) "poster") 2977 ((equal (downcase followup-to) "poster")
2603 If a message is posted to several newsgroups, Followup-To is often 3000 If a message is posted to several newsgroups, Followup-To is often
2604 used to direct the following discussion to one newsgroup only, 3001 used to direct the following discussion to one newsgroup only,
2605 because discussions that are spread over several newsgroup tend to 3002 because discussions that are spread over several newsgroup tend to
2606 be fragmented and very difficult to follow. 3003 be fragmented and very difficult to follow.
2607 3004
2608 Also, some source/announcment newsgroups are not indented for discussion; 3005 Also, some source/announcement newsgroups are not indented for discussion;
2609 responses here are directed to other newsgroups.")) 3006 responses here are directed to other newsgroups."))
2610 (cons 'Newsgroups followup-to) 3007 (cons 'Newsgroups followup-to)
2611 (cons 'Newsgroups newsgroups)))))) 3008 (cons 'Newsgroups newsgroups))))))
2612 (t 3009 (t
2613 `((Newsgroups . ,newsgroups)))) 3010 `((Newsgroups . ,newsgroups))))
2614 ,@(and distribution (list (cons 'Distribution distribution))) 3011 ,@(and distribution (list (cons 'Distribution distribution)))
2615 (References . ,(concat (or references "") (and references " ") 3012 ,@(if (or references message-id)
2616 (or message-id ""))) 3013 `((References . ,(concat (or references "") (and references " ")
3014 (or message-id "")))))
2617 ,@(when (and mct 3015 ,@(when (and mct
2618 (not (equal (downcase mct) "never"))) 3016 (not (equal (downcase mct) "never")))
2619 (list (cons 'Cc (if (equal (downcase mct) "always") 3017 (list (cons 'Cc (if (equal (downcase mct) "always")
2620 (or reply-to from "") 3018 (or reply-to from "")
2621 mct))))) 3019 mct)))))
2638 ;; Get header info. from original article. 3036 ;; Get header info. from original article.
2639 (save-restriction 3037 (save-restriction
2640 (message-narrow-to-head) 3038 (message-narrow-to-head)
2641 (setq from (message-fetch-field "from") 3039 (setq from (message-fetch-field "from")
2642 newsgroups (message-fetch-field "newsgroups") 3040 newsgroups (message-fetch-field "newsgroups")
2643 message-id (message-fetch-field "message-id") 3041 message-id (message-fetch-field "message-id" t)
2644 distribution (message-fetch-field "distribution"))) 3042 distribution (message-fetch-field "distribution")))
2645 ;; Make sure that this article was written by the user. 3043 ;; Make sure that this article was written by the user.
2646 (unless (string-equal 3044 (unless (string-equal
2647 (downcase (cadr (mail-extract-address-components from))) 3045 (downcase (cadr (mail-extract-address-components from)))
2648 (downcase (message-make-address))) 3046 (downcase (message-make-address)))
2657 "Control: cancel " message-id "\n" 3055 "Control: cancel " message-id "\n"
2658 (if distribution 3056 (if distribution
2659 (concat "Distribution: " distribution "\n") 3057 (concat "Distribution: " distribution "\n")
2660 "") 3058 "")
2661 mail-header-separator "\n" 3059 mail-header-separator "\n"
2662 "This is a cancel message from " from ".\n") 3060 message-cancel-message)
2663 (message "Canceling your article...") 3061 (message "Canceling your article...")
2664 (let ((message-syntax-checks 'dont-check-for-anything-just-trust-me)) 3062 (let ((message-syntax-checks 'dont-check-for-anything-just-trust-me))
2665 (funcall message-send-news-function)) 3063 (funcall message-send-news-function))
2666 (message "Canceling your article...done") 3064 (message "Canceling your article...done")
2667 (kill-buffer buf))))) 3065 (kill-buffer buf)))))
2715 3113
2716 ;;; Forwarding messages. 3114 ;;; Forwarding messages.
2717 3115
2718 (defun message-make-forward-subject () 3116 (defun message-make-forward-subject ()
2719 "Return a Subject header suitable for the message in the current buffer." 3117 "Return a Subject header suitable for the message in the current buffer."
2720 (concat "[" (or (message-fetch-field (if (message-news-p) "newsgroups" "from")) 3118 (save-excursion
2721 "(nowhere)") 3119 (save-restriction
2722 "] " (or (message-fetch-field "Subject") ""))) 3120 (current-buffer)
3121 (message-narrow-to-head)
3122 (concat "[" (or (message-fetch-field
3123 (if (message-news-p) "newsgroups" "from"))
3124 "(nowhere)")
3125 "] " (or (message-fetch-field "Subject") "")))))
2723 3126
2724 ;;;###autoload 3127 ;;;###autoload
2725 (defun message-forward (&optional news) 3128 (defun message-forward (&optional news)
2726 "Forward the current message via mail. 3129 "Forward the current message via mail.
2727 Optional NEWS will use news to forward instead of mail." 3130 Optional NEWS will use news to forward instead of mail."
2728 (interactive "P") 3131 (interactive "P")
2729 (let ((cur (current-buffer)) 3132 (let ((cur (current-buffer))
2730 (subject (message-make-forward-subject))) 3133 (subject (message-make-forward-subject))
3134 art-beg)
2731 (if news (message-news nil subject) (message-mail nil subject)) 3135 (if news (message-news nil subject) (message-mail nil subject))
2732 ;; Put point where we want it before inserting the forwarded 3136 ;; Put point where we want it before inserting the forwarded
2733 ;; message. 3137 ;; message.
2734 (if message-signature-before-forwarded-message 3138 (if message-signature-before-forwarded-message
2735 (goto-char (point-max)) 3139 (goto-char (point-max))
2739 (insert "\n")) 3143 (insert "\n"))
2740 ;; Narrow to the area we are to insert. 3144 ;; Narrow to the area we are to insert.
2741 (narrow-to-region (point) (point)) 3145 (narrow-to-region (point) (point))
2742 ;; Insert the separators and the forwarded buffer. 3146 ;; Insert the separators and the forwarded buffer.
2743 (insert message-forward-start-separator) 3147 (insert message-forward-start-separator)
3148 (setq art-beg (point))
2744 (insert-buffer-substring cur) 3149 (insert-buffer-substring cur)
2745 (goto-char (point-max)) 3150 (goto-char (point-max))
2746 (insert message-forward-end-separator) 3151 (insert message-forward-end-separator)
2747 (set-text-properties (point-min) (point-max) nil) 3152 (set-text-properties (point-min) (point-max) nil)
2748 ;; Remove all unwanted headers. 3153 ;; Remove all unwanted headers.
2749 (goto-char (point-min)) 3154 (goto-char art-beg)
2750 (forward-line 1)
2751 (narrow-to-region (point) (if (search-forward "\n\n" nil t) 3155 (narrow-to-region (point) (if (search-forward "\n\n" nil t)
2752 (1- (point)) 3156 (1- (point))
2753 (point))) 3157 (point)))
2754 (goto-char (point-min)) 3158 (goto-char (point-min))
2755 (message-remove-header message-included-forward-headers t nil t) 3159 (message-remove-header message-included-forward-headers t nil t)
2758 3162
2759 ;;;###autoload 3163 ;;;###autoload
2760 (defun message-resend (address) 3164 (defun message-resend (address)
2761 "Resend the current article to ADDRESS." 3165 "Resend the current article to ADDRESS."
2762 (interactive "sResend message to: ") 3166 (interactive "sResend message to: ")
3167 (message "Resending message to %s..." address)
2763 (save-excursion 3168 (save-excursion
2764 (let ((cur (current-buffer)) 3169 (let ((cur (current-buffer))
2765 beg) 3170 beg)
2766 ;; We first set up a normal mail buffer. 3171 ;; We first set up a normal mail buffer.
2767 (set-buffer (get-buffer-create " *message resend*")) 3172 (set-buffer (get-buffer-create " *message resend*"))
2791 (insert mail-header-separator) 3196 (insert mail-header-separator)
2792 ;; Rename all old ("Also-")Resent headers. 3197 ;; Rename all old ("Also-")Resent headers.
2793 (while (re-search-backward "^\\(Also-\\)?Resent-" beg t) 3198 (while (re-search-backward "^\\(Also-\\)?Resent-" beg t)
2794 (beginning-of-line) 3199 (beginning-of-line)
2795 (insert "Also-")) 3200 (insert "Also-"))
3201 ;; Quote any "From " lines at the beginning.
3202 (goto-char beg)
3203 (when (looking-at "From ")
3204 (replace-match "X-From-Line: "))
2796 ;; Send it. 3205 ;; Send it.
2797 (message-send-mail) 3206 (message-send-mail)
2798 (kill-buffer (current-buffer))))) 3207 (kill-buffer (current-buffer)))
3208 (message "Resending message to %s...done" address)))
2799 3209
2800 ;;;###autoload 3210 ;;;###autoload
2801 (defun message-bounce () 3211 (defun message-bounce ()
2802 "Re-mail the current message. 3212 "Re-mail the current message.
2803 This only makes sense if the current message is a bounce message than 3213 This only makes sense if the current message is a bounce message than
2903 Works by overstriking characters. 3313 Works by overstriking characters.
2904 Called from program, takes two arguments START and END 3314 Called from program, takes two arguments START and END
2905 which specify the range to operate on." 3315 which specify the range to operate on."
2906 (interactive "r") 3316 (interactive "r")
2907 (save-excursion 3317 (save-excursion
2908 (let ((end1 (make-marker))) 3318 (let ((end1 (make-marker)))
2909 (move-marker end1 (max start end)) 3319 (move-marker end1 (max start end))
2910 (goto-char (min start end)) 3320 (goto-char (min start end))
2911 (while (< (point) end1) 3321 (while (< (point) end1)
2912 (or (looking-at "[_\^@- ]") 3322 (or (looking-at "[_\^@- ]")
2913 (insert (following-char) "\b")) 3323 (insert (following-char) "\b"))
2914 (forward-char 1))))) 3324 (forward-char 1)))))
2915 3325
2916 ;;;###autoload 3326 ;;;###autoload
2917 (defun unbold-region (start end) 3327 (defun unbold-region (start end)
2918 "Remove all boldness (overstruck characters) in the region. 3328 "Remove all boldness (overstruck characters) in the region.
2919 Called from program, takes two arguments START and END 3329 Called from program, takes two arguments START and END
2920 which specify the range to operate on." 3330 which specify the range to operate on."
2921 (interactive "r") 3331 (interactive "r")
2922 (save-excursion 3332 (save-excursion
2923 (let ((end1 (make-marker))) 3333 (let ((end1 (make-marker)))
2924 (move-marker end1 (max start end)) 3334 (move-marker end1 (max start end))
2925 (goto-char (min start end)) 3335 (goto-char (min start end))
2926 (while (re-search-forward "\b" end1 t) 3336 (while (re-search-forward "\b" end1 t)
2927 (if (eq (following-char) (char-after (- (point) 2))) 3337 (if (eq (following-char) (char-after (- (point) 2)))
2928 (delete-char -2)))))) 3338 (delete-char -2))))))
2929 3339
2930 (defalias 'message-exchange-point-and-mark 'exchange-point-and-mark) 3340 (defalias 'message-exchange-point-and-mark 'exchange-point-and-mark)
2931 3341
2932 ;; Support for toolbar 3342 ;; Support for toolbar
2933 (when (string-match "XEmacs\\|Lucid" emacs-version) 3343 (when (string-match "XEmacs\\|Lucid" emacs-version)
2948 (message-expand-group) 3358 (message-expand-group)
2949 (tab-to-tab-stop))) 3359 (tab-to-tab-stop)))
2950 3360
2951 (defvar gnus-active-hashtb) 3361 (defvar gnus-active-hashtb)
2952 (defun message-expand-group () 3362 (defun message-expand-group ()
2953 (let* ((b (save-excursion (skip-chars-backward "^, :\t\n") (point))) 3363 (let* ((b (save-excursion
3364 (save-restriction
3365 (narrow-to-region
3366 (save-excursion
3367 (beginning-of-line)
3368 (skip-chars-forward "^:")
3369 (1+ (point)))
3370 (point))
3371 (skip-chars-backward "^, \t\n") (point))))
2954 (completion-ignore-case t) 3372 (completion-ignore-case t)
2955 (string (buffer-substring b (point))) 3373 (string (buffer-substring b (point)))
2956 (hashtb (and (boundp 'gnus-active-hashtb) gnus-active-hashtb)) 3374 (hashtb (and (boundp 'gnus-active-hashtb) gnus-active-hashtb))
2957 (completions (all-completions string hashtb)) 3375 (completions (all-completions string hashtb))
2958 (cur (current-buffer)) 3376 (cur (current-buffer))
2981 (goto-char (point-min)) 3399 (goto-char (point-min))
2982 (pop-to-buffer cur))))))) 3400 (pop-to-buffer cur)))))))
2983 3401
2984 ;;; Help stuff. 3402 ;;; Help stuff.
2985 3403
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
2990 (defun message-talkative-question (ask question show &rest text) 3404 (defun message-talkative-question (ask question show &rest text)
2991 "Call FUNCTION with argument QUESTION, displaying the rest of the arguments in a temporary buffer if SHOW. 3405 "Call FUNCTION with argument QUESTION, displaying the rest of the arguments in a temporary buffer if SHOW.
2992 The following arguments may contain lists of values." 3406 The following arguments may contain lists of values."
2993 (if (and show 3407 (if (and show
2994 (setq text (message-flatten-list text))) 3408 (setq text (message-flatten-list text)))
2999 (mapcar 'princ text) 3413 (mapcar 'princ text)
3000 (goto-char (point-min)))) 3414 (goto-char (point-min))))
3001 (funcall ask question)) 3415 (funcall ask question))
3002 (funcall ask question))) 3416 (funcall ask question)))
3003 3417
3004 (defun message-flatten-list (&rest list) 3418 (defun message-flatten-list (list)
3005 (message-flatten-list-1 list)) 3419 "Return a new, flat list that contains all elements of LIST.
3006 3420
3007 (defun message-flatten-list-1 (list) 3421 \(message-flatten-list '(1 (2 3 (4 5 (6))) 7))
3422 => (1 2 3 4 5 6 7)"
3008 (cond ((consp list) 3423 (cond ((consp list)
3009 (apply 'append (mapcar 'message-flatten-list-1 list))) 3424 (apply 'append (mapcar 'message-flatten-list list)))
3010 (list 3425 (list
3011 (list list)))) 3426 (list list))))
3012 3427
3428 (defun message-generate-new-buffer-clone-locals (name &optional varstr)
3429 "Create and return a buffer with a name based on NAME using generate-new-buffer.
3430 Then clone the local variables and values from the old buffer to the
3431 new one, cloning only the locals having a substring matching the
3432 regexp varstr."
3433 (let ((oldlocals (buffer-local-variables)))
3434 (save-excursion
3435 (set-buffer (generate-new-buffer name))
3436 (mapcar (lambda (dude)
3437 (when (and (car dude)
3438 (or (not varstr)
3439 (string-match varstr (symbol-name (car dude)))))
3440 (ignore-errors
3441 (set (make-local-variable (car dude))
3442 (cdr dude)))))
3443 oldlocals)
3444 (current-buffer))))
3445
3013 (run-hooks 'message-load-hook) 3446 (run-hooks 'message-load-hook)
3014 3447
3015 (provide 'message) 3448 (provide 'message)
3016 3449
3017 ;;; message.el ends here 3450 ;;; message.el ends here