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)