gnus-msg.el 66 KB

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