Merge changes made in Gnus trunk.
[bpt/emacs.git] / lisp / gnus / gnus-msg.el
CommitLineData
eec82323 1;;; gnus-msg.el --- mail and post interface for Gnus
e84b4b86 2
95df8112 3;; Copyright (C) 1995-2011 Free Software Foundation, Inc.
eec82323
LMI
4
5;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
6748645f 6;; Lars Magne Ingebrigtsen <larsi@gnus.org>
eec82323
LMI
7;; Keywords: news
8
9;; This file is part of GNU Emacs.
10
5e809f55 11;; GNU Emacs is free software: you can redistribute it and/or modify
eec82323 12;; it under the terms of the GNU General Public License as published by
5e809f55
GM
13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
eec82323
LMI
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
5e809f55 22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
eec82323
LMI
23
24;;; Commentary:
25
26;;; Code:
27
249ffa67
RS
28(eval-when-compile (require 'cl))
29
eec82323
LMI
30(require 'gnus)
31(require 'gnus-ems)
32(require 'message)
33(require 'gnus-art)
23f87bed 34(require 'gnus-util)
eec82323 35
16409b0b 36(defcustom gnus-post-method 'current
eec82323 37 "*Preferred method for posting USENET news.
eec82323 38
e818c17f
SZ
39If this variable is `current' (which is the default), Gnus will use
40the \"current\" select method when posting. If it is `native', Gnus
41will use the native select method when posting.
6748645f
LMI
42
43This method will not be used in mail groups and the like, only in
44\"real\" newsgroups.
45
e818c17f 46If not `native' nor `current', the value must be a valid method as discussed
16409b0b
GM
47in the documentation of `gnus-select-method'. It can also be a list of
48methods. If that is the case, the user will be queried for what select
6748645f
LMI
49method to use when posting."
50 :group 'gnus-group-foreign
e818c17f
SZ
51 :link '(custom-manual "(gnus)Posting Server")
52 :type `(choice (const native)
53 (const current)
6748645f 54 (sexp :tag "Methods" ,gnus-select-method)))
eec82323 55
23f87bed 56(defcustom gnus-outgoing-message-group nil
ed797193 57 "All outgoing messages will be put in this group.
eec82323
LMI
58If you want to store all your outgoing mail and articles in the group
59\"nnml:archive\", you set this variable to that value. This variable
60can also be a list of group names.
61
62If you want to have greater control over what group to put each
63message in, you can set this variable to a function that checks the
64current newsgroup name and then returns a suitable group name (or list
23f87bed
MB
65of names)."
66 :group 'gnus-message
4a2358e9
MB
67 :type '(choice (const nil)
68 (function)
69 (string :tag "Group")
70 (repeat :tag "List of groups" (string :tag "Group"))))
eec82323 71
ed797193
G
72(make-obsolete-variable 'gnus-outgoing-message-group 'gnus-message-archive-group "24.1")
73
23f87bed
MB
74(defcustom gnus-mailing-list-groups nil
75 "*If non-nil a regexp matching groups that are really mailing lists.
eec82323
LMI
76This is useful when you're reading a mailing list that has been
77gatewayed to a newsgroup, and you want to followup to an article in
23f87bed
MB
78the group."
79 :group 'gnus-message
80 :type '(choice (regexp)
81 (const nil)))
eec82323 82
23f87bed
MB
83(defcustom gnus-add-to-list nil
84 "*If non-nil, add a `to-list' parameter automatically."
85 :group 'gnus-message
86 :type 'boolean)
eec82323 87
23f87bed 88(defcustom gnus-crosspost-complaint
eec82323
LMI
89 "Hi,
90
91You posted the article below with the following Newsgroups header:
92
93Newsgroups: %s
94
95The %s group, at least, was an inappropriate recipient
96of this message. Please trim your Newsgroups header to exclude this
97group before posting in the future.
98
99Thank you.
100
101"
102 "Format string to be inserted when complaining about crossposts.
103The first %s will be replaced by the Newsgroups header;
23f87bed
MB
104the second with the current group name."
105 :group 'gnus-message
106 :type 'string)
107
108(defcustom gnus-message-setup-hook nil
109 "Hook run after setting up a message buffer."
110 :group 'gnus-message
437ce4be 111 :options '(message-remove-blank-cited-lines)
23f87bed
MB
112 :type 'hook)
113
114(defcustom gnus-bug-create-help-buffer t
115 "*Should we create the *Gnus Help Bug* buffer?"
116 :group 'gnus-message
117 :type 'boolean)
118
119(defcustom gnus-posting-styles nil
120 "*Alist of styles to use when posting.
121See Info node `(gnus)Posting Styles'."
122 :group 'gnus-message
123 :link '(custom-manual "(gnus)Posting Styles")
124 :type '(repeat (cons (choice (regexp)
125 (variable)
126 (list (const header)
127 (string :tag "Header")
128 (regexp :tag "Regexp"))
129 (function)
130 (sexp))
131 (repeat (list
132 (choice (const signature)
133 (const signature-file)
134 (const organization)
135 (const address)
136 (const x-face-file)
137 (const name)
138 (const body)
139 (symbol)
140 (string :tag "Header"))
141 (choice (string)
142 (function)
143 (variable)
144 (sexp)))))))
145
146(defcustom gnus-gcc-mark-as-read nil
147 "If non-nil, automatically mark Gcc articles as read."
bf247b6e 148 :version "22.1"
23f87bed
MB
149 :group 'gnus-message
150 :type 'boolean)
151
152(make-obsolete-variable 'gnus-inews-mark-gcc-as-read
265ac10b 153 'gnus-gcc-mark-as-read "Emacs 22.1")
23f87bed
MB
154
155(defcustom gnus-gcc-externalize-attachments nil
156 "Should local-file attachments be included as external parts in Gcc copies?
157If it is `all', attach files as external parts;
158if a regexp and matches the Gcc group name, attach files as external parts;
159if nil, attach files as normal parts."
bf247b6e 160 :version "22.1"
23f87bed
MB
161 :group 'gnus-message
162 :type '(choice (const nil :tag "None")
163 (const all :tag "Any")
164 (string :tag "Regexp")))
165
166(gnus-define-group-parameter
167 posting-charset-alist
168 :type list
169 :function-document
170 "Return the permitted unencoded charsets for posting of GROUP."
171 :variable gnus-group-posting-charset-alist
172 :variable-default
25fc4fd5 173 '(("^\\(no\\|fr\\)\\.[^,]*\\(,[ \t\n]*\\(no\\|fr\\)\\.[^,]*\\)*$" iso-8859-1 (iso-8859-1))
16409b0b
GM
174 ("^\\(fido7\\|relcom\\)\\.[^,]*\\(,[ \t\n]*\\(fido7\\|relcom\\)\\.[^,]*\\)*$" koi8-r (koi8-r))
175 (message-this-is-mail nil nil)
176 (message-this-is-news nil t))
23f87bed 177 :variable-document
16409b0b
GM
178 "Alist of regexps and permitted unencoded charsets for posting.
179Each element of the alist has the form (TEST HEADER BODY-LIST), where
180TEST is either a regular expression matching the newsgroup header or a
181variable to query,
182HEADER is the charset which may be left unencoded in the header (nil
183means encode all charsets),
184BODY-LIST is a list of charsets which may be encoded using 8bit
185content-transfer encoding in the body, or one of the special values
186nil (always encode using quoted-printable) or t (always use 8bit).
187
188Note that any value other than nil for HEADER infringes some RFCs, so
189use this option with care."
23f87bed
MB
190 :variable-group gnus-charset
191 :variable-type
192 '(repeat (list :tag "Permitted unencoded charsets"
193 (choice :tag "Where"
194 (regexp :tag "Group")
195 (const :tag "Mail message" :value message-this-is-mail)
196 (const :tag "News article" :value message-this-is-news))
197 (choice :tag "Header"
198 (const :tag "None" nil)
199 (symbol :tag "Charset"))
200 (choice :tag "Body"
201 (const :tag "Any" :value t)
202 (const :tag "None" :value nil)
203 (repeat :tag "Charsets"
204 (symbol :tag "Charset")))))
205 :parameter-type '(choice :tag "Permitted unencoded charsets"
206 :value nil
207 (repeat (symbol)))
208 :parameter-document "\
209List of charsets that are permitted to be unencoded.")
210
211(defcustom gnus-debug-files
212 '("gnus.el" "gnus-sum.el" "gnus-group.el"
213 "gnus-art.el" "gnus-start.el" "gnus-async.el"
214 "gnus-msg.el" "gnus-score.el" "gnus-win.el" "gnus-topic.el"
215 "gnus-agent.el" "gnus-cache.el" "gnus-srvr.el"
216 "mm-util.el" "mm-decode.el" "nnmail.el" "message.el")
217 "Files whose variables will be reported in `gnus-bug'."
bf247b6e 218 :version "22.1"
23f87bed
MB
219 :group 'gnus-message
220 :type '(repeat (string :tag "File")))
221
222(defcustom gnus-debug-exclude-variables
223 '(mm-mime-mule-charset-alist
224 nnmail-split-fancy message-minibuffer-local-map)
225 "Variables that should not be reported in `gnus-bug'."
bf247b6e 226 :version "22.1"
23f87bed
MB
227 :group 'gnus-message
228 :type '(repeat (symbol :tag "Variable")))
229
230(defcustom gnus-discouraged-post-methods
231 '(nndraft nnml nnimap nnmaildir nnmh nnfolder nndir)
232 "A list of back ends that are not used in \"real\" newsgroups.
233This variable is used only when `gnus-post-method' is `current'."
bf247b6e 234 :version "22.1"
23f87bed
MB
235 :group 'gnus-group-foreign
236 :type '(repeat (symbol :tag "Back end")))
237
238(defcustom gnus-message-replysign
239 nil
240 "Automatically sign replies to signed messages.
241See also the `mml-default-sign-method' variable."
242 :group 'gnus-message
243 :type 'boolean)
244
b173bdd9 245(defcustom gnus-message-replyencrypt t
23f87bed
MB
246 "Automatically encrypt replies to encrypted messages.
247See also the `mml-default-encrypt-method' variable."
37657cbd 248 :version "24.1"
23f87bed
MB
249 :group 'gnus-message
250 :type 'boolean)
251
252(defcustom gnus-message-replysignencrypted
253 t
254 "Setting this causes automatically encrypted messages to also be signed."
255 :group 'gnus-message
256 :type 'boolean)
257
01c52d31
MB
258(defcustom gnus-confirm-mail-reply-to-news (and gnus-novice-user
259 (not gnus-expert-user))
23f87bed
MB
260 "If non-nil, Gnus requests confirmation when replying to news.
261This is done because new users often reply by mistake when reading
262news.
263This can also be a function receiving the group name as the only
e7f767c2
GM
264parameter, which should return non-nil if a confirmation is needed; or
265a regexp, in which case a confirmation is asked for if the group name
23f87bed 266matches the regexp."
330f707b 267 :version "23.1" ;; No Gnus (default changed)
23f87bed
MB
268 :group 'gnus-message
269 :type '(choice (const :tag "No" nil)
270 (const :tag "Yes" t)
e7f767c2
GM
271 (regexp :tag "If group matches regexp")
272 (function :tag "If function evaluates to non-nil")))
23f87bed
MB
273
274(defcustom gnus-confirm-treat-mail-like-news
275 nil
276 "If non-nil, Gnus will treat mail like news with regard to confirmation
277when replying by mail. See the `gnus-confirm-mail-reply-to-news' variable
278for fine-tuning this.
279If nil, Gnus will never ask for confirmation if replying to mail."
bf247b6e 280 :version "22.1"
23f87bed
MB
281 :group 'gnus-message
282 :type 'boolean)
283
284(defcustom gnus-summary-resend-default-address t
285 "If non-nil, Gnus tries to suggest a default address to resend to.
286If nil, the address field will always be empty after invoking
287`gnus-summary-resend-message'."
bf247b6e 288 :version "22.1"
23f87bed
MB
289 :group 'gnus-message
290 :type 'boolean)
6748645f 291
01c52d31
MB
292(defcustom gnus-message-highlight-citation
293 t ;; gnus-treat-highlight-citation ;; gnus-cite dependency
294 "Enable highlighting of different citation levels in message-mode."
330f707b 295 :version "23.1" ;; No Gnus
01c52d31
MB
296 :group 'gnus-cite
297 :group 'gnus-message
298 :type 'boolean)
299
300(autoload 'gnus-message-citation-mode "gnus-cite" nil t)
301
eec82323
LMI
302;;; Internal variables.
303
6748645f
LMI
304(defvar gnus-inhibit-posting-styles nil
305 "Inhibit the use of posting styles.")
306
23f87bed 307(defvar gnus-article-yanked-articles nil)
eec82323
LMI
308(defvar gnus-message-buffer "*Mail Gnus*")
309(defvar gnus-article-copy nil)
23f87bed 310(defvar gnus-check-before-posting nil)
eec82323 311(defvar gnus-last-posting-server nil)
6748645f 312(defvar gnus-message-group-art nil)
eec82323 313
23f87bed
MB
314(defvar gnus-msg-force-broken-reply-to nil)
315
eec82323
LMI
316(defconst gnus-bug-message
317 "Sending a bug report to the Gnus Towers.
318========================================
319
320The buffer below is a mail buffer. When you press `C-c C-c', it will
321be sent to the Gnus Bug Exterminators.
322
16409b0b
GM
323The thing near the bottom of the buffer is how the environment
324settings will be included in the mail. Please do not delete that.
325They will tell the Bug People what your environment is, so that it
326will be easier to locate the bugs.
eec82323
LMI
327
328If you have found a bug that makes Emacs go \"beep\", set
329debug-on-error to t (`M-x set-variable RET debug-on-error RET t RET')
330and include the backtrace in your bug report.
331
332Please describe the bug in annoying, painstaking detail.
333
334Thank you for your help in stamping out bugs.
335")
336
8abf1b22 337(autoload 'gnus-uu-post-news "gnus-uu" nil t)
eec82323
LMI
338
339\f
340;;;
341;;; Gnus Posting Functions
342;;;
343
344(gnus-define-keys (gnus-summary-send-map "S" gnus-summary-mode-map)
345 "p" gnus-summary-post-news
23f87bed 346 "i" gnus-summary-news-other-window
eec82323
LMI
347 "f" gnus-summary-followup
348 "F" gnus-summary-followup-with-original
349 "c" gnus-summary-cancel-article
350 "s" gnus-summary-supersede-article
351 "r" gnus-summary-reply
16409b0b 352 "y" gnus-summary-yank-message
eec82323
LMI
353 "R" gnus-summary-reply-with-original
354 "w" gnus-summary-wide-reply
355 "W" gnus-summary-wide-reply-with-original
23f87bed
MB
356 "v" gnus-summary-very-wide-reply
357 "V" gnus-summary-very-wide-reply-with-original
eec82323
LMI
358 "n" gnus-summary-followup-to-mail
359 "N" gnus-summary-followup-to-mail-with-original
360 "m" gnus-summary-mail-other-window
361 "u" gnus-uu-post-news
362 "\M-c" gnus-summary-mail-crosspost-complaint
23f87bed
MB
363 "Br" gnus-summary-reply-broken-reply-to
364 "BR" gnus-summary-reply-broken-reply-to-with-original
eec82323
LMI
365 "om" gnus-summary-mail-forward
366 "op" gnus-summary-post-forward
367 "Om" gnus-uu-digest-mail-forward
368 "Op" gnus-uu-digest-post-forward)
369
370(gnus-define-keys (gnus-send-bounce-map "D" gnus-summary-send-map)
371 "b" gnus-summary-resend-bounced-mail
372 ;; "c" gnus-summary-send-draft
23f87bed
MB
373 "r" gnus-summary-resend-message
374 "e" gnus-summary-resend-message-edit)
eec82323
LMI
375
376;;; Internal functions.
377
01c52d31 378(defun gnus-inews-make-draft (articles)
23f87bed
MB
379 `(lambda ()
380 (gnus-inews-make-draft-meta-information
01c52d31 381 ,(gnus-group-decoded-name gnus-newsgroup-name) ',articles)))
23f87bed 382
eec82323
LMI
383(defvar gnus-article-reply nil)
384(defmacro gnus-setup-message (config &rest forms)
6748645f 385 (let ((winconf (make-symbol "gnus-setup-message-winconf"))
4a3988d5 386 (winconf-name (make-symbol "gnus-setup-message-winconf-name"))
6748645f
LMI
387 (buffer (make-symbol "gnus-setup-message-buffer"))
388 (article (make-symbol "gnus-setup-message-article"))
23f87bed 389 (yanked (make-symbol "gnus-setup-yanked-articles"))
6748645f 390 (group (make-symbol "gnus-setup-message-group")))
eec82323 391 `(let ((,winconf (current-window-configuration))
8e22bee0 392 (,winconf-name gnus-current-window-configuration)
eec82323 393 (,buffer (buffer-name (current-buffer)))
23f87bed
MB
394 (,article gnus-article-reply)
395 (,yanked gnus-article-yanked-articles)
6748645f 396 (,group gnus-newsgroup-name)
eec82323 397 (message-header-setup-hook
6748645f 398 (copy-sequence message-header-setup-hook))
16409b0b 399 (mbl mml-buffer-list)
6748645f 400 (message-mode-hook (copy-sequence message-mode-hook)))
16409b0b 401 (setq mml-buffer-list nil)
eec82323 402 (add-hook 'message-header-setup-hook 'gnus-inews-insert-gcc)
87ba2830
MB
403 ;; message-newsreader and message-mailer were formerly set in
404 ;; gnus-inews-add-send-actions, but this is too late when
405 ;; message-generate-headers-first is used. --ansel
406 (add-hook 'message-mode-hook
407 (lambda nil
408 (setq message-newsreader
409 (setq message-mailer (gnus-extended-version)))))
23f87bed
MB
410 ;; #### FIXME: for a reason that I did not manage to identify yet,
411 ;; the variable `gnus-newsgroup-name' does not honor a dynamically
412 ;; scoped or setq'ed value from a caller like `C-u gnus-summary-mail'.
413 ;; After evaluation of @forms below, it gets the value we actually want
414 ;; to override, and the posting styles are used. For that reason, I've
415 ;; added an optional argument to `gnus-configure-posting-styles' to
416 ;; make sure that the correct value for the group name is used. -- drv
417 (add-hook 'message-mode-hook
418 (if (memq ,config '(reply-yank reply))
419 (lambda ()
420 (gnus-configure-posting-styles ,group))
421 (lambda ()
422 ;; There may be an old " *gnus article copy*" buffer.
423 (let (gnus-article-copy)
424 (gnus-configure-posting-styles ,group)))))
36d3245f 425 (gnus-alist-pull ',(intern gnus-draft-meta-information-header)
23f87bed
MB
426 message-required-headers)
427 (when (and ,group
428 (not (string= ,group "")))
429 (push (cons
430 (intern gnus-draft-meta-information-header)
01c52d31 431 (gnus-inews-make-draft (or ,yanked ,article)))
23f87bed 432 message-required-headers))
eec82323 433 (unwind-protect
6748645f
LMI
434 (progn
435 ,@forms)
23f87bed 436 (gnus-inews-add-send-actions ,winconf ,buffer ,article ,config
4a3988d5 437 ,yanked ',winconf-name)
eec82323 438 (setq gnus-message-buffer (current-buffer))
6748645f
LMI
439 (set (make-local-variable 'gnus-message-group-art)
440 (cons ,group ,article))
16409b0b 441 (set (make-local-variable 'gnus-newsgroup-name) ,group)
01c52d31
MB
442 ;; Enable highlighting of different citation levels
443 (when gnus-message-highlight-citation
444 (gnus-message-citation-mode 1))
16409b0b
GM
445 (gnus-run-hooks 'gnus-message-setup-hook)
446 (if (eq major-mode 'message-mode)
25fc4fd5
SZ
447 (let ((mbl1 mml-buffer-list))
448 (setq mml-buffer-list mbl) ;; Global value
449 (set (make-local-variable 'mml-buffer-list) mbl1);; Local value
23f87bed
MB
450 (gnus-make-local-hook 'kill-buffer-hook)
451 (gnus-make-local-hook 'change-major-mode-hook)
6553d8f2 452 (add-hook 'change-major-mode-hook 'mml-destroy-buffers nil t)
16409b0b
GM
453 (add-hook 'kill-buffer-hook 'mml-destroy-buffers t t))
454 (mml-destroy-buffers)
455 (setq mml-buffer-list mbl)))
23f87bed 456 (message-hide-headers)
6748645f 457 (gnus-add-buffer)
eec82323 458 (gnus-configure-windows ,config t)
23f87bed 459 (run-hooks 'post-command-hook)
eec82323
LMI
460 (set-buffer-modified-p nil))))
461
01c52d31
MB
462(defun gnus-inews-make-draft-meta-information (group articles)
463 (when (numberp articles)
464 (setq articles (list articles)))
465 (concat "(\"" group "\""
466 (if articles
467 (concat " "
468 (mapconcat
469 (lambda (elem)
470 (number-to-string
471 (if (consp elem)
472 (car elem)
473 elem)))
474 articles " "))
475 "")
23f87bed
MB
476 ")"))
477
25fc4fd5 478;;;###autoload
23f87bed 479(defun gnus-msg-mail (&optional to subject other-headers continue
25ca2e61 480 switch-action yank-action send-actions return-action)
25fc4fd5
SZ
481 "Start editing a mail message to be sent.
482Like `message-mail', but with Gnus paraphernalia, particularly the
483Gcc: header for archiving purposes."
484 (interactive)
23f87bed
MB
485 (let ((buf (current-buffer))
486 mail-buf)
487 (gnus-setup-message 'message
488 (message-mail to subject other-headers continue
25ca2e61 489 nil yank-action send-actions return-action))
23f87bed
MB
490 (when switch-action
491 (setq mail-buf (current-buffer))
492 (switch-to-buffer buf)
493 (apply switch-action mail-buf nil)))
25fc4fd5
SZ
494 ;; COMPOSEFUNC should return t if succeed. Undocumented ???
495 t)
496
23f87bed
MB
497;;;###autoload
498(defun gnus-button-mailto (address)
499 "Mail to ADDRESS."
500 (set-buffer (gnus-copy-article-buffer))
501 (gnus-setup-message 'message
bfff13ab 502 (message-reply address)))
23f87bed
MB
503
504;;;###autoload
505(defun gnus-button-reply (&optional to-address wide)
506 "Like `message-reply'."
507 (interactive)
508 (gnus-setup-message 'message
bfff13ab 509 (message-reply to-address wide)))
23f87bed 510
25fc4fd5
SZ
511;;;###autoload
512(define-mail-user-agent 'gnus-user-agent
23f87bed
MB
513 'gnus-msg-mail 'message-send-and-exit
514 'message-kill-buffer 'message-send-hook)
25fc4fd5 515
16409b0b
GM
516(defun gnus-setup-posting-charset (group)
517 (let ((alist gnus-group-posting-charset-alist)
518 (group (or group ""))
519 elem)
520 (when group
521 (catch 'found
522 (while (setq elem (pop alist))
523 (when (or (and (stringp (car elem))
524 (string-match (car elem) group))
23f87bed 525 (and (functionp (car elem))
16409b0b
GM
526 (funcall (car elem) group))
527 (and (symbolp (car elem))
528 (symbol-value (car elem))))
529 (throw 'found (cons (cadr elem) (caddr elem)))))))))
530
23f87bed 531(defun gnus-inews-add-send-actions (winconf buffer article
8e22bee0
G
532 &optional config yanked
533 winconf-name)
23f87bed 534 (gnus-make-local-hook 'message-sent-hook)
0342aa5b
DL
535 (add-hook 'message-sent-hook (if gnus-agent 'gnus-agent-possibly-do-gcc
536 'gnus-inews-do-gcc) nil t)
537 (when gnus-agent
23f87bed 538 (gnus-make-local-hook 'message-header-hook)
0342aa5b 539 (add-hook 'message-header-hook 'gnus-agent-possibly-save-gcc nil t))
eec82323 540 (setq message-post-method
01c52d31 541 `(lambda (&optional arg)
eec82323 542 (gnus-post-method arg ,gnus-newsgroup-name)))
eec82323 543 (message-add-action
8e22bee0 544 `(progn
4a3988d5 545 (setq gnus-current-window-configuration ',winconf-name)
8e22bee0
G
546 (when (gnus-buffer-exists-p ,buffer)
547 (set-window-configuration ,winconf)))
23f87bed
MB
548 'exit 'postpone 'kill)
549 (let ((to-be-marked (cond
550 (yanked
551 (mapcar
552 (lambda (x) (if (listp x) (car x) x)) yanked))
553 (article (if (listp article) article (list article)))
554 (t nil))))
555 (message-add-action
556 `(when (gnus-buffer-exists-p ,buffer)
228b6ecd 557 (with-current-buffer ,buffer
23f87bed
MB
558 ,(when to-be-marked
559 (if (eq config 'forward)
560 `(gnus-summary-mark-article-as-forwarded ',to-be-marked)
561 `(gnus-summary-mark-article-as-replied ',to-be-marked)))))
562 'send)))
eec82323
LMI
563
564(put 'gnus-setup-message 'lisp-indent-function 1)
565(put 'gnus-setup-message 'edebug-form-spec '(form body))
566
567;;; Post news commands of Gnus group mode and summary mode
568
16409b0b
GM
569(defun gnus-group-mail (&optional arg)
570 "Start composing a mail.
571If ARG, use the group under the point to find a posting style.
572If ARG is 1, prompt for a group name to find the posting style."
573 (interactive "P")
574 ;; We can't `let' gnus-newsgroup-name here, since that leads
575 ;; to local variables leaking.
576 (let ((group gnus-newsgroup-name)
23f87bed
MB
577 ;; make sure last viewed article doesn't affect posting styles:
578 (gnus-article-copy)
16409b0b
GM
579 (buffer (current-buffer)))
580 (unwind-protect
581 (progn
582 (setq gnus-newsgroup-name
583 (if arg
584 (if (= 1 (prefix-numeric-value arg))
01c52d31 585 (gnus-group-completing-read
229b59da
G
586 "Use posting style of group"
587 nil (gnus-read-active-file-p))
16409b0b
GM
588 (gnus-group-group-name))
589 ""))
23f87bed 590 ;; #### see comment in gnus-setup-message -- drv
16409b0b 591 (gnus-setup-message 'message (message-mail)))
228b6ecd 592 (with-current-buffer buffer
16409b0b 593 (setq gnus-newsgroup-name group)))))
eec82323 594
23f87bed
MB
595(defun gnus-group-news (&optional arg)
596 "Start composing a news.
597If ARG, post to group under point.
598If ARG is 1, prompt for group name to post to.
599
600This function prepares a news even when using mail groups. This is useful
601for posting messages to mail groups without actually sending them over the
602network. The corresponding back end must have a 'request-post method."
603 (interactive "P")
604 ;; We can't `let' gnus-newsgroup-name here, since that leads
605 ;; to local variables leaking.
606 (let ((group gnus-newsgroup-name)
607 ;; make sure last viewed article doesn't affect posting styles:
608 (gnus-article-copy)
609 (buffer (current-buffer)))
610 (unwind-protect
611 (progn
612 (setq gnus-newsgroup-name
613 (if arg
614 (if (= 1 (prefix-numeric-value arg))
229b59da
G
615 (gnus-group-completing-read "Use group"
616 nil
01c52d31 617 (gnus-read-active-file-p))
23f87bed
MB
618 (gnus-group-group-name))
619 ""))
620 ;; #### see comment in gnus-setup-message -- drv
621 (gnus-setup-message 'message
622 (message-news (gnus-group-real-name gnus-newsgroup-name))))
228b6ecd 623 (with-current-buffer buffer
23f87bed
MB
624 (setq gnus-newsgroup-name group)))))
625
eec82323 626(defun gnus-group-post-news (&optional arg)
23f87bed
MB
627 "Start composing a message (a news by default).
628If ARG, post to group under point. If ARG is 1, prompt for group name.
629Depending on the selected group, the message might be either a mail or
630a news."
eec82323 631 (interactive "P")
6748645f 632 ;; Bind this variable here to make message mode hooks work ok.
eec82323
LMI
633 (let ((gnus-newsgroup-name
634 (if arg
635 (if (= 1 (prefix-numeric-value arg))
229b59da 636 (gnus-group-completing-read "Newsgroup" nil
01c52d31 637 (gnus-read-active-file-p))
eec82323 638 (gnus-group-group-name))
23f87bed
MB
639 ""))
640 ;; make sure last viewed article doesn't affect posting styles:
641 (gnus-article-copy))
642 (gnus-post-news 'post gnus-newsgroup-name nil nil nil nil
643 (string= gnus-newsgroup-name ""))))
644
645(defun gnus-summary-mail-other-window (&optional arg)
646 "Start composing a mail in another window.
647Use the posting of the current group by default.
648If ARG, don't do that. If ARG is 1, prompt for group name to find the
649posting style."
650 (interactive "P")
651 ;; We can't `let' gnus-newsgroup-name here, since that leads
652 ;; to local variables leaking.
653 (let ((group gnus-newsgroup-name)
654 ;; make sure last viewed article doesn't affect posting styles:
655 (gnus-article-copy)
656 (buffer (current-buffer)))
657 (unwind-protect
658 (progn
659 (setq gnus-newsgroup-name
660 (if arg
661 (if (= 1 (prefix-numeric-value arg))
229b59da
G
662 (gnus-group-completing-read "Use group"
663 nil
01c52d31 664 (gnus-read-active-file-p))
23f87bed
MB
665 "")
666 gnus-newsgroup-name))
667 ;; #### see comment in gnus-setup-message -- drv
668 (gnus-setup-message 'message (message-mail)))
228b6ecd 669 (with-current-buffer buffer
23f87bed
MB
670 (setq gnus-newsgroup-name group)))))
671
672(defun gnus-summary-news-other-window (&optional arg)
673 "Start composing a news in another window.
674Post to the current group by default.
675If ARG, don't do that. If ARG is 1, prompt for group name to post to.
676
677This function prepares a news even when using mail groups. This is useful
678for posting messages to mail groups without actually sending them over the
679network. The corresponding back end must have a 'request-post method."
680 (interactive "P")
681 ;; We can't `let' gnus-newsgroup-name here, since that leads
682 ;; to local variables leaking.
683 (let ((group gnus-newsgroup-name)
684 ;; make sure last viewed article doesn't affect posting styles:
685 (gnus-article-copy)
686 (buffer (current-buffer)))
687 (unwind-protect
688 (progn
689 (setq gnus-newsgroup-name
690 (if arg
691 (if (= 1 (prefix-numeric-value arg))
229b59da
G
692 (gnus-group-completing-read "Use group"
693 nil
01c52d31 694 (gnus-read-active-file-p))
23f87bed
MB
695 "")
696 gnus-newsgroup-name))
697 ;; #### see comment in gnus-setup-message -- drv
698 (gnus-setup-message 'message
699 (progn
700 (message-news (gnus-group-real-name gnus-newsgroup-name))
701 (set (make-local-variable 'gnus-discouraged-post-methods)
01c52d31 702 (remove
23f87bed 703 (car (gnus-find-method-for-group gnus-newsgroup-name))
01c52d31 704 gnus-discouraged-post-methods)))))
228b6ecd 705 (with-current-buffer buffer
23f87bed
MB
706 (setq gnus-newsgroup-name group)))))
707
708(defun gnus-summary-post-news (&optional arg)
709 "Start composing a message. Post to the current group by default.
710If ARG, don't do that. If ARG is 1, prompt for a group name to post to.
711Depending on the selected group, the message might be either a mail or
712a news."
713 (interactive "P")
714 ;; Bind this variable here to make message mode hooks work ok.
715 (let ((gnus-newsgroup-name
716 (if arg
717 (if (= 1 (prefix-numeric-value arg))
229b59da 718 (gnus-group-completing-read "Newsgroup" nil
01c52d31 719 (gnus-read-active-file-p))
23f87bed
MB
720 "")
721 gnus-newsgroup-name))
722 ;; make sure last viewed article doesn't affect posting styles:
723 (gnus-article-copy))
eec82323
LMI
724 (gnus-post-news 'post gnus-newsgroup-name)))
725
eec82323
LMI
726
727(defun gnus-summary-followup (yank &optional force-news)
728 "Compose a followup to an article.
23f87bed
MB
729If prefix argument YANK is non-nil, the original article is yanked
730automatically.
731YANK is a list of elements, where the car of each element is the
732article number, and the cdr is the string to be yanked."
eec82323
LMI
733 (interactive
734 (list (and current-prefix-arg
735 (gnus-summary-work-articles 1))))
eec82323 736 (when yank
23f87bed
MB
737 (gnus-summary-goto-subject
738 (if (listp (car yank))
739 (caar yank)
740 (car yank))))
eec82323
LMI
741 (save-window-excursion
742 (gnus-summary-select-article))
743 (let ((headers (gnus-summary-article-header (gnus-summary-article-number)))
744 (gnus-newsgroup-name gnus-newsgroup-name))
745 ;; Send a followup.
746 (gnus-post-news nil gnus-newsgroup-name
747 headers gnus-article-buffer
23f87bed
MB
748 yank nil force-news)
749 (gnus-summary-handle-replysign)))
eec82323
LMI
750
751(defun gnus-summary-followup-with-original (n &optional force-news)
23f87bed
MB
752 "Compose a followup to an article and include the original article.
753The text in the region will be yanked. If the region isn't
754active, the entire article will be yanked."
eec82323
LMI
755 (interactive "P")
756 (gnus-summary-followup (gnus-summary-work-articles n) force-news))
757
758(defun gnus-summary-followup-to-mail (&optional arg)
759 "Followup to the current mail message via news."
760 (interactive
761 (list (and current-prefix-arg
762 (gnus-summary-work-articles 1))))
763 (gnus-summary-followup arg t))
764
765(defun gnus-summary-followup-to-mail-with-original (&optional arg)
766 "Followup to the current mail message via news."
767 (interactive "P")
768 (gnus-summary-followup (gnus-summary-work-articles arg) t))
769
770(defun gnus-inews-yank-articles (articles)
23f87bed 771 (let (beg article yank-string)
eec82323
LMI
772 (message-goto-body)
773 (while (setq article (pop articles))
23f87bed
MB
774 (when (listp article)
775 (setq yank-string (nth 1 article)
776 article (nth 0 article)))
eec82323
LMI
777 (save-window-excursion
778 (set-buffer gnus-summary-buffer)
779 (gnus-summary-select-article nil nil nil article)
780 (gnus-summary-remove-process-mark article))
23f87bed 781 (gnus-copy-article-buffer nil yank-string)
eec82323 782 (let ((message-reply-buffer gnus-article-copy)
23f87bed
MB
783 (message-reply-headers
784 ;; The headers are decoded.
785 (with-current-buffer gnus-article-copy
786 (save-restriction
787 (nnheader-narrow-to-headers)
788 (nnheader-parse-naked-head)))))
eec82323 789 (message-yank-original)
c429815a 790 (message-exchange-point-and-mark)
eec82323
LMI
791 (setq beg (or beg (mark t))))
792 (when articles
793 (insert "\n")))
794 (push-mark)
795 (goto-char beg)))
796
6748645f
LMI
797(defun gnus-summary-cancel-article (&optional n symp)
798 "Cancel an article you posted.
799Uses the process-prefix convention. If given the symbolic
800prefix `a', cancel using the standard posting method; if not
801post using the current select method."
802 (interactive (gnus-interactive "P\ny"))
01c52d31 803 (let ((message-post-method
eec82323 804 `(lambda (arg)
01c52d31
MB
805 (gnus-post-method (eq ',symp 'a) ,gnus-newsgroup-name))))
806 (dolist (article (gnus-summary-work-articles n))
eec82323
LMI
807 (when (gnus-summary-select-article t nil nil article)
808 (when (gnus-eval-in-buffer-window gnus-original-article-buffer
809 (message-cancel-news))
810 (gnus-summary-mark-as-read article gnus-canceled-mark)
811 (gnus-cache-remove-article 1))
812 (gnus-article-hide-headers-if-wanted))
813 (gnus-summary-remove-process-mark article))))
814
815(defun gnus-summary-supersede-article ()
816 "Compose an article that will supersede a previous article.
817This is done simply by taking the old article and adding a Supersedes
818header line with the old Message-ID."
819 (interactive)
9153f10d
MB
820 (let ((article (gnus-summary-article-number))
821 (mail-parse-charset gnus-newsgroup-charset))
eec82323
LMI
822 (gnus-setup-message 'reply-yank
823 (gnus-summary-select-article t)
824 (set-buffer gnus-original-article-buffer)
825 (message-supersede)
826 (push
827 `((lambda ()
6748645f 828 (when (gnus-buffer-exists-p ,gnus-summary-buffer)
228b6ecd 829 (with-current-buffer ,gnus-summary-buffer
eec82323
LMI
830 (gnus-cache-possibly-remove-article ,article nil nil nil t)
831 (gnus-summary-mark-as-read ,article gnus-canceled-mark)))))
2f62a044
MB
832 message-send-actions)
833 ;; Add Gcc header.
2f62a044 834 (gnus-inews-insert-gcc))))
25fc4fd5 835
eec82323
LMI
836\f
837
23f87bed 838(defun gnus-copy-article-buffer (&optional article-buffer yank-string)
eec82323
LMI
839 ;; make a copy of the article buffer with all text properties removed
840 ;; this copy is in the buffer gnus-article-copy.
841 ;; if ARTICLE-BUFFER is nil, gnus-article-buffer is used
842 ;; this buffer should be passed to all mail/news reply/post routines.
6748645f 843 (setq gnus-article-copy (gnus-get-buffer-create " *gnus article copy*"))
228b6ecd 844 (with-current-buffer gnus-article-copy
16409b0b 845 (mm-enable-multibyte))
eec82323 846 (let ((article-buffer (or article-buffer gnus-article-buffer))
6748645f 847 end beg)
eec82323 848 (if (not (and (get-buffer article-buffer)
6748645f 849 (gnus-buffer-exists-p article-buffer)))
eec82323 850 (error "Can't find any article buffer")
228b6ecd 851 (with-current-buffer article-buffer
23f87bed
MB
852 (let ((gnus-newsgroup-charset (or gnus-article-charset
853 gnus-newsgroup-charset))
854 (gnus-newsgroup-ignored-charsets
855 (or gnus-article-ignored-charsets
856 gnus-newsgroup-ignored-charsets)))
857 (save-restriction
858 ;; Copy over the (displayed) article buffer, delete
859 ;; hidden text and remove text properties.
860 (widen)
861 (copy-to-buffer gnus-article-copy (point-min) (point-max))
862 (set-buffer gnus-article-copy)
863 (when yank-string
864 (message-goto-body)
865 (delete-region (point) (point-max))
866 (insert yank-string))
867 (gnus-article-delete-text-of-type 'annotation)
7dafe00b 868 (gnus-article-delete-text-of-type 'multipart)
23f87bed
MB
869 (gnus-remove-text-with-property 'gnus-prev)
870 (gnus-remove-text-with-property 'gnus-next)
871 (gnus-remove-text-with-property 'gnus-decoration)
872 (insert
873 (prog1
874 (buffer-substring-no-properties (point-min) (point-max))
875 (erase-buffer)))
876 ;; Find the original headers.
877 (set-buffer gnus-original-article-buffer)
878 (goto-char (point-min))
879 (while (looking-at message-unix-mail-delimiter)
880 (forward-line 1))
881 (let ((mail-header-separator ""))
882 (setq beg (point)
883 end (or (message-goto-body)
884 ;; There may be just a header.
885 (point-max))))
886 ;; Delete the headers from the displayed articles.
887 (set-buffer gnus-article-copy)
888 (let ((mail-header-separator ""))
889 (delete-region (goto-char (point-min))
890 (or (message-goto-body) (point-max))))
891 ;; Insert the original article headers.
892 (insert-buffer-substring gnus-original-article-buffer beg end)
893 ;; Decode charsets.
894 (let ((gnus-article-decode-hook
895 (delq 'article-decode-charset
270a576a
MB
896 (copy-sequence gnus-article-decode-hook)))
897 (rfc2047-quote-decoded-words-containing-tspecials t))
23f87bed 898 (run-hooks 'gnus-article-decode-hook)))))
eec82323
LMI
899 gnus-article-copy)))
900
901(defun gnus-post-news (post &optional group header article-buffer yank subject
902 force-news)
903 (when article-buffer
904 (gnus-copy-article-buffer))
23f87bed
MB
905 (let ((gnus-article-reply (and article-buffer (gnus-summary-article-number)))
906 (gnus-article-yanked-articles yank)
eec82323
LMI
907 (add-to-list gnus-add-to-list))
908 (gnus-setup-message (cond (yank 'reply-yank)
909 (article-buffer 'reply)
910 (t 'message))
911 (let* ((group (or group gnus-newsgroup-name))
16409b0b 912 (charset (gnus-group-name-charset nil group))
eec82323
LMI
913 (pgroup group)
914 to-address to-group mailing-list to-list
915 newsgroup-p)
916 (when group
23f87bed 917 (setq to-address (gnus-parameter-to-address group)
eec82323 918 to-group (gnus-group-find-parameter group 'to-group)
23f87bed 919 to-list (gnus-parameter-to-list group)
eec82323
LMI
920 newsgroup-p (gnus-group-find-parameter group 'newsgroup)
921 mailing-list (when gnus-mailing-list-groups
922 (string-match gnus-mailing-list-groups group))
16409b0b
GM
923 group (gnus-group-name-decode (gnus-group-real-name group)
924 charset)))
eec82323
LMI
925 (if (or (and to-group
926 (gnus-news-group-p to-group))
927 newsgroup-p
928 force-news
929 (and (gnus-news-group-p
930 (or pgroup gnus-newsgroup-name)
23f87bed 931 (or header gnus-current-article))
eec82323
LMI
932 (not mailing-list)
933 (not to-list)
934 (not to-address)))
935 ;; This is news.
936 (if post
f4dd4ae8
MB
937 (message-news
938 (or to-group
939 (and (not (gnus-virtual-group-p pgroup)) group)))
eec82323 940 (set-buffer gnus-article-copy)
6748645f 941 (gnus-msg-treat-broken-reply-to)
23f87bed
MB
942 (message-followup (if (or newsgroup-p force-news)
943 (if (save-restriction
944 (article-narrow-to-head)
945 (message-fetch-field "newsgroups"))
946 nil
947 "")
948 to-group)))
eec82323
LMI
949 ;; The is mail.
950 (if post
951 (progn
952 (message-mail (or to-address to-list))
953 ;; Arrange for mail groups that have no `to-address' to
954 ;; get that when the user sends off the mail.
955 (when (and (not to-list)
956 (not to-address)
957 add-to-list)
958 (push (list 'gnus-inews-add-to-address pgroup)
959 message-send-actions)))
960 (set-buffer gnus-article-copy)
6748645f
LMI
961 (gnus-msg-treat-broken-reply-to)
962 (message-wide-reply to-address)))
eec82323
LMI
963 (when yank
964 (gnus-inews-yank-articles yank))))))
965
23f87bed 966(defun gnus-msg-treat-broken-reply-to (&optional force)
8f688cb0 967 "Remove the Reply-to header if broken-reply-to."
23f87bed
MB
968 (when (or force
969 (gnus-group-find-parameter
970 gnus-newsgroup-name 'broken-reply-to))
6748645f
LMI
971 (save-restriction
972 (message-narrow-to-head)
973 (message-remove-header "reply-to"))))
974
eec82323
LMI
975(defun gnus-post-method (arg group &optional silent)
976 "Return the posting method based on GROUP and ARG.
977If SILENT, don't prompt the user."
23f87bed
MB
978 (let ((gnus-post-method (or (gnus-parameter-post-method group)
979 gnus-post-method))
980 (group-method (gnus-find-method-for-group group)))
eec82323
LMI
981 (cond
982 ;; If the group-method is nil (which shouldn't happen) we use
983 ;; the default method.
984 ((null group-method)
23f87bed
MB
985 (or (and (listp gnus-post-method) ;If not current/native/nil
986 (not (listp (car gnus-post-method))) ; and not a list of methods
987 gnus-post-method) ;then use it.
988 gnus-select-method
989 message-post-method))
6748645f 990 ;; We want the inverse of the default
eec82323 991 ((and arg (not (eq arg 0)))
23f87bed 992 (if (eq gnus-post-method 'current)
6748645f
LMI
993 gnus-select-method
994 group-method))
eec82323
LMI
995 ;; We query the user for a post method.
996 ((or arg
23f87bed 997 (and (listp gnus-post-method)
eec82323
LMI
998 (listp (car gnus-post-method))))
999 (let* ((methods
1000 ;; Collect all methods we know about.
1001 (append
23f87bed 1002 (when (listp gnus-post-method)
eec82323
LMI
1003 (if (listp (car gnus-post-method))
1004 gnus-post-method
1005 (list gnus-post-method)))
1006 gnus-secondary-select-methods
6748645f 1007 (mapcar 'cdr gnus-server-alist)
16409b0b 1008 (mapcar 'car gnus-opened-servers)
eec82323
LMI
1009 (list gnus-select-method)
1010 (list group-method)))
1011 method-alist post-methods method)
1012 ;; Weed out all mail methods.
1013 (while methods
1014 (setq method (gnus-server-get-method "" (pop methods)))
16409b0b
GM
1015 (when (and (or (gnus-method-option-p method 'post)
1016 (gnus-method-option-p method 'post-mail))
1017 (not (member method post-methods)))
eec82323
LMI
1018 (push method post-methods)))
1019 ;; Create a name-method alist.
1020 (setq method-alist
1021 (mapcar
1022 (lambda (m)
23f87bed
MB
1023 (if (equal (cadr m) "")
1024 (list (symbol-name (car m)) m)
1025 (list (concat (cadr m) " (" (symbol-name (car m)) ")") m)))
eec82323
LMI
1026 post-methods))
1027 ;; Query the user.
1028 (cadr
1029 (assoc
1030 (setq gnus-last-posting-server
1031 (if (and silent
1032 gnus-last-posting-server)
1033 ;; Just use the last value.
1034 gnus-last-posting-server
229b59da
G
1035 (gnus-completing-read
1036 "Posting method" (mapcar 'car method-alist) t
eec82323
LMI
1037 (cons (or gnus-last-posting-server "") 0))))
1038 method-alist))))
1039 ;; Override normal method.
6748645f 1040 ((and (eq gnus-post-method 'current)
23f87bed
MB
1041 (not (memq (car group-method) gnus-discouraged-post-methods))
1042 (gnus-get-function group-method 'request-post t))
1043 (assert (not arg))
16409b0b 1044 group-method)
23f87bed
MB
1045 ;; Use gnus-post-method.
1046 ((listp gnus-post-method) ;A method...
1047 (assert (not (listp (car gnus-post-method)))) ;... not a list of methods.
eec82323 1048 gnus-post-method)
23f87bed 1049 ;; Use the normal select method (nil or native).
eec82323
LMI
1050 (t gnus-select-method))))
1051
eec82323
LMI
1052\f
1053
eec82323 1054(defun gnus-extended-version ()
23f87bed
MB
1055 "Stringified Gnus version and Emacs version.
1056See the variable `gnus-user-agent'."
eec82323 1057 (interactive)
4a2358e9
MB
1058 (if (stringp gnus-user-agent)
1059 gnus-user-agent
1060 ;; `gnus-user-agent' is a list:
1061 (let* ((float-output-format nil)
1062 (gnus-v
1063 (when (memq 'gnus gnus-user-agent)
1064 (concat "Gnus/"
1065 (prin1-to-string (gnus-continuum-version gnus-version) t)
1066 " (" gnus-version ")")))
1067 (emacs-v (gnus-emacs-version)))
1068 (concat gnus-v (when (and gnus-v emacs-v) " ")
1069 emacs-v))))
eec82323 1070
eec82323
LMI
1071\f
1072;;;
1073;;; Gnus Mail Functions
1074;;;
1075
1076;;; Mail reply commands of Gnus summary mode
1077
23f87bed
MB
1078(defun gnus-summary-reply (&optional yank wide very-wide)
1079 "Start composing a mail reply to the current message.
eec82323 1080If prefix argument YANK is non-nil, the original article is yanked
23f87bed
MB
1081automatically.
1082If WIDE, make a wide reply.
1083If VERY-WIDE, make a very wide reply."
eec82323
LMI
1084 (interactive
1085 (list (and current-prefix-arg
1086 (gnus-summary-work-articles 1))))
23f87bed
MB
1087 ;; Allow user to require confirmation before replying by mail to the
1088 ;; author of a news article (or mail message).
5415d076 1089 (when (or (not (or (gnus-news-group-p gnus-newsgroup-name)
23f87bed
MB
1090 gnus-confirm-treat-mail-like-news))
1091 (not (cond ((stringp gnus-confirm-mail-reply-to-news)
1092 (string-match gnus-confirm-mail-reply-to-news
1093 gnus-newsgroup-name))
1094 ((functionp gnus-confirm-mail-reply-to-news)
5415d076
G
1095 (funcall gnus-confirm-mail-reply-to-news
1096 gnus-newsgroup-name))
23f87bed 1097 (t gnus-confirm-mail-reply-to-news)))
b890d447
MB
1098 (if (or wide very-wide)
1099 t ;; Ignore gnus-confirm-mail-reply-to-news for wide and very
1100 ;; wide replies.
1101 (y-or-n-p "Really reply by mail to article author? ")))
23f87bed
MB
1102 (let* ((article
1103 (if (listp (car yank))
1104 (caar yank)
1105 (car yank)))
1106 (gnus-article-reply (or article (gnus-summary-article-number)))
1107 (gnus-article-yanked-articles yank)
1108 (headers ""))
1109 ;; Stripping headers should be specified with mail-yank-ignored-headers.
eec82323 1110 (when yank
23f87bed
MB
1111 (gnus-summary-goto-subject article))
1112 (gnus-setup-message (if yank 'reply-yank 'reply)
1113 (if (not very-wide)
1114 (gnus-summary-select-article)
1115 (dolist (article very-wide)
1116 (gnus-summary-select-article nil nil nil article)
228b6ecd 1117 (with-current-buffer (gnus-copy-article-buffer)
23f87bed
MB
1118 (gnus-msg-treat-broken-reply-to)
1119 (save-restriction
1120 (message-narrow-to-head)
1121 (setq headers (concat headers (buffer-string)))))))
1122 (set-buffer (gnus-copy-article-buffer))
1123 (gnus-msg-treat-broken-reply-to gnus-msg-force-broken-reply-to)
1124 (save-restriction
1125 (message-narrow-to-head)
1126 (when very-wide
1127 (erase-buffer)
1128 (insert headers))
1129 (goto-char (point-max)))
1130 (mml-quote-region (point) (point-max))
5415d076 1131 (message-reply nil wide 'switch-to-buffer)
23f87bed
MB
1132 (when yank
1133 (gnus-inews-yank-articles yank))
1134 (gnus-summary-handle-replysign)))))
1135
1136(defun gnus-summary-handle-replysign ()
1137 "Check the various replysign variables and take action accordingly."
1138 (when (or gnus-message-replysign gnus-message-replyencrypt)
1139 (let (signed encrypted)
228b6ecd 1140 (with-current-buffer gnus-article-buffer
23f87bed
MB
1141 (setq signed (memq 'signed gnus-article-wash-types))
1142 (setq encrypted (memq 'encrypted gnus-article-wash-types)))
1143 (cond ((and gnus-message-replyencrypt encrypted)
1144 (mml-secure-message mml-default-encrypt-method
1145 (if gnus-message-replysignencrypted
1146 'signencrypt
1147 'encrypt)))
1148 ((and gnus-message-replysign signed)
1149 (mml-secure-message mml-default-sign-method 'sign))))))
eec82323
LMI
1150
1151(defun gnus-summary-reply-with-original (n &optional wide)
1152 "Start composing a reply mail to the current message.
1153The original article will be yanked."
1154 (interactive "P")
1155 (gnus-summary-reply (gnus-summary-work-articles n) wide))
1156
23f87bed
MB
1157(defun gnus-summary-reply-broken-reply-to (&optional yank wide very-wide)
1158 "Like `gnus-summary-reply' except removing reply-to field.
1159If prefix argument YANK is non-nil, the original article is yanked
1160automatically.
1161If WIDE, make a wide reply.
1162If VERY-WIDE, make a very wide reply."
1163 (interactive
1164 (list (and current-prefix-arg
1165 (gnus-summary-work-articles 1))))
1166 (let ((gnus-msg-force-broken-reply-to t))
1167 (gnus-summary-reply yank wide very-wide)))
1168
1169(defun gnus-summary-reply-broken-reply-to-with-original (n &optional wide)
1170 "Like `gnus-summary-reply-with-original' except removing reply-to field.
1171The original article will be yanked."
1172 (interactive "P")
1173 (gnus-summary-reply-broken-reply-to (gnus-summary-work-articles n) wide))
1174
eec82323
LMI
1175(defun gnus-summary-wide-reply (&optional yank)
1176 "Start composing a wide reply mail to the current message.
1177If prefix argument YANK is non-nil, the original article is yanked
1178automatically."
1179 (interactive
1180 (list (and current-prefix-arg
1181 (gnus-summary-work-articles 1))))
1182 (gnus-summary-reply yank t))
1183
1184(defun gnus-summary-wide-reply-with-original (n)
1185 "Start composing a wide reply mail to the current message.
23f87bed
MB
1186The original article will be yanked.
1187Uses the process/prefix convention."
eec82323
LMI
1188 (interactive "P")
1189 (gnus-summary-reply-with-original n t))
1190
23f87bed
MB
1191(defun gnus-summary-very-wide-reply (&optional yank)
1192 "Start composing a very wide reply mail to the current message.
1193If prefix argument YANK is non-nil, the original article is yanked
1194automatically."
1195 (interactive
1196 (list (and current-prefix-arg
1197 (gnus-summary-work-articles 1))))
1198 (gnus-summary-reply yank t (gnus-summary-work-articles yank)))
1199
1200(defun gnus-summary-very-wide-reply-with-original (n)
1201 "Start composing a very wide reply mail to the current message.
1202The original article will be yanked."
1203 (interactive "P")
1204 (gnus-summary-reply
1205 (gnus-summary-work-articles n) t (gnus-summary-work-articles n)))
1206
16409b0b 1207(defun gnus-summary-mail-forward (&optional arg post)
23f87bed
MB
1208 "Forward the current message(s) to another user.
1209If process marks exist, forward all marked messages;
1210if ARG is nil, see `message-forward-as-mime' and `message-forward-show-mml';
16409b0b 1211if ARG is 1, decode the message and forward directly inline;
25fc4fd5 1212if ARG is 2, forward message as an rfc822 MIME section;
16409b0b 1213if ARG is 3, decode message and forward as an rfc822 MIME section;
25fc4fd5 1214if ARG is 4, forward message directly inline;
16409b0b 1215otherwise, use flipped `message-forward-as-mime'.
23f87bed
MB
1216If POST, post instead of mail.
1217For the `inline' alternatives, also see the variable
1218`message-forward-ignored-headers'."
eec82323 1219 (interactive "P")
23f87bed
MB
1220 (if (cdr (gnus-summary-work-articles nil))
1221 ;; Process marks are given.
1222 (gnus-uu-digest-mail-forward arg post)
1223 ;; No process marks.
1224 (let ((message-forward-as-mime message-forward-as-mime)
1225 (message-forward-show-mml message-forward-show-mml))
1226 (cond
1227 ((null arg))
1228 ((eq arg 1)
1229 (setq message-forward-as-mime nil
1230 message-forward-show-mml t))
1231 ((eq arg 2)
1232 (setq message-forward-as-mime t
1233 message-forward-show-mml nil))
1234 ((eq arg 3)
1235 (setq message-forward-as-mime t
1236 message-forward-show-mml t))
1237 ((eq arg 4)
1238 (setq message-forward-as-mime nil
1239 message-forward-show-mml nil))
1240 (t
1241 (setq message-forward-as-mime (not message-forward-as-mime))))
1242 (let* ((gnus-article-reply (gnus-summary-article-number))
1243 (gnus-article-yanked-articles (list gnus-article-reply)))
1244 (gnus-setup-message 'forward
1245 (gnus-summary-select-article)
1246 (let ((mail-parse-charset
1247 (or (and (gnus-buffer-live-p gnus-article-buffer)
1248 (with-current-buffer gnus-article-buffer
1249 gnus-article-charset))
1250 gnus-newsgroup-charset))
1251 (mail-parse-ignored-charsets
1252 gnus-newsgroup-ignored-charsets))
1253 (set-buffer gnus-original-article-buffer)
1254 (message-forward post)))))))
eec82323
LMI
1255
1256(defun gnus-summary-resend-message (address n)
1257 "Resend the current article to ADDRESS."
23f87bed
MB
1258 (interactive
1259 (list (message-read-from-minibuffer
1260 "Resend message(s) to: "
1261 (when (and gnus-summary-resend-default-address
1262 (gnus-buffer-live-p gnus-original-article-buffer))
1263 ;; If some other article is currently selected, the
1264 ;; initial-contents is wrong. Whatever, it is just the
1265 ;; initial-contents.
1266 (with-current-buffer gnus-original-article-buffer
1267 (nnmail-fetch-field "to"))))
1268 current-prefix-arg))
01c52d31
MB
1269 (dolist (article (gnus-summary-work-articles n))
1270 (gnus-summary-select-article nil nil nil article)
228b6ecd 1271 (with-current-buffer gnus-original-article-buffer
a3f57c41
G
1272 (let ((gnus-gcc-externalize-attachments nil))
1273 (message-resend address)))
01c52d31 1274 (gnus-summary-mark-article-as-forwarded article)))
23f87bed
MB
1275
1276;; From: Matthieu Moy <Matthieu.Moy@imag.fr>
1277(defun gnus-summary-resend-message-edit ()
1278 "Resend an article that has already been sent.
1279A new buffer will be created to allow the user to modify body and
1280contents of the message, and then, everything will happen as when
1281composing a new message."
1282 (interactive)
9153f10d 1283 (let ((mail-parse-charset gnus-newsgroup-charset))
23f87bed
MB
1284 (gnus-setup-message 'reply-yank
1285 (gnus-summary-select-article t)
1286 (set-buffer gnus-original-article-buffer)
1287 (let ((cur (current-buffer))
1288 (to (message-fetch-field "to")))
1289 ;; Get a normal message buffer.
1290 (message-pop-to-buffer (message-buffer-name "Resend" to))
1291 (insert-buffer-substring cur)
1292 (mime-to-mml)
1293 (message-narrow-to-head-1)
1294 ;; Gnus will generate a new one when sending.
1295 (message-remove-header "Message-ID")
23f87bed 1296 ;; Remove unwanted headers.
2f62a044 1297 (message-remove-header message-ignored-resent-headers t)
23f87bed
MB
1298 (goto-char (point-max))
1299 (insert mail-header-separator)
2f62a044 1300 ;; Add Gcc header.
2f62a044 1301 (gnus-inews-insert-gcc)
23f87bed
MB
1302 (goto-char (point-min))
1303 (when (re-search-forward "^To:\\|^Newsgroups:" nil 'move)
1304 (forward-char 1))
1305 (widen)))))
eec82323 1306
16409b0b 1307(defun gnus-summary-post-forward (&optional arg)
eec82323 1308 "Forward the current article to a newsgroup.
16409b0b 1309See `gnus-summary-mail-forward' for ARG."
eec82323 1310 (interactive "P")
16409b0b 1311 (gnus-summary-mail-forward arg t))
eec82323 1312
eec82323
LMI
1313(defun gnus-summary-mail-crosspost-complaint (n)
1314 "Send a complaint about crossposting to the current article(s)."
1315 (interactive "P")
01c52d31
MB
1316 (dolist (article (gnus-summary-work-articles n))
1317 (set-buffer gnus-summary-buffer)
1318 (gnus-summary-goto-subject article)
1319 (let ((group (gnus-group-real-name gnus-newsgroup-name))
1320 newsgroups followup-to)
1321 (gnus-summary-select-article)
1322 (set-buffer gnus-original-article-buffer)
1323 (if (and (<= (length (message-tokenize-header
1324 (setq newsgroups
1325 (mail-fetch-field "newsgroups"))
1326 ", "))
1327 1)
1328 (or (not (setq followup-to (mail-fetch-field "followup-to")))
1329 (not (member group (message-tokenize-header
1330 followup-to ", ")))))
1331 (if followup-to
1332 (gnus-message 1 "Followup-to restricted")
1333 (gnus-message 1 "Not a crossposted article"))
1334 (set-buffer gnus-summary-buffer)
1335 (gnus-summary-reply-with-original 1)
1336 (set-buffer gnus-message-buffer)
1337 (message-goto-body)
1338 (insert (format gnus-crosspost-complaint newsgroups group))
1339 (message-goto-subject)
1340 (re-search-forward " *$")
1341 (replace-match " (crosspost notification)" t t)
1342 (gnus-deactivate-mark)
1343 (when (gnus-y-or-n-p "Send this complaint? ")
1344 (message-send-and-exit))))))
eec82323 1345
eec82323
LMI
1346(defun gnus-mail-parse-comma-list ()
1347 (let (accumulated
1348 beg)
1349 (skip-chars-forward " ")
1350 (while (not (eobp))
1351 (setq beg (point))
1352 (skip-chars-forward "^,")
1353 (while (zerop
1354 (save-excursion
1355 (save-restriction
1356 (let ((i 0))
1357 (narrow-to-region beg (point))
1358 (goto-char beg)
1359 (logand (progn
1360 (while (search-forward "\"" nil t)
1361 (incf i))
1362 (if (zerop i) 2 i))
1363 2)))))
1364 (skip-chars-forward ",")
1365 (skip-chars-forward "^,"))
1366 (skip-chars-backward " ")
1367 (push (buffer-substring beg (point))
1368 accumulated)
1369 (skip-chars-forward "^,")
1370 (skip-chars-forward ", "))
1371 accumulated))
1372
1373(defun gnus-inews-add-to-address (group)
1374 (let ((to-address (mail-fetch-field "to")))
1375 (when (and to-address
1376 (gnus-alive-p))
1377 ;; This mail group doesn't have a `to-list', so we add one
1378 ;; here. Magic!
1379 (when (gnus-y-or-n-p
23f87bed 1380 (format "Do you want to add this as `to-list': %s? " to-address))
eec82323
LMI
1381 (gnus-group-add-parameter group (cons 'to-list to-address))))))
1382
1383(defun gnus-put-message ()
1384 "Put the current message in some group and return to Gnus."
1385 (interactive)
1386 (let ((reply gnus-article-reply)
1387 (winconf gnus-prev-winconf)
1388 (group gnus-newsgroup-name))
23f87bed
MB
1389 (unless (and group
1390 (not (gnus-group-read-only-p group)))
1391 (setq group (read-string "Put in group: " nil (gnus-writable-groups))))
eec82323 1392
01c52d31 1393 (when (gnus-group-entry group)
eec82323 1394 (error "No such group: %s" group))
eec82323
LMI
1395 (save-excursion
1396 (save-restriction
1397 (widen)
1398 (message-narrow-to-headers)
23f87bed
MB
1399 (let ((gnus-deletable-headers nil))
1400 (message-generate-headers
1401 (if (message-news-p)
1402 message-required-news-headers
1403 message-required-mail-headers)))
eec82323 1404 (goto-char (point-max))
23f87bed
MB
1405 (if (string-match " " group)
1406 (insert "Gcc: \"" group "\"\n")
1407 (insert "Gcc: " group "\n"))
eec82323 1408 (widen)))
eec82323 1409 (gnus-inews-do-gcc)
23f87bed
MB
1410 (when (and (get-buffer gnus-group-buffer)
1411 (gnus-buffer-exists-p (car-safe reply))
1412 (cdr reply))
1413 (set-buffer (car reply))
1414 (gnus-summary-mark-article-as-replied (cdr reply)))
1415 (when winconf
1416 (set-window-configuration winconf))))
eec82323
LMI
1417
1418(defun gnus-article-mail (yank)
1419 "Send a reply to the address near point.
1420If YANK is non-nil, include the original article."
1421 (interactive "P")
1422 (let ((address
1423 (buffer-substring
1424 (save-excursion (re-search-backward "[ \t\n]" nil t) (1+ (point)))
1425 (save-excursion (re-search-forward "[ \t\n]" nil t) (1- (point))))))
1426 (when address
23f87bed 1427 (gnus-msg-mail address)
eec82323
LMI
1428 (when yank
1429 (gnus-inews-yank-articles (list (cdr gnus-article-current)))))))
1430
1431(defvar nntp-server-type)
1432(defun gnus-bug ()
1433 "Send a bug report to the Gnus maintainers."
1434 (interactive)
1435 (unless (gnus-alive-p)
1436 (error "Gnus has been shut down"))
88818fbe
SZ
1437 (gnus-setup-message (if (message-mail-user-agent) 'message 'bug)
1438 (unless (message-mail-user-agent)
1439 (delete-other-windows)
1440 (when gnus-bug-create-help-buffer
1441 (switch-to-buffer "*Gnus Help Bug*")
1442 (erase-buffer)
1443 (insert gnus-bug-message)
1444 (goto-char (point-min)))
1445 (message-pop-to-buffer "*Gnus Bug*"))
1446 (let ((message-this-is-mail t))
1447 (message-setup `((To . ,gnus-maintainer) (Subject . ""))))
6748645f
LMI
1448 (when gnus-bug-create-help-buffer
1449 (push `(gnus-bug-kill-buffer) message-send-actions))
eec82323
LMI
1450 (goto-char (point-min))
1451 (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$"))
1452 (forward-line 1)
6748645f
LMI
1453 (insert (gnus-version) "\n"
1454 (emacs-version) "\n")
eec82323
LMI
1455 (when (and (boundp 'nntp-server-type)
1456 (stringp nntp-server-type))
1457 (insert nntp-server-type))
1458 (insert "\n\n\n\n\n")
16409b0b 1459 (let (text)
228b6ecd 1460 (with-current-buffer (gnus-get-buffer-create " *gnus environment info*")
23f87bed 1461 (erase-buffer)
16409b0b
GM
1462 (gnus-debug)
1463 (setq text (buffer-string)))
23f87bed 1464 (insert "<#part type=application/emacs-lisp disposition=inline description=\"User settings\">\n" text "\n<#/part>"))
eec82323
LMI
1465 (goto-char (point-min))
1466 (search-forward "Subject: " nil t)
1467 (message "")))
1468
1469(defun gnus-bug-kill-buffer ()
1470 (when (get-buffer "*Gnus Help Bug*")
1471 (kill-buffer "*Gnus Help Bug*")))
1472
16409b0b
GM
1473(defun gnus-summary-yank-message (buffer n)
1474 "Yank the current article into a composed message."
1475 (interactive
229b59da 1476 (list (gnus-completing-read "Buffer" (message-buffers) t)
16409b0b
GM
1477 current-prefix-arg))
1478 (gnus-summary-iterate n
23f87bed 1479 (let ((gnus-inhibit-treatment t))
16409b0b 1480 (gnus-summary-select-article))
228b6ecd 1481 (with-current-buffer buffer
16409b0b
GM
1482 (message-yank-buffer gnus-article-buffer))))
1483
eec82323
LMI
1484(defun gnus-debug ()
1485 "Attempts to go through the Gnus source file and report what variables have been changed.
1486The source file has to be in the Emacs load path."
1487 (interactive)
23f87bed 1488 (let ((files gnus-debug-files)
6748645f 1489 (point (point))
eec82323
LMI
1490 file expr olist sym)
1491 (gnus-message 4 "Please wait while we snoop your variables...")
1492 (sit-for 0)
1493 ;; Go through all the files looking for non-default values for variables.
228b6ecd 1494 (with-current-buffer (gnus-get-buffer-create " *gnus bug info*")
eec82323
LMI
1495 (while files
1496 (erase-buffer)
1497 (when (and (setq file (locate-library (pop files)))
1498 (file-exists-p file))
1499 (insert-file-contents file)
1500 (goto-char (point-min))
1501 (if (not (re-search-forward "^;;* *Internal variables" nil t))
1502 (gnus-message 4 "Malformed sources in file %s" file)
1503 (narrow-to-region (point-min) (point))
1504 (goto-char (point-min))
1505 (while (setq expr (ignore-errors (read (current-buffer))))
1506 (ignore-errors
1507 (and (or (eq (car expr) 'defvar)
1508 (eq (car expr) 'defcustom))
1509 (stringp (nth 3 expr))
23f87bed 1510 (not (memq (nth 1 expr) gnus-debug-exclude-variables))
eec82323
LMI
1511 (or (not (boundp (nth 1 expr)))
1512 (not (equal (eval (nth 2 expr))
1513 (symbol-value (nth 1 expr)))))
1514 (push (nth 1 expr) olist)))))))
1515 (kill-buffer (current-buffer)))
1516 (when (setq olist (nreverse olist))
1517 (insert "------------------ Environment follows ------------------\n\n"))
1518 (while olist
1519 (if (boundp (car olist))
23f87bed
MB
1520 (ignore-errors
1521 (gnus-pp
1522 `(setq ,(car olist)
1523 ,(if (or (consp (setq sym (symbol-value (car olist))))
1524 (and (symbolp sym)
1525 (not (or (eq sym nil)
1526 (eq sym t)))))
1527 (list 'quote (symbol-value (car olist)))
1528 (symbol-value (car olist))))))
eec82323
LMI
1529 (insert ";; (makeunbound '" (symbol-name (car olist)) ")\n"))
1530 (setq olist (cdr olist)))
1531 (insert "\n\n")
6748645f 1532 ;; Remove any control chars - they seem to cause trouble for some
eec82323 1533 ;; mailers. (Byte-compiled output from the stuff above.)
6748645f 1534 (goto-char point)
ef1b088a 1535 (while (re-search-forward (mm-string-to-multibyte
7c3bb5a5 1536 "[\000-\010\013-\037\200-\237]") nil t)
6748645f
LMI
1537 (replace-match (format "\\%03o" (string-to-char (match-string 0)))
1538 t t))))
eec82323
LMI
1539
1540;;; Treatment of rejected articles.
1541;;; Bounced mail.
1542
1543(defun gnus-summary-resend-bounced-mail (&optional fetch)
1544 "Re-mail the current message.
23f87bed 1545This only makes sense if the current message is a bounce message that
eec82323
LMI
1546contains some mail you have written which has been bounced back to
1547you.
1548If FETCH, try to fetch the article that this is a reply to, if indeed
1549this is a reply."
1550 (interactive "P")
1551 (gnus-summary-select-article t)
2f62a044
MB
1552 (let (summary-buffer parent)
1553 (if fetch
1554 (progn
1555 (setq summary-buffer (current-buffer))
1556 (set-buffer gnus-original-article-buffer)
1557 (article-goto-body)
1558 (when (re-search-forward "^References:\n?" nil t)
1559 (while (memq (char-after) '(?\t ? ))
1560 (forward-line 1))
1561 (skip-chars-backward "\t\n ")
1562 (setq parent
1563 (gnus-parent-id (buffer-substring (match-end 0) (point))))))
1564 (set-buffer gnus-original-article-buffer))
1565 (gnus-setup-message 'compose-bounce
eec82323 1566 (message-bounce)
2f62a044 1567 ;; Add Gcc header.
2f62a044 1568 (gnus-inews-insert-gcc)
eec82323 1569 ;; If there are references, we fetch the article we answered to.
2f62a044
MB
1570 (when parent
1571 (with-current-buffer summary-buffer
1572 (gnus-summary-refer-article parent)
1573 (gnus-summary-show-all-headers))))))
eec82323
LMI
1574
1575;;; Gcc handling.
1576
0342aa5b 1577(defun gnus-inews-group-method (group)
23f87bed
MB
1578 (cond
1579 ;; If the group doesn't exist, we assume
1580 ;; it's an archive group...
1581 ((and (null (gnus-get-info group))
1582 (eq (car (gnus-server-to-method gnus-message-archive-method))
1583 (car (gnus-server-to-method (gnus-group-method group)))))
1584 gnus-message-archive-method)
1585 ;; Use the method.
1586 ((gnus-info-method (gnus-get-info group))
1587 (gnus-info-method (gnus-get-info group)))
1588 ;; Find the method.
1589 (t (gnus-server-to-method (gnus-group-method group)))))
0342aa5b 1590
eec82323
LMI
1591;; Do Gcc handling, which copied the message over to some group.
1592(defun gnus-inews-do-gcc (&optional gcc)
1593 (interactive)
23f87bed
MB
1594 (save-excursion
1595 (save-restriction
1596 (message-narrow-to-headers)
1597 (let ((gcc (or gcc (mail-fetch-field "gcc" nil t)))
1598 (cur (current-buffer))
1599 groups group method group-art
1600 mml-externalize-attachments)
1601 (when gcc
1602 (message-remove-header "gcc")
1603 (widen)
1604 (setq groups (message-unquote-tokens
1605 (message-tokenize-header gcc " ,")))
1606 ;; Copy the article over to some group(s).
1607 (while (setq group (pop groups))
4d8a28ec
MB
1608 (setq method (gnus-inews-group-method group)
1609 group (mm-encode-coding-string
1610 group
1611 (gnus-group-name-charset method group)))
1612 (unless (gnus-check-server method)
23f87bed
MB
1613 (error "Can't open server %s" (if (stringp method) method
1614 (car method))))
99e65b2d 1615 (unless (gnus-request-group group t method)
23f87bed
MB
1616 (gnus-request-create-group group method))
1617 (setq mml-externalize-attachments
1618 (if (stringp gnus-gcc-externalize-attachments)
1619 (string-match gnus-gcc-externalize-attachments group)
1620 gnus-gcc-externalize-attachments))
1621 (save-excursion
1622 (nnheader-set-temp-buffer " *acc*")
1623 (insert-buffer-substring cur)
1624 (message-encode-message-body)
1625 (save-restriction
1626 (message-narrow-to-headers)
1627 (let* ((mail-parse-charset message-default-charset)
1628 (newsgroups-field (save-restriction
1629 (message-narrow-to-headers-or-head)
1630 (message-fetch-field "Newsgroups")))
1631 (followup-field (save-restriction
1632 (message-narrow-to-headers-or-head)
1633 (message-fetch-field "Followup-To")))
1634 ;; BUG: We really need to get the charset for
1635 ;; each name in the Newsgroups and Followup-To
1636 ;; lines to allow crossposting between group
1637 ;; namess with incompatible character sets.
1638 ;; -- Per Abrahamsen <abraham@dina.kvl.dk> 2001-10-08.
1639 (group-field-charset
1640 (gnus-group-name-charset
1641 method (or newsgroups-field "")))
1642 (followup-field-charset
1643 (gnus-group-name-charset
1644 method (or followup-field "")))
1645 (rfc2047-header-encoding-alist
1646 (append
1647 (when group-field-charset
1648 (list (cons "Newsgroups" group-field-charset)))
1649 (when followup-field-charset
1650 (list (cons "Followup-To" followup-field-charset)))
1651 rfc2047-header-encoding-alist)))
1652 (mail-encode-encoded-word-buffer)))
1653 (goto-char (point-min))
1654 (when (re-search-forward
1655 (concat "^" (regexp-quote mail-header-separator) "$")
1656 nil t)
1657 (replace-match "" t t ))
01c52d31
MB
1658 (when (or (not (gnus-check-backend-function
1659 'request-accept-article group))
1660 (not (setq group-art
1661 (gnus-request-accept-article
1662 group method t t))))
23f87bed 1663 (gnus-message 1 "Couldn't store article in group %s: %s"
01c52d31 1664 group (gnus-status-message method)))
e3e955fe
MB
1665 (when (stringp method)
1666 (setq method (gnus-server-to-method method)))
1667 (when (and (listp method)
1668 (gnus-native-method-p method))
1669 (setq group (gnus-group-short-name group)))
23f87bed
MB
1670 (when (and group-art
1671 ;; FIXME: Should gcc-mark-as-read work when
1672 ;; Gnus is not running?
1673 (gnus-alive-p)
1674 (or gnus-gcc-mark-as-read
1675 (and
1676 (boundp 'gnus-inews-mark-gcc-as-read)
1677 (symbol-value 'gnus-inews-mark-gcc-as-read))))
1678 (gnus-group-mark-article-read group (cdr group-art)))
1679 (kill-buffer (current-buffer)))))))))
eec82323 1680
ed797193 1681(defun gnus-inews-insert-gcc (&optional group)
eec82323 1682 "Insert the Gcc to say where the article is to be archived."
ed797193
G
1683 (let* ((group (or group gnus-newsgroup-name))
1684 (group (when group (gnus-group-decoded-name group)))
1685 (var (or gnus-outgoing-message-group gnus-message-archive-group))
6748645f 1686 (gcc-self-val
ed797193 1687 (and group (gnus-group-find-parameter group 'gcc-self)))
16409b0b 1688 result
eec82323
LMI
1689 (groups
1690 (cond
1691 ((null gnus-message-archive-method)
1692 ;; Ignore.
1693 nil)
1694 ((stringp var)
1695 ;; Just a single group.
1696 (list var))
1697 ((null var)
1698 ;; We don't want this.
1699 nil)
1700 ((and (listp var) (stringp (car var)))
1701 ;; A list of groups.
1702 var)
23f87bed 1703 ((functionp var)
eec82323
LMI
1704 ;; A function.
1705 (funcall var group))
1706 (t
1707 ;; An alist of regexps/functions/forms.
1708 (while (and var
1709 (not
1710 (setq result
1711 (cond
1712 ((stringp (caar var))
1713 ;; Regexp.
1714 (when (string-match (caar var) group)
1715 (cdar var)))
23f87bed 1716 ((functionp (car var))
eec82323
LMI
1717 ;; Function.
1718 (funcall (car var) group))
1719 (t
1720 (eval (car var)))))))
1721 (setq var (cdr var)))
1722 result)))
1723 name)
6748645f 1724 (when (or groups gcc-self-val)
eec82323
LMI
1725 (when (stringp groups)
1726 (setq groups (list groups)))
1727 (save-excursion
1728 (save-restriction
1729 (message-narrow-to-headers)
1730 (goto-char (point-max))
1731 (insert "Gcc: ")
6748645f
LMI
1732 (if gcc-self-val
1733 ;; Use the `gcc-self' param value instead.
eec82323
LMI
1734 (progn
1735 (insert
1736 (if (stringp gcc-self-val)
23f87bed
MB
1737 (if (string-match " " gcc-self-val)
1738 (concat "\"" gcc-self-val "\"")
1739 gcc-self-val)
1740 ;; In nndoc groups, we use the parent group name
1741 ;; instead of the current group.
1742 (let ((group (or (gnus-group-find-parameter
1743 gnus-newsgroup-name 'parent-group)
1744 group)))
1745 (if (string-match " " group)
1746 (concat "\"" group "\"")
1747 group))))
eec82323
LMI
1748 (if (not (eq gcc-self-val 'none))
1749 (insert "\n")
23f87bed 1750 (gnus-delete-line)))
6748645f 1751 ;; Use the list of groups.
eec82323 1752 (while (setq name (pop groups))
23f87bed
MB
1753 (let ((str (if (string-match ":" name)
1754 name
1755 (gnus-group-prefixed-name
1756 name gnus-message-archive-method))))
1757 (insert (if (string-match " " str)
1758 (concat "\"" str "\"")
1759 str)))
eec82323
LMI
1760 (when groups
1761 (insert " ")))
1762 (insert "\n")))))))
1763
23f87bed
MB
1764(defun gnus-mailing-list-followup-to ()
1765 "Look at the headers in the current buffer and return a Mail-Followup-To address."
1766 (let ((x-been-there (gnus-fetch-original-field "x-beenthere"))
1767 (list-post (gnus-fetch-original-field "list-post")))
1768 (when (and list-post
1769 (string-match "mailto:\\([^>]+\\)" list-post))
1770 (setq list-post (match-string 1 list-post)))
1771 (or list-post
1772 x-been-there)))
1773
6748645f
LMI
1774;;; Posting styles.
1775
23f87bed 1776(defun gnus-configure-posting-styles (&optional group-name)
6748645f
LMI
1777 "Configure posting styles according to `gnus-posting-styles'."
1778 (unless gnus-inhibit-posting-styles
23f87bed 1779 (let ((group (or group-name gnus-newsgroup-name ""))
16409b0b 1780 (styles gnus-posting-styles)
23f87bed 1781 style match attribute value v results
16409b0b
GM
1782 filep name address element)
1783 ;; If the group has a posting-style parameter, add it at the end with a
1784 ;; regexp matching everything, to be sure it takes precedence over all
1785 ;; the others.
1786 (when gnus-newsgroup-name
1787 (let ((tmp-style (gnus-group-find-parameter group 'posting-style t)))
1788 (when tmp-style
1789 (setq styles (append styles (list (cons ".*" tmp-style)))))))
6748645f 1790 ;; Go through all styles and look for matches.
16409b0b
GM
1791 (dolist (style styles)
1792 (setq match (pop style))
1793 (goto-char (point-min))
1794 (when (cond
1795 ((stringp match)
1796 ;; Regexp string match on the group name.
1797 (string-match match group))
1798 ((eq match 'header)
23f87bed
MB
1799 ;; Obsolete format of header match.
1800 (and (gnus-buffer-live-p gnus-article-copy)
1801 (with-current-buffer gnus-article-copy
9b5773bc
MB
1802 (save-restriction
1803 (nnheader-narrow-to-headers)
1804 (let ((header (message-fetch-field (pop style))))
1805 (and header
1806 (string-match (pop style) header)))))))
16409b0b 1807 ((or (symbolp match)
23f87bed 1808 (functionp match))
16409b0b 1809 (cond
23f87bed 1810 ((functionp match)
16409b0b
GM
1811 ;; Function to be called.
1812 (funcall match))
1813 ((boundp match)
1814 ;; Variable to be checked.
1815 (symbol-value match))))
1816 ((listp match)
23f87bed
MB
1817 (cond
1818 ((eq (car match) 'header)
1819 ;; New format of header match.
1820 (and (gnus-buffer-live-p gnus-article-copy)
1821 (with-current-buffer gnus-article-copy
9b5773bc
MB
1822 (save-restriction
1823 (nnheader-narrow-to-headers)
1824 (let ((header (message-fetch-field (nth 1 match))))
1825 (and header
1826 (string-match (nth 2 match) header)))))))
23f87bed
MB
1827 (t
1828 ;; This is a form to be evaled.
1829 (eval match)))))
6748645f 1830 ;; We have a match, so we set the variables.
16409b0b
GM
1831 (dolist (attribute style)
1832 (setq element (pop attribute)
16409b0b
GM
1833 filep nil)
1834 (setq value
1835 (cond
1836 ((eq (car attribute) :file)
1837 (setq filep t)
1838 (cadr attribute))
1839 ((eq (car attribute) :value)
1840 (cadr attribute))
1841 (t
1842 (car attribute))))
1843 ;; We get the value.
1844 (setq v
1845 (cond
1846 ((stringp value)
389b76fa 1847 (if (and (stringp match)
87732ef3 1848 (gnus-string-match-p "\\\\[&[:digit:]]" value)
389b76fa
G
1849 (match-beginning 1))
1850 (gnus-match-substitute-replacement value nil nil group)
1851 value))
16409b0b 1852 ((or (symbolp value)
23f87bed
MB
1853 (functionp value))
1854 (cond ((functionp value)
16409b0b
GM
1855 (funcall value))
1856 ((boundp value)
1857 (symbol-value value))))
1858 ((listp value)
1859 (eval value))))
1860 ;; Translate obsolescent value.
23f87bed
MB
1861 (cond
1862 ((eq element 'signature-file)
16409b0b
GM
1863 (setq element 'signature
1864 filep t))
23f87bed
MB
1865 ((eq element 'x-face-file)
1866 (setq element 'x-face
1867 filep t)))
01c52d31
MB
1868 ;; Post-processing for the signature posting-style:
1869 (and (eq element 'signature) filep
1870 message-signature-directory
1871 ;; don't actually use the signature directory
1872 ;; if message-signature-file contains a path.
1873 (not (file-name-directory v))
1874 (setq v (nnheader-concat message-signature-directory v)))
16409b0b
GM
1875 ;; Get the contents of file elems.
1876 (when (and filep v)
1877 (setq v (with-temp-buffer
1878 (insert-file-contents v)
5f49be3f
MB
1879 (buffer-substring
1880 (point-min)
1881 (progn
1882 (goto-char (point-max))
1883 (if (zerop (skip-chars-backward "\n"))
1884 (point)
1885 (1+ (point))))))))
16409b0b
GM
1886 (setq results (delq (assoc element results) results))
1887 (push (cons element v) results))))
1888 ;; Now we have all the styles, so we insert them.
1889 (setq name (assq 'name results)
1890 address (assq 'address results))
1891 (setq results (delq name (delq address results)))
23f87bed
MB
1892 (gnus-make-local-hook 'message-setup-hook)
1893 (setq results (sort results (lambda (x y)
1894 (string-lessp (car x) (car y)))))
16409b0b
GM
1895 (dolist (result results)
1896 (add-hook 'message-setup-hook
1897 (cond
1898 ((eq 'eval (car result))
1899 'ignore)
1900 ((eq 'body (car result))
1901 `(lambda ()
1902 (save-excursion
1903 (message-goto-body)
1904 (insert ,(cdr result)))))
1905 ((eq 'signature (car result))
1906 (set (make-local-variable 'message-signature) nil)
1907 (set (make-local-variable 'message-signature-file) nil)
1908 (if (not (cdr result))
1909 'ignore
1910 `(lambda ()
1911 (save-excursion
1912 (let ((message-signature ,(cdr result)))
1913 (when message-signature
1914 (message-insert-signature)))))))
1915 (t
1916 (let ((header
1917 (if (symbolp (car result))
1918 (capitalize (symbol-name (car result)))
1919 (car result))))
1920 `(lambda ()
1921 (save-excursion
1922 (message-remove-header ,header)
1923 (let ((value ,(cdr result)))
1924 (when value
1925 (message-goto-eoh)
23f87bed
MB
1926 (insert ,header ": " value)
1927 (unless (bolp)
1928 (insert "\n")))))))))
1929 nil 'local))
16409b0b
GM
1930 (when (or name address)
1931 (add-hook 'message-setup-hook
1932 `(lambda ()
23f87bed
MB
1933 (set (make-local-variable 'user-mail-address)
1934 ,(or (cdr address) user-mail-address))
16409b0b
GM
1935 (let ((user-full-name ,(or (cdr name) (user-full-name)))
1936 (user-mail-address
1937 ,(or (cdr address) user-mail-address)))
1938 (save-excursion
1939 (message-remove-header "From")
1940 (message-goto-eoh)
23f87bed
MB
1941 (insert "From: " (message-make-from) "\n"))))
1942 nil 'local)))))
eec82323
LMI
1943
1944;;; Allow redefinition of functions.
1945
1946(gnus-ems-redefine)
1947
1948(provide 'gnus-msg)
1949
1950;;; gnus-msg.el ends here