aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChong Yidong2008-12-13 14:19:56 +0000
committerChong Yidong2008-12-13 14:19:56 +0000
commit7635ef3856717a023d81ef246b2a4023c9eff7e6 (patch)
tree94399475968d558ad0e9850a10d21557ed884c1a
parentf047d0db1973d73fdb8b9bbfd8e60540f7efc361 (diff)
downloademacs-7635ef3856717a023d81ef246b2a4023c9eff7e6.tar.gz
emacs-7635ef3856717a023d81ef246b2a4023c9eff7e6.zip
(pmail-output-to-babyl-file): Rewrite, assuming mbox
internal format. (pmail-convert-to-babyl-format, pmail-nuke-pinhead-header): New functions, moved from pmail.el.
-rw-r--r--lisp/mail/pmailout.el283
1 files changed, 219 insertions, 64 deletions
diff --git a/lisp/mail/pmailout.el b/lisp/mail/pmailout.el
index 11965f9dfac..f0d0ae9c361 100644
--- a/lisp/mail/pmailout.el
+++ b/lisp/mail/pmailout.el
@@ -171,79 +171,234 @@ Note: it means the file has no messages in it.\n\^_"))
171 (if (pmail-message-deleted-p pmail-current-message) 171 (if (pmail-message-deleted-p pmail-current-message)
172 (progn (setq redelete t) 172 (progn (setq redelete t)
173 (pmail-set-attribute pmail-deleted-attr-index nil))) 173 (pmail-set-attribute pmail-deleted-attr-index nil)))
174 (save-restriction 174 (let ((coding-system-for-write
175 (widen) 175 (or pmail-file-coding-system
176 ;; Decide whether to append to a file or to an Emacs buffer. 176 'emacs-mule-unix))
177 (save-excursion 177 cur beg end)
178 (let ((buf (find-buffer-visiting file-name)) 178 (pmail-swap-buffers-maybe)
179 (cur (current-buffer)) 179 (setq cur (current-buffer))
180 (beg (1+ (pmail-msgbeg pmail-current-message))) 180 (save-restriction
181 (end (1+ (pmail-msgend pmail-current-message))) 181 (save-excursion
182 (coding-system-for-write 182 (widen)
183 (or pmail-file-coding-system 183 (setq beg (pmail-msgbeg pmail-current-message)
184 'emacs-mule-unix))) 184 end (pmail-msgend pmail-current-message))
185 (if (not buf) 185 ;; Output to a file.
186 ;; Output to a file. 186 (set-buffer (get-buffer-create " pmail-out-temp"))
187 (if pmail-fields-not-to-output 187 (insert-buffer-substring cur beg end)
188 ;; Delete some fields while we output. 188 (if pmail-fields-not-to-output
189 (let ((obuf (current-buffer))) 189 (pmail-delete-unwanted-fields))
190 (set-buffer (get-buffer-create " pmail-out-temp")) 190 ;; Convert to Babyl format.
191 (insert-buffer-substring obuf beg end) 191 (pmail-convert-to-babyl-format)
192 (pmail-delete-unwanted-fields) 192 (append-to-file (point-min) (point-max) file-name)
193 (append-to-file (point-min) (point-max) file-name) 193 (set-buffer cur)
194 (set-buffer obuf) 194 (kill-buffer (get-buffer " pmail-out-temp")))))
195 (kill-buffer (get-buffer " pmail-out-temp")))
196 (append-to-file beg end file-name))
197 (if (eq buf (current-buffer))
198 (error "Can't output message to same file it's already in"))
199 ;; File has been visited, in buffer BUF.
200 (set-buffer buf)
201 (let ((buffer-read-only nil)
202 (msg (and (boundp 'pmail-current-message)
203 pmail-current-message)))
204 ;; If MSG is non-nil, buffer is in PMAIL mode.
205 (if msg
206 (progn
207 ;; Turn on auto save mode, if it's off in this
208 ;; buffer but enabled by default.
209 (and (not buffer-auto-save-file-name)
210 auto-save-default
211 (auto-save-mode t))
212 (pmail-maybe-set-message-counters)
213 (widen)
214 (narrow-to-region (point-max) (point-max))
215 (insert-buffer-substring cur beg end)
216 (goto-char (point-min))
217 (widen)
218 (search-backward "\n\^_")
219 (narrow-to-region (point) (point-max))
220 (pmail-delete-unwanted-fields)
221 (pmail-count-new-messages t)
222 (if (pmail-summary-exists)
223 (pmail-select-summary
224 (pmail-update-summary)))
225 (pmail-show-message msg))
226 ;; Output file not in pmail mode => just insert at the end.
227 (narrow-to-region (point-min) (1+ (buffer-size)))
228 (goto-char (point-max))
229 (insert-buffer-substring cur beg end)
230 (pmail-delete-unwanted-fields)))))))
231 (pmail-set-attribute pmail-filed-attr-index t)) 195 (pmail-set-attribute pmail-filed-attr-index t))
232 (if redelete (pmail-set-attribute pmail-deleted-attr-index t)))) 196 (if redelete (pmail-set-attribute pmail-deleted-attr-index t))))
233 (setq count (1- count)) 197 (setq count (1- count))
234 (if pmail-delete-after-output 198 (if pmail-delete-after-output
235 (unless 199 (unless (if (and (= count 0) stay)
236 (if (and (= count 0) stay) 200 (pmail-delete-message)
237 (pmail-delete-message) 201 (pmail-delete-forward))
238 (pmail-delete-forward))
239 (setq count 0)) 202 (setq count 0))
240 (if (> count 0) 203 (if (> count 0)
241 (unless 204 (unless (if (not stay)
242 (if (not stay) (pmail-next-undeleted-message 1)) 205 (pmail-next-undeleted-message 1))
243 (setq count 0))))))) 206 (setq count 0))))))
207 (pmail-show-message))
244 208
245(defalias 'pmail-output-to-pmail-file 'pmail-output-to-babyl-file) 209(defalias 'pmail-output-to-pmail-file 'pmail-output-to-babyl-file)
246 210
211(defun pmail-convert-to-babyl-format ()
212 (let ((count 0) start
213 (case-fold-search nil)
214 (buffer-undo-list t))
215 (goto-char (point-min))
216 (save-restriction
217 (while (not (eobp))
218 (setq start (point))
219 (unless (looking-at "^From ")
220 (error "Invalid mbox message"))
221 (insert "\^L\n0, unseen,,\n*** EOOH ***\n")
222 (pmail-nuke-pinhead-header)
223 ;; If this message has a Content-Length field,
224 ;; skip to the end of the contents.
225 (let* ((header-end (save-excursion
226 (and (re-search-forward "\n\n" nil t)
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
288 (unless (mail-unquote-printable-region
289 header-end (point) nil t t)
290 (message "Malformed MIME quoted-printable message"))
291 ;; Change "quoted-printable" to "8bit",
292 ;; to reflect the decoding we just did.
293 (goto-char quoted-printable-header-field-end)
294 (delete-region (point) (search-backward ":"))
295 (insert ": 8bit")))
296 (if base64-header-field-end
297 (save-excursion
298 (when (condition-case nil
299 (progn
300 (base64-decode-region
301 (1+ header-end)
302 (save-excursion
303 ;; Prevent base64-decode-region
304 ;; from removing newline characters.
305 (skip-chars-backward "\n\t ")
306 (point)))
307 t)
308 (error nil))
309 ;; Change "base64" to "8bit", to reflect the
310 ;; decoding we just did.
311 (goto-char base64-header-field-end)
312 (delete-region (point) (search-backward ":"))
313 (insert ": 8bit")))))
314 (save-excursion
315 (save-restriction
316 (narrow-to-region start (point))
317 (goto-char (point-min))
318 (while (search-forward "\n\^_" nil t) ; single char
319 (replace-match "\n^_")))) ; 2 chars: "^" and "_"
320 ;; This is for malformed messages that don't end in newline.
321 ;; There shouldn't be any, but some users say occasionally
322 ;; there are some.
323 (or (bolp) (newline))
324 (insert ?\^_)
325 (setq last-coding-system-used nil)
326 (or pmail-enable-mime
327 (not pmail-enable-multibyte)
328 (let ((mime-charset
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
349;; Delete the "From ..." line, creating various other headers with
350;; information from it if they don't already exist. Now puts the
351;; original line into a mail-from: header line for debugging and for
352;; use by the pmail-output function.
353(defun pmail-nuke-pinhead-header ()
354 (save-excursion
355 (save-restriction
356 (let ((start (point))
357 (end (progn
358 (condition-case ()
359 (search-forward "\n\n")
360 (error
361 (goto-char (point-max))
362 (insert "\n\n")))
363 (point)))
364 has-from has-date)
365 (narrow-to-region start end)
366 (let ((case-fold-search t))
367 (goto-char start)
368 (setq has-from (search-forward "\nFrom:" nil t))
369 (goto-char start)
370 (setq has-date (and (search-forward "\nDate:" nil t) (point)))
371 (goto-char start))
372 (let ((case-fold-search nil))
373 (if (re-search-forward (concat "^" pmail-unix-mail-delimiter) nil t)
374 (replace-match
375 (concat
376 "Mail-from: \\&"
377 ;; Keep and reformat the date if we don't
378 ;; have a Date: field.
379 (if has-date
380 ""
381 (concat
382 "Date: \\2, \\4 \\3 \\9 \\5 "
383
384 ;; The timezone could be matched by group 7 or group 10.
385 ;; If neither of them matched, assume EST, since only
386 ;; Easterners would be so sloppy.
387 ;; It's a shame the substitution can't use "\\10".
388 (cond
389 ((/= (match-beginning 7) (match-end 7)) "\\7")
390 ((/= (match-beginning 10) (match-end 10))
391 (buffer-substring (match-beginning 10)
392 (match-end 10)))
393 (t "EST"))
394 "\n"))
395 ;; Keep and reformat the sender if we don't
396 ;; have a From: field.
397 (if has-from
398 ""
399 "From: \\1\n"))
400 t)))))))
401
247;;;###autoload 402;;;###autoload
248(defcustom pmail-fields-not-to-output nil 403(defcustom pmail-fields-not-to-output nil
249 "*Regexp describing fields to exclude when outputting a message to a file." 404 "*Regexp describing fields to exclude when outputting a message to a file."