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