Mercurial > hg > xemacs
comparison mail-extras.el @ 44:b09e8120dc53
copied in from lucid, moved use-text-not-html support to my-news,
still has a lot of diary-related stuff which is _currently_ only relevant on ecclerig
author | Henry S. Thompson <ht@inf.ed.ac.uk> |
---|---|
date | Wed, 20 Dec 2023 17:58:34 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
43:eee08de75336 | 44:b09e8120dc53 |
---|---|
1 ;; Last edited: Fri Nov 2 10:26:24 1990 | |
2 ;; extra widgets for rmail and rmailsum | |
3 ;; Copyright (C) 1990 Henry S. Thompson | |
4 | |
5 ;; This file is part of GNU Emacs. | |
6 | |
7 ;; GNU Emacs is distributed in the hope that it will be useful, | |
8 ;; but WITHOUT ANY WARRANTY. No author or distributor | |
9 ;; accepts responsibility to anyone for the consequences of using it | |
10 ;; or for whether it serves any particular purpose or works at all, | |
11 ;; unless he says so in writing. Refer to the GNU Emacs General Public | |
12 ;; License for full details. | |
13 | |
14 ;; Everyone is granted permission to copy, modify and redistribute | |
15 ;; GNU Emacs, but only under the conditions described in the | |
16 ;; GNU Emacs General Public License. A copy of this license is | |
17 ;; supposed to have been given to you along with GNU Emacs so you | |
18 ;; can know your rights and responsibilities. It should be in a | |
19 ;; file named COPYING. Among other things, the copyright notice | |
20 ;; and this notice must be preserved on all copies. | |
21 | |
22 (require 'rmail) | |
23 (require 'sendmail) | |
24 | |
25 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
26 ;; mods and fixes for reading mail ;; | |
27 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
28 | |
29 (defvar ht-last-file (expand-file-name "~/XMAIL") | |
30 "default for moving mail to") | |
31 (make-variable-buffer-local 'ht-last-file) | |
32 | |
33 (defvar rmht-always-recompress t | |
34 "If non-nil, when saving into compressed babyl file, | |
35 always recompress and save immediately") | |
36 | |
37 (defvar rmht-allow-autosave t | |
38 "if non-nil, leaves autosave alone for compressed babyl files, | |
39 otherwise turns it off") | |
40 | |
41 (add-hook 'rmail-mode-hook 'rmail-mode-fun1) | |
42 (add-hook 'rmail-mode-hook 'rmail-mode-fun2) | |
43 | |
44 ;; run the first time in to RMAIL | |
45 (defun rmail-mode-fun1 () | |
46 "add ht's mods to RMAIL" | |
47 (define-key rmail-mode-map "R" 'reply-w/o-cc) | |
48 (define-key rmail-mode-map "M" 'rmht-output) | |
49 (define-key rmail-mode-map "H" 'print-buffer) | |
50 (define-key rmail-mode-map "W" 'edit-and-move-to-diary) | |
51 (define-key rmail-mode-map "D" 'update-default-diary) | |
52 (define-key rmail-mode-map "F" 're-post-failed-mail) | |
53 (define-key rmail-mode-map "B" 'ht-write-body-to-file) | |
54 (define-key rmail-mode-map "E" 'extract-attachment) | |
55 ;; fix the doc string | |
56 (repl-comment 'rmail-mode | |
57 "Rmail Mode is used by \\[rmail] for editing Rmail files. | |
58 All normal editing commands are turned off. | |
59 Instead, these commands are available (additions from ht's mail-extras.el | |
60 indicated by *: | |
61 | |
62 . Move point to front of this message (same as \\[beginning-of-buffer]). | |
63 SPC Scroll to next screen of this message. | |
64 DEL Scroll to previous screen of this message. | |
65 n Move to Next non-deleted message. | |
66 p Move to Previous non-deleted message. | |
67 M-n Move to Next message whether deleted or not. | |
68 M-p Move to Previous message whether deleted or not. | |
69 > Move to the last message in Rmail file. | |
70 j Jump to message specified by numeric position in file. | |
71 M-s Search for string and show message it is found in. | |
72 d Delete this message, move to next nondeleted. | |
73 C-d Delete this message, move to previous nondeleted. | |
74 u Undelete message. Tries current message, then earlier messages | |
75 till a deleted message is found. | |
76 e Expunge deleted messages. | |
77 s Expunge and save the file. | |
78 q Quit Rmail: expunge, save, then switch to another buffer. | |
79 C-x C-s Save without expunging. | |
80 g Move new mail from system spool directory or mbox into this file. | |
81 m Mail a message (same as \\[mail-other-window]). | |
82 c Continue composing outgoing message started before. | |
83 r Reply to this message. Like m but initializes some fields. | |
84 R * Like r, but reply to originator only. | |
85 f Forward this message to another user. | |
86 F * like f, but assumes message is \"failed mail\" for re-sending | |
87 o Output this message to an Rmail file (append it). | |
88 C-o Output this message to a Unix-format mail file (append it). | |
89 M * Output this message to a file, | |
90 in format determined by extension (babyl for RMAIL/msg for Unix). | |
91 B * Write the body of the message to a file, leaving a pointer | |
92 H * Print the message (same as \\<global-map>\\[print-buffer]).\\<rmail-mode-map> | |
93 i Input Rmail file. Run Rmail on that file. | |
94 a Add label to message. It will be displayed in the mode line. | |
95 k Kill label. Remove a label from current message. | |
96 C-M-n Move to Next message with specified label | |
97 (label defaults to last one specified). | |
98 Standard labels: filed, unseen, answered, forwarded, deleted. | |
99 Any other label is present only if you add it with `a'. | |
100 C-M-p Move to Previous message with specified label | |
101 h, C-M-h Show headers buffer, with a one line summary of each message. | |
102 l, C-M-l Like h only just messages with particular label(s) are summarized. | |
103 C-M-r Like h only just messages with particular recipient(s) are summarized. | |
104 t Toggle header, show Rmail header if unformatted or vice versa. | |
105 w Edit the current message. C-c C-c to return to Rmail. | |
106 W * Edit the subject field. C-c C-c to move the message to the Diary. | |
107 D * Update the Diary. | |
108 | |
109 Messages for the diary (see also \\[describe-mode] in rmail-summary mode | |
110 or \\[describe-function] rmail-summary-mode) should have a subject field | |
111 which begins with the date and optional time of the event described therein. | |
112 These must be in the form | |
113 d m y t | |
114 where d is one or two digits for the day, | |
115 m is either the full month name or the first three letters thereof, | |
116 y is two digits for the year, | |
117 and t, if present, is 4 digits for the time, | |
118 thus for example | |
119 31 Jun 91 1530 | |
120 ") | |
121 (remove-hook 'rmail-mode-hook 'rmail-mode-fun1)) | |
122 | |
123 (defun rmail-mode-fun2 () | |
124 "always run in RMAIL mode" | |
125 (setq case-fold-search t)) | |
126 | |
127 (defun reply-w/o-cc () | |
128 "Reply as r, but without sending to other recipients" | |
129 (interactive) | |
130 (rmail-reply t)) | |
131 | |
132 (defun rmht-output (&optional file-name gnus) | |
133 "Move to a file, determining format by extension (babyl/msg)" | |
134 (interactive) | |
135 (if (not file-name) | |
136 (setq file-name (car (get-move-file-name)))) | |
137 (if (string-match "\\.g?[zZ]$" file-name) | |
138 (let ((clean-file-name (substring file-name 0 (match-beginning 0))) | |
139 there) | |
140 (if (setq there (get-file-buffer clean-file-name)) | |
141 nil | |
142 (save-window-excursion (rmail clean-file-name) | |
143 (setq there | |
144 (get-file-buffer clean-file-name)))) | |
145 (rmht-output clean-file-name gnus) | |
146 (if rmht-always-recompress | |
147 (save-excursion | |
148 (set-buffer there) | |
149 (save-buffer)) | |
150 (if (not rmht-allow-autosave) | |
151 (save-excursion | |
152 (set-buffer there) | |
153 (auto-save-mode -1))))) | |
154 (setq file-name (expand-file-name file-name)) | |
155 (save-excursion | |
156 (if (string-match "\\.babyl$" file-name) | |
157 (if gnus | |
158 (gnus-output-to-rmail file-name) | |
159 (rmail-output-to-rmail-file file-name 1)) | |
160 (if (string-match "\\.msg$" file-name) | |
161 (if (or (get-file-buffer file-name) | |
162 (file-exists-p file-name) | |
163 (yes-or-no-p | |
164 (concat "\"" file-name "\" does not exist, create it? "))) | |
165 (rmail-output file-name 1) | |
166 (error "Output file does not exist")) | |
167 (error "not a valid mail file: %s" file-name)))) | |
168 (setq ht-last-file file-name) | |
169 (if (not gnus) (ht-rmail-delete-forward)))) | |
170 | |
171 (defun get-move-file-name () | |
172 "get a file name for moving a message to" | |
173 (list (read-file-name | |
174 (concat "Output message to file: (default " | |
175 (file-name-nondirectory ht-last-file) | |
176 ") ") | |
177 (file-name-directory ht-last-file) | |
178 ht-last-file))) | |
179 | |
180 (defun re-post-failed-mail () | |
181 "try to salvage the original from failed mail and prepare to resend it" | |
182 (interactive) | |
183 (rmail-forward nil) | |
184 (let ((top (point)) | |
185 subjp textp) | |
186 (re-search-forward "^Subject: ") | |
187 (kill-line nil) | |
188 (setq subjp (point)) | |
189 (re-search-forward "^From: ") ; the bouncer | |
190 (re-search-forward "^From: ") ; should be us | |
191 (re-search-forward "^Subject: ") | |
192 (kill-line nil) | |
193 (save-excursion (goto-char subjp) | |
194 (yank)) | |
195 (beginning-of-line 3) | |
196 (setq textp (point)) | |
197 (goto-char top) | |
198 (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$")) | |
199 (beginning-of-line 2) | |
200 (delete-region (point) textp) | |
201 (goto-char top))) | |
202 | |
203 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
204 ;; mods and fixes for mail summaries ;; | |
205 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
206 | |
207 (add-hook 'rmail-summary-mode-hook 'rmail-summary-mode-fun1) | |
208 | |
209 ;; run the first time we make a summary window | |
210 (defun rmail-summary-mode-fun1 () | |
211 "install ht's mods" | |
212 (define-key rmail-summary-mode-map "r" 'rms-reply-w-cc) | |
213 (define-key rmail-summary-mode-map "R" 'rms-reply-w/o-cc) | |
214 (define-key rmail-summary-mode-map "s" 'diary-save) | |
215 (define-key rmail-summary-mode-map "m" 'rms-move) | |
216 (define-key rmail-summary-mode-map "d" 'rms-delete) | |
217 (define-key rmail-summary-mode-map "h" 'rms-hardcopy) | |
218 (define-key rmail-summary-mode-map " " 'ht-rmailsum-scroll-msg-up) | |
219 (define-key rmail-summary-mode-map "\177" 'ht-rmailsum-scroll-msg-down) | |
220 ;; fix the doc string | |
221 (repl-comment 'rmail-summary-mode | |
222 "Major mode in effect in Rmail summary buffer. | |
223 A subset of the Rmail mode commands are supported in this mode. | |
224 As commands are issued in the summary buffer the corresponding | |
225 mail message is displayed in the rmail buffer. | |
226 Modifications from ht's mail-extras.el indicated with *: | |
227 | |
228 n Move to next undeleted message, or arg messages. | |
229 p Move to previous undeleted message, or arg messages. | |
230 C-n Move to next, or forward arg messages. | |
231 C-p Move to previous, or previous arg messages. | |
232 j Jump to the message at the cursor location. | |
233 d Delete the message at the cursor location and move to next message. | |
234 u Undelete this or previous deleted message. | |
235 q Quit Rmail. | |
236 x Exit and kill the summary window. | |
237 space * If cursor is on line of current message, | |
238 scroll message window forward. Otherwise, jump to indicated message. | |
239 delete * same as space, but scrolls backward. | |
240 r * Same as r in rmail window. Reply to current message. | |
241 R * Same as R in rmail window. Reply to current message, originator only. | |
242 s * Update and save the rmail file, and re-summarise. Re-sorts if Diary. | |
243 m * Same as M in rmail window. Moves message to file. | |
244 h * Same as H in rmail window. Prints message on line printer. | |
245 | |
246 Entering this mode calls value of hook variable rmail-summary-mode-hook. | |
247 | |
248 If the file summarised is called by the name given in ht-diary-file-name, | |
249 which defaults to diary.babyl, | |
250 then the summary will be called *Diary*, sorted in date order and | |
251 formated in a special way. | |
252 | |
253 Messages in the diary should have a subject field | |
254 which begins with the date and optional time of the event described therein. | |
255 These must be in the form | |
256 d m y t | |
257 where d is one or two digits for the day, | |
258 m is either the full month name or the first three letters thereof, | |
259 y is two digits for the year, | |
260 and t, if present, is 4 digits for the time, | |
261 thus for example | |
262 Subject: 31 Jun 91 1530 Hades freezing ceremony followed by champagne reception | |
263 ") | |
264 (remove-hook 'rmail-summary-mode-hook 'rmail-summary-mode-fun1)) | |
265 | |
266 (defun rmht-sum-reply (sender-only) | |
267 "reply to current message" | |
268 (rmail-summary-goto-msg) | |
269 (pop-to-buffer rmail-buffer) | |
270 (rmail-reply sender-only) | |
271 (switch-to-buffer rmail-summary-buffer) | |
272 (switch-to-buffer "*mail*") | |
273 ) | |
274 | |
275 (defun rms-reply-w-cc () | |
276 "Do r in RMAIL - reply to everybody" | |
277 (interactive) | |
278 (rmht-sum-reply nil)) | |
279 | |
280 (defun rms-reply-w/o-cc () | |
281 "Do R in RMAIL - reply to sender only" | |
282 (interactive) | |
283 (rmht-sum-reply t)) | |
284 | |
285 (defun rms-save () | |
286 "expunge deleted messages, save RMAIL file and re-display headers" | |
287 (interactive) | |
288 (pop-to-buffer rmail-buffer) | |
289 (rmail-expunge-and-save) | |
290 (rmail-summary)) | |
291 | |
292 (defun rms-delete () | |
293 "delete current and move down to next in summary buffer" | |
294 (interactive) | |
295 (rmail-summary-goto-msg) | |
296 (save-excursion | |
297 (rmail-summary-delete-forward nil)) | |
298 (rms-del)) | |
299 | |
300 (defun rms-move () | |
301 "Move to a file, mode determined by file extension (babyl/msg)" | |
302 (interactive) | |
303 (rmail-summary-goto-msg) | |
304 (save-excursion | |
305 (set-buffer rmail-buffer) | |
306 (rmht-output)) | |
307 (rms-del)) | |
308 | |
309 (defun rms-del () | |
310 "mark current summary line as deleted and move down" | |
311 (let ((buffer-read-only nil)) | |
312 (skip-chars-forward " ") | |
313 (skip-chars-forward "[0-9]") | |
314 (delete-char 1) | |
315 (insert "D")) | |
316 (forward-line 1)) | |
317 | |
318 (defun rms-hardcopy () | |
319 "hardcopy the current message" | |
320 (interactive) | |
321 (pop-to-buffer rmail-buffer) | |
322 (print-buffer) | |
323 (pop-to-buffer rmail-summary-buffer)) | |
324 | |
325 | |
326 ;; fix interpretation of SPACE and DEL in summary windows to | |
327 ;; 1) scroll the right window regardless of how many panes are up; | |
328 ;; 2) go to the message associated with the current line if not already there, | |
329 ;; a la gnus, for instance | |
330 | |
331 (defun ht-rmailsum-normalise () | |
332 "if not already showing message named on current line, go to it & return t" | |
333 (beginning-of-line) | |
334 (let ((current-msg-num (cdr (assoc 'rmail-current-message | |
335 (buffer-local-variables | |
336 (or rmail-buffer | |
337 (error | |
338 "not in a summary buffer")))))) | |
339 (line-message-num (string-to-int | |
340 (buffer-substring | |
341 (point) | |
342 (min (point-max)(+ 5 (point))))))) | |
343 (if (= current-msg-num line-message-num) | |
344 nil | |
345 (rmail-summary-goto-msg line-message-num) | |
346 t))) | |
347 | |
348 (defun ht-rmailsum-scroll-msg-up (&optional dist) | |
349 "goto other message or scroll current message forward" | |
350 (interactive "P") | |
351 (if (ht-rmailsum-normalise) | |
352 nil | |
353 (pop-to-buffer rmail-buffer) | |
354 (scroll-up dist) | |
355 (pop-to-buffer rmail-summary-buffer))) | |
356 | |
357 (defun ht-rmailsum-scroll-msg-down (&optional dist) | |
358 "goto other message or scroll current message backward" | |
359 (interactive "P") | |
360 (if (ht-rmailsum-normalise) | |
361 nil | |
362 (pop-to-buffer rmail-buffer) | |
363 (scroll-down dist) | |
364 (pop-to-buffer rmail-summary-buffer))) | |
365 | |
366 (autoload 'edit-and-move-to-diary "diary") | |
367 (autoload 'update-diary "diary") | |
368 (autoload 'diary-save "diary") | |
369 | |
370 ;;; I _think_ (almost?) everything above here is diary-related, so belongs | |
371 ;;; in diary.el. | |
372 | |
373 ;; unfortunately, gnus mucks about with the buffers before calling | |
374 ;; mail, so we have to intervene to make the about-to-mail-hook work right | |
375 | |
376 (defun ht-Subject-mode-fun () | |
377 "fix the map to save window state" | |
378 ; (define-key gnus-summary-mode-map "r" 'ht-Subject-mail-reply) | |
379 ; (define-key gnus-summary-mode-map "R" 'ht-Subject-mail-reply-with-original) | |
380 ; (define-key gnus-summary-mode-map "m" 'ht-Subject-mail-other-window) | |
381 (define-key gnus-summary-save-map "M" 'ht-Subject-move) | |
382 (remove-hook 'gnus-summary-mode-hook 'ht-Subject-mode-fun)) | |
383 | |
384 (add-hook 'gnus-summary-mode-hook 'ht-Subject-mode-fun) | |
385 | |
386 (defun ht-Subject-mail-reply (yank) | |
387 "Runs about-to-mail-hook, then calls gnus-summary-mail-reply" | |
388 (interactive "P") | |
389 (require 'sendmail) | |
390 (run-hooks 'about-to-mail-hook) | |
391 (let (about-to-mail-hook) | |
392 (gnus-summary-reply yank))) | |
393 | |
394 (defun ht-Subject-mail-reply-with-original () | |
395 "Runs about-to-mail-hook, then calls gnus-summary-mail-reply-with-original" | |
396 (interactive) | |
397 (require 'sendmail) | |
398 (run-hooks 'about-to-mail-hook) | |
399 (let (about-to-mail-hook) | |
400 (gnus-summary-reply-with-original))) | |
401 | |
402 (defun ht-Subject-mail-other-window () | |
403 "Runs about-to-mail-hook, then calls gnus-summary-mail-other-window" | |
404 (interactive) | |
405 (require 'sendmail) | |
406 (run-hooks 'about-to-mail-hook) | |
407 (let (about-to-mail-hook) | |
408 (gnus-summary-mail-other-window))) | |
409 | |
410 (defun ht-Subject-move () | |
411 "Move article to a file, mode determined by file extension (babyl/msg)" | |
412 (interactive) | |
413 (gnus-summary-select-article) | |
414 (save-excursion | |
415 (set-buffer gnus-article-buffer) | |
416 (rmht-output nil t))) | |
417 | |
418 | |
419 (defun ht-write-body-to-file (file) | |
420 "Write the body of the message to a file and replace it with a pointer" | |
421 (interactive "FFile to save in: ") | |
422 (goto-char (point-min)) | |
423 (or (search-forward "\n\n" nil t) | |
424 (error "Can't find text")) | |
425 (write-region (point)(point-max) file) | |
426 (rmail-edit-current-message) | |
427 (delete-region (point)(point-max)) | |
428 (insert "\n>> " file "\n") | |
429 (rmail-cease-edit) | |
430 (rmht-output)) | |
431 | |
432 (defun extract-attachment () | |
433 "extract attachments from a multi-part mime message" | |
434 (interactive) | |
435 (rmail-toggle-header) | |
436 (mime/viewer-mode) | |
437 (let ((pt 0)) | |
438 (while (progn | |
439 (mime-viewer/next-content) | |
440 (and | |
441 (equal "*Preview-RMAIL*" (buffer-name (current-buffer))) | |
442 (not (= pt (point))))) | |
443 (setq pt (point)) | |
444 (if (looking-at "^\\[[0-9]* [^ ]+ <") | |
445 (mime-viewer/extract-content)))) | |
446 (if (not (equal "*Preview-RMAIL*" (buffer-name (current-buffer)))) | |
447 ;; we fell off the end | |
448 (rmail-previous-undeleted-message 1)) | |
449 (kill-buffer "*Preview-RMAIL*") | |
450 ) | |
451 | |
452 ;(load-library "mailcrypt") ; provides "mc-setversion" | |
453 ;(mc-setversion "gpg") ; for PGP 2.6 (default); also "5.0" and "gpg" | |
454 ;(autoload 'mc-install-write-mode "mailcrypt" nil t) | |
455 ;(autoload 'mc-install-read-mode "mailcrypt" nil t) | |
456 ;(add-hook 'mail-mode-hook 'mc-install-write-mode) | |
457 ;(add-hook 'gnus-summary-mode-hook 'mc-install-read-mode) | |
458 ;(add-hook 'message-mode-hook 'mc-install-write-mode) | |
459 ;(add-hook 'news-reply-mode-hook 'mc-install-write-mode) | |
460 ;(setq mc-passwd-timeout 6000) | |
461 ;;; Key server at Cambridge University (Cambridge, England) | |
462 ;(setq mc-pgp-fetch-methods '(mc-pgp-fetch-from-keyrings | |
463 ; mc-pgp-fetch-from-http)) | |
464 ;(require 'pgg) | |
465 ;(add-hook 'message-send-hook 'my-sign-message) | |
466 (setq hack-yn-map (copy-keymap query-replace-map)) | |
467 (define-key hack-yn-map 'return 'act) | |
468 | |
469 (defun my-sign-message () | |
470 (goto-char (point-min)) | |
471 (unless | |
472 (or | |
473 (re-search-forward "<#\\(part\\|mml\\) " nil t) | |
474 ; signing attachments doesn't seem | |
475 ; to work well | |
476 (search-forward "\n-- \nHenry S. Thompson, Central Edinburgh LM" nil t) | |
477 ; Don't sign Quaker mail | |
478 ) | |
479 (let* ((headers (mail-header-extract-no-properties)) | |
480 (cc (mail-header 'cc)) | |
481 (to (mail-header 'to))) | |
482 (if (and to | |
483 (not (string-match "htcalendar[@]markup\.co\.uk" to)) | |
484 (not (string-match "^ht$" to)) | |
485 (or | |
486 (string-match "w3.org" to) | |
487 (and cc (string-match "w3.org" cc)) | |
488 (let ((query-replace-map hack-yn-map)) | |
489 (y-or-n-p "Sign message? ")))) | |
490 (mml-secure-message-sign-pgp))))) | |
491 | |
492 (provide 'mail-extras) |