aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman2008-12-29 19:12:22 +0000
committerRichard M. Stallman2008-12-29 19:12:22 +0000
commit5921f0a48cc137ff342ddfdd25b3bdec18c0baca (patch)
treec159e83408c7daad6a2226ee6f5b0f2525b8dd09
parente3021fe7dbe7a4bbbe9b4c9433c0f01f64cdcef3 (diff)
downloademacs-5921f0a48cc137ff342ddfdd25b3bdec18c0baca.tar.gz
emacs-5921f0a48cc137ff342ddfdd25b3bdec18c0baca.zip
(pmail-output-decode-coding): New variable.
(pmail-delete-unwanted-fields): Greatly simplified. (pmail-output-as-babyl): New function. (pmail-convert-to-babyl-format): Considerably simplified: assume just one message and don't worry about Content-Type. (pmail-output-as-mbox): New function. (pmail-output): Total rewrite. (pmail-output-as-seen): New command. (pmail-output-read-pmail-file-name): Function deleted. (pmail-output-to-babyl-file): Function deleted. (pmail-output-body-to-file): Don't set an attribute.
-rw-r--r--lisp/mail/pmailout.el691
1 files changed, 307 insertions, 384 deletions
diff --git a/lisp/mail/pmailout.el b/lisp/mail/pmailout.el
index ad00211d012..2d459453b2f 100644
--- a/lisp/mail/pmailout.el
+++ b/lisp/mail/pmailout.el
@@ -29,6 +29,13 @@
29(provide 'pmailout) 29(provide 'pmailout)
30 30
31;;;###autoload 31;;;###autoload
32(defcustom pmail-output-decode-coding nil
33 "*If non-nil, do coding system decoding when outputting message as Babyl."
34 :type '(choice (const :tag "on" t)
35 (const :tag "off" nil))
36 :group 'pmail)
37
38;;;###autoload
32(defcustom pmail-output-file-alist nil 39(defcustom pmail-output-file-alist nil
33 "*Alist matching regexps to suggested output Pmail files. 40 "*Alist matching regexps to suggested output Pmail files.
34This is a list of elements of the form (REGEXP . NAME-EXP). 41This is a list of elements of the form (REGEXP . NAME-EXP).
@@ -42,39 +49,6 @@ a file name as a string."
42 sexp))) 49 sexp)))
43 :group 'pmail-output) 50 :group 'pmail-output)
44 51
45(defun pmail-output-read-pmail-file-name ()
46 "Read the file name to use for `pmail-output-to-babyl-file'.
47Set `pmail-default-pmail-file' to this name as well as returning it."
48 (let ((default-file
49 (let (answer tail)
50 (setq tail pmail-output-file-alist)
51 ;; Suggest a file based on a pattern match.
52 (while (and tail (not answer))
53 (save-excursion
54 (set-buffer pmail-buffer)
55 (goto-char (point-min))
56 (if (re-search-forward (car (car tail)) nil t)
57 (setq answer (eval (cdr (car tail)))))
58 (setq tail (cdr tail))))
59 ;; If no suggestions, use same file as last time.
60 (expand-file-name (or answer pmail-default-pmail-file)))))
61 (let ((read-file
62 (expand-file-name
63 (read-file-name
64 (concat "Output message to Pmail file (default "
65 (file-name-nondirectory default-file)
66 "): ")
67 (file-name-directory default-file)
68 (abbreviate-file-name default-file))
69 (file-name-directory default-file))))
70 ;; If the user enters just a directory,
71 ;; use the name within that directory chosen by the default.
72 (setq pmail-default-pmail-file
73 (if (file-directory-p read-file)
74 (expand-file-name (file-name-nondirectory default-file)
75 read-file)
76 read-file)))))
77
78(defun pmail-output-read-file-name () 52(defun pmail-output-read-file-name ()
79 "Read the file name to use for `pmail-output'. 53 "Read the file name to use for `pmail-output'.
80Set `pmail-default-file' to this name as well as returning it." 54Set `pmail-default-file' to this name as well as returning it."
@@ -93,7 +67,7 @@ Set `pmail-default-file' to this name as well as returning it."
93 (let ((read-file 67 (let ((read-file
94 (expand-file-name 68 (expand-file-name
95 (read-file-name 69 (read-file-name
96 (concat "Output message to Unix mail file (default " 70 (concat "Output message to mail file (default "
97 (file-name-nondirectory default-file) 71 (file-name-nondirectory default-file)
98 "): ") 72 "): ")
99 (file-name-directory default-file) 73 (file-name-directory default-file)
@@ -107,244 +81,137 @@ Set `pmail-default-file' to this name as well as returning it."
107 (or read-file (file-name-nondirectory default-file)) 81 (or read-file (file-name-nondirectory default-file))
108 (file-name-directory default-file))))))) 82 (file-name-directory default-file)))))))
109 83
110(declare-function pmail-update-summary "pmailsum" (&rest ignore))
111
112;;; There are functions elsewhere in Emacs that use this function;
113;;; look at them before you change the calling method.
114;;;###autoload 84;;;###autoload
115(defun pmail-output-to-babyl-file (file-name &optional count stay) 85(defcustom pmail-fields-not-to-output nil
116 "Append the current message to a Babyl file named FILE-NAME. 86 "*Regexp describing fields to exclude when outputting a message to a file."
117If the file does not exist, ask if it should be created. 87 :type '(choice (const :tag "None" nil)
118If file is being visited, the message is appended to the Emacs 88 regexp)
119buffer visiting that file. 89 :group 'pmail-output)
120If the file exists and is not a Babyl file, the message is
121appended in inbox format, the same way `pmail-output' does it.
122
123The default file name comes from `pmail-default-pmail-file',
124which is updated to the name you use in this command.
125 90
126A prefix argument COUNT says to output that many consecutive messages, 91;; Delete from the buffer header fields we don't want output.
127starting with the current one. Deleted messages are skipped and don't count. 92;; Buffer should be pre-narrowed to the header.
93;; PRESERVE is a regexp for fields NEVER to delete.
94(defun pmail-delete-unwanted-fields (preserve)
95 (if pmail-fields-not-to-output
96 (save-excursion
97 (goto-char (point-min))
98 (while (re-search-forward pmail-fields-not-to-output nil t)
99 (beginning-of-line)
100 (unless (looking-at preserve)
101 (delete-region (point)
102 (progn (forward-line 1) (point))))))))
103
104(defun pmail-output-as-babyl (file-name nomsg)
105 "Convert the current buffer's text to Babyl and output to FILE-NAME.
106It alters the current buffer's text, so it should be a temp buffer."
107 (let ((coding-system-for-write
108 'emacs-mule-unix))
109 (save-restriction
110 (goto-char (point-min))
111 (search-forward "\n\n" nil 'move)
112 (narrow-to-region (point-min) (point))
113 (if pmail-fields-not-to-output
114 (pmail-delete-unwanted-fields nil)))
128 115
129If the optional argument STAY is non-nil, then leave the last filed 116 ;; Convert to Babyl format.
130message up instead of moving forward to the next non-deleted message." 117 (pmail-convert-to-babyl-format)
131 (interactive 118 ;; Write it into the file.
132 (list (pmail-output-read-pmail-file-name) 119 (write-region (point-min) (point-max) file-name t nomsg)))
133 (prefix-numeric-value current-prefix-arg)))
134 (or count (setq count 1))
135 (setq file-name
136 (expand-file-name file-name
137 (file-name-directory pmail-default-pmail-file)))
138 (if (and (file-readable-p file-name) (not (mail-file-babyl-p file-name)))
139 (pmail-output file-name count)
140 (pmail-maybe-set-message-counters)
141 (setq file-name (abbreviate-file-name file-name))
142 (or (find-buffer-visiting file-name)
143 (file-exists-p file-name)
144 (if (yes-or-no-p
145 (concat "\"" file-name "\" does not exist, create it? "))
146 (let ((file-buffer (create-file-buffer file-name)))
147 (save-excursion
148 (set-buffer file-buffer)
149 (let ((buffer-read-only nil))
150 (insert "BABYL OPTIONS: -*- pmail -*-
151Version: 5
152Labels:
153Note: This is the header of an pmail file.
154Note: If you are seeing it in pmail,
155Note: it means the file has no messages in it.\n\^_"))
156 (let ((require-final-newline nil)
157 (coding-system-for-write
158 (or pmail-file-coding-system
159 'emacs-mule-unix)))
160 (write-region (point-min) (point-max) file-name t 1)))
161 (kill-buffer file-buffer))
162 (error "Output file does not exist")))
163 (while (> count 0)
164 (let (redelete)
165 (unwind-protect
166 (progn
167 (set-buffer pmail-buffer)
168 ;; Temporarily turn off Deleted attribute.
169 ;; Do this outside the save-restriction, since it would
170 ;; shift the place in the buffer where the visible text starts.
171 (if (pmail-message-deleted-p pmail-current-message)
172 (progn (setq redelete t)
173 (pmail-set-attribute pmail-deleted-attr-index nil)))
174 (let ((coding-system-for-write
175 (or pmail-file-coding-system
176 'emacs-mule-unix))
177 cur beg end)
178 (pmail-swap-buffers-maybe)
179 (setq cur (current-buffer))
180 (save-restriction
181 (save-excursion
182 (widen)
183 (setq beg (pmail-msgbeg pmail-current-message)
184 end (pmail-msgend pmail-current-message))
185 ;; Output to a file.
186 (set-buffer (get-buffer-create " pmail-out-temp"))
187 (insert-buffer-substring cur beg end)
188 (if pmail-fields-not-to-output
189 (pmail-delete-unwanted-fields))
190 ;; Convert to Babyl format.
191 (pmail-convert-to-babyl-format)
192 (append-to-file (point-min) (point-max) file-name)
193 (set-buffer cur)
194 (kill-buffer (get-buffer " pmail-out-temp")))))
195 (pmail-set-attribute pmail-filed-attr-index t))
196 (if redelete (pmail-set-attribute pmail-deleted-attr-index t))))
197 (setq count (1- count))
198 (if pmail-delete-after-output
199 (unless (if (and (= count 0) stay)
200 (pmail-delete-message)
201 (pmail-delete-forward))
202 (setq count 0))
203 (if (> count 0)
204 (unless (if (not stay)
205 (pmail-next-undeleted-message 1))
206 (setq count 0))))))
207 (pmail-show-message))
208
209(defalias 'pmail-output-to-pmail-file 'pmail-output-to-babyl-file)
210 120
211(defun pmail-convert-to-babyl-format () 121(defun pmail-convert-to-babyl-format ()
212 (let ((count 0) start 122 (let ((count 0) (start (point-min))
213 (case-fold-search nil) 123 (case-fold-search nil)
214 (buffer-undo-list t)) 124 (buffer-undo-list t))
215 (goto-char (point-min)) 125 (goto-char (point-min))
216 (save-restriction 126 (save-restriction
217 (while (not (eobp)) 127 (unless (looking-at "^From ")
218 (setq start (point)) 128 (error "Invalid mbox message"))
219 (unless (looking-at "^From ") 129 (insert "\^L\n0, unseen,,\n*** EOOH ***\n")
220 (error "Invalid mbox message")) 130 (pmail-nuke-pinhead-header)
221 (insert "\^L\n0, unseen,,\n*** EOOH ***\n") 131 ;; Decode base64 or quoted printable contents, Rmail style.
222 (pmail-nuke-pinhead-header) 132 (let* ((header-end (save-excursion
223 ;; If this message has a Content-Length field, 133 (and (re-search-forward "\n\n" nil t)
224 ;; skip to the end of the contents. 134 (1- (point)))))
225 (let* ((header-end (save-excursion 135 (case-fold-search t)
226 (and (re-search-forward "\n\n" nil t) 136 (quoted-printable-header-field-end
227 (1- (point)))))
228 (case-fold-search t)
229 (quoted-printable-header-field-end
230 (save-excursion
231 (re-search-forward
232 "^content-transfer-encoding:\\(\n?[\t ]\\)*quoted-printable\\(\n?[\t ]\\)*"
233 header-end t)))
234 (base64-header-field-end
235 (and
236 ;; Don't decode non-text data.
237 (save-excursion
238 (re-search-forward
239 "^content-type:\\(\n?[\t ]\\)\\(text\\|message\\)/"
240 header-end t))
241 (save-excursion
242 (re-search-forward
243 "^content-transfer-encoding:\\(\n?[\t ]\\)*base64\\(\n?[\t ]\\)*"
244 header-end t))))
245 (size
246 ;; Get the numeric value from the Content-Length field.
247 (save-excursion
248 ;; Back up to end of prev line,
249 ;; in case the Content-Length field comes first.
250 (forward-char -1)
251 (and (search-forward "\ncontent-length: "
252 header-end t)
253 (let ((beg (point))
254 (eol (progn (end-of-line) (point))))
255 (string-to-number (buffer-substring beg eol)))))))
256 (and size
257 (if (and (natnump size)
258 (<= (+ header-end size) (point-max))
259 ;; Make sure this would put us at a position
260 ;; that we could continue from.
261 (save-excursion
262 (goto-char (+ header-end size))
263 (skip-chars-forward "\n")
264 (or (eobp)
265 (and (looking-at "BABYL OPTIONS:")
266 (search-forward "\n\^_" nil t))
267 (and (looking-at "\^L")
268 (search-forward "\n\^_" nil t))
269 (let ((case-fold-search t))
270 (looking-at pmail-mmdf-delim1))
271 (looking-at "From "))))
272 (goto-char (+ header-end size))
273 (message "Ignoring invalid Content-Length field")
274 (sit-for 1 0 t)))
275 (if (let ((case-fold-search nil))
276 (re-search-forward
277 (concat "^[\^_]?\\("
278 pmail-unix-mail-delimiter
279 "\\|"
280 pmail-mmdf-delim1 "\\|"
281 "^BABYL OPTIONS:\\|"
282 "\^L\n[01],\\)") nil t))
283 (goto-char (match-beginning 1))
284 (goto-char (point-max)))
285 (setq count (1+ count))
286 (if quoted-printable-header-field-end
287 (save-excursion 137 (save-excursion
288 (unless (mail-unquote-printable-region 138 (re-search-forward
289 header-end (point) nil t t) 139 "^content-transfer-encoding:\\(\n?[\t ]\\)*quoted-printable\\(\n?[\t ]\\)*"
290 (message "Malformed MIME quoted-printable message")) 140 header-end t)))
291 ;; Change "quoted-printable" to "8bit", 141 (base64-header-field-end
292 ;; to reflect the decoding we just did. 142 (and
293 (goto-char quoted-printable-header-field-end) 143 ;; Don't decode non-text data.
144 (save-excursion
145 (re-search-forward
146 "^content-type:\\(\n?[\t ]\\)\\(text\\|message\\)/"
147 header-end t))
148 (save-excursion
149 (re-search-forward
150 "^content-transfer-encoding:\\(\n?[\t ]\\)*base64\\(\n?[\t ]\\)*"
151 header-end t)))))
152
153 (goto-char (point-max))
154 (if quoted-printable-header-field-end
155 (save-excursion
156 (unless (mail-unquote-printable-region
157 header-end (point) nil t t)
158 (message "Malformed MIME quoted-printable message"))
159 ;; Change "quoted-printable" to "8bit",
160 ;; to reflect the decoding we just did.
161 (goto-char quoted-printable-header-field-end)
162 (delete-region (point) (search-backward ":"))
163 (insert ": 8bit")))
164 (if base64-header-field-end
165 (save-excursion
166 (when (condition-case nil
167 (progn
168 (base64-decode-region
169 (1+ header-end)
170 (save-excursion
171 ;; Prevent base64-decode-region
172 ;; from removing newline characters.
173 (skip-chars-backward "\n\t ")
174 (point)))
175 t)
176 (error nil))
177 ;; Change "base64" to "8bit", to reflect the
178 ;; decoding we just did.
179 (goto-char base64-header-field-end)
294 (delete-region (point) (search-backward ":")) 180 (delete-region (point) (search-backward ":"))
295 (insert ": 8bit"))) 181 (insert ": 8bit")))))
296 (if base64-header-field-end 182 ;; Transform anything within the message text
297 (save-excursion 183 ;; that might appear to be the end of a Babyl-format message.
298 (when (condition-case nil 184 (save-excursion
299 (progn 185 (save-restriction
300 (base64-decode-region 186 (narrow-to-region start (point))
301 (1+ header-end) 187 (goto-char (point-min))
302 (save-excursion 188 (while (search-forward "\n\^_" nil t) ; single char
303 ;; Prevent base64-decode-region 189 (replace-match "\n^_")))) ; 2 chars: "^" and "_"
304 ;; from removing newline characters. 190 ;; This is for malformed messages that don't end in newline.
305 (skip-chars-backward "\n\t ") 191 ;; There shouldn't be any, but some users say occasionally
306 (point))) 192 ;; there are some.
307 t) 193 (or (bolp) (newline))
308 (error nil)) 194 (insert ?\^_)
309 ;; Change "base64" to "8bit", to reflect the 195 (setq last-coding-system-used nil)
310 ;; decoding we just did. 196 ;; Decode coding system, following specs in the message header,
311 (goto-char base64-header-field-end) 197 ;; and record what coding system was decoded.
312 (delete-region (point) (search-backward ":")) 198 (if pmail-output-decode-coding
313 (insert ": 8bit"))))) 199 (let ((mime-charset
314 (save-excursion 200 (if (save-excursion
315 (save-restriction 201 (goto-char start)
316 (narrow-to-region start (point)) 202 (search-forward "\n\n" nil t)
317 (goto-char (point-min)) 203 (let ((case-fold-search t))
318 (while (search-forward "\n\^_" nil t) ; single char 204 (re-search-backward
319 (replace-match "\n^_")))) ; 2 chars: "^" and "_" 205 pmail-mime-charset-pattern
320 ;; This is for malformed messages that don't end in newline. 206 start t)))
321 ;; There shouldn't be any, but some users say occasionally 207 (intern (downcase (match-string 1))))))
322 ;; there are some. 208 (pmail-decode-region start (point) mime-charset)))
323 (or (bolp) (newline)) 209 (save-excursion
324 (insert ?\^_) 210 (goto-char start)
325 (setq last-coding-system-used nil) 211 (forward-line 3)
326 (or pmail-enable-mime 212 (insert "X-Coding-System: "
327 (not pmail-enable-multibyte) 213 (symbol-name last-coding-system-used)
328 (let ((mime-charset 214 "\n")))))
329 (if (and pmail-decode-mime-charset
330 (save-excursion
331 (goto-char start)
332 (search-forward "\n\n" nil t)
333 (let ((case-fold-search t))
334 (re-search-backward
335 pmail-mime-charset-pattern
336 start t))))
337 (intern (downcase (match-string 1))))))
338 (pmail-decode-region start (point) mime-charset)))
339 (save-excursion
340 (goto-char start)
341 (forward-line 3)
342 (insert "X-Coding-System: "
343 (symbol-name last-coding-system-used)
344 "\n"))
345 (narrow-to-region (point) (point-max))
346 (and (= 0 (% count 10))
347 (message "Converting to Babyl format...%d" count))))))
348 215
349;; Delete the "From ..." line, creating various other headers with 216;; Delete the "From ..." line, creating various other headers with
350;; information from it if they don't already exist. Now puts the 217;; information from it if they don't already exist. Now puts the
@@ -398,31 +265,54 @@ Note: it means the file has no messages in it.\n\^_"))
398 "" 265 ""
399 "From: \\1\n")) 266 "From: \\1\n"))
400 t))))))) 267 t)))))))
268
269(defun pmail-output-as-mbox (file-name nomsg)
270 "Convert the current buffer's text to mbox Babyl and output to FILE-NAME.
271It alters the current buffer's text, so it should be a temp buffer."
272 (let ((case-fold-search t)
273 mail-from mime-version content-type)
401 274
402;;;###autoload 275 ;; Preserve the Mail-From and MIME-Version fields
403(defcustom pmail-fields-not-to-output nil 276 ;; even if they have been pruned.
404 "*Regexp describing fields to exclude when outputting a message to a file." 277 (search-forward "\n\n" nil 'move)
405 :type '(choice (const :tag "None" nil) 278 (narrow-to-region (point-min) (point))
406 regexp)
407 :group 'pmail-output)
408 279
409;; Delete from the buffer header fields we don't want output. 280 (pmail-delete-unwanted-fields
410;; NOT-PMAIL if t means this buffer does not have the full header 281 (if pmail-enable-mime "Mail-From"
411;; and *** EOOH *** that a message in an Pmail file has. 282 "Mail-From\\|MIME-Version\\|Content-type"))
412(defun pmail-delete-unwanted-fields (&optional not-pmail)
413 (if pmail-fields-not-to-output
414 (save-excursion
415 (goto-char (point-min))
416 ;; Find the end of the header.
417 (if (and (or not-pmail (search-forward "\n*** EOOH ***\n" nil t))
418 (search-forward "\n\n" nil t))
419 (let ((end (point-marker)))
420 (goto-char (point-min))
421 (while (re-search-forward pmail-fields-not-to-output end t)
422 (beginning-of-line)
423 (delete-region (point)
424 (progn (forward-line 1) (point)))))))))
425 283
284 (widen)
285
286 ;; Make sure message ends with blank line.
287 (goto-char (point-max))
288 (unless (bolp)
289 (insert "\n"))
290 (unless (looking-back "\n\n")
291 (insert "\n"))
292
293 ;; Generate a From line from other header fields
294 ;; if necessary.
295 (goto-char (point-min))
296 (unless (looking-at "From ")
297 (insert "From "
298 (mail-strip-quoted-names
299 (save-excursion
300 (save-restriction
301 (goto-char (point-min))
302 (narrow-to-region
303 (point)
304 (or (search-forward "\n\n" nil)
305 (point-max)))
306 (or (mail-fetch-field "from")
307 (mail-fetch-field "really-from")
308 (mail-fetch-field "sender")
309 "unknown"))))
310 " " (current-time-string) "\n"))
311
312 (let ((coding-system-for-write
313 'raw-text-unix))
314 (write-region (point-min) (point-max) file-name t nomsg))))
315
426;;; There are functions elsewhere in Emacs that use this function; 316;;; There are functions elsewhere in Emacs that use this function;
427;;; look at them before you change the calling method. 317;;; look at them before you change the calling method.
428;;;###autoload 318;;;###autoload
@@ -430,11 +320,9 @@ Note: it means the file has no messages in it.\n\^_"))
430 "Append this message to system-inbox-format mail file named FILE-NAME. 320 "Append this message to system-inbox-format mail file named FILE-NAME.
431A prefix argument COUNT says to output that many consecutive messages, 321A prefix argument COUNT says to output that many consecutive messages,
432starting with the current one. Deleted messages are skipped and don't count. 322starting with the current one. Deleted messages are skipped and don't count.
433When called from lisp code, COUNT may be omitted and defaults to 1. 323When called from Lisp code, COUNT may be omitted and defaults to 1.
434 324
435If the pruned message header is shown on the current message, then 325This outputs the complete message header even the display is pruned.
436messages will be appended with pruned headers; otherwise, messages
437will be appended with their original headers.
438 326
439The default file name comes from `pmail-default-file', 327The default file name comes from `pmail-default-file',
440which is updated to the name you use in this command. 328which is updated to the name you use in this command.
@@ -451,104 +339,141 @@ The optional fourth argument FROM-GNUS is set when called from GNUS."
451 (expand-file-name file-name 339 (expand-file-name file-name
452 (and pmail-default-file 340 (and pmail-default-file
453 (file-name-directory pmail-default-file)))) 341 (file-name-directory pmail-default-file))))
454 (if (and (file-readable-p file-name) (mail-file-babyl-p file-name)) 342 (set-buffer pmail-buffer)
455 (pmail-output-to-babyl-file file-name count) 343
456 (set-buffer pmail-buffer) 344 ;; Warn about creating new file.
457 (let ((orig-count count) 345 (or (find-buffer-visiting file-name)
458 (pmailbuf pmail-buffer) 346 (file-exists-p file-name)
459 (case-fold-search t) 347 (yes-or-no-p
460 (tembuf (get-buffer-create " pmail-output")) 348 (concat "\"" file-name "\" does not exist, create it? "))
461 header-beginning 349 (error "Output file does not exist"))
462 mail-from mime-version content-type) 350
463 (while (> count 0) 351 (let ((orig-count count)
464 ;; Preserve the Mail-From and MIME-Version fields 352 (case-fold-search t)
465 ;; even if they have been pruned. 353 (tembuf (get-buffer-create " pmail-output"))
466 (or from-gnus 354 (babyl-format
355 (and (file-readable-p file-name) (mail-file-babyl-p file-name))))
356
357 (unwind-protect
358 (while (> count 0)
359 (with-current-buffer pmail-buffer
360 (let (cur beg end)
361 (setq beg (pmail-msgbeg pmail-current-message)
362 end (pmail-msgend pmail-current-message))
363 ;; All access to the buffer's local variables is now finished...
364 (save-excursion
365 ;; ... so it is ok to go to a different buffer.
366 (if (pmail-buffers-swapped-p) (set-buffer pmail-view-buffer))
367 (setq cur (current-buffer))
368 (save-restriction
369 (widen)
370 (with-current-buffer tembuf
371 (insert-buffer-substring cur beg end)
372 ;; Convert the text to one format or another and output.
373 (if babyl-format
374 (pmail-output-as-babyl file-name (if noattribute 'nomsg))
375 (pmail-output-as-mbox file-name
376 (if noattribute 'nomsg))))))))
377
378 ;; Mark message as "filed".
379 (unless noattribute
380 (pmail-set-attribute pmail-filed-attr-index t))
381
382 (setq count (1- count))
383
384 (or from-gnus
385 (let ((next-message-p
386 (if pmail-delete-after-output
387 (pmail-delete-forward)
388 (if (> count 0)
389 (pmail-next-undeleted-message 1))))
390 (num-appended (- orig-count count)))
391 (if (and (> count 0) (not next-message-p))
392 (error "Only %d message%s appended" num-appended
393 (if (= num-appended 1) "" "s"))))))
394 (kill-buffer tembuf))))
395
396(defun pmail-output-as-seen (file-name &optional count noattribute from-gnus)
397 "Append this message to system-inbox-format mail file named FILE-NAME.
398A prefix argument COUNT says to output that many consecutive messages,
399starting with the current one. Deleted messages are skipped and don't count.
400When called from Lisp code, COUNT may be omitted and defaults to 1.
401
402This outputs the message header as you see it.
403
404The default file name comes from `pmail-default-file',
405which is updated to the name you use in this command.
406
407The optional third argument NOATTRIBUTE, if non-nil, says not
408to set the `filed' attribute, and not to display a message.
409
410The optional fourth argument FROM-GNUS is set when called from GNUS."
411 (interactive
412 (list (pmail-output-read-file-name)
413 (prefix-numeric-value current-prefix-arg)))
414 (or count (setq count 1))
415 (setq file-name
416 (expand-file-name file-name
417 (and pmail-default-file
418 (file-name-directory pmail-default-file))))
419 (set-buffer pmail-buffer)
420
421 ;; Warn about creating new file.
422 (or (find-buffer-visiting file-name)
423 (file-exists-p file-name)
424 (yes-or-no-p
425 (concat "\"" file-name "\" does not exist, create it? "))
426 (error "Output file does not exist"))
427
428 (if (and (file-readable-p file-name) (mail-file-babyl-p file-name))
429 (error "Cannot output `as seen' to a Babyl file"))
430
431 (let ((orig-count count)
432 (case-fold-search t)
433 (tembuf (get-buffer-create " pmail-output")))
434
435 (unwind-protect
436 (while (> count 0)
437 (let (cur beg end)
438 ;; If operating from whole-mbox buffer, get message bounds.
439 (if (not (pmail-buffers-swapped-p))
440 (setq beg (pmail-msgbeg pmail-current-message)
441 end (pmail-msgend pmail-current-message)))
442 ;; All access to the buffer's local variables is now finished...
467 (save-excursion 443 (save-excursion
444 (setq cur (current-buffer))
468 (save-restriction 445 (save-restriction
469 (goto-char (if (pmail-buffers-swapped-p) 446 (widen)
470 (point-min) 447 ;; If operating from the view buffer, get the bounds.
471 (pmail-msgbeg pmail-current-message))) 448 (unless beg
472 (setq header-beginning (point)) 449 (setq beg (point-min)
473 (search-forward "\n\n" nil 'move) 450 end (point-max)))
474 (narrow-to-region header-beginning (point)) 451
475 (setq mail-from (mail-fetch-field "Mail-From")) 452 (with-current-buffer tembuf
476 (unless pmail-enable-mime 453 (insert-buffer-substring cur beg end)
477 (setq mime-version (mail-fetch-field "MIME-Version") 454 ;; Convert the text to one format or another and output.
478 content-type (mail-fetch-field "Content-type")))))) 455 (pmail-output-as-mbox file-name
479 (save-excursion 456 (if noattribute 'nomsg))))))
480 (set-buffer tembuf) 457
481 (erase-buffer) 458 ;; Mark message as "filed".
482 (insert-buffer-substring pmailbuf) 459 (unless noattribute
483 (save-excursion 460 (pmail-set-attribute pmail-filed-attr-index t))
484 (goto-char (min (point-min) (- (point-max) 2))) 461
485 (unless (looking-at "\n\n") 462 (setq count (1- count))
486 (goto-char (point-max)) 463
487 (insert "\n\n"))) 464 (or from-gnus
488 (when pmail-enable-mime 465 (let ((next-message-p
489 (goto-char (point-min)) 466 (if pmail-delete-after-output
490 (forward-line 2) 467 (pmail-delete-forward)
491 (delete-region (point-min) (point)) 468 (if (> count 0)
492 (search-forward "\n\n") 469 (pmail-next-undeleted-message 1))))
493 (delete-region (match-beginning 0) 470 (num-appended (- orig-count count)))
494 (if (search-forward "\n\n") 471 (if (and (> count 0) (not next-message-p))
495 (1- (match-end 0)))) 472 (error "Only %d message%s appended" num-appended
496 (setq buffer-file-coding-system (or pmail-file-coding-system 473 (if (= num-appended 1) "" "s"))))))
497 'raw-text)))
498 (pmail-delete-unwanted-fields t)
499 (or (bolp) (insert "\n"))
500 (goto-char (point-min))
501 (if mail-from
502 (insert mail-from "\n")
503 (insert "From "
504 (mail-strip-quoted-names
505 (save-excursion
506 (save-restriction
507 (goto-char (point-min))
508 (narrow-to-region
509 (point)
510 (or (search-forward "\n\n" nil)
511 (point-max)))
512 (or (mail-fetch-field "from")
513 (mail-fetch-field "really-from")
514 (mail-fetch-field "sender")
515 "unknown"))))
516 " " (current-time-string) "\n"))
517 (when mime-version
518 (insert "MIME-Version: " mime-version)
519 ;; Some malformed MIME messages set content-type to nil.
520 (when content-type
521 (insert "\nContent-type: " content-type "\n")))
522 ;; ``Quote'' "\nFrom " as "\n>From "
523 ;; (note that this isn't really quoting, as there is no requirement
524 ;; that "\n[>]+From " be quoted in the same transparent way.)
525 (let ((case-fold-search nil))
526 (while (search-forward "\nFrom " nil t)
527 (forward-char -5)
528 (insert ?>)))
529 (write-region (point-min) (point-max) file-name t
530 (if noattribute 'nomsg)))
531 (or noattribute
532 (if (equal major-mode 'pmail-mode)
533 (pmail-set-attribute pmail-filed-attr-index t)))
534 (setq count (1- count))
535 (or from-gnus
536 (let ((next-message-p
537 (if pmail-delete-after-output
538 (pmail-delete-forward)
539 (if (> count 0)
540 (pmail-next-undeleted-message 1))))
541 (num-appended (- orig-count count)))
542 (if (and (> count 0) (not next-message-p))
543 (progn
544 (error "%s"
545 (save-excursion
546 (set-buffer pmailbuf)
547 (format "Only %d message%s appended" num-appended
548 (if (= num-appended 1) "" "s"))))
549 (setq count 0))))))
550 (kill-buffer tembuf)))) 474 (kill-buffer tembuf))))
551 475
476
552;;;###autoload 477;;;###autoload
553(defun pmail-output-body-to-file (file-name) 478(defun pmail-output-body-to-file (file-name)
554 "Write this message body to the file FILE-NAME. 479 "Write this message body to the file FILE-NAME.
@@ -573,9 +498,7 @@ FILE-NAME defaults, interactively, from the Subject field of the message."
573 (and (file-exists-p file-name) 498 (and (file-exists-p file-name)
574 (not (y-or-n-p (format "File %s exists; overwrite? " file-name))) 499 (not (y-or-n-p (format "File %s exists; overwrite? " file-name)))
575 (error "Operation aborted")) 500 (error "Operation aborted"))
576 (write-region (point) (point-max) file-name) 501 (write-region (point) (point-max) file-name))
577 (if (equal major-mode 'pmail-mode)
578 (pmail-set-attribute pmail-stored-attr-index t)))
579 (if pmail-delete-after-output 502 (if pmail-delete-after-output
580 (pmail-delete-forward))) 503 (pmail-delete-forward)))
581 504