diff options
| author | Richard M. Stallman | 2004-05-10 16:24:26 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 2004-05-10 16:24:26 +0000 |
| commit | 6740652e6d63701107312f7dd1efcc623c4b38fc (patch) | |
| tree | ee5891a431fa662f5833521d222fd7bda1caddc1 | |
| parent | b82a6ae78c2112209f81b9b64470ae92c0350a2c (diff) | |
| download | emacs-6740652e6d63701107312f7dd1efcc623c4b38fc.tar.gz emacs-6740652e6d63701107312f7dd1efcc623c4b38fc.zip | |
(unrmail): Mostly rewritten. Parses the file
directly, without calling any functions in Rmail.
(unrmail-unprune): Function deleted.
| -rw-r--r-- | lisp/mail/unrmail.el | 189 |
1 files changed, 121 insertions, 68 deletions
diff --git a/lisp/mail/unrmail.el b/lisp/mail/unrmail.el index 55f611b53ad..db6990d625b 100644 --- a/lisp/mail/unrmail.el +++ b/lisp/mail/unrmail.el | |||
| @@ -51,43 +51,71 @@ For example, invoke `emacs -batch -f batch-unrmail RMAIL'." | |||
| 51 | (defun unrmail (file to-file) | 51 | (defun unrmail (file to-file) |
| 52 | "Convert Rmail file FILE to system inbox format file TO-FILE." | 52 | "Convert Rmail file FILE to system inbox format file TO-FILE." |
| 53 | (interactive "fUnrmail (rmail file): \nFUnrmail into (new mailbox file): ") | 53 | (interactive "fUnrmail (rmail file): \nFUnrmail into (new mailbox file): ") |
| 54 | (let ((message-count 1) | 54 | (with-temp-buffer |
| 55 | ;; Prevent rmail from making, or switching to, a summary buffer. | 55 | ;; Read in the old Rmail file with no decoding. |
| 56 | (rmail-display-summary nil) | 56 | (let ((coding-system-for-read 'raw-text)) |
| 57 | (rmail-delete-after-output nil) | 57 | (insert-file-contents file)) |
| 58 | (temp-buffer (get-buffer-create " unrmail"))) | 58 | ;; But make it multibyte. |
| 59 | (rmail file) | 59 | (set-buffer-multibyte t) |
| 60 | |||
| 61 | (if (not (looking-at "BABYL OPTIONS")) | ||
| 62 | (error "This file is not in Babyl format")) | ||
| 63 | |||
| 64 | ;; Decode the file contents just as Rmail did. | ||
| 65 | (let ((modifiedp (buffer-modified-p)) | ||
| 66 | (coding-system rmail-file-coding-system) | ||
| 67 | from to) | ||
| 68 | (goto-char (point-min)) | ||
| 69 | (search-forward "\n\^_" nil t) ; Skip BABYL header. | ||
| 70 | (setq from (point)) | ||
| 71 | (goto-char (point-max)) | ||
| 72 | (search-backward "\n\^_" from 'mv) | ||
| 73 | (setq to (point)) | ||
| 74 | (unless (and coding-system | ||
| 75 | (coding-system-p coding-system)) | ||
| 76 | (setq coding-system | ||
| 77 | ;; Emacs 21.1 and later writes RMAIL files in emacs-mule, but | ||
| 78 | ;; earlier versions did that with the current buffer's encoding. | ||
| 79 | ;; So we want to favor detection of emacs-mule (whose normal | ||
| 80 | ;; priority is quite low), but still allow detection of other | ||
| 81 | ;; encodings if emacs-mule won't fit. The call to | ||
| 82 | ;; detect-coding-with-priority below achieves that. | ||
| 83 | (car (detect-coding-with-priority | ||
| 84 | from to | ||
| 85 | '((coding-category-emacs-mule . emacs-mule)))))) | ||
| 86 | (unless (memq coding-system | ||
| 87 | '(undecided undecided-unix)) | ||
| 88 | (set-buffer-modified-p t) ; avoid locking when decoding | ||
| 89 | (let ((buffer-undo-list t)) | ||
| 90 | (decode-coding-region from to coding-system)) | ||
| 91 | (setq coding-system last-coding-system-used)) | ||
| 92 | |||
| 93 | (setq buffer-file-coding-system nil) | ||
| 94 | |||
| 95 | ;; We currently don't use this value, but maybe we should. | ||
| 96 | (setq save-buffer-coding-system | ||
| 97 | (or coding-system 'undecided))) | ||
| 98 | |||
| 60 | ;; Default the directory of TO-FILE based on where FILE is. | 99 | ;; Default the directory of TO-FILE based on where FILE is. |
| 61 | (setq to-file (expand-file-name to-file default-directory)) | 100 | (setq to-file (expand-file-name to-file default-directory)) |
| 62 | (condition-case () | 101 | (condition-case () |
| 63 | (delete-file to-file) | 102 | (delete-file to-file) |
| 64 | (file-error nil)) | 103 | (file-error nil)) |
| 65 | (message "Writing messages to %s..." to-file) | 104 | (message "Writing messages to %s..." to-file) |
| 66 | (save-restriction | 105 | (goto-char (point-min)) |
| 67 | (widen) | 106 | |
| 68 | (while (<= message-count rmail-total-messages) | 107 | (let ((temp-buffer (get-buffer-create " unrmail")) |
| 69 | (let ((beg (rmail-msgbeg message-count)) | 108 | (from-buffer (current-buffer))) |
| 70 | (end (rmail-msgbeg (1+ message-count))) | 109 | |
| 71 | (from-buffer (current-buffer)) | 110 | ;; Process the messages one by one. |
| 72 | (coding (or rmail-file-coding-system 'raw-text)) | 111 | (while (search-forward "\^_\^l" nil t) |
| 112 | (let ((beg (point)) | ||
| 113 | (end (save-excursion | ||
| 114 | (if (search-forward "\^_" nil t) | ||
| 115 | (1- (point)) (point-max)))) | ||
| 116 | (coding 'raw-text) | ||
| 73 | label-line attrs keywords | 117 | label-line attrs keywords |
| 74 | header-beginning mail-from) | 118 | mail-from reformatted) |
| 75 | (save-excursion | ||
| 76 | (goto-char (rmail-msgbeg message-count)) | ||
| 77 | (setq header-beginning (point)) | ||
| 78 | (search-forward "\n*** EOOH ***\n") | ||
| 79 | (forward-line -1) | ||
| 80 | (search-forward "\n\n") | ||
| 81 | (save-restriction | ||
| 82 | (narrow-to-region header-beginning (point)) | ||
| 83 | (setq mail-from | ||
| 84 | (or (mail-fetch-field "Mail-From") | ||
| 85 | (concat "From " | ||
| 86 | (mail-strip-quoted-names (or (mail-fetch-field "from") | ||
| 87 | (mail-fetch-field "really-from") | ||
| 88 | (mail-fetch-field "sender") | ||
| 89 | "unknown")) | ||
| 90 | " " (current-time-string)))))) | ||
| 91 | (with-current-buffer temp-buffer | 119 | (with-current-buffer temp-buffer |
| 92 | (setq buffer-undo-list t) | 120 | (setq buffer-undo-list t) |
| 93 | (erase-buffer) | 121 | (erase-buffer) |
| @@ -95,11 +123,15 @@ For example, invoke `emacs -batch -f batch-unrmail RMAIL'." | |||
| 95 | (insert-buffer-substring from-buffer beg end) | 123 | (insert-buffer-substring from-buffer beg end) |
| 96 | (goto-char (point-min)) | 124 | (goto-char (point-min)) |
| 97 | (forward-line 1) | 125 | (forward-line 1) |
| 126 | ;; Record whether the header is reformatted. | ||
| 127 | (setq reformatted (= (following-char) ?1)) | ||
| 128 | |||
| 129 | ;; Collect the label line, then get the attributes | ||
| 130 | ;; and the keywords from it. | ||
| 98 | (setq label-line | 131 | (setq label-line |
| 99 | (buffer-substring (point) | 132 | (buffer-substring (point) |
| 100 | (progn (forward-line 1) | 133 | (save-excursion (forward-line 1) |
| 101 | (point)))) | 134 | (point)))) |
| 102 | (forward-line -1) | ||
| 103 | (search-forward ",,") | 135 | (search-forward ",,") |
| 104 | (unless (eolp) | 136 | (unless (eolp) |
| 105 | (setq keywords | 137 | (setq keywords |
| @@ -118,9 +150,61 @@ For example, invoke `emacs -batch -f batch-unrmail RMAIL'." | |||
| 118 | (if (string-match ", resent," label-line) ?R ?-) | 150 | (if (string-match ", resent," label-line) ?R ?-) |
| 119 | (if (string-match ", unseen," label-line) ?\ ?-) | 151 | (if (string-match ", unseen," label-line) ?\ ?-) |
| 120 | (if (string-match ", stored," label-line) ?S ?-))) | 152 | (if (string-match ", stored," label-line) ?S ?-))) |
| 121 | (unrmail-unprune) | 153 | |
| 154 | ;; Delete the special Babyl lines at the start, | ||
| 155 | ;; and the ***EOOH*** line, and the reformatted header if any. | ||
| 156 | (goto-char (point-min)) | ||
| 157 | (if reformatted | ||
| 158 | (progn | ||
| 159 | (forward-line 2) | ||
| 160 | ;; Delete Summary-Line headers. | ||
| 161 | (let ((case-fold-search t)) | ||
| 162 | (while (looking-at "Summary-Line:") | ||
| 163 | (forward-line 1))) | ||
| 164 | (delete-region (point-min) (point)) | ||
| 165 | ;; Delete the old reformatted header. | ||
| 166 | (re-search-forward "^[*][*][*] EOOH [*][*][*]\n") | ||
| 167 | (forward-line -1) | ||
| 168 | (let ((start (point))) | ||
| 169 | (search-forward "\n\n") | ||
| 170 | (delete-region start (point)))) | ||
| 171 | ;; Not reformatted. Delete the special | ||
| 172 | ;; lines before the real header. | ||
| 173 | (re-search-forward "^[*][*][*] EOOH [*][*][*]\n") | ||
| 174 | (delete-region (point-min) (point))) | ||
| 175 | |||
| 176 | ;; Some operations on the message header itself. | ||
| 122 | (goto-char (point-min)) | 177 | (goto-char (point-min)) |
| 178 | (save-restriction | ||
| 179 | (narrow-to-region | ||
| 180 | (point-min) | ||
| 181 | (save-excursion (search-forward "\n\n" nil 'move) (point))) | ||
| 182 | |||
| 183 | ;; Fetch or construct what we should use in the `From ' line. | ||
| 184 | (setq mail-from | ||
| 185 | (or (mail-fetch-field "Mail-From") | ||
| 186 | (concat "From " | ||
| 187 | (mail-strip-quoted-names (or (mail-fetch-field "from") | ||
| 188 | (mail-fetch-field "really-from") | ||
| 189 | (mail-fetch-field "sender") | ||
| 190 | "unknown")) | ||
| 191 | " " (current-time-string)))) | ||
| 192 | |||
| 193 | ;; If the message specifies a coding system, use it. | ||
| 194 | (let ((maybe-coding (mail-fetch-field "X-Coding-System"))) | ||
| 195 | (if maybe-coding | ||
| 196 | (setq coding (intern maybe-coding)))) | ||
| 197 | |||
| 198 | ;; Delete the Mail-From: header field if any. | ||
| 199 | (when (re-search-forward "^Mail-from:" nil t) | ||
| 200 | (beginning-of-line) | ||
| 201 | (delete-region (point) | ||
| 202 | (progn (forward-line 1) (point))))) | ||
| 203 | |||
| 204 | (goto-char (point-min)) | ||
| 205 | ;; Insert the `From ' line. | ||
| 123 | (insert mail-from "\n") | 206 | (insert mail-from "\n") |
| 207 | ;; Record the keywords and attributes in our special way. | ||
| 124 | (insert "X-BABYL-V6-ATTRIBUTES: " (apply 'string attrs) "\n") | 208 | (insert "X-BABYL-V6-ATTRIBUTES: " (apply 'string attrs) "\n") |
| 125 | (when keywords | 209 | (when keywords |
| 126 | (insert "X-BABYL-V6-KEYWORDS: " keywords "\n")) | 210 | (insert "X-BABYL-V6-KEYWORDS: " keywords "\n")) |
| @@ -132,43 +216,12 @@ For example, invoke `emacs -batch -f batch-unrmail RMAIL'." | |||
| 132 | (while (search-forward "\nFrom " nil t) | 216 | (while (search-forward "\nFrom " nil t) |
| 133 | (forward-char -5) | 217 | (forward-char -5) |
| 134 | (insert ?>))) | 218 | (insert ?>))) |
| 219 | ;; Write it to the output file. | ||
| 135 | (write-region (point-min) (point-max) to-file t | 220 | (write-region (point-min) (point-max) to-file t |
| 136 | 'nomsg))) | 221 | 'nomsg)))) |
| 137 | (setq message-count (1+ message-count)))) | 222 | (kill-buffer temp-buffer)) |
| 138 | (message "Writing messages to %s...done" to-file))) | 223 | (message "Writing messages to %s...done" to-file))) |
| 139 | 224 | ||
| 140 | (defun unrmail-unprune () | ||
| 141 | (let* ((pruned | ||
| 142 | (save-excursion | ||
| 143 | (goto-char (point-min)) | ||
| 144 | (forward-line 1) | ||
| 145 | (= (following-char) ?1)))) | ||
| 146 | (if pruned | ||
| 147 | (progn | ||
| 148 | (goto-char (point-min)) | ||
| 149 | (forward-line 2) | ||
| 150 | ;; Delete Summary-Line headers. | ||
| 151 | (let ((case-fold-search t)) | ||
| 152 | (while (looking-at "Summary-Line:") | ||
| 153 | (forward-line 1))) | ||
| 154 | (delete-region (point-min) (point)) | ||
| 155 | ;; Delete the old reformatted header. | ||
| 156 | (re-search-forward "^[*][*][*] EOOH [*][*][*]\n") | ||
| 157 | (forward-line -1) | ||
| 158 | (let ((start (point))) | ||
| 159 | (search-forward "\n\n") | ||
| 160 | (delete-region start (point)))) | ||
| 161 | ;; Delete everything up to the real header. | ||
| 162 | (goto-char (point-min)) | ||
| 163 | (re-search-forward "^[*][*][*] EOOH [*][*][*]\n") | ||
| 164 | (delete-region (point-min) (point))) | ||
| 165 | (goto-char (point-min)) | ||
| 166 | (when (re-search-forward "^Mail-from:") | ||
| 167 | (beginning-of-line) | ||
| 168 | (delete-region (point) | ||
| 169 | (progn (forward-line 1) (point)))))) | ||
| 170 | |||
| 171 | |||
| 172 | (provide 'unrmail) | 225 | (provide 'unrmail) |
| 173 | 226 | ||
| 174 | ;;; unrmail.el ends here | 227 | ;;; unrmail.el ends here |