Mercurial > emacs
comparison lisp/mail/undigest.el @ 48868:3395df62dc04
Now supports MIME too.
author | Francesco Potortì <pot@gnu.org> |
---|---|
date | Mon, 16 Dec 2002 16:22:41 +0000 |
parents | 770c9bc95b39 |
children | 0d1bd8730873 |
comparison
equal
deleted
inserted
replaced
48867:1bd259d860a2 | 48868:3395df62dc04 |
---|---|
1 ;;; undigest.el --- digest-cracking support for the RMAIL mail reader | 1 ;;; undigest.el --- digest-cracking support for the RMAIL mail reader |
2 | 2 |
3 ;; Copyright (C) 1985, 1986, 1994, 1996 Free Software Foundation, Inc. | 3 ;; Copyright (C) 1985, 1986, 1994, 1996, 2002 |
4 ;; Free Software Foundation, Inc. | |
4 | 5 |
5 ;; Maintainer: FSF | 6 ;; Maintainer: FSF |
6 ;; Keywords: mail | 7 ;; Keywords: mail |
7 | 8 |
8 ;; This file is part of GNU Emacs. | 9 ;; This file is part of GNU Emacs. |
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
23 ;; Boston, MA 02111-1307, USA. | 24 ;; Boston, MA 02111-1307, USA. |
24 | 25 |
25 ;;; Commentary: | 26 ;;; Commentary: |
26 | 27 |
27 ;; See Internet RFC 934 | 28 ;; See Internet RFC 934 and RFC 1153 |
28 | 29 |
29 ;;; Code: | 30 ;;; Code: |
30 | 31 |
31 (require 'rmail) | 32 (require 'rmail) |
32 | 33 |
33 (defcustom rmail-digest-end-regexps | 34 (defconst rmail-digest-methods |
34 (list "End of.*Digest.*\n" "End of.*\n") | 35 '(rmail-digest-parse-mime |
35 "*Regexps matching the end of a digest message." | 36 rmail-digest-parse-rfc1153strict |
36 :group 'rmail | 37 rmail-digest-parse-rfc1153sloppy |
37 :type '(repeat regexp)) | 38 rmail-digest-parse-rfc934) |
39 "List of digest parsing functions, in preference order. | |
40 | |
41 The functions operate on the current narrowing, and take no argument. A | |
42 function returns nil if it cannot parse the digest. If it can, it | |
43 returns a list of cons pairs containing the start and end positions of | |
44 each undigestified message as markers.") | |
45 | |
46 (defconst rmail-digest-mail-separator | |
47 "\^_\^L\n0, unseen,,\n*** EOOH ***\n" | |
48 "String substituted to the digest separator to create separate messages.") | |
49 | |
50 | |
51 | |
52 (defun rmail-digest-parse-mime () | |
53 (goto-char (point-min)) | |
54 (when (let ((head-end (progn (search-forward "\n\n" nil t) (point)))) | |
55 (goto-char (point-min)) | |
56 (and head-end | |
57 (re-search-forward | |
58 (concat | |
59 "^Content-type: multipart/digest;" | |
60 "\\s-* boundary=\"?\\([^\";\n]+\\)[\";\n]") head-end t) | |
61 (search-forward (match-string 1) nil t))) | |
62 ;; Ok, prolog separator found | |
63 (let ((start (make-marker)) | |
64 (end (make-marker)) | |
65 (separator (concat "\n--" (match-string 0) "\n\n")) | |
66 result) | |
67 (while (search-forward separator nil t) | |
68 (move-marker start (match-beginning 0)) | |
69 (move-marker end (match-end 0)) | |
70 (add-to-list 'result (cons (copy-marker start) (copy-marker end t)))) | |
71 ;; Return the list of marker pairs | |
72 (nreverse result)))) | |
73 | |
74 (defun rmail-digest-parse-rfc1153strict () | |
75 "Parse following strictly the method defined in RFC 1153. | |
76 See rmail-digest-methods." | |
77 (rmail-digest-rfc1153 | |
78 "^-\\{70\\}\n\n" | |
79 "^\n-\\{30\\}\n\n" | |
80 "^\n-\\{30\\}\n\nEnd of .* Digest.*\n\\*\\{15,\\}\n+\'")) | |
81 | |
82 (defun rmail-digest-parse-rfc1153sloppy () | |
83 "Parse using the method defined in RFC 1153, allowing for some sloppiness. | |
84 See rmail-digest-methods." | |
85 (rmail-digest-rfc1153 | |
86 "^-\\{55,\\}\n\n" | |
87 "^\n-\\{27,\\}\n\n" | |
88 "^\n-\\{27,\\}\n\nEnd of")) | |
89 | |
90 (defun rmail-digest-rfc1153 (prolog-sep message-sep trailer-sep) | |
91 (goto-char (point-min)) | |
92 (when (re-search-forward prolog-sep nil t) | |
93 ;; Ok, prolog separator found | |
94 (let ((start (make-marker)) | |
95 (end (make-marker)) | |
96 separator result) | |
97 (move-marker start (match-beginning 0)) | |
98 (move-marker end (match-end 0)) | |
99 (setq result (cons (copy-marker start) (copy-marker end t))) | |
100 (when (re-search-forward message-sep nil t) | |
101 ;; Ok, at least one message separator found | |
102 (setq separator (match-string 0)) | |
103 (when (re-search-forward trailer-sep nil t) | |
104 ;; Wonderful, we found a trailer, too. Now, go on splitting | |
105 ;; the digest into separate rmail messages | |
106 (goto-char (cdar result)) | |
107 (while (search-forward separator nil t) | |
108 (move-marker start (match-beginning 0)) | |
109 (move-marker end (match-end 0)) | |
110 (add-to-list 'result | |
111 (cons (copy-marker start) (copy-marker end t)))) | |
112 ;; Undo masking of separators inside digestified messages | |
113 (goto-char (point-min)) | |
114 (while (search-forward | |
115 (replace-regexp-in-string "\n-" "\n " separator) nil t) | |
116 (replace-match separator)) | |
117 ;; Return the list of marker pairs | |
118 (nreverse result)))))) | |
119 | |
120 (defun rmail-digest-parse-rfc934 () | |
121 (goto-char (point-min)) | |
122 (when (re-search-forward "^\n?-[^ ].*\n\n?" nil t) | |
123 ;; Message separator found | |
124 (let ((start (make-marker)) | |
125 (end (make-marker)) | |
126 (separator (match-string 0)) | |
127 result) | |
128 (goto-char (point-min)) | |
129 (while (search-forward separator nil t) | |
130 (move-marker start (match-beginning 0)) | |
131 (move-marker end (match-end 0)) | |
132 (add-to-list 'result (cons (copy-marker start) (copy-marker end t)))) | |
133 ;; Undo masking of separators inside digestified messages | |
134 (goto-char (point-min)) | |
135 (while (search-forward "\n- -" nil t) | |
136 (replace-match "\n-")) | |
137 ;; Return the list of marker pairs | |
138 (nreverse result)))) | |
139 | |
140 | |
38 | 141 |
39 ;;;###autoload | 142 ;;;###autoload |
40 (defun undigestify-rmail-message () | 143 (defun undigestify-rmail-message () |
41 "Break up a digest message into its constituent messages. | 144 "Break up a digest message into its constituent messages. |
42 Leaves original message, deleted, before the undigestified messages." | 145 Leaves original message, deleted, before the undigestified messages." |
43 (interactive) | 146 (interactive) |
44 (with-current-buffer rmail-buffer | 147 (with-current-buffer rmail-buffer |
45 (widen) | 148 (widen) |
46 (let ((buffer-read-only nil) | |
47 (msg-string (buffer-substring (rmail-msgbeg rmail-current-message) | |
48 (rmail-msgend rmail-current-message)))) | |
49 (goto-char (rmail-msgend rmail-current-message)) | |
50 (narrow-to-region (point) (point)) | |
51 (insert msg-string) | |
52 (narrow-to-region (point-min) (1- (point-max)))) | |
53 (let ((error t) | 149 (let ((error t) |
54 (buffer-read-only nil)) | 150 (buffer-read-only nil)) |
151 (goto-char (rmail-msgend rmail-current-message)) | |
152 (let ((msg-copy (buffer-substring (rmail-msgbeg rmail-current-message) | |
153 (rmail-msgend rmail-current-message)))) | |
154 (narrow-to-region (point) (point)) | |
155 (insert msg-copy)) | |
156 (narrow-to-region (point-min) (1- (point-max))) | |
55 (unwind-protect | 157 (unwind-protect |
56 (progn | 158 (progn |
57 (save-restriction | 159 (save-restriction |
58 (goto-char (point-min)) | 160 (goto-char (point-min)) |
59 (delete-region (point-min) | 161 (delete-region (point-min) |
60 (progn (search-forward "\n*** EOOH ***\n") | 162 (progn (search-forward "\n*** EOOH ***\n" nil t) |
61 (point))) | 163 (point))) |
62 (insert "\^_\^L\n0, unseen,,\n*** EOOH ***\n") | 164 (insert "\n" rmail-digest-mail-separator) |
63 (narrow-to-region (point) | 165 (narrow-to-region (point) |
64 (point-max)) | 166 (point-max)) |
65 (let* ((fill-prefix "") | 167 (let ((fill-prefix "") |
66 (case-fold-search t) | 168 (case-fold-search t) |
67 start | 169 digest-name type start end separator fun-list sep-list) |
68 (digest-name | 170 (setq digest-name (mail-strip-quoted-names |
69 (mail-strip-quoted-names | 171 (save-restriction |
70 (or (save-restriction | 172 (search-forward "\n\n" nil 'move) |
71 (search-forward "\n\n") | 173 (setq start (point)) |
72 (setq start (point)) | 174 (narrow-to-region (point-min) start) |
73 (narrow-to-region (point-min) (point)) | 175 (or (mail-fetch-field "Reply-To") |
74 (goto-char (point-max)) | 176 (mail-fetch-field "To") |
75 (or (mail-fetch-field "Reply-To") | 177 (mail-fetch-field "Apparently-To") |
76 (mail-fetch-field "To") | 178 (mail-fetch-field "From"))))) |
77 (mail-fetch-field "Apparently-To") | 179 (unless digest-name |
78 (mail-fetch-field "From"))) | 180 (error "Message is not a digest--bad header")) |
79 (error "Message is not a digest--bad header"))))) | 181 |
80 (save-excursion | 182 (setq fun-list rmail-digest-methods) |
81 (let (found | 183 (while (and fun-list |
82 (regexps rmail-digest-end-regexps)) | 184 (null (setq sep-list (funcall (car fun-list))))) |
83 (while (and regexps (not found)) | 185 (setq fun-list (cdr fun-list))) |
84 (goto-char (point-max)) | 186 (unless sep-list |
85 ;; compensate for broken un*x digestifiers. Sigh Sigh. | 187 (error "Message is not a digest--no messages found")) |
86 (setq found (re-search-backward | 188 |
87 (concat "^\\(?:" (car regexps) "\\)") | 189 ;;; Split the digest into separate rmail messages |
88 start t)) | 190 (while sep-list |
89 (setq regexps (cdr regexps))) | 191 (let ((start (caar sep-list)) |
90 (unless found | 192 (end (cdar sep-list))) |
91 (error "Message is not a digest--no end line")))) | 193 (delete-region start end) |
92 (re-search-forward (concat "^" (make-string 55 ?-) "-*\n*")) | 194 (goto-char start) |
93 (replace-match "\^_\^L\n0, unseen,,\n*** EOOH ***\n") | 195 (insert rmail-digest-mail-separator) |
94 (save-restriction | 196 (search-forward "\n\n" (caar (cdr sep-list)) 'move) |
95 (narrow-to-region (point) | 197 (save-restriction |
96 (progn (search-forward "\n\n") | 198 (narrow-to-region end (point)) |
97 (point))) | 199 (unless (mail-fetch-field "To") |
98 (if (mail-fetch-field "To") nil | 200 (goto-char start) |
99 (goto-char (point-min)) | 201 (insert "To: " digest-name "\n"))) |
100 (insert "To: " digest-name "\n"))) | 202 (set-marker start nil) |
101 (while (re-search-forward | 203 (set-marker end nil)) |
102 (concat "\n\n" (make-string 27 ?-) "-*\n*") | 204 (setq sep-list (cdr sep-list))))) |
103 nil t) | 205 |
104 (replace-match "\n\n\^_\^L\n0, unseen,,\n*** EOOH ***\n") | |
105 (save-restriction | |
106 (if (looking-at "End ") | |
107 (insert "To: " digest-name "\n\n") | |
108 (narrow-to-region (point) | |
109 (progn (search-forward "\n\n" | |
110 nil 'move) | |
111 (point)))) | |
112 (if (mail-fetch-field "To") | |
113 nil | |
114 (goto-char (point-min)) | |
115 (insert "To: " digest-name "\n"))) | |
116 ;; Digestifiers may insert `- ' on lines that start with `-'. | |
117 ;; Undo that. | |
118 (save-excursion | |
119 (goto-char (point-min)) | |
120 (if (re-search-forward | |
121 "\n\n----------------------------*\n*" | |
122 nil t) | |
123 (let ((end (point-marker))) | |
124 (goto-char (point-min)) | |
125 (while (re-search-forward "^- " end t) | |
126 (delete-char -2))))) | |
127 ))) | |
128 (setq error nil) | 206 (setq error nil) |
129 (message "Message successfully undigestified") | 207 (message "Message successfully undigestified") |
130 (let ((n rmail-current-message)) | 208 (let ((n rmail-current-message)) |
131 (rmail-forget-messages) | 209 (rmail-forget-messages) |
132 (rmail-show-message n) | 210 (rmail-show-message n) |