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