1;;; rnewspost.el --- USENET news poster/mailer for GNU Emacs 2 3;; Copyright (C) 1985, 1986, 1987, 1995, 2001, 2002, 2003, 2004, 4;; 2005, 2006, 2007 Free Software Foundation, Inc. 5 6;; Maintainer: FSF 7;; Keywords: mail, news 8 9;; This file is part of GNU Emacs. 10 11;; GNU Emacs is free software; you can redistribute it and/or modify 12;; it under the terms of the GNU General Public License as published by 13;; the Free Software Foundation; either version 2, or (at your option) 14;; any later version. 15 16;; GNU Emacs is distributed in the hope that it will be useful, 17;; but WITHOUT ANY WARRANTY; without even the implied warranty of 18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19;; GNU General Public License for more details. 20 21;; You should have received a copy of the GNU General Public License 22;; along with GNU Emacs; see the file COPYING. If not, write to the 23;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 24;; Boston, MA 02110-1301, USA. 25 26;;; Change Log: 27 28;; moved posting and mail code from rnews.el 29;; tower@gnu.org Wed Oct 29 1986 30;; brought posting code almost up to the revision of RFC 850 for News 2.11 31;; - couldn't see handling the special meaning of the Keyword: poster 32;; - not worth the code space to support the old A news Title: (which 33;; Subject: replaced) and Article-I.D.: (which Message-ID: replaced) 34;; tower@gnu.org Nov 86 35;; changed C-c C-r key-binding due to rename of news-caesar-buffer-body 36;; tower@gnu.org 21 Nov 86 37;; added (require 'rnews) tower@gnu.org 22 Apr 87 38;; restricted call of news-show-all-headers in news-post-news & news-reply 39;; tower@gnu.org 28 Apr 87 40;; commented out Posting-Front-End to save USENET bytes tower@gnu.org Jul 31 87 41;; commented out -n and -t args in news-inews tower@gnu.org 15 Oct 87 42 43;Now in paths.el. 44;(defvar news-inews-program "inews" 45; "Function to post news.") 46 47;; Replying and posting news items are done by these functions. 48;; imported from rmail and modified to work with rnews ... 49;; Mon Mar 25,1985 at 03:07:04 ads@mit-hermes. 50;; this is done so that rnews can operate independently from rmail.el and 51;; sendmail and doesn't have to autoload these functions. 52;; 53;;; >> Nuked by Mly to autoload those functions again, as the duplication of 54;;; >> code was making maintenance too difficult. 55 56;;; Commentary: 57 58;;; Code: 59 60(require 'sendmail) 61(require 'rnews) 62 63(defvar mail-reply-buffer) 64 65(defvar news-reply-mode-map () "Mode map used by news-reply.") 66 67(or news-reply-mode-map 68 (progn 69 (setq news-reply-mode-map (make-keymap)) 70 (define-key news-reply-mode-map "\C-c\C-f\C-d" 'news-reply-distribution) 71 (define-key news-reply-mode-map "\C-c\C-f\C-k" 'news-reply-keywords) 72 (define-key news-reply-mode-map "\C-c\C-f\C-n" 'news-reply-newsgroups) 73 (define-key news-reply-mode-map "\C-c\C-f\C-f" 'news-reply-followup-to) 74 (define-key news-reply-mode-map "\C-c\C-f\C-s" 'mail-subject) 75 (define-key news-reply-mode-map "\C-c\C-f\C-a" 'news-reply-summary) 76 (define-key news-reply-mode-map "\C-c\C-t" 'mail-text) 77 (define-key news-reply-mode-map "\C-c\C-r" 'news-caesar-buffer-body) 78 (define-key news-reply-mode-map "\C-c\C-w" 'news-reply-signature) 79 (define-key news-reply-mode-map "\C-c\C-y" 'news-reply-yank-original) 80 (define-key news-reply-mode-map "\C-c\C-q" 'mail-fill-yanked-message) 81 (define-key news-reply-mode-map "\C-c\C-c" 'news-inews) 82 (define-key news-reply-mode-map "\C-c\C-s" 'news-inews) 83 (define-key news-reply-mode-map [menu-bar] (make-sparse-keymap)) 84 (define-key news-reply-mode-map [menu-bar fields] 85 (cons "Fields" (make-sparse-keymap "Fields"))) 86 (define-key news-reply-mode-map [menu-bar fields news-reply-distribution] 87 '("Distribution" . news-reply-distribution)) 88 (define-key news-reply-mode-map [menu-bar fields news-reply-keywords] 89 '("Keywords" . news-reply-keywords)) 90 (define-key news-reply-mode-map [menu-bar fields news-reply-newsgroups] 91 '("Newsgroups" . news-reply-newsgroups)) 92 (define-key news-reply-mode-map [menu-bar fields news-reply-followup-to] 93 '("Followup-to" . news-reply-followup-to)) 94 (define-key news-reply-mode-map [menu-bar fields mail-subject] 95 '("Subject" . mail-subject)) 96 (define-key news-reply-mode-map [menu-bar fields news-reply-summary] 97 '("Summary" . news-reply-summary)) 98 (define-key news-reply-mode-map [menu-bar fields mail-text] 99 '("Text" . mail-text)) 100 (define-key news-reply-mode-map [menu-bar news] 101 (cons "News" (make-sparse-keymap "News"))) 102 (define-key news-reply-mode-map [menu-bar news news-caesar-buffer-body] 103 '("Rot13" . news-caesar-buffer-body)) 104 (define-key news-reply-mode-map [menu-bar news news-reply-yank-original] 105 '("Yank Original" . news-reply-yank-original)) 106 (define-key news-reply-mode-map [menu-bar news mail-fill-yanked-message] 107 '("Fill Yanked Messages" . mail-fill-yanked-message)) 108 (define-key news-reply-mode-map [menu-bar news news-inews] 109 '("Send" . news-inews)))) 110 111(defun news-reply-mode () 112 "Major mode for editing news to be posted on USENET. 113First-time posters are asked to please read the articles in newsgroup: 114 news.announce.newusers . 115Like Text Mode but with these additional commands: 116 117C-c C-s news-inews (post the message) C-c C-c news-inews 118C-c C-f move to a header field (and create it if there isn't): 119 C-c C-f C-n move to Newsgroups: C-c C-f C-s move to Subj: 120 C-c C-f C-f move to Followup-To: C-c C-f C-k move to Keywords: 121 C-c C-f C-d move to Distribution: C-c C-f C-a move to Summary: 122C-c C-y news-reply-yank-original (insert current message, in NEWS). 123C-c C-q mail-fill-yanked-message (fill what was yanked). 124C-c C-r caesar rotate all letters by 13 places in the article's body (rot13)." 125 (interactive) 126 (kill-all-local-variables) 127 (make-local-variable 'mail-reply-buffer) 128 (setq mail-reply-buffer nil) 129 (set-syntax-table text-mode-syntax-table) 130 (use-local-map news-reply-mode-map) 131 (setq local-abbrev-table text-mode-abbrev-table) 132 (setq major-mode 'news-reply-mode) 133 (setq mode-name "News Reply") 134 (make-local-variable 'paragraph-separate) 135 (make-local-variable 'paragraph-start) 136 (run-mode-hooks 'text-mode-hook 'news-reply-mode-hook)) 137 138(defvar news-reply-yank-from "" 139 "Save `From:' field for `news-reply-yank-original'.") 140 141(defvar news-reply-yank-message-id "" 142 "Save `Message-Id:' field for `news-reply-yank-original'.") 143 144(defun news-reply-yank-original (arg) 145 "Insert the message being replied to, if any (in Mail mode). 146Puts point before the text and mark after. 147Indents each nonblank line ARG spaces (default 3). 148Just \\[universal-argument] as argument means don't indent 149and don't delete any header fields." 150 (interactive "P") 151 (mail-yank-original arg) 152 (exchange-point-and-mark) 153 (run-hooks 'news-reply-header-hook)) 154 155(defvar news-reply-header-hook 156 (lambda () 157 (insert "In article " news-reply-yank-message-id 158 " " news-reply-yank-from " writes:\n\n")) 159 "Hook for inserting a header at the top of a yanked message.") 160 161(defun news-reply-newsgroups () 162 "Move point to end of `Newsgroups:' field. 163RFC 850 constrains the `Newsgroups:' field to be a comma-separated list 164of valid newsgroup names at your site. For example, 165 Newsgroups: news.misc,comp.misc,rec.misc" 166 (interactive) 167 (expand-abbrev) 168 (goto-char (point-min)) 169 (mail-position-on-field "Newsgroups")) 170 171(defun news-reply-followup-to () 172 "Move point to end of `Followup-To:' field. Create the field if none. 173One usually requests followups to only one newsgroup. 174RFC 850 constrains the `Followup-To:' field to be a comma-separated list 175of valid newsgroups names at your site, and it must be a subset of the 176`Newsgroups:' field. For example: 177 Newsgroups: news.misc,comp.misc,rec.misc,misc.misc,soc.misc 178 Followup-To: news.misc,comp.misc,rec.misc" 179 (interactive) 180 (expand-abbrev) 181 (or (mail-position-on-field "Followup-To" t) 182 (progn (mail-position-on-field "newsgroups") 183 (insert "\nFollowup-To: "))) 184 ;; @@ could do a completing read based on the Newsgroups: field to 185 ;; @@ fill in the Followup-To: field 186) 187 188(defun news-reply-distribution () 189 "Move point to end of `Distribution:' optional field. 190Create the field if none. Without this field the posting goes to all of 191USENET. The field is used to restrict the posting to parts of USENET." 192 (interactive) 193 (expand-abbrev) 194 (mail-position-on-field "Distribution") 195 ;; @@could do a completing read based on the news library file: 196 ;; @@ ../distributions to fill in the field. 197 ) 198 199(defun news-reply-keywords () 200 "Move point to end of `Keywords:' optional field. Create the field if none. 201Used as an aid to the news reader, it can contain a few, well selected keywords 202identifying the message." 203 (interactive) 204 (expand-abbrev) 205 (mail-position-on-field "Keywords")) 206 207(defun news-reply-summary () 208 "Move point to end of `Summary:' optional field. Create the field if none. 209Used as an aid to the news reader, it can contain a succinct 210summary (abstract) of the message." 211 (interactive) 212 (expand-abbrev) 213 (mail-position-on-field "Summary")) 214 215(defun news-reply-signature () 216 "The inews program appends `~/.signature' automatically." 217 (interactive) 218 (message "Posting news will append your signature automatically.")) 219 220(defun news-setup (to subject in-reply-to newsgroups replybuffer) 221 "Set up the news reply or posting buffer with the proper headers and mode." 222 (setq mail-reply-buffer replybuffer) 223 (let ((mail-setup-hook nil) 224 ;; Avoid inserting a signature. 225 (mail-signature)) 226 (if (null to) 227 ;; this hack is needed so that inews wont be confused by 228 ;; the fcc: and bcc: fields 229 (let ((mail-self-blind nil) 230 (mail-archive-file-name nil)) 231 (mail-setup to subject in-reply-to nil replybuffer nil) 232 (beginning-of-line) 233 (delete-region (point) (progn (forward-line 1) (point))) 234 (goto-char (point-max))) 235 (mail-setup to subject in-reply-to nil replybuffer nil)) 236 ;;;(mail-position-on-field "Posting-Front-End") 237 ;;;(insert (emacs-version)) 238 (goto-char (point-max)) 239 (if (let ((case-fold-search t)) 240 (re-search-backward "^Subject:" (point-min) t)) 241 (progn (beginning-of-line) 242 (insert "Newsgroups: " (or newsgroups "") "\n") 243 (if (not newsgroups) 244 (backward-char 1) 245 (goto-char (point-max))))) 246 (let (actual-header-separator) 247 (rfc822-goto-eoh) 248 (setq actual-header-separator (buffer-substring 249 (point) 250 (save-excursion (end-of-line) (point)))) 251 (setq paragraph-start 252 (concat "^" actual-header-separator "$\\|" paragraph-start)) 253 (setq paragraph-separate 254 (concat "^" actual-header-separator "$\\|" paragraph-separate))) 255 (run-hooks 'news-setup-hook))) 256 257(defun news-inews () 258 "Send a news message using inews." 259 (interactive) 260 (let* (newsgroups subject 261 (case-fold-search nil)) 262 (save-excursion 263 (save-restriction 264 (narrow-to-region (point-min) (mail-header-end)) 265 (setq newsgroups (mail-fetch-field "newsgroups") 266 subject (mail-fetch-field "subject"))) 267 (widen) 268 (goto-char (point-min)) 269 (run-hooks 'news-inews-hook) 270 (mail-sendmail-undelimit-header) 271 (goto-char (point-max)) 272 ;; require a newline at the end for inews to append .signature to 273 (or (= (preceding-char) ?\n) 274 (insert ?\n)) 275 (message "Posting to USENET...") 276 (unwind-protect 277 (if (not (eq 0 278 (call-process-region (point-min) (point-max) 279 news-inews-program nil 0 nil 280 "-h"))) ; take all header lines! 281 ;@@ setting of subject and newsgroups still needed? 282 ;"-t" subject 283 ;"-n" newsgroups 284 (error "Posting to USENET failed") 285 (message "Posting to USENET... done")) 286 (mail-sendmail-delimit-header) 287 (set-buffer-modified-p nil))) 288 (bury-buffer))) 289 290;@@ shares some code with news-reply and news-post-news 291(defun news-mail-reply () 292 "Mail a reply to the author of the current article. 293While composing the reply, use \\[news-reply-yank-original] to yank the 294original message into it." 295 (interactive) 296 (let (from cc subject date to reply-to message-id 297 (buffer (current-buffer))) 298 (save-restriction 299 (narrow-to-region (point-min) (progn (goto-line (point-min)) 300 (search-forward "\n\n") 301 (- (point) 1))) 302 (setq from (mail-fetch-field "from") 303 subject (mail-fetch-field "subject") 304 reply-to (mail-fetch-field "reply-to") 305 date (mail-fetch-field "date") 306 message-id (mail-fetch-field "message-id"))) 307 (setq to from) 308 (pop-to-buffer "*mail*") 309 (mail nil 310 (if reply-to reply-to to) 311 subject 312 (let ((stop-pos (string-match " *at \\| *@ \\| *(\\| *<" from))) 313 (concat (if stop-pos (substring from 0 stop-pos) from) 314 "'s message " 315 (if message-id 316 (concat message-id " of ") 317 "of ") 318 date)) 319 nil 320 buffer))) 321 322;@@ the guts of news-reply and news-post-news should be combined. -tower 323(defun news-reply () 324 "Compose and post a reply (aka a followup) to the current article on USENET. 325While composing the followup, use \\[news-reply-yank-original] to yank the 326original message into it." 327 (interactive) 328 (if (y-or-n-p "Are you sure you want to followup to all of USENET? ") 329 (let (from cc subject date to followup-to newsgroups message-of 330 references distribution message-id 331 (buffer (current-buffer))) 332 (save-restriction 333 (and (not (= 0 (buffer-size))) ;@@real problem is non-existence of 334 ;@@ of article file 335 (equal major-mode 'news-mode) ;@@ if rmail-mode, 336 ;@@ should show full headers 337 (progn 338 (news-show-all-headers) ;@@ should save/restore header state, 339 ;@@ but rnews.el lacks support 340 (narrow-to-region (point-min) (progn (goto-char (point-min)) 341 (search-forward "\n\n") 342 (- (point) 1))))) 343 (setq from (mail-fetch-field "from") 344 news-reply-yank-from from 345 ;; @@ not handling old Title: field 346 subject (mail-fetch-field "subject") 347 date (mail-fetch-field "date") 348 followup-to (mail-fetch-field "followup-to") 349 newsgroups (or followup-to 350 (mail-fetch-field "newsgroups")) 351 references (mail-fetch-field "references") 352 ;; @@ not handling old Article-I.D.: field 353 distribution (mail-fetch-field "distribution") 354 message-id (mail-fetch-field "message-id") 355 news-reply-yank-message-id message-id) 356 (pop-to-buffer "*post-news*") 357 (news-reply-mode) 358 (if (and (buffer-modified-p) 359 (not 360 (y-or-n-p "Unsent article being composed; erase it? "))) 361 () 362 (progn 363 (erase-buffer) 364 (and subject 365 (progn (if (string-match "\\`Re: " subject) 366 (while (string-match "\\`Re: " subject) 367 (setq subject (substring subject 4)))) 368 (setq subject (concat "Re: " subject)))) 369 (and from 370 (progn 371 (let ((stop-pos 372 (string-match " *at \\| *@ \\| *(\\| *<" from))) 373 (setq message-of 374 (concat 375 (if stop-pos (substring from 0 stop-pos) from) 376 "'s message " 377 (if message-id 378 (concat message-id " of ") 379 "of ") 380 date))))) 381 (news-setup 382 nil 383 subject 384 message-of 385 newsgroups 386 buffer) 387 (if followup-to 388 (progn (news-reply-followup-to) 389 (insert followup-to))) 390 (if distribution 391 (progn 392 (mail-position-on-field "Distribution") 393 (insert distribution))) 394 (mail-position-on-field "References") 395 (if references 396 (insert references)) 397 (if (and references message-id) 398 (insert " ")) 399 (if message-id 400 (insert message-id)) 401 (goto-char (point-max)))))) 402 (message ""))) 403 404;@@ the guts of news-reply and news-post-news should be combined. -tower 405;;;###autoload 406(defun news-post-news (&optional noquery) 407 "Begin editing a new USENET news article to be posted. 408Type \\[describe-mode] once editing the article to get a list of commands. 409If NOQUERY is non-nil, we do not query before doing the work." 410 (interactive) 411 (if (or noquery 412 (y-or-n-p "Are you sure you want to post to all of USENET? ")) 413 (let ((buffer (current-buffer))) 414 (save-restriction 415 (and (not (= 0 (buffer-size))) ;@@real problem is non-existence of 416 ;@@ of article file 417 (equal major-mode 'news-mode) ;@@ if rmail-mode, 418 ;@@ should show full headers 419 (progn 420 (news-show-all-headers) ;@@ should save/restore header state, 421 ;@@ but rnews.el lacks support 422 (narrow-to-region (point-min) (progn (goto-char (point-min)) 423 (search-forward "\n\n") 424 (- (point) 1))))) 425 (setq news-reply-yank-from (mail-fetch-field "from") 426 ;; @@ not handling old Article-I.D.: field 427 news-reply-yank-message-id (mail-fetch-field "message-id"))) 428 (pop-to-buffer "*post-news*") 429 (news-reply-mode) 430 (if (and (buffer-modified-p) 431 (not (y-or-n-p "Unsent article being composed; erase it? "))) 432 () ;@@ not saving point from last time 433 (progn (erase-buffer) 434 (news-setup () () () () buffer)))) 435 (message ""))) 436 437(defun news-mail-other-window () 438 "Send mail in another window. 439While composing the message, use \\[news-reply-yank-original] to yank the 440original message into it." 441 (interactive) 442 (mail-other-window nil nil nil nil nil (current-buffer))) 443 444(provide 'rnewspost) 445 446;;; arch-tag: 18f7b2af-cf9a-49e4-878b-71eb49913e00 447;;; rnewspost.el ends here 448