Merge from gnus--devo--0
[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)))
b890d447
MB
1104 (if (or wide very-wide)
1105 t ;; Ignore gnus-confirm-mail-reply-to-news for wide and very
1106 ;; wide replies.
1107 (y-or-n-p "Really reply by mail to article author? ")))
23f87bed
MB
1108 (let* ((article
1109 (if (listp (car yank))
1110 (caar yank)
1111 (car yank)))
1112 (gnus-article-reply (or article (gnus-summary-article-number)))
1113 (gnus-article-yanked-articles yank)
1114 (headers ""))
1115 ;; Stripping headers should be specified with mail-yank-ignored-headers.
eec82323 1116 (when yank
23f87bed
MB
1117 (gnus-summary-goto-subject article))
1118 (gnus-setup-message (if yank 'reply-yank 'reply)
1119 (if (not very-wide)
1120 (gnus-summary-select-article)
1121 (dolist (article very-wide)
1122 (gnus-summary-select-article nil nil nil article)
1123 (save-excursion
1124 (set-buffer (gnus-copy-article-buffer))
1125 (gnus-msg-treat-broken-reply-to)
1126 (save-restriction
1127 (message-narrow-to-head)
1128 (setq headers (concat headers (buffer-string)))))))
1129 (set-buffer (gnus-copy-article-buffer))
1130 (gnus-msg-treat-broken-reply-to gnus-msg-force-broken-reply-to)
1131 (save-restriction
1132 (message-narrow-to-head)
1133 (when very-wide
1134 (erase-buffer)
1135 (insert headers))
1136 (goto-char (point-max)))
1137 (mml-quote-region (point) (point-max))
1138 (message-reply nil wide)
1139 (when yank
1140 (gnus-inews-yank-articles yank))
1141 (gnus-summary-handle-replysign)))))
1142
1143(defun gnus-summary-handle-replysign ()
1144 "Check the various replysign variables and take action accordingly."
1145 (when (or gnus-message-replysign gnus-message-replyencrypt)
1146 (let (signed encrypted)
1147 (save-excursion
1148 (set-buffer gnus-article-buffer)
1149 (setq signed (memq 'signed gnus-article-wash-types))
1150 (setq encrypted (memq 'encrypted gnus-article-wash-types)))
1151 (cond ((and gnus-message-replyencrypt encrypted)
1152 (mml-secure-message mml-default-encrypt-method
1153 (if gnus-message-replysignencrypted
1154 'signencrypt
1155 'encrypt)))
1156 ((and gnus-message-replysign signed)
1157 (mml-secure-message mml-default-sign-method 'sign))))))
eec82323
LMI
1158
1159(defun gnus-summary-reply-with-original (n &optional wide)
1160 "Start composing a reply mail to the current message.
1161The original article will be yanked."
1162 (interactive "P")
1163 (gnus-summary-reply (gnus-summary-work-articles n) wide))
1164
23f87bed
MB
1165(defun gnus-summary-reply-broken-reply-to (&optional yank wide very-wide)
1166 "Like `gnus-summary-reply' except removing reply-to field.
1167If prefix argument YANK is non-nil, the original article is yanked
1168automatically.
1169If WIDE, make a wide reply.
1170If VERY-WIDE, make a very wide reply."
1171 (interactive
1172 (list (and current-prefix-arg
1173 (gnus-summary-work-articles 1))))
1174 (let ((gnus-msg-force-broken-reply-to t))
1175 (gnus-summary-reply yank wide very-wide)))
1176
1177(defun gnus-summary-reply-broken-reply-to-with-original (n &optional wide)
1178 "Like `gnus-summary-reply-with-original' except removing reply-to field.
1179The original article will be yanked."
1180 (interactive "P")
1181 (gnus-summary-reply-broken-reply-to (gnus-summary-work-articles n) wide))
1182
eec82323
LMI
1183(defun gnus-summary-wide-reply (&optional yank)
1184 "Start composing a wide reply mail to the current message.
1185If prefix argument YANK is non-nil, the original article is yanked
1186automatically."
1187 (interactive
1188 (list (and current-prefix-arg
1189 (gnus-summary-work-articles 1))))
1190 (gnus-summary-reply yank t))
1191
1192(defun gnus-summary-wide-reply-with-original (n)
1193 "Start composing a wide reply mail to the current message.
23f87bed
MB
1194The original article will be yanked.
1195Uses the process/prefix convention."
eec82323
LMI
1196 (interactive "P")
1197 (gnus-summary-reply-with-original n t))
1198
23f87bed
MB
1199(defun gnus-summary-very-wide-reply (&optional yank)
1200 "Start composing a very wide reply mail to the current message.
1201If prefix argument YANK is non-nil, the original article is yanked
1202automatically."
1203 (interactive
1204 (list (and current-prefix-arg
1205 (gnus-summary-work-articles 1))))
1206 (gnus-summary-reply yank t (gnus-summary-work-articles yank)))
1207
1208(defun gnus-summary-very-wide-reply-with-original (n)
1209 "Start composing a very wide reply mail to the current message.
1210The original article will be yanked."
1211 (interactive "P")
1212 (gnus-summary-reply
1213 (gnus-summary-work-articles n) t (gnus-summary-work-articles n)))
1214
16409b0b 1215(defun gnus-summary-mail-forward (&optional arg post)
23f87bed
MB
1216 "Forward the current message(s) to another user.
1217If process marks exist, forward all marked messages;
1218if ARG is nil, see `message-forward-as-mime' and `message-forward-show-mml';
16409b0b 1219if ARG is 1, decode the message and forward directly inline;
25fc4fd5 1220if ARG is 2, forward message as an rfc822 MIME section;
16409b0b 1221if ARG is 3, decode message and forward as an rfc822 MIME section;
25fc4fd5 1222if ARG is 4, forward message directly inline;
16409b0b 1223otherwise, use flipped `message-forward-as-mime'.
23f87bed
MB
1224If POST, post instead of mail.
1225For the `inline' alternatives, also see the variable
1226`message-forward-ignored-headers'."
eec82323 1227 (interactive "P")
23f87bed
MB
1228 (if (cdr (gnus-summary-work-articles nil))
1229 ;; Process marks are given.
1230 (gnus-uu-digest-mail-forward arg post)
1231 ;; No process marks.
1232 (let ((message-forward-as-mime message-forward-as-mime)
1233 (message-forward-show-mml message-forward-show-mml))
1234 (cond
1235 ((null arg))
1236 ((eq arg 1)
1237 (setq message-forward-as-mime nil
1238 message-forward-show-mml t))
1239 ((eq arg 2)
1240 (setq message-forward-as-mime t
1241 message-forward-show-mml nil))
1242 ((eq arg 3)
1243 (setq message-forward-as-mime t
1244 message-forward-show-mml t))
1245 ((eq arg 4)
1246 (setq message-forward-as-mime nil
1247 message-forward-show-mml nil))
1248 (t
1249 (setq message-forward-as-mime (not message-forward-as-mime))))
1250 (let* ((gnus-article-reply (gnus-summary-article-number))
1251 (gnus-article-yanked-articles (list gnus-article-reply)))
1252 (gnus-setup-message 'forward
1253 (gnus-summary-select-article)
1254 (let ((mail-parse-charset
1255 (or (and (gnus-buffer-live-p gnus-article-buffer)
1256 (with-current-buffer gnus-article-buffer
1257 gnus-article-charset))
1258 gnus-newsgroup-charset))
1259 (mail-parse-ignored-charsets
1260 gnus-newsgroup-ignored-charsets))
1261 (set-buffer gnus-original-article-buffer)
1262 (message-forward post)))))))
eec82323
LMI
1263
1264(defun gnus-summary-resend-message (address n)
1265 "Resend the current article to ADDRESS."
23f87bed
MB
1266 (interactive
1267 (list (message-read-from-minibuffer
1268 "Resend message(s) to: "
1269 (when (and gnus-summary-resend-default-address
1270 (gnus-buffer-live-p gnus-original-article-buffer))
1271 ;; If some other article is currently selected, the
1272 ;; initial-contents is wrong. Whatever, it is just the
1273 ;; initial-contents.
1274 (with-current-buffer gnus-original-article-buffer
1275 (nnmail-fetch-field "to"))))
1276 current-prefix-arg))
01c52d31
MB
1277 (dolist (article (gnus-summary-work-articles n))
1278 (gnus-summary-select-article nil nil nil article)
1279 (save-excursion
1280 (set-buffer gnus-original-article-buffer)
1281 (message-resend address))
1282 (gnus-summary-mark-article-as-forwarded article)))
23f87bed
MB
1283
1284;; From: Matthieu Moy <Matthieu.Moy@imag.fr>
1285(defun gnus-summary-resend-message-edit ()
1286 "Resend an article that has already been sent.
1287A new buffer will be created to allow the user to modify body and
1288contents of the message, and then, everything will happen as when
1289composing a new message."
1290 (interactive)
1291 (let ((article (gnus-summary-article-number)))
1292 (gnus-setup-message 'reply-yank
1293 (gnus-summary-select-article t)
1294 (set-buffer gnus-original-article-buffer)
1295 (let ((cur (current-buffer))
1296 (to (message-fetch-field "to")))
1297 ;; Get a normal message buffer.
1298 (message-pop-to-buffer (message-buffer-name "Resend" to))
1299 (insert-buffer-substring cur)
1300 (mime-to-mml)
1301 (message-narrow-to-head-1)
1302 ;; Gnus will generate a new one when sending.
1303 (message-remove-header "Message-ID")
23f87bed 1304 ;; Remove unwanted headers.
2f62a044 1305 (message-remove-header message-ignored-resent-headers t)
23f87bed
MB
1306 (goto-char (point-max))
1307 (insert mail-header-separator)
2f62a044
MB
1308 ;; Add Gcc header.
1309 (gnus-inews-insert-archive-gcc)
1310 (gnus-inews-insert-gcc)
23f87bed
MB
1311 (goto-char (point-min))
1312 (when (re-search-forward "^To:\\|^Newsgroups:" nil 'move)
1313 (forward-char 1))
1314 (widen)))))
eec82323 1315
16409b0b 1316(defun gnus-summary-post-forward (&optional arg)
eec82323 1317 "Forward the current article to a newsgroup.
16409b0b 1318See `gnus-summary-mail-forward' for ARG."
eec82323 1319 (interactive "P")
16409b0b 1320 (gnus-summary-mail-forward arg t))
eec82323
LMI
1321
1322(defvar gnus-nastygram-message
1323 "The following article was inappropriately posted to %s.\n\n"
1324 "Format string to insert in nastygrams.
1325The current group name will be inserted at \"%s\".")
1326
1327(defun gnus-summary-mail-nastygram (n)
1328 "Send a nastygram to the author of the current article."
1329 (interactive "P")
1330 (when (or gnus-expert-user
1331 (gnus-y-or-n-p
1332 "Really send a nastygram to the author of the current article? "))
1333 (let ((group gnus-newsgroup-name))
1334 (gnus-summary-reply-with-original n)
1335 (set-buffer gnus-message-buffer)
1336 (message-goto-body)
1337 (insert (format gnus-nastygram-message group))
1338 (message-send-and-exit))))
1339
1340(defun gnus-summary-mail-crosspost-complaint (n)
1341 "Send a complaint about crossposting to the current article(s)."
1342 (interactive "P")
01c52d31
MB
1343 (dolist (article (gnus-summary-work-articles n))
1344 (set-buffer gnus-summary-buffer)
1345 (gnus-summary-goto-subject article)
1346 (let ((group (gnus-group-real-name gnus-newsgroup-name))
1347 newsgroups followup-to)
1348 (gnus-summary-select-article)
1349 (set-buffer gnus-original-article-buffer)
1350 (if (and (<= (length (message-tokenize-header
1351 (setq newsgroups
1352 (mail-fetch-field "newsgroups"))
1353 ", "))
1354 1)
1355 (or (not (setq followup-to (mail-fetch-field "followup-to")))
1356 (not (member group (message-tokenize-header
1357 followup-to ", ")))))
1358 (if followup-to
1359 (gnus-message 1 "Followup-to restricted")
1360 (gnus-message 1 "Not a crossposted article"))
1361 (set-buffer gnus-summary-buffer)
1362 (gnus-summary-reply-with-original 1)
1363 (set-buffer gnus-message-buffer)
1364 (message-goto-body)
1365 (insert (format gnus-crosspost-complaint newsgroups group))
1366 (message-goto-subject)
1367 (re-search-forward " *$")
1368 (replace-match " (crosspost notification)" t t)
1369 (gnus-deactivate-mark)
1370 (when (gnus-y-or-n-p "Send this complaint? ")
1371 (message-send-and-exit))))))
eec82323 1372
eec82323
LMI
1373(defun gnus-mail-parse-comma-list ()
1374 (let (accumulated
1375 beg)
1376 (skip-chars-forward " ")
1377 (while (not (eobp))
1378 (setq beg (point))
1379 (skip-chars-forward "^,")
1380 (while (zerop
1381 (save-excursion
1382 (save-restriction
1383 (let ((i 0))
1384 (narrow-to-region beg (point))
1385 (goto-char beg)
1386 (logand (progn
1387 (while (search-forward "\"" nil t)
1388 (incf i))
1389 (if (zerop i) 2 i))
1390 2)))))
1391 (skip-chars-forward ",")
1392 (skip-chars-forward "^,"))
1393 (skip-chars-backward " ")
1394 (push (buffer-substring beg (point))
1395 accumulated)
1396 (skip-chars-forward "^,")
1397 (skip-chars-forward ", "))
1398 accumulated))
1399
1400(defun gnus-inews-add-to-address (group)
1401 (let ((to-address (mail-fetch-field "to")))
1402 (when (and to-address
1403 (gnus-alive-p))
1404 ;; This mail group doesn't have a `to-list', so we add one
1405 ;; here. Magic!
1406 (when (gnus-y-or-n-p
23f87bed 1407 (format "Do you want to add this as `to-list': %s? " to-address))
eec82323
LMI
1408 (gnus-group-add-parameter group (cons 'to-list to-address))))))
1409
1410(defun gnus-put-message ()
1411 "Put the current message in some group and return to Gnus."
1412 (interactive)
1413 (let ((reply gnus-article-reply)
1414 (winconf gnus-prev-winconf)
1415 (group gnus-newsgroup-name))
23f87bed
MB
1416 (unless (and group
1417 (not (gnus-group-read-only-p group)))
1418 (setq group (read-string "Put in group: " nil (gnus-writable-groups))))
eec82323 1419
01c52d31 1420 (when (gnus-group-entry group)
eec82323 1421 (error "No such group: %s" group))
eec82323
LMI
1422 (save-excursion
1423 (save-restriction
1424 (widen)
1425 (message-narrow-to-headers)
23f87bed
MB
1426 (let ((gnus-deletable-headers nil))
1427 (message-generate-headers
1428 (if (message-news-p)
1429 message-required-news-headers
1430 message-required-mail-headers)))
eec82323 1431 (goto-char (point-max))
23f87bed
MB
1432 (if (string-match " " group)
1433 (insert "Gcc: \"" group "\"\n")
1434 (insert "Gcc: " group "\n"))
eec82323 1435 (widen)))
eec82323 1436 (gnus-inews-do-gcc)
23f87bed
MB
1437 (when (and (get-buffer gnus-group-buffer)
1438 (gnus-buffer-exists-p (car-safe reply))
1439 (cdr reply))
1440 (set-buffer (car reply))
1441 (gnus-summary-mark-article-as-replied (cdr reply)))
1442 (when winconf
1443 (set-window-configuration winconf))))
eec82323
LMI
1444
1445(defun gnus-article-mail (yank)
1446 "Send a reply to the address near point.
1447If YANK is non-nil, include the original article."
1448 (interactive "P")
1449 (let ((address
1450 (buffer-substring
1451 (save-excursion (re-search-backward "[ \t\n]" nil t) (1+ (point)))
1452 (save-excursion (re-search-forward "[ \t\n]" nil t) (1- (point))))))
1453 (when address
23f87bed 1454 (gnus-msg-mail address)
eec82323
LMI
1455 (when yank
1456 (gnus-inews-yank-articles (list (cdr gnus-article-current)))))))
1457
1458(defvar nntp-server-type)
1459(defun gnus-bug ()
1460 "Send a bug report to the Gnus maintainers."
1461 (interactive)
1462 (unless (gnus-alive-p)
1463 (error "Gnus has been shut down"))
88818fbe
SZ
1464 (gnus-setup-message (if (message-mail-user-agent) 'message 'bug)
1465 (unless (message-mail-user-agent)
1466 (delete-other-windows)
1467 (when gnus-bug-create-help-buffer
1468 (switch-to-buffer "*Gnus Help Bug*")
1469 (erase-buffer)
1470 (insert gnus-bug-message)
1471 (goto-char (point-min)))
1472 (message-pop-to-buffer "*Gnus Bug*"))
1473 (let ((message-this-is-mail t))
1474 (message-setup `((To . ,gnus-maintainer) (Subject . ""))))
6748645f
LMI
1475 (when gnus-bug-create-help-buffer
1476 (push `(gnus-bug-kill-buffer) message-send-actions))
eec82323
LMI
1477 (goto-char (point-min))
1478 (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$"))
1479 (forward-line 1)
6748645f
LMI
1480 (insert (gnus-version) "\n"
1481 (emacs-version) "\n")
eec82323
LMI
1482 (when (and (boundp 'nntp-server-type)
1483 (stringp nntp-server-type))
1484 (insert nntp-server-type))
1485 (insert "\n\n\n\n\n")
16409b0b
GM
1486 (let (text)
1487 (save-excursion
1488 (set-buffer (gnus-get-buffer-create " *gnus environment info*"))
23f87bed 1489 (erase-buffer)
16409b0b
GM
1490 (gnus-debug)
1491 (setq text (buffer-string)))
23f87bed 1492 (insert "<#part type=application/emacs-lisp disposition=inline description=\"User settings\">\n" text "\n<#/part>"))
eec82323
LMI
1493 (goto-char (point-min))
1494 (search-forward "Subject: " nil t)
1495 (message "")))
1496
1497(defun gnus-bug-kill-buffer ()
1498 (when (get-buffer "*Gnus Help Bug*")
1499 (kill-buffer "*Gnus Help Bug*")))
1500
16409b0b
GM
1501(defun gnus-summary-yank-message (buffer n)
1502 "Yank the current article into a composed message."
1503 (interactive
1504 (list (completing-read "Buffer: " (mapcar 'list (message-buffers)) nil t)
1505 current-prefix-arg))
1506 (gnus-summary-iterate n
23f87bed 1507 (let ((gnus-inhibit-treatment t))
16409b0b
GM
1508 (gnus-summary-select-article))
1509 (save-excursion
1510 (set-buffer buffer)
1511 (message-yank-buffer gnus-article-buffer))))
1512
eec82323
LMI
1513(defun gnus-debug ()
1514 "Attempts to go through the Gnus source file and report what variables have been changed.
1515The source file has to be in the Emacs load path."
1516 (interactive)
23f87bed 1517 (let ((files gnus-debug-files)
6748645f 1518 (point (point))
eec82323
LMI
1519 file expr olist sym)
1520 (gnus-message 4 "Please wait while we snoop your variables...")
1521 (sit-for 0)
1522 ;; Go through all the files looking for non-default values for variables.
1523 (save-excursion
6748645f 1524 (set-buffer (gnus-get-buffer-create " *gnus bug info*"))
eec82323
LMI
1525 (while files
1526 (erase-buffer)
1527 (when (and (setq file (locate-library (pop files)))
1528 (file-exists-p file))
1529 (insert-file-contents file)
1530 (goto-char (point-min))
1531 (if (not (re-search-forward "^;;* *Internal variables" nil t))
1532 (gnus-message 4 "Malformed sources in file %s" file)
1533 (narrow-to-region (point-min) (point))
1534 (goto-char (point-min))
1535 (while (setq expr (ignore-errors (read (current-buffer))))
1536 (ignore-errors
1537 (and (or (eq (car expr) 'defvar)
1538 (eq (car expr) 'defcustom))
1539 (stringp (nth 3 expr))
23f87bed 1540 (not (memq (nth 1 expr) gnus-debug-exclude-variables))
eec82323
LMI
1541 (or (not (boundp (nth 1 expr)))
1542 (not (equal (eval (nth 2 expr))
1543 (symbol-value (nth 1 expr)))))
1544 (push (nth 1 expr) olist)))))))
1545 (kill-buffer (current-buffer)))
1546 (when (setq olist (nreverse olist))
1547 (insert "------------------ Environment follows ------------------\n\n"))
1548 (while olist
1549 (if (boundp (car olist))
23f87bed
MB
1550 (ignore-errors
1551 (gnus-pp
1552 `(setq ,(car olist)
1553 ,(if (or (consp (setq sym (symbol-value (car olist))))
1554 (and (symbolp sym)
1555 (not (or (eq sym nil)
1556 (eq sym t)))))
1557 (list 'quote (symbol-value (car olist)))
1558 (symbol-value (car olist))))))
eec82323
LMI
1559 (insert ";; (makeunbound '" (symbol-name (car olist)) ")\n"))
1560 (setq olist (cdr olist)))
1561 (insert "\n\n")
6748645f 1562 ;; Remove any control chars - they seem to cause trouble for some
eec82323 1563 ;; mailers. (Byte-compiled output from the stuff above.)
6748645f 1564 (goto-char point)
eb6a2b61 1565 (while (re-search-forward (mm-string-as-multibyte
7c3bb5a5 1566 "[\000-\010\013-\037\200-\237]") nil t)
6748645f
LMI
1567 (replace-match (format "\\%03o" (string-to-char (match-string 0)))
1568 t t))))
eec82323
LMI
1569
1570;;; Treatment of rejected articles.
1571;;; Bounced mail.
1572
1573(defun gnus-summary-resend-bounced-mail (&optional fetch)
1574 "Re-mail the current message.
23f87bed 1575This only makes sense if the current message is a bounce message that
eec82323
LMI
1576contains some mail you have written which has been bounced back to
1577you.
1578If FETCH, try to fetch the article that this is a reply to, if indeed
1579this is a reply."
1580 (interactive "P")
1581 (gnus-summary-select-article t)
2f62a044
MB
1582 (let (summary-buffer parent)
1583 (if fetch
1584 (progn
1585 (setq summary-buffer (current-buffer))
1586 (set-buffer gnus-original-article-buffer)
1587 (article-goto-body)
1588 (when (re-search-forward "^References:\n?" nil t)
1589 (while (memq (char-after) '(?\t ? ))
1590 (forward-line 1))
1591 (skip-chars-backward "\t\n ")
1592 (setq parent
1593 (gnus-parent-id (buffer-substring (match-end 0) (point))))))
1594 (set-buffer gnus-original-article-buffer))
1595 (gnus-setup-message 'compose-bounce
eec82323 1596 (message-bounce)
2f62a044
MB
1597 ;; Add Gcc header.
1598 (gnus-inews-insert-archive-gcc)
1599 (gnus-inews-insert-gcc)
eec82323 1600 ;; If there are references, we fetch the article we answered to.
2f62a044
MB
1601 (when parent
1602 (with-current-buffer summary-buffer
1603 (gnus-summary-refer-article parent)
1604 (gnus-summary-show-all-headers))))))
eec82323
LMI
1605
1606;;; Gcc handling.
1607
0342aa5b 1608(defun gnus-inews-group-method (group)
23f87bed
MB
1609 (cond
1610 ;; If the group doesn't exist, we assume
1611 ;; it's an archive group...
1612 ((and (null (gnus-get-info group))
1613 (eq (car (gnus-server-to-method gnus-message-archive-method))
1614 (car (gnus-server-to-method (gnus-group-method group)))))
1615 gnus-message-archive-method)
1616 ;; Use the method.
1617 ((gnus-info-method (gnus-get-info group))
1618 (gnus-info-method (gnus-get-info group)))
1619 ;; Find the method.
1620 (t (gnus-server-to-method (gnus-group-method group)))))
0342aa5b 1621
eec82323
LMI
1622;; Do Gcc handling, which copied the message over to some group.
1623(defun gnus-inews-do-gcc (&optional gcc)
1624 (interactive)
23f87bed
MB
1625 (save-excursion
1626 (save-restriction
1627 (message-narrow-to-headers)
1628 (let ((gcc (or gcc (mail-fetch-field "gcc" nil t)))
1629 (cur (current-buffer))
1630 groups group method group-art
1631 mml-externalize-attachments)
1632 (when gcc
1633 (message-remove-header "gcc")
1634 (widen)
1635 (setq groups (message-unquote-tokens
1636 (message-tokenize-header gcc " ,")))
1637 ;; Copy the article over to some group(s).
1638 (while (setq group (pop groups))
4d8a28ec
MB
1639 (setq method (gnus-inews-group-method group)
1640 group (mm-encode-coding-string
1641 group
1642 (gnus-group-name-charset method group)))
1643 (unless (gnus-check-server method)
23f87bed
MB
1644 (error "Can't open server %s" (if (stringp method) method
1645 (car method))))
1646 (unless (gnus-request-group group nil method)
1647 (gnus-request-create-group group method))
1648 (setq mml-externalize-attachments
1649 (if (stringp gnus-gcc-externalize-attachments)
1650 (string-match gnus-gcc-externalize-attachments group)
1651 gnus-gcc-externalize-attachments))
1652 (save-excursion
1653 (nnheader-set-temp-buffer " *acc*")
1654 (insert-buffer-substring cur)
1655 (message-encode-message-body)
1656 (save-restriction
1657 (message-narrow-to-headers)
1658 (let* ((mail-parse-charset message-default-charset)
1659 (newsgroups-field (save-restriction
1660 (message-narrow-to-headers-or-head)
1661 (message-fetch-field "Newsgroups")))
1662 (followup-field (save-restriction
1663 (message-narrow-to-headers-or-head)
1664 (message-fetch-field "Followup-To")))
1665 ;; BUG: We really need to get the charset for
1666 ;; each name in the Newsgroups and Followup-To
1667 ;; lines to allow crossposting between group
1668 ;; namess with incompatible character sets.
1669 ;; -- Per Abrahamsen <abraham@dina.kvl.dk> 2001-10-08.
1670 (group-field-charset
1671 (gnus-group-name-charset
1672 method (or newsgroups-field "")))
1673 (followup-field-charset
1674 (gnus-group-name-charset
1675 method (or followup-field "")))
1676 (rfc2047-header-encoding-alist
1677 (append
1678 (when group-field-charset
1679 (list (cons "Newsgroups" group-field-charset)))
1680 (when followup-field-charset
1681 (list (cons "Followup-To" followup-field-charset)))
1682 rfc2047-header-encoding-alist)))
1683 (mail-encode-encoded-word-buffer)))
1684 (goto-char (point-min))
1685 (when (re-search-forward
1686 (concat "^" (regexp-quote mail-header-separator) "$")
1687 nil t)
1688 (replace-match "" t t ))
01c52d31
MB
1689 (when (or (not (gnus-check-backend-function
1690 'request-accept-article group))
1691 (not (setq group-art
1692 (gnus-request-accept-article
1693 group method t t))))
23f87bed 1694 (gnus-message 1 "Couldn't store article in group %s: %s"
01c52d31 1695 group (gnus-status-message method)))
23f87bed
MB
1696 (when (and group-art
1697 ;; FIXME: Should gcc-mark-as-read work when
1698 ;; Gnus is not running?
1699 (gnus-alive-p)
1700 (or gnus-gcc-mark-as-read
1701 (and
1702 (boundp 'gnus-inews-mark-gcc-as-read)
1703 (symbol-value 'gnus-inews-mark-gcc-as-read))))
1704 (gnus-group-mark-article-read group (cdr group-art)))
1705 (kill-buffer (current-buffer)))))))))
eec82323
LMI
1706
1707(defun gnus-inews-insert-gcc ()
1708 "Insert Gcc headers based on `gnus-outgoing-message-group'."
1709 (save-excursion
1710 (save-restriction
1711 (message-narrow-to-headers)
1712 (let* ((group gnus-outgoing-message-group)
1713 (gcc (cond
23f87bed 1714 ((functionp group)
eec82323 1715 (funcall group))
4a2358e9 1716 ((or (stringp group) (listp group))
eec82323
LMI
1717 group))))
1718 (when gcc
1719 (insert "Gcc: "
23f87bed
MB
1720 (if (stringp gcc)
1721 (if (string-match " " gcc)
1722 (concat "\"" gcc "\"")
1723 gcc)
1724 (mapconcat (lambda (group)
1725 (if (string-match " " group)
1726 (concat "\"" group "\"")
1727 group))
1728 gcc " "))
eec82323
LMI
1729 "\n"))))))
1730
1731(defun gnus-inews-insert-archive-gcc (&optional group)
1732 "Insert the Gcc to say where the article is to be archived."
01c52d31
MB
1733 (setq group (cond (group
1734 (gnus-group-decoded-name group))
1735 (gnus-newsgroup-name
1736 (gnus-group-decoded-name gnus-newsgroup-name))
1737 (t
1738 "")))
eec82323 1739 (let* ((var gnus-message-archive-group)
6748645f
LMI
1740 (gcc-self-val
1741 (and gnus-newsgroup-name
16409b0b 1742 (not (equal gnus-newsgroup-name ""))
6748645f
LMI
1743 (gnus-group-find-parameter
1744 gnus-newsgroup-name 'gcc-self)))
16409b0b 1745 result
eec82323
LMI
1746 (groups
1747 (cond
1748 ((null gnus-message-archive-method)
1749 ;; Ignore.
1750 nil)
1751 ((stringp var)
1752 ;; Just a single group.
1753 (list var))
1754 ((null var)
1755 ;; We don't want this.
1756 nil)
1757 ((and (listp var) (stringp (car var)))
1758 ;; A list of groups.
1759 var)
23f87bed 1760 ((functionp var)
eec82323
LMI
1761 ;; A function.
1762 (funcall var group))
1763 (t
1764 ;; An alist of regexps/functions/forms.
1765 (while (and var
1766 (not
1767 (setq result
1768 (cond
1769 ((stringp (caar var))
1770 ;; Regexp.
1771 (when (string-match (caar var) group)
1772 (cdar var)))
23f87bed 1773 ((functionp (car var))
eec82323
LMI
1774 ;; Function.
1775 (funcall (car var) group))
1776 (t
1777 (eval (car var)))))))
1778 (setq var (cdr var)))
1779 result)))
1780 name)
6748645f 1781 (when (or groups gcc-self-val)
eec82323
LMI
1782 (when (stringp groups)
1783 (setq groups (list groups)))
1784 (save-excursion
1785 (save-restriction
1786 (message-narrow-to-headers)
1787 (goto-char (point-max))
1788 (insert "Gcc: ")
6748645f
LMI
1789 (if gcc-self-val
1790 ;; Use the `gcc-self' param value instead.
eec82323
LMI
1791 (progn
1792 (insert
1793 (if (stringp gcc-self-val)
23f87bed
MB
1794 (if (string-match " " gcc-self-val)
1795 (concat "\"" gcc-self-val "\"")
1796 gcc-self-val)
1797 ;; In nndoc groups, we use the parent group name
1798 ;; instead of the current group.
1799 (let ((group (or (gnus-group-find-parameter
1800 gnus-newsgroup-name 'parent-group)
1801 group)))
1802 (if (string-match " " group)
1803 (concat "\"" group "\"")
1804 group))))
eec82323
LMI
1805 (if (not (eq gcc-self-val 'none))
1806 (insert "\n")
23f87bed 1807 (gnus-delete-line)))
6748645f 1808 ;; Use the list of groups.
eec82323 1809 (while (setq name (pop groups))
23f87bed
MB
1810 (let ((str (if (string-match ":" name)
1811 name
1812 (gnus-group-prefixed-name
1813 name gnus-message-archive-method))))
1814 (insert (if (string-match " " str)
1815 (concat "\"" str "\"")
1816 str)))
eec82323
LMI
1817 (when groups
1818 (insert " ")))
1819 (insert "\n")))))))
1820
23f87bed
MB
1821(defun gnus-mailing-list-followup-to ()
1822 "Look at the headers in the current buffer and return a Mail-Followup-To address."
1823 (let ((x-been-there (gnus-fetch-original-field "x-beenthere"))
1824 (list-post (gnus-fetch-original-field "list-post")))
1825 (when (and list-post
1826 (string-match "mailto:\\([^>]+\\)" list-post))
1827 (setq list-post (match-string 1 list-post)))
1828 (or list-post
1829 x-been-there)))
1830
6748645f
LMI
1831;;; Posting styles.
1832
23f87bed 1833(defun gnus-configure-posting-styles (&optional group-name)
6748645f
LMI
1834 "Configure posting styles according to `gnus-posting-styles'."
1835 (unless gnus-inhibit-posting-styles
23f87bed 1836 (let ((group (or group-name gnus-newsgroup-name ""))
16409b0b 1837 (styles gnus-posting-styles)
23f87bed 1838 style match attribute value v results
16409b0b
GM
1839 filep name address element)
1840 ;; If the group has a posting-style parameter, add it at the end with a
1841 ;; regexp matching everything, to be sure it takes precedence over all
1842 ;; the others.
1843 (when gnus-newsgroup-name
1844 (let ((tmp-style (gnus-group-find-parameter group 'posting-style t)))
1845 (when tmp-style
1846 (setq styles (append styles (list (cons ".*" tmp-style)))))))
6748645f 1847 ;; Go through all styles and look for matches.
16409b0b
GM
1848 (dolist (style styles)
1849 (setq match (pop style))
1850 (goto-char (point-min))
1851 (when (cond
1852 ((stringp match)
1853 ;; Regexp string match on the group name.
1854 (string-match match group))
1855 ((eq match 'header)
23f87bed
MB
1856 ;; Obsolete format of header match.
1857 (and (gnus-buffer-live-p gnus-article-copy)
1858 (with-current-buffer gnus-article-copy
9b5773bc
MB
1859 (save-restriction
1860 (nnheader-narrow-to-headers)
1861 (let ((header (message-fetch-field (pop style))))
1862 (and header
1863 (string-match (pop style) header)))))))
16409b0b 1864 ((or (symbolp match)
23f87bed 1865 (functionp match))
16409b0b 1866 (cond
23f87bed 1867 ((functionp match)
16409b0b
GM
1868 ;; Function to be called.
1869 (funcall match))
1870 ((boundp match)
1871 ;; Variable to be checked.
1872 (symbol-value match))))
1873 ((listp match)
23f87bed
MB
1874 (cond
1875 ((eq (car match) 'header)
1876 ;; New format of header match.
1877 (and (gnus-buffer-live-p gnus-article-copy)
1878 (with-current-buffer gnus-article-copy
9b5773bc
MB
1879 (save-restriction
1880 (nnheader-narrow-to-headers)
1881 (let ((header (message-fetch-field (nth 1 match))))
1882 (and header
1883 (string-match (nth 2 match) header)))))))
23f87bed
MB
1884 (t
1885 ;; This is a form to be evaled.
1886 (eval match)))))
6748645f 1887 ;; We have a match, so we set the variables.
16409b0b
GM
1888 (dolist (attribute style)
1889 (setq element (pop attribute)
16409b0b
GM
1890 filep nil)
1891 (setq value
1892 (cond
1893 ((eq (car attribute) :file)
1894 (setq filep t)
1895 (cadr attribute))
1896 ((eq (car attribute) :value)
1897 (cadr attribute))
1898 (t
1899 (car attribute))))
1900 ;; We get the value.
1901 (setq v
1902 (cond
1903 ((stringp value)
1904 value)
1905 ((or (symbolp value)
23f87bed
MB
1906 (functionp value))
1907 (cond ((functionp value)
16409b0b
GM
1908 (funcall value))
1909 ((boundp value)
1910 (symbol-value value))))
1911 ((listp value)
1912 (eval value))))
1913 ;; Translate obsolescent value.
23f87bed
MB
1914 (cond
1915 ((eq element 'signature-file)
16409b0b
GM
1916 (setq element 'signature
1917 filep t))
23f87bed
MB
1918 ((eq element 'x-face-file)
1919 (setq element 'x-face
1920 filep t)))
01c52d31
MB
1921 ;; Post-processing for the signature posting-style:
1922 (and (eq element 'signature) filep
1923 message-signature-directory
1924 ;; don't actually use the signature directory
1925 ;; if message-signature-file contains a path.
1926 (not (file-name-directory v))
1927 (setq v (nnheader-concat message-signature-directory v)))
16409b0b
GM
1928 ;; Get the contents of file elems.
1929 (when (and filep v)
1930 (setq v (with-temp-buffer
1931 (insert-file-contents v)
5f49be3f
MB
1932 (buffer-substring
1933 (point-min)
1934 (progn
1935 (goto-char (point-max))
1936 (if (zerop (skip-chars-backward "\n"))
1937 (point)
1938 (1+ (point))))))))
16409b0b
GM
1939 (setq results (delq (assoc element results) results))
1940 (push (cons element v) results))))
1941 ;; Now we have all the styles, so we insert them.
1942 (setq name (assq 'name results)
1943 address (assq 'address results))
1944 (setq results (delq name (delq address results)))
23f87bed
MB
1945 (gnus-make-local-hook 'message-setup-hook)
1946 (setq results (sort results (lambda (x y)
1947 (string-lessp (car x) (car y)))))
16409b0b
GM
1948 (dolist (result results)
1949 (add-hook 'message-setup-hook
1950 (cond
1951 ((eq 'eval (car result))
1952 'ignore)
1953 ((eq 'body (car result))
1954 `(lambda ()
1955 (save-excursion
1956 (message-goto-body)
1957 (insert ,(cdr result)))))
1958 ((eq 'signature (car result))
1959 (set (make-local-variable 'message-signature) nil)
1960 (set (make-local-variable 'message-signature-file) nil)
1961 (if (not (cdr result))
1962 'ignore
1963 `(lambda ()
1964 (save-excursion
1965 (let ((message-signature ,(cdr result)))
1966 (when message-signature
1967 (message-insert-signature)))))))
1968 (t
1969 (let ((header
1970 (if (symbolp (car result))
1971 (capitalize (symbol-name (car result)))
1972 (car result))))
1973 `(lambda ()
1974 (save-excursion
1975 (message-remove-header ,header)
1976 (let ((value ,(cdr result)))
1977 (when value
1978 (message-goto-eoh)
23f87bed
MB
1979 (insert ,header ": " value)
1980 (unless (bolp)
1981 (insert "\n")))))))))
1982 nil 'local))
16409b0b
GM
1983 (when (or name address)
1984 (add-hook 'message-setup-hook
1985 `(lambda ()
23f87bed
MB
1986 (set (make-local-variable 'user-mail-address)
1987 ,(or (cdr address) user-mail-address))
16409b0b
GM
1988 (let ((user-full-name ,(or (cdr name) (user-full-name)))
1989 (user-mail-address
1990 ,(or (cdr address) user-mail-address)))
1991 (save-excursion
1992 (message-remove-header "From")
1993 (message-goto-eoh)
23f87bed
MB
1994 (insert "From: " (message-make-from) "\n"))))
1995 nil 'local)))))
eec82323
LMI
1996
1997;;; Allow redefinition of functions.
1998
1999(gnus-ems-redefine)
2000
2001(provide 'gnus-msg)
2002
ab5796a9 2003;;; arch-tag: 9f22b2f5-1c0a-49de-916e-4c88e984852b
eec82323 2004;;; gnus-msg.el ends here