| 1 | ;;; gnus-msg.el --- mail and post interface for Gnus |
| 2 | ;; Copyright (C) 1995,96,97 Free Software Foundation, Inc. |
| 3 | |
| 4 | ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet> |
| 5 | ;; Lars Magne Ingebrigtsen <larsi@ifi.uio.no> |
| 6 | ;; Keywords: news |
| 7 | |
| 8 | ;; This file is part of GNU Emacs. |
| 9 | |
| 10 | ;; GNU Emacs is free software; you can redistribute it and/or modify |
| 11 | ;; it under the terms of the GNU General Public License as published by |
| 12 | ;; the Free Software Foundation; either version 2, or (at your option) |
| 13 | ;; any later version. |
| 14 | |
| 15 | ;; GNU Emacs is distributed in the hope that it will be useful, |
| 16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 18 | ;; GNU General Public License for more details. |
| 19 | |
| 20 | ;; You should have received a copy of the GNU General Public License |
| 21 | ;; along with GNU Emacs; see the file COPYING. If not, write to the |
| 22 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| 23 | ;; Boston, MA 02111-1307, USA. |
| 24 | |
| 25 | ;;; Commentary: |
| 26 | |
| 27 | ;;; Code: |
| 28 | |
| 29 | (require 'gnus) |
| 30 | (require 'gnus-ems) |
| 31 | (require 'message) |
| 32 | (require 'gnus-art) |
| 33 | |
| 34 | ;; Added by Sudish Joseph <joseph@cis.ohio-state.edu>. |
| 35 | (defvar gnus-post-method nil |
| 36 | "*Preferred method for posting USENET news. |
| 37 | If this variable is nil, Gnus will use the current method to decide |
| 38 | which method to use when posting. If it is non-nil, it will override |
| 39 | the current method. This method will not be used in mail groups and |
| 40 | the like, only in \"real\" newsgroups. |
| 41 | |
| 42 | The value must be a valid method as discussed in the documentation of |
| 43 | `gnus-select-method'. It can also be a list of methods. If that is |
| 44 | the case, the user will be queried for what select method to use when |
| 45 | posting.") |
| 46 | |
| 47 | (defvar gnus-outgoing-message-group nil |
| 48 | "*All outgoing messages will be put in this group. |
| 49 | If you want to store all your outgoing mail and articles in the group |
| 50 | \"nnml:archive\", you set this variable to that value. This variable |
| 51 | can also be a list of group names. |
| 52 | |
| 53 | If you want to have greater control over what group to put each |
| 54 | message in, you can set this variable to a function that checks the |
| 55 | current newsgroup name and then returns a suitable group name (or list |
| 56 | of names).") |
| 57 | |
| 58 | (defvar gnus-mailing-list-groups nil |
| 59 | "*Regexp matching groups that are really mailing lists. |
| 60 | This is useful when you're reading a mailing list that has been |
| 61 | gatewayed to a newsgroup, and you want to followup to an article in |
| 62 | the group.") |
| 63 | |
| 64 | (defvar gnus-add-to-list nil |
| 65 | "*If non-nil, add a `to-list' parameter automatically.") |
| 66 | |
| 67 | (defvar gnus-sent-message-ids-file |
| 68 | (nnheader-concat gnus-directory "Sent-Message-IDs") |
| 69 | "File where Gnus saves a cache of sent message ids.") |
| 70 | |
| 71 | (defvar gnus-sent-message-ids-length 1000 |
| 72 | "The number of sent Message-IDs to save.") |
| 73 | |
| 74 | (defvar gnus-crosspost-complaint |
| 75 | "Hi, |
| 76 | |
| 77 | You posted the article below with the following Newsgroups header: |
| 78 | |
| 79 | Newsgroups: %s |
| 80 | |
| 81 | The %s group, at least, was an inappropriate recipient |
| 82 | of this message. Please trim your Newsgroups header to exclude this |
| 83 | group before posting in the future. |
| 84 | |
| 85 | Thank you. |
| 86 | |
| 87 | " |
| 88 | "Format string to be inserted when complaining about crossposts. |
| 89 | The first %s will be replaced by the Newsgroups header; |
| 90 | the second with the current group name.") |
| 91 | |
| 92 | (defvar gnus-message-setup-hook nil |
| 93 | "Hook run after setting up a message buffer.") |
| 94 | |
| 95 | ;;; Internal variables. |
| 96 | |
| 97 | (defvar gnus-message-buffer "*Mail Gnus*") |
| 98 | (defvar gnus-article-copy nil) |
| 99 | (defvar gnus-last-posting-server nil) |
| 100 | |
| 101 | (defconst gnus-bug-message |
| 102 | "Sending a bug report to the Gnus Towers. |
| 103 | ======================================== |
| 104 | |
| 105 | The buffer below is a mail buffer. When you press `C-c C-c', it will |
| 106 | be sent to the Gnus Bug Exterminators. |
| 107 | |
| 108 | At the bottom of the buffer you'll see lots of variable settings. |
| 109 | Please do not delete those. They will tell the Bug People what your |
| 110 | environment is, so that it will be easier to locate the bugs. |
| 111 | |
| 112 | If you have found a bug that makes Emacs go \"beep\", set |
| 113 | debug-on-error to t (`M-x set-variable RET debug-on-error RET t RET') |
| 114 | and include the backtrace in your bug report. |
| 115 | |
| 116 | Please describe the bug in annoying, painstaking detail. |
| 117 | |
| 118 | Thank you for your help in stamping out bugs. |
| 119 | ") |
| 120 | |
| 121 | (eval-and-compile |
| 122 | (autoload 'gnus-uu-post-news "gnus-uu" nil t) |
| 123 | (autoload 'news-setup "rnewspost") |
| 124 | (autoload 'news-reply-mode "rnewspost") |
| 125 | (autoload 'rmail-dont-reply-to "mail-utils") |
| 126 | (autoload 'rmail-output "rmailout")) |
| 127 | |
| 128 | \f |
| 129 | ;;; |
| 130 | ;;; Gnus Posting Functions |
| 131 | ;;; |
| 132 | |
| 133 | (gnus-define-keys (gnus-summary-send-map "S" gnus-summary-mode-map) |
| 134 | "p" gnus-summary-post-news |
| 135 | "f" gnus-summary-followup |
| 136 | "F" gnus-summary-followup-with-original |
| 137 | "c" gnus-summary-cancel-article |
| 138 | "s" gnus-summary-supersede-article |
| 139 | "r" gnus-summary-reply |
| 140 | "R" gnus-summary-reply-with-original |
| 141 | "w" gnus-summary-wide-reply |
| 142 | "W" gnus-summary-wide-reply-with-original |
| 143 | "n" gnus-summary-followup-to-mail |
| 144 | "N" gnus-summary-followup-to-mail-with-original |
| 145 | "m" gnus-summary-mail-other-window |
| 146 | "u" gnus-uu-post-news |
| 147 | "\M-c" gnus-summary-mail-crosspost-complaint |
| 148 | "om" gnus-summary-mail-forward |
| 149 | "op" gnus-summary-post-forward |
| 150 | "Om" gnus-uu-digest-mail-forward |
| 151 | "Op" gnus-uu-digest-post-forward) |
| 152 | |
| 153 | (gnus-define-keys (gnus-send-bounce-map "D" gnus-summary-send-map) |
| 154 | "b" gnus-summary-resend-bounced-mail |
| 155 | ;; "c" gnus-summary-send-draft |
| 156 | "r" gnus-summary-resend-message) |
| 157 | |
| 158 | ;;; Internal functions. |
| 159 | |
| 160 | (defvar gnus-article-reply nil) |
| 161 | (defmacro gnus-setup-message (config &rest forms) |
| 162 | (let ((winconf (make-symbol "winconf")) |
| 163 | (buffer (make-symbol "buffer")) |
| 164 | (article (make-symbol "article"))) |
| 165 | `(let ((,winconf (current-window-configuration)) |
| 166 | (,buffer (buffer-name (current-buffer))) |
| 167 | (,article (and gnus-article-reply (gnus-summary-article-number))) |
| 168 | (message-header-setup-hook |
| 169 | (copy-sequence message-header-setup-hook))) |
| 170 | (add-hook 'message-header-setup-hook 'gnus-inews-insert-gcc) |
| 171 | (add-hook 'message-header-setup-hook 'gnus-inews-insert-archive-gcc) |
| 172 | (unwind-protect |
| 173 | ,@forms |
| 174 | (gnus-inews-add-send-actions ,winconf ,buffer ,article) |
| 175 | (setq gnus-message-buffer (current-buffer)) |
| 176 | (make-local-variable 'gnus-newsgroup-name) |
| 177 | (run-hooks 'gnus-message-setup-hook)) |
| 178 | (gnus-configure-windows ,config t) |
| 179 | (set-buffer-modified-p nil)))) |
| 180 | |
| 181 | (defun gnus-inews-add-send-actions (winconf buffer article) |
| 182 | (make-local-hook 'message-sent-hook) |
| 183 | (add-hook 'message-sent-hook 'gnus-inews-do-gcc nil t) |
| 184 | (setq message-post-method |
| 185 | `(lambda (arg) |
| 186 | (gnus-post-method arg ,gnus-newsgroup-name))) |
| 187 | (setq message-newsreader (setq message-mailer (gnus-extended-version))) |
| 188 | (message-add-action |
| 189 | `(set-window-configuration ,winconf) 'exit 'postpone 'kill) |
| 190 | (message-add-action |
| 191 | `(when (buffer-name (get-buffer ,buffer)) |
| 192 | (save-excursion |
| 193 | (set-buffer (get-buffer ,buffer)) |
| 194 | ,(when article |
| 195 | `(gnus-summary-mark-article-as-replied ,article)))) |
| 196 | 'send)) |
| 197 | |
| 198 | (put 'gnus-setup-message 'lisp-indent-function 1) |
| 199 | (put 'gnus-setup-message 'edebug-form-spec '(form body)) |
| 200 | |
| 201 | ;;; Post news commands of Gnus group mode and summary mode |
| 202 | |
| 203 | (defun gnus-group-mail () |
| 204 | "Start composing a mail." |
| 205 | (interactive) |
| 206 | (gnus-setup-message 'message |
| 207 | (message-mail))) |
| 208 | |
| 209 | (defun gnus-group-post-news (&optional arg) |
| 210 | "Start composing a news message. |
| 211 | If ARG, post to the group under point. |
| 212 | If ARG is 1, prompt for a group name." |
| 213 | (interactive "P") |
| 214 | ;; Bind this variable here to make message mode hooks |
| 215 | ;; work ok. |
| 216 | (let ((gnus-newsgroup-name |
| 217 | (if arg |
| 218 | (if (= 1 (prefix-numeric-value arg)) |
| 219 | (completing-read "Newsgroup: " gnus-active-hashtb nil |
| 220 | (gnus-read-active-file-p)) |
| 221 | (gnus-group-group-name)) |
| 222 | ""))) |
| 223 | (gnus-post-news 'post gnus-newsgroup-name))) |
| 224 | |
| 225 | (defun gnus-summary-post-news () |
| 226 | "Start composing a news message." |
| 227 | (interactive) |
| 228 | (gnus-set-global-variables) |
| 229 | (gnus-post-news 'post gnus-newsgroup-name)) |
| 230 | |
| 231 | (defun gnus-summary-followup (yank &optional force-news) |
| 232 | "Compose a followup to an article. |
| 233 | If prefix argument YANK is non-nil, original article is yanked automatically." |
| 234 | (interactive |
| 235 | (list (and current-prefix-arg |
| 236 | (gnus-summary-work-articles 1)))) |
| 237 | (gnus-set-global-variables) |
| 238 | (when yank |
| 239 | (gnus-summary-goto-subject (car yank))) |
| 240 | (save-window-excursion |
| 241 | (gnus-summary-select-article)) |
| 242 | (let ((headers (gnus-summary-article-header (gnus-summary-article-number))) |
| 243 | (gnus-newsgroup-name gnus-newsgroup-name)) |
| 244 | ;; Send a followup. |
| 245 | (gnus-post-news nil gnus-newsgroup-name |
| 246 | headers gnus-article-buffer |
| 247 | yank nil force-news))) |
| 248 | |
| 249 | (defun gnus-summary-followup-with-original (n &optional force-news) |
| 250 | "Compose a followup to an article and include the original article." |
| 251 | (interactive "P") |
| 252 | (gnus-summary-followup (gnus-summary-work-articles n) force-news)) |
| 253 | |
| 254 | (defun gnus-summary-followup-to-mail (&optional arg) |
| 255 | "Followup to the current mail message via news." |
| 256 | (interactive |
| 257 | (list (and current-prefix-arg |
| 258 | (gnus-summary-work-articles 1)))) |
| 259 | (gnus-summary-followup arg t)) |
| 260 | |
| 261 | (defun gnus-summary-followup-to-mail-with-original (&optional arg) |
| 262 | "Followup to the current mail message via news." |
| 263 | (interactive "P") |
| 264 | (gnus-summary-followup (gnus-summary-work-articles arg) t)) |
| 265 | |
| 266 | (defun gnus-inews-yank-articles (articles) |
| 267 | (let (beg article) |
| 268 | (message-goto-body) |
| 269 | (while (setq article (pop articles)) |
| 270 | (save-window-excursion |
| 271 | (set-buffer gnus-summary-buffer) |
| 272 | (gnus-summary-select-article nil nil nil article) |
| 273 | (gnus-summary-remove-process-mark article)) |
| 274 | (gnus-copy-article-buffer) |
| 275 | (let ((message-reply-buffer gnus-article-copy) |
| 276 | (message-reply-headers gnus-current-headers)) |
| 277 | (message-yank-original) |
| 278 | (setq beg (or beg (mark t)))) |
| 279 | (when articles |
| 280 | (insert "\n"))) |
| 281 | (push-mark) |
| 282 | (goto-char beg))) |
| 283 | |
| 284 | (defun gnus-summary-cancel-article (n) |
| 285 | "Cancel an article you posted." |
| 286 | (interactive "P") |
| 287 | (gnus-set-global-variables) |
| 288 | (let ((articles (gnus-summary-work-articles n)) |
| 289 | (message-post-method |
| 290 | `(lambda (arg) |
| 291 | (gnus-post-method nil ,gnus-newsgroup-name))) |
| 292 | article) |
| 293 | (while (setq article (pop articles)) |
| 294 | (when (gnus-summary-select-article t nil nil article) |
| 295 | (when (gnus-eval-in-buffer-window gnus-original-article-buffer |
| 296 | (message-cancel-news)) |
| 297 | (gnus-summary-mark-as-read article gnus-canceled-mark) |
| 298 | (gnus-cache-remove-article 1)) |
| 299 | (gnus-article-hide-headers-if-wanted)) |
| 300 | (gnus-summary-remove-process-mark article)))) |
| 301 | |
| 302 | (defun gnus-summary-supersede-article () |
| 303 | "Compose an article that will supersede a previous article. |
| 304 | This is done simply by taking the old article and adding a Supersedes |
| 305 | header line with the old Message-ID." |
| 306 | (interactive) |
| 307 | (gnus-set-global-variables) |
| 308 | (let ((article (gnus-summary-article-number))) |
| 309 | (gnus-setup-message 'reply-yank |
| 310 | (gnus-summary-select-article t) |
| 311 | (set-buffer gnus-original-article-buffer) |
| 312 | (message-supersede) |
| 313 | (push |
| 314 | `((lambda () |
| 315 | (when (buffer-name (get-buffer ,gnus-summary-buffer)) |
| 316 | (save-excursion |
| 317 | (set-buffer (get-buffer ,gnus-summary-buffer)) |
| 318 | (gnus-cache-possibly-remove-article ,article nil nil nil t) |
| 319 | (gnus-summary-mark-as-read ,article gnus-canceled-mark))))) |
| 320 | message-send-actions)))) |
| 321 | |
| 322 | \f |
| 323 | |
| 324 | (defun gnus-copy-article-buffer (&optional article-buffer) |
| 325 | ;; make a copy of the article buffer with all text properties removed |
| 326 | ;; this copy is in the buffer gnus-article-copy. |
| 327 | ;; if ARTICLE-BUFFER is nil, gnus-article-buffer is used |
| 328 | ;; this buffer should be passed to all mail/news reply/post routines. |
| 329 | (setq gnus-article-copy (get-buffer-create " *gnus article copy*")) |
| 330 | (buffer-disable-undo gnus-article-copy) |
| 331 | (or (memq gnus-article-copy gnus-buffer-list) |
| 332 | (push gnus-article-copy gnus-buffer-list)) |
| 333 | (let ((article-buffer (or article-buffer gnus-article-buffer)) |
| 334 | end beg contents) |
| 335 | (if (not (and (get-buffer article-buffer) |
| 336 | (buffer-name (get-buffer article-buffer)))) |
| 337 | (error "Can't find any article buffer") |
| 338 | (save-excursion |
| 339 | (set-buffer article-buffer) |
| 340 | (save-restriction |
| 341 | ;; Copy over the (displayed) article buffer, delete |
| 342 | ;; hidden text and remove text properties. |
| 343 | (widen) |
| 344 | (copy-to-buffer gnus-article-copy (point-min) (point-max)) |
| 345 | (set-buffer gnus-article-copy) |
| 346 | (gnus-article-delete-text-of-type 'annotation) |
| 347 | (gnus-remove-text-with-property 'gnus-prev) |
| 348 | (gnus-remove-text-with-property 'gnus-next) |
| 349 | (insert |
| 350 | (prog1 |
| 351 | (format "%s" (buffer-string)) |
| 352 | (erase-buffer))) |
| 353 | ;; Find the original headers. |
| 354 | (set-buffer gnus-original-article-buffer) |
| 355 | (goto-char (point-min)) |
| 356 | (while (looking-at message-unix-mail-delimiter) |
| 357 | (forward-line 1)) |
| 358 | (setq beg (point)) |
| 359 | (setq end (or (search-forward "\n\n" nil t) (point))) |
| 360 | ;; Delete the headers from the displayed articles. |
| 361 | (set-buffer gnus-article-copy) |
| 362 | (delete-region (goto-char (point-min)) |
| 363 | (or (search-forward "\n\n" nil t) (point))) |
| 364 | ;; Insert the original article headers. |
| 365 | (insert-buffer-substring gnus-original-article-buffer beg end) |
| 366 | (gnus-article-decode-rfc1522))) |
| 367 | gnus-article-copy))) |
| 368 | |
| 369 | (defun gnus-post-news (post &optional group header article-buffer yank subject |
| 370 | force-news) |
| 371 | (when article-buffer |
| 372 | (gnus-copy-article-buffer)) |
| 373 | (let ((gnus-article-reply article-buffer) |
| 374 | (add-to-list gnus-add-to-list)) |
| 375 | (gnus-setup-message (cond (yank 'reply-yank) |
| 376 | (article-buffer 'reply) |
| 377 | (t 'message)) |
| 378 | (let* ((group (or group gnus-newsgroup-name)) |
| 379 | (pgroup group) |
| 380 | to-address to-group mailing-list to-list |
| 381 | newsgroup-p) |
| 382 | (when group |
| 383 | (setq to-address (gnus-group-find-parameter group 'to-address) |
| 384 | to-group (gnus-group-find-parameter group 'to-group) |
| 385 | to-list (gnus-group-find-parameter group 'to-list) |
| 386 | newsgroup-p (gnus-group-find-parameter group 'newsgroup) |
| 387 | mailing-list (when gnus-mailing-list-groups |
| 388 | (string-match gnus-mailing-list-groups group)) |
| 389 | group (gnus-group-real-name group))) |
| 390 | (if (or (and to-group |
| 391 | (gnus-news-group-p to-group)) |
| 392 | newsgroup-p |
| 393 | force-news |
| 394 | (and (gnus-news-group-p |
| 395 | (or pgroup gnus-newsgroup-name) |
| 396 | (if header (mail-header-number header) |
| 397 | gnus-current-article)) |
| 398 | (not mailing-list) |
| 399 | (not to-list) |
| 400 | (not to-address))) |
| 401 | ;; This is news. |
| 402 | (if post |
| 403 | (message-news (or to-group group)) |
| 404 | (set-buffer gnus-article-copy) |
| 405 | (message-followup (if (or newsgroup-p force-news) nil to-group))) |
| 406 | ;; The is mail. |
| 407 | (if post |
| 408 | (progn |
| 409 | (message-mail (or to-address to-list)) |
| 410 | ;; Arrange for mail groups that have no `to-address' to |
| 411 | ;; get that when the user sends off the mail. |
| 412 | (when (and (not to-list) |
| 413 | (not to-address) |
| 414 | add-to-list) |
| 415 | (push (list 'gnus-inews-add-to-address pgroup) |
| 416 | message-send-actions))) |
| 417 | (set-buffer gnus-article-copy) |
| 418 | (message-wide-reply to-address |
| 419 | (gnus-group-find-parameter |
| 420 | gnus-newsgroup-name 'broken-reply-to)))) |
| 421 | (when yank |
| 422 | (gnus-inews-yank-articles yank)))))) |
| 423 | |
| 424 | (defun gnus-post-method (arg group &optional silent) |
| 425 | "Return the posting method based on GROUP and ARG. |
| 426 | If SILENT, don't prompt the user." |
| 427 | (let ((group-method (gnus-find-method-for-group group))) |
| 428 | (cond |
| 429 | ;; If the group-method is nil (which shouldn't happen) we use |
| 430 | ;; the default method. |
| 431 | ((null group-method) |
| 432 | (or gnus-post-method gnus-select-method message-post-method)) |
| 433 | ;; We want this group's method. |
| 434 | ((and arg (not (eq arg 0))) |
| 435 | group-method) |
| 436 | ;; We query the user for a post method. |
| 437 | ((or arg |
| 438 | (and gnus-post-method |
| 439 | (listp (car gnus-post-method)))) |
| 440 | (let* ((methods |
| 441 | ;; Collect all methods we know about. |
| 442 | (append |
| 443 | (when gnus-post-method |
| 444 | (if (listp (car gnus-post-method)) |
| 445 | gnus-post-method |
| 446 | (list gnus-post-method))) |
| 447 | gnus-secondary-select-methods |
| 448 | (list gnus-select-method) |
| 449 | (list group-method))) |
| 450 | method-alist post-methods method) |
| 451 | ;; Weed out all mail methods. |
| 452 | (while methods |
| 453 | (setq method (gnus-server-get-method "" (pop methods))) |
| 454 | (when (or (gnus-method-option-p method 'post) |
| 455 | (gnus-method-option-p method 'post-mail)) |
| 456 | (push method post-methods))) |
| 457 | ;; Create a name-method alist. |
| 458 | (setq method-alist |
| 459 | (mapcar |
| 460 | (lambda (m) |
| 461 | (list (concat (cadr m) " (" (symbol-name (car m)) ")") m)) |
| 462 | post-methods)) |
| 463 | ;; Query the user. |
| 464 | (cadr |
| 465 | (assoc |
| 466 | (setq gnus-last-posting-server |
| 467 | (if (and silent |
| 468 | gnus-last-posting-server) |
| 469 | ;; Just use the last value. |
| 470 | gnus-last-posting-server |
| 471 | (completing-read |
| 472 | "Posting method: " method-alist nil t |
| 473 | (cons (or gnus-last-posting-server "") 0)))) |
| 474 | method-alist)))) |
| 475 | ;; Override normal method. |
| 476 | (gnus-post-method |
| 477 | gnus-post-method) |
| 478 | ;; Use the normal select method. |
| 479 | (t gnus-select-method)))) |
| 480 | |
| 481 | ;;; |
| 482 | ;;; Check whether the message has been sent already. |
| 483 | ;;; |
| 484 | |
| 485 | (defvar gnus-inews-sent-ids nil) |
| 486 | |
| 487 | (defun gnus-inews-reject-message () |
| 488 | "Check whether this message has already been sent." |
| 489 | (when gnus-sent-message-ids-file |
| 490 | (let ((message-id (save-restriction (message-narrow-to-headers) |
| 491 | (mail-fetch-field "message-id"))) |
| 492 | end) |
| 493 | (when message-id |
| 494 | (unless gnus-inews-sent-ids |
| 495 | (ignore-errors |
| 496 | (load t t t))) |
| 497 | (if (member message-id gnus-inews-sent-ids) |
| 498 | ;; Reject this message. |
| 499 | (not (gnus-yes-or-no-p |
| 500 | (format "Message %s already sent. Send anyway? " |
| 501 | message-id))) |
| 502 | (push message-id gnus-inews-sent-ids) |
| 503 | ;; Chop off the last Message-IDs. |
| 504 | (when (setq end (nthcdr gnus-sent-message-ids-length |
| 505 | gnus-inews-sent-ids)) |
| 506 | (setcdr end nil)) |
| 507 | (nnheader-temp-write gnus-sent-message-ids-file |
| 508 | (gnus-prin1 `(setq gnus-inews-sent-ids ',gnus-inews-sent-ids))) |
| 509 | nil))))) |
| 510 | |
| 511 | \f |
| 512 | |
| 513 | ;; Dummy to avoid byte-compile warning. |
| 514 | (defvar nnspool-rejected-article-hook) |
| 515 | |
| 516 | ;;; Since the X-Newsreader/X-Mailer are ``vanity'' headers, they might |
| 517 | ;;; as well include the Emacs version as well. |
| 518 | ;;; The following function works with later GNU Emacs, and XEmacs. |
| 519 | (defun gnus-extended-version () |
| 520 | "Stringified Gnus version and Emacs version" |
| 521 | (interactive) |
| 522 | (concat |
| 523 | gnus-version |
| 524 | "/" |
| 525 | (cond |
| 526 | ((string-match "^\\([0-9]+\\.[0-9]+\\)\\.[.0-9]+$" emacs-version) |
| 527 | (concat "Emacs " (substring emacs-version |
| 528 | (match-beginning 1) |
| 529 | (match-end 1)))) |
| 530 | ((string-match "\\([A-Z]*[Mm][Aa][Cc][Ss]\\)[^(]*\\(\\((beta.*)\\|'\\)\\)?" |
| 531 | emacs-version) |
| 532 | (concat (substring emacs-version |
| 533 | (match-beginning 1) |
| 534 | (match-end 1)) |
| 535 | (format " %d.%d" emacs-major-version emacs-minor-version) |
| 536 | (if (match-beginning 3) |
| 537 | (substring emacs-version |
| 538 | (match-beginning 3) |
| 539 | (match-end 3)) |
| 540 | ""))) |
| 541 | (t emacs-version)))) |
| 542 | |
| 543 | ;; Written by "Mr. Per Persson" <pp@gnu.ai.mit.edu>. |
| 544 | (defun gnus-inews-insert-mime-headers () |
| 545 | (goto-char (point-min)) |
| 546 | (let ((mail-header-separator |
| 547 | (progn |
| 548 | (goto-char (point-min)) |
| 549 | (if (and (search-forward (concat "\n" mail-header-separator "\n") |
| 550 | nil t) |
| 551 | (not (search-backward "\n\n" nil t))) |
| 552 | mail-header-separator |
| 553 | "")))) |
| 554 | (or (mail-position-on-field "Mime-Version") |
| 555 | (insert "1.0") |
| 556 | (cond ((save-restriction |
| 557 | (widen) |
| 558 | (goto-char (point-min)) |
| 559 | (re-search-forward "[\200-\377]" nil t)) |
| 560 | (or (mail-position-on-field "Content-Type") |
| 561 | (insert "text/plain; charset=ISO-8859-1")) |
| 562 | (or (mail-position-on-field "Content-Transfer-Encoding") |
| 563 | (insert "8bit"))) |
| 564 | (t (or (mail-position-on-field "Content-Type") |
| 565 | (insert "text/plain; charset=US-ASCII")) |
| 566 | (or (mail-position-on-field "Content-Transfer-Encoding") |
| 567 | (insert "7bit"))))))) |
| 568 | |
| 569 | \f |
| 570 | ;;; |
| 571 | ;;; Gnus Mail Functions |
| 572 | ;;; |
| 573 | |
| 574 | ;;; Mail reply commands of Gnus summary mode |
| 575 | |
| 576 | (defun gnus-summary-reply (&optional yank wide) |
| 577 | "Start composing a reply mail to the current message. |
| 578 | If prefix argument YANK is non-nil, the original article is yanked |
| 579 | automatically." |
| 580 | (interactive |
| 581 | (list (and current-prefix-arg |
| 582 | (gnus-summary-work-articles 1)))) |
| 583 | ;; Stripping headers should be specified with mail-yank-ignored-headers. |
| 584 | (gnus-set-global-variables) |
| 585 | (when yank |
| 586 | (gnus-summary-goto-subject (car yank))) |
| 587 | (let ((gnus-article-reply t)) |
| 588 | (gnus-setup-message (if yank 'reply-yank 'reply) |
| 589 | (gnus-summary-select-article) |
| 590 | (set-buffer (gnus-copy-article-buffer)) |
| 591 | (message-reply nil wide (gnus-group-find-parameter |
| 592 | gnus-newsgroup-name 'broken-reply-to)) |
| 593 | (when yank |
| 594 | (gnus-inews-yank-articles yank))))) |
| 595 | |
| 596 | (defun gnus-summary-reply-with-original (n &optional wide) |
| 597 | "Start composing a reply mail to the current message. |
| 598 | The original article will be yanked." |
| 599 | (interactive "P") |
| 600 | (gnus-summary-reply (gnus-summary-work-articles n) wide)) |
| 601 | |
| 602 | (defun gnus-summary-wide-reply (&optional yank) |
| 603 | "Start composing a wide reply mail to the current message. |
| 604 | If prefix argument YANK is non-nil, the original article is yanked |
| 605 | automatically." |
| 606 | (interactive |
| 607 | (list (and current-prefix-arg |
| 608 | (gnus-summary-work-articles 1)))) |
| 609 | (gnus-summary-reply yank t)) |
| 610 | |
| 611 | (defun gnus-summary-wide-reply-with-original (n) |
| 612 | "Start composing a wide reply mail to the current message. |
| 613 | The original article will be yanked." |
| 614 | (interactive "P") |
| 615 | (gnus-summary-reply-with-original n t)) |
| 616 | |
| 617 | (defun gnus-summary-mail-forward (&optional full-headers post) |
| 618 | "Forward the current message to another user. |
| 619 | If FULL-HEADERS (the prefix), include full headers when forwarding." |
| 620 | (interactive "P") |
| 621 | (gnus-set-global-variables) |
| 622 | (gnus-setup-message 'forward |
| 623 | (gnus-summary-select-article) |
| 624 | (set-buffer gnus-original-article-buffer) |
| 625 | (let ((message-included-forward-headers |
| 626 | (if full-headers "" message-included-forward-headers))) |
| 627 | (message-forward post)))) |
| 628 | |
| 629 | (defun gnus-summary-resend-message (address n) |
| 630 | "Resend the current article to ADDRESS." |
| 631 | (interactive "sResend message(s) to: \nP") |
| 632 | (let ((articles (gnus-summary-work-articles n)) |
| 633 | article) |
| 634 | (while (setq article (pop articles)) |
| 635 | (gnus-summary-select-article nil nil nil article) |
| 636 | (save-excursion |
| 637 | (set-buffer gnus-original-article-buffer) |
| 638 | (message-resend address))))) |
| 639 | |
| 640 | (defun gnus-summary-post-forward (&optional full-headers) |
| 641 | "Forward the current article to a newsgroup. |
| 642 | If FULL-HEADERS (the prefix), include full headers when forwarding." |
| 643 | (interactive "P") |
| 644 | (gnus-summary-mail-forward full-headers t)) |
| 645 | |
| 646 | (defvar gnus-nastygram-message |
| 647 | "The following article was inappropriately posted to %s.\n\n" |
| 648 | "Format string to insert in nastygrams. |
| 649 | The current group name will be inserted at \"%s\".") |
| 650 | |
| 651 | (defun gnus-summary-mail-nastygram (n) |
| 652 | "Send a nastygram to the author of the current article." |
| 653 | (interactive "P") |
| 654 | (when (or gnus-expert-user |
| 655 | (gnus-y-or-n-p |
| 656 | "Really send a nastygram to the author of the current article? ")) |
| 657 | (let ((group gnus-newsgroup-name)) |
| 658 | (gnus-summary-reply-with-original n) |
| 659 | (set-buffer gnus-message-buffer) |
| 660 | (message-goto-body) |
| 661 | (insert (format gnus-nastygram-message group)) |
| 662 | (message-send-and-exit)))) |
| 663 | |
| 664 | (defun gnus-summary-mail-crosspost-complaint (n) |
| 665 | "Send a complaint about crossposting to the current article(s)." |
| 666 | (interactive "P") |
| 667 | (let ((articles (gnus-summary-work-articles n)) |
| 668 | article) |
| 669 | (while (setq article (pop articles)) |
| 670 | (set-buffer gnus-summary-buffer) |
| 671 | (gnus-summary-goto-subject article) |
| 672 | (let ((group (gnus-group-real-name gnus-newsgroup-name)) |
| 673 | newsgroups followup-to) |
| 674 | (gnus-summary-select-article) |
| 675 | (set-buffer gnus-original-article-buffer) |
| 676 | (if (and (<= (length (message-tokenize-header |
| 677 | (setq newsgroups (mail-fetch-field "newsgroups")) |
| 678 | ", ")) |
| 679 | 1) |
| 680 | (or (not (setq followup-to (mail-fetch-field "followup-to"))) |
| 681 | (not (member group (message-tokenize-header |
| 682 | followup-to ", "))))) |
| 683 | (if followup-to |
| 684 | (gnus-message 1 "Followup-to restricted") |
| 685 | (gnus-message 1 "Not a crossposted article")) |
| 686 | (set-buffer gnus-summary-buffer) |
| 687 | (gnus-summary-reply-with-original 1) |
| 688 | (set-buffer gnus-message-buffer) |
| 689 | (message-goto-body) |
| 690 | (insert (format gnus-crosspost-complaint newsgroups group)) |
| 691 | (message-goto-subject) |
| 692 | (re-search-forward " *$") |
| 693 | (replace-match " (crosspost notification)" t t) |
| 694 | (when (gnus-y-or-n-p "Send this complaint? ") |
| 695 | (message-send-and-exit))))))) |
| 696 | |
| 697 | (defun gnus-summary-mail-other-window () |
| 698 | "Compose mail in other window." |
| 699 | (interactive) |
| 700 | (gnus-setup-message 'message |
| 701 | (message-mail))) |
| 702 | |
| 703 | (defun gnus-mail-parse-comma-list () |
| 704 | (let (accumulated |
| 705 | beg) |
| 706 | (skip-chars-forward " ") |
| 707 | (while (not (eobp)) |
| 708 | (setq beg (point)) |
| 709 | (skip-chars-forward "^,") |
| 710 | (while (zerop |
| 711 | (save-excursion |
| 712 | (save-restriction |
| 713 | (let ((i 0)) |
| 714 | (narrow-to-region beg (point)) |
| 715 | (goto-char beg) |
| 716 | (logand (progn |
| 717 | (while (search-forward "\"" nil t) |
| 718 | (incf i)) |
| 719 | (if (zerop i) 2 i)) |
| 720 | 2))))) |
| 721 | (skip-chars-forward ",") |
| 722 | (skip-chars-forward "^,")) |
| 723 | (skip-chars-backward " ") |
| 724 | (push (buffer-substring beg (point)) |
| 725 | accumulated) |
| 726 | (skip-chars-forward "^,") |
| 727 | (skip-chars-forward ", ")) |
| 728 | accumulated)) |
| 729 | |
| 730 | (defun gnus-inews-add-to-address (group) |
| 731 | (let ((to-address (mail-fetch-field "to"))) |
| 732 | (when (and to-address |
| 733 | (gnus-alive-p)) |
| 734 | ;; This mail group doesn't have a `to-list', so we add one |
| 735 | ;; here. Magic! |
| 736 | (when (gnus-y-or-n-p |
| 737 | (format "Do you want to add this as `to-list': %s " to-address)) |
| 738 | (gnus-group-add-parameter group (cons 'to-list to-address)))))) |
| 739 | |
| 740 | (defun gnus-put-message () |
| 741 | "Put the current message in some group and return to Gnus." |
| 742 | (interactive) |
| 743 | (let ((reply gnus-article-reply) |
| 744 | (winconf gnus-prev-winconf) |
| 745 | (group gnus-newsgroup-name)) |
| 746 | |
| 747 | (or (and group (not (gnus-group-read-only-p group))) |
| 748 | (setq group (read-string "Put in group: " nil |
| 749 | (gnus-writable-groups)))) |
| 750 | (when (gnus-gethash group gnus-newsrc-hashtb) |
| 751 | (error "No such group: %s" group)) |
| 752 | |
| 753 | (save-excursion |
| 754 | (save-restriction |
| 755 | (widen) |
| 756 | (message-narrow-to-headers) |
| 757 | (let (gnus-deletable-headers) |
| 758 | (if (message-news-p) |
| 759 | (message-generate-headers message-required-news-headers) |
| 760 | (message-generate-headers message-required-mail-headers))) |
| 761 | (goto-char (point-max)) |
| 762 | (insert "Gcc: " group "\n") |
| 763 | (widen))) |
| 764 | |
| 765 | (gnus-inews-do-gcc) |
| 766 | |
| 767 | (when (get-buffer gnus-group-buffer) |
| 768 | (when (gnus-buffer-exists-p (car-safe reply)) |
| 769 | (set-buffer (car reply)) |
| 770 | (and (cdr reply) |
| 771 | (gnus-summary-mark-article-as-replied |
| 772 | (cdr reply)))) |
| 773 | (when winconf |
| 774 | (set-window-configuration winconf))))) |
| 775 | |
| 776 | (defun gnus-article-mail (yank) |
| 777 | "Send a reply to the address near point. |
| 778 | If YANK is non-nil, include the original article." |
| 779 | (interactive "P") |
| 780 | (let ((address |
| 781 | (buffer-substring |
| 782 | (save-excursion (re-search-backward "[ \t\n]" nil t) (1+ (point))) |
| 783 | (save-excursion (re-search-forward "[ \t\n]" nil t) (1- (point)))))) |
| 784 | (when address |
| 785 | (message-reply address) |
| 786 | (when yank |
| 787 | (gnus-inews-yank-articles (list (cdr gnus-article-current))))))) |
| 788 | |
| 789 | (defvar nntp-server-type) |
| 790 | (defun gnus-bug () |
| 791 | "Send a bug report to the Gnus maintainers." |
| 792 | (interactive) |
| 793 | (unless (gnus-alive-p) |
| 794 | (error "Gnus has been shut down")) |
| 795 | (gnus-setup-message 'bug |
| 796 | (delete-other-windows) |
| 797 | (switch-to-buffer "*Gnus Help Bug*") |
| 798 | (erase-buffer) |
| 799 | (insert gnus-bug-message) |
| 800 | (goto-char (point-min)) |
| 801 | (message-pop-to-buffer "*Gnus Bug*") |
| 802 | (message-setup `((To . ,gnus-maintainer) (Subject . ""))) |
| 803 | (push `(gnus-bug-kill-buffer) message-send-actions) |
| 804 | (goto-char (point-min)) |
| 805 | (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$")) |
| 806 | (forward-line 1) |
| 807 | (insert (gnus-version) "\n") |
| 808 | (insert (emacs-version) "\n") |
| 809 | (when (and (boundp 'nntp-server-type) |
| 810 | (stringp nntp-server-type)) |
| 811 | (insert nntp-server-type)) |
| 812 | (insert "\n\n\n\n\n") |
| 813 | (gnus-debug) |
| 814 | (goto-char (point-min)) |
| 815 | (search-forward "Subject: " nil t) |
| 816 | (message ""))) |
| 817 | |
| 818 | (defun gnus-bug-kill-buffer () |
| 819 | (when (get-buffer "*Gnus Help Bug*") |
| 820 | (kill-buffer "*Gnus Help Bug*"))) |
| 821 | |
| 822 | (defun gnus-debug () |
| 823 | "Attempts to go through the Gnus source file and report what variables have been changed. |
| 824 | The source file has to be in the Emacs load path." |
| 825 | (interactive) |
| 826 | (let ((files '("gnus.el" "gnus-sum.el" "gnus-group.el" |
| 827 | "gnus-art.el" "gnus-start.el" "gnus-async.el" |
| 828 | "gnus-msg.el" "gnus-score.el" "gnus-win.el" "gnus-topic.el" |
| 829 | "nnmail.el" "message.el")) |
| 830 | file expr olist sym) |
| 831 | (gnus-message 4 "Please wait while we snoop your variables...") |
| 832 | (sit-for 0) |
| 833 | ;; Go through all the files looking for non-default values for variables. |
| 834 | (save-excursion |
| 835 | (set-buffer (get-buffer-create " *gnus bug info*")) |
| 836 | (buffer-disable-undo (current-buffer)) |
| 837 | (while files |
| 838 | (erase-buffer) |
| 839 | (when (and (setq file (locate-library (pop files))) |
| 840 | (file-exists-p file)) |
| 841 | (insert-file-contents file) |
| 842 | (goto-char (point-min)) |
| 843 | (if (not (re-search-forward "^;;* *Internal variables" nil t)) |
| 844 | (gnus-message 4 "Malformed sources in file %s" file) |
| 845 | (narrow-to-region (point-min) (point)) |
| 846 | (goto-char (point-min)) |
| 847 | (while (setq expr (ignore-errors (read (current-buffer)))) |
| 848 | (ignore-errors |
| 849 | (and (or (eq (car expr) 'defvar) |
| 850 | (eq (car expr) 'defcustom)) |
| 851 | (stringp (nth 3 expr)) |
| 852 | (or (not (boundp (nth 1 expr))) |
| 853 | (not (equal (eval (nth 2 expr)) |
| 854 | (symbol-value (nth 1 expr))))) |
| 855 | (push (nth 1 expr) olist))))))) |
| 856 | (kill-buffer (current-buffer))) |
| 857 | (when (setq olist (nreverse olist)) |
| 858 | (insert "------------------ Environment follows ------------------\n\n")) |
| 859 | (while olist |
| 860 | (if (boundp (car olist)) |
| 861 | (condition-case () |
| 862 | (pp `(setq ,(car olist) |
| 863 | ,(if (or (consp (setq sym (symbol-value (car olist)))) |
| 864 | (and (symbolp sym) |
| 865 | (not (or (eq sym nil) |
| 866 | (eq sym t))))) |
| 867 | (list 'quote (symbol-value (car olist))) |
| 868 | (symbol-value (car olist)))) |
| 869 | (current-buffer)) |
| 870 | (error |
| 871 | (format "(setq %s 'whatever)\n" (car olist)))) |
| 872 | (insert ";; (makeunbound '" (symbol-name (car olist)) ")\n")) |
| 873 | (setq olist (cdr olist))) |
| 874 | (insert "\n\n") |
| 875 | ;; Remove any null chars - they seem to cause trouble for some |
| 876 | ;; mailers. (Byte-compiled output from the stuff above.) |
| 877 | (goto-char (point-min)) |
| 878 | (while (re-search-forward "[\000\200]" nil t) |
| 879 | (replace-match "" t t)))) |
| 880 | |
| 881 | ;;; Treatment of rejected articles. |
| 882 | ;;; Bounced mail. |
| 883 | |
| 884 | (defun gnus-summary-resend-bounced-mail (&optional fetch) |
| 885 | "Re-mail the current message. |
| 886 | This only makes sense if the current message is a bounce message than |
| 887 | contains some mail you have written which has been bounced back to |
| 888 | you. |
| 889 | If FETCH, try to fetch the article that this is a reply to, if indeed |
| 890 | this is a reply." |
| 891 | (interactive "P") |
| 892 | (gnus-summary-select-article t) |
| 893 | (set-buffer gnus-original-article-buffer) |
| 894 | (gnus-setup-message 'compose-bounce |
| 895 | (let* ((references (mail-fetch-field "references")) |
| 896 | (parent (and references (gnus-parent-id references)))) |
| 897 | (message-bounce) |
| 898 | ;; If there are references, we fetch the article we answered to. |
| 899 | (and fetch parent |
| 900 | (gnus-summary-refer-article parent) |
| 901 | (gnus-summary-show-all-headers))))) |
| 902 | |
| 903 | ;;; Gcc handling. |
| 904 | |
| 905 | ;; Do Gcc handling, which copied the message over to some group. |
| 906 | (defun gnus-inews-do-gcc (&optional gcc) |
| 907 | (interactive) |
| 908 | (when (gnus-alive-p) |
| 909 | (save-excursion |
| 910 | (save-restriction |
| 911 | (message-narrow-to-headers) |
| 912 | (let ((gcc (or gcc (mail-fetch-field "gcc" nil t))) |
| 913 | (cur (current-buffer)) |
| 914 | groups group method) |
| 915 | (when gcc |
| 916 | (message-remove-header "gcc") |
| 917 | (widen) |
| 918 | (setq groups (message-tokenize-header gcc " ,")) |
| 919 | ;; Copy the article over to some group(s). |
| 920 | (while (setq group (pop groups)) |
| 921 | (gnus-check-server |
| 922 | (setq method |
| 923 | (cond ((and (null (gnus-get-info group)) |
| 924 | (eq (car gnus-message-archive-method) |
| 925 | (car |
| 926 | (gnus-server-to-method |
| 927 | (gnus-group-method group))))) |
| 928 | ;; If the group doesn't exist, we assume |
| 929 | ;; it's an archive group... |
| 930 | gnus-message-archive-method) |
| 931 | ;; Use the method. |
| 932 | ((gnus-info-method (gnus-get-info group)) |
| 933 | (gnus-info-method (gnus-get-info group))) |
| 934 | ;; Find the method. |
| 935 | (t (gnus-group-method group))))) |
| 936 | (gnus-check-server method) |
| 937 | (unless (gnus-request-group group t method) |
| 938 | (gnus-request-create-group group method)) |
| 939 | (save-excursion |
| 940 | (nnheader-set-temp-buffer " *acc*") |
| 941 | (insert-buffer-substring cur) |
| 942 | (goto-char (point-min)) |
| 943 | (when (re-search-forward |
| 944 | (concat "^" (regexp-quote mail-header-separator) "$") |
| 945 | nil t) |
| 946 | (replace-match "" t t )) |
| 947 | (unless (gnus-request-accept-article group method t) |
| 948 | (gnus-message 1 "Couldn't store article in group %s: %s" |
| 949 | group (gnus-status-message method)) |
| 950 | (sit-for 2)) |
| 951 | (kill-buffer (current-buffer)))))))))) |
| 952 | |
| 953 | (defun gnus-inews-insert-gcc () |
| 954 | "Insert Gcc headers based on `gnus-outgoing-message-group'." |
| 955 | (save-excursion |
| 956 | (save-restriction |
| 957 | (message-narrow-to-headers) |
| 958 | (let* ((group gnus-outgoing-message-group) |
| 959 | (gcc (cond |
| 960 | ((gnus-functionp group) |
| 961 | (funcall group)) |
| 962 | ((or (stringp group) (list group)) |
| 963 | group)))) |
| 964 | (when gcc |
| 965 | (insert "Gcc: " |
| 966 | (if (stringp gcc) gcc |
| 967 | (mapconcat 'identity gcc " ")) |
| 968 | "\n")))))) |
| 969 | |
| 970 | (defun gnus-inews-insert-archive-gcc (&optional group) |
| 971 | "Insert the Gcc to say where the article is to be archived." |
| 972 | (let* ((var gnus-message-archive-group) |
| 973 | (group (or group gnus-newsgroup-name "")) |
| 974 | result |
| 975 | gcc-self-val |
| 976 | (groups |
| 977 | (cond |
| 978 | ((null gnus-message-archive-method) |
| 979 | ;; Ignore. |
| 980 | nil) |
| 981 | ((stringp var) |
| 982 | ;; Just a single group. |
| 983 | (list var)) |
| 984 | ((null var) |
| 985 | ;; We don't want this. |
| 986 | nil) |
| 987 | ((and (listp var) (stringp (car var))) |
| 988 | ;; A list of groups. |
| 989 | var) |
| 990 | ((gnus-functionp var) |
| 991 | ;; A function. |
| 992 | (funcall var group)) |
| 993 | (t |
| 994 | ;; An alist of regexps/functions/forms. |
| 995 | (while (and var |
| 996 | (not |
| 997 | (setq result |
| 998 | (cond |
| 999 | ((stringp (caar var)) |
| 1000 | ;; Regexp. |
| 1001 | (when (string-match (caar var) group) |
| 1002 | (cdar var))) |
| 1003 | ((gnus-functionp (car var)) |
| 1004 | ;; Function. |
| 1005 | (funcall (car var) group)) |
| 1006 | (t |
| 1007 | (eval (car var))))))) |
| 1008 | (setq var (cdr var))) |
| 1009 | result))) |
| 1010 | name) |
| 1011 | (when groups |
| 1012 | (when (stringp groups) |
| 1013 | (setq groups (list groups))) |
| 1014 | (save-excursion |
| 1015 | (save-restriction |
| 1016 | (message-narrow-to-headers) |
| 1017 | (goto-char (point-max)) |
| 1018 | (insert "Gcc: ") |
| 1019 | (if (and gnus-newsgroup-name |
| 1020 | (setq gcc-self-val |
| 1021 | (gnus-group-find-parameter |
| 1022 | gnus-newsgroup-name 'gcc-self))) |
| 1023 | (progn |
| 1024 | (insert |
| 1025 | (if (stringp gcc-self-val) |
| 1026 | gcc-self-val |
| 1027 | group)) |
| 1028 | (if (not (eq gcc-self-val 'none)) |
| 1029 | (insert "\n") |
| 1030 | (progn |
| 1031 | (beginning-of-line) |
| 1032 | (kill-line)))) |
| 1033 | (while (setq name (pop groups)) |
| 1034 | (insert (if (string-match ":" name) |
| 1035 | name |
| 1036 | (gnus-group-prefixed-name |
| 1037 | name gnus-message-archive-method))) |
| 1038 | (when groups |
| 1039 | (insert " "))) |
| 1040 | (insert "\n"))))))) |
| 1041 | |
| 1042 | (defun gnus-summary-send-draft () |
| 1043 | "Enter a mail/post buffer to edit and send the draft." |
| 1044 | (interactive) |
| 1045 | (gnus-set-global-variables) |
| 1046 | (let (buf) |
| 1047 | (if (not (setq buf (gnus-request-restore-buffer |
| 1048 | (gnus-summary-article-number) gnus-newsgroup-name))) |
| 1049 | (error "Couldn't restore the article") |
| 1050 | (switch-to-buffer buf) |
| 1051 | (when (eq major-mode 'news-reply-mode) |
| 1052 | (local-set-key "\C-c\C-c" 'gnus-inews-news)) |
| 1053 | ;; Insert the separator. |
| 1054 | (goto-char (point-min)) |
| 1055 | (search-forward "\n\n") |
| 1056 | (forward-char -1) |
| 1057 | (insert mail-header-separator) |
| 1058 | ;; Configure windows. |
| 1059 | (let ((gnus-draft-buffer (current-buffer))) |
| 1060 | (gnus-configure-windows 'draft t) |
| 1061 | (goto-char (point)))))) |
| 1062 | |
| 1063 | (gnus-add-shutdown 'gnus-inews-close 'gnus) |
| 1064 | |
| 1065 | (defun gnus-inews-close () |
| 1066 | (setq gnus-inews-sent-ids nil)) |
| 1067 | |
| 1068 | ;;; Allow redefinition of functions. |
| 1069 | |
| 1070 | (gnus-ems-redefine) |
| 1071 | |
| 1072 | (provide 'gnus-msg) |
| 1073 | |
| 1074 | ;;; gnus-msg.el ends here |