X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/4e23cd0ccde4ad1e14fe2870ccf140487af649b2..8bbff0d64d0e6ba21366c9fb24f6973e6c59b8ac:/lisp/mail/rmail.el diff --git a/lisp/mail/rmail.el b/lisp/mail/rmail.el index d150324fc7..67b04b5696 100644 --- a/lisp/mail/rmail.el +++ b/lisp/mail/rmail.el @@ -1,4 +1,4 @@ -;;; rmail.el --- main code of "RMAIL" mail reader for Emacs +;;; rmail.el --- main code of "RMAIL" mail reader for Emacs -*- lexical-binding:t -*- ;; Copyright (C) 1985-1988, 1993-1998, 2000-2015 Free Software ;; Foundation, Inc. @@ -393,7 +393,7 @@ go to that message and type \\[rmail-toggle-header] twice." "Regexp to match Header fields that Rmail should display. If nil, display all header fields except those matched by `rmail-ignored-headers'." - :type '(choice regexp (const :tag "All")) + :type '(choice regexp (const :tag "All" nil)) :group 'rmail-headers) ;;;###autoload @@ -407,7 +407,7 @@ If nil, display all header fields except those matched by (defcustom rmail-highlighted-headers (purecopy "^From:\\|^Subject:") "Regexp to match Header fields that Rmail should normally highlight. A value of nil means don't highlight. Uses the face `rmail-highlight'." - :type 'regexp + :type '(choice regexp (const :tag "None" nil)) :group 'rmail-headers) (defface rmail-highlight @@ -889,12 +889,12 @@ that knows the exact ordering of the \\( \\) subexpressions.") Signal an error and set `rmail-mime-feature' to nil if the feature isn't provided." (when rmail-enable-mime - (condition-case err + (condition-case nil (require rmail-mime-feature) (error (display-warning 'rmail - (format "Although MIME support is requested + (format-message "Although MIME support is requested through `rmail-enable-mime' being non-nil, the required feature `%s' (the value of `rmail-mime-feature') is not available in the current session. @@ -1586,13 +1586,12 @@ Hook `rmail-quit-hook' is run after expunging." (interactive) ;; This let var was called rmail-buffer, but that interfered ;; with the buffer-local var used in summary buffers. - (let ((buffer-to-bury (current-buffer))) - (if (rmail-summary-exists) - (let (window) - (while (setq window (get-buffer-window rmail-summary-buffer)) - (quit-window nil window)) - (bury-buffer rmail-summary-buffer))) - (quit-window))) + (if (rmail-summary-exists) + (let (window) + (while (setq window (get-buffer-window rmail-summary-buffer)) + (quit-window nil window)) + (bury-buffer rmail-summary-buffer))) + (quit-window)) (defun rmail-duplicate-message () "Create a duplicated copy of the current message. @@ -1760,15 +1759,14 @@ not be a new one). It returns non-nil if it got any new messages." ;; This loops if any members of the inbox list have the same ;; basename (see "name conflict" below). (while all-files - (let ((opoint (point)) - ;; If buffer has not changed yet, and has not been + (let (;; If buffer has not changed yet, and has not been ;; saved yet, don't replace the old backup file now. (make-backup-files (and make-backup-files (buffer-modified-p))) (buffer-read-only nil) ;; Don't make undo records while getting mail. (buffer-undo-list t) - delete-files success files file-last-names) + delete-files files file-last-names) ;; Pull files off all-files onto files as long as there is ;; no name conflict. A conflict happens when two inbox ;; file names have the same last component. @@ -1787,7 +1785,7 @@ not be a new one). It returns non-nil if it got any new messages." ;; Make sure we end with a blank line unless there are ;; no messages, as required by mbox format (Bug#9974). (unless (bobp) - (while (not (looking-back "\n\n")) + (while (not (looking-back "\n\n" (- (point) 2))) (insert "\n"))) (setq found (or (rmail-get-new-mail-1 file-name files delete-files) @@ -1910,9 +1908,10 @@ is non-nil if the user has supplied the password interactively. ((string-match "^po:\\([^:]+\\)\\(:\\(.*\\)\\)?" file) (let (got-password supplied-password - (proto "pop") - (user (match-string 1 file)) - (host (match-string 3 file))) + ;; (proto "pop") + ;; (user (match-string 1 file)) + ;; (host (match-string 3 file)) + ) (when rmail-remote-password-required (setq got-password (not (rmail-have-password))) @@ -1945,8 +1944,7 @@ SIZE is the original size of the newly read mail. Value is the size of the newly read mail after conversion." ;; Detect previous Babyl format files. (let ((case-fold-search nil) - (old-file file) - new-file) + (old-file file)) (cond ((looking-at "BABYL OPTIONS:") ;; The new mail is in Babyl version 5 format. Use unrmail ;; to convert it. @@ -1972,7 +1970,7 @@ Value is the size of the newly read mail after conversion." (or (memq (file-locked-p buffer-file-name) '(nil t)) (error "RMAIL file %s is locked" (file-name-nondirectory buffer-file-name))) - (let (file tofile delete-files movemail popmail got-password password) + (let (file tofile delete-files popmail got-password password) (while files ;; Handle remote mailbox names specially; don't expand as filenames ;; in case the userid contains a directory separator. @@ -2092,7 +2090,7 @@ Value is the size of the newly read mail after conversion." ;; Make sure the read-in mbox data properly ends with a ;; blank line unless it is of size 0. (unless (zerop size) - (while (not (looking-back "\n\n")) + (while (not (looking-back "\n\n" (- (point) 2))) (insert "\n"))) (if (not (and rmail-preserve-inbox (string= file tofile))) (setq delete-files (cons tofile delete-files))))) @@ -2127,7 +2125,7 @@ Value is the size of the newly read mail after conversion." Call with point at the end of the message." (unless (bolp) (insert "\n")) - (unless (looking-back "\n\n") + (unless (looking-back "\n\n" (- (point) 2)) (insert "\n"))) (defun rmail-add-mbox-headers () @@ -2144,7 +2142,7 @@ new messages. Return the number of new messages." (value "------U-") (case-fold-search nil) (delim (concat "\n\n" rmail-unix-mail-delimiter)) - limit stop) + stop) ;; Detect an empty inbox file. (unless (= start (point-max)) ;; Scan the new messages to establish a count and to ensure that @@ -2664,8 +2662,8 @@ Ask the user whether to add that list name to `mail-mailing-lists'." "\\>\\)")) addr)) (y-or-n-p - (format "Add `%s' to `mail-mailing-lists'? " - addr))) + (format-message "Add `%s' to `mail-mailing-lists'? " + addr))) (customize-save-variable 'mail-mailing-lists (cons addr mail-mailing-lists))))))))) @@ -2889,7 +2887,7 @@ The current mail message becomes the message displayed." (setq blurb (format "Showing message %d...done" msg))))) blurb)) -(defun rmail-copy-headers (beg end &optional ignored-headers) +(defun rmail-copy-headers (beg _end &optional ignored-headers) "Copy displayed header fields to the message viewer buffer. BEG and END marks the start and end positions of the message in the mbox buffer. If the optional argument IGNORED-HEADERS is @@ -2942,7 +2940,8 @@ buffer to the end of the headers." (1+ (match-beginning 0)) (point-max)))) (if (and (looking-at ignored-headers) - (not (looking-at rmail-nonignored-headers))) + (not (and rmail-nonignored-headers + (looking-at rmail-nonignored-headers)))) (goto-char lim) (append-to-buffer rmail-view-buffer (point) lim) (goto-char lim)))) @@ -3152,7 +3151,7 @@ or forward if N is negative." (rmail-maybe-set-message-counters) (rmail-show-message rmail-total-messages)) -(defun rmail-next-error-move (msg-pos bad-marker) +(defun rmail-next-error-move (msg-pos _bad-marker) "Move to an error locus (probably grep hit) in an Rmail buffer. MSG-POS is a marker pointing at the error message in the grep buffer. BAD-MARKER is a marker that ought to point at where to move to, @@ -3462,21 +3461,20 @@ STATE non-nil means mark as deleted." "Back up to deleted message, select it, and undelete it." (interactive "p") (set-buffer rmail-buffer) - (let (value) - (dotimes (i count) - (let ((msg rmail-current-message)) - (while (and (> msg 0) - (not (rmail-message-deleted-p msg))) - (setq msg (1- msg))) - (if (= msg 0) - (error "No previous deleted message") - (if (/= msg rmail-current-message) - (rmail-show-message msg)) - (rmail-set-attribute rmail-deleted-attr-index nil) - (if (rmail-summary-exists) - (with-current-buffer rmail-summary-buffer - (rmail-summary-mark-undeleted msg)))))) - (rmail-maybe-display-summary))) + (dotimes (_ count) + (let ((msg rmail-current-message)) + (while (and (> msg 0) + (not (rmail-message-deleted-p msg))) + (setq msg (1- msg))) + (if (= msg 0) + (error "No previous deleted message") + (if (/= msg rmail-current-message) + (rmail-show-message msg)) + (rmail-set-attribute rmail-deleted-attr-index nil) + (if (rmail-summary-exists) + (with-current-buffer rmail-summary-buffer + (rmail-summary-mark-undeleted msg)))))) + (rmail-maybe-display-summary)) (defun rmail-delete-forward (&optional count) "Delete this message and move to next nondeleted one. @@ -3490,7 +3488,7 @@ Returns t if a new message is displayed after the delete, or nil otherwise." (let (value backward) (if (< count 0) (setq count (- count) backward t)) - (dotimes (i count) + (dotimes (_ count) (rmail-set-attribute rmail-deleted-attr-index t) (run-hooks 'rmail-delete-message-hook) (let ((del-msg rmail-current-message)) @@ -3787,7 +3785,7 @@ use \\[mail-yank-original] to yank the original message into it." (if (zerop rmail-current-message) (error "There is no message to reply to")) (let (from reply-to cc subject date to message-id references - resent-to resent-cc resent-reply-to + ;; resent-to resent-cc resent-reply-to (msgnum rmail-current-message)) (rmail-apply-in-message rmail-current-message @@ -3802,14 +3800,14 @@ use \\[mail-yank-original] to yank the original message into it." date (mail-fetch-field "date") message-id (mail-fetch-field "message-id") references (mail-fetch-field "references" nil nil t) - resent-reply-to (mail-fetch-field "resent-reply-to" nil t) ;; Bug#512. It's inappropriate to reply to these addresses. -;;; resent-cc (and (not just-sender) -;;; (mail-fetch-field "resent-cc" nil t)) -;;; resent-to (or (mail-fetch-field "resent-to" nil t) "") -;;; resent-subject (mail-fetch-field "resent-subject") -;;; resent-date (mail-fetch-field "resent-date") -;;; resent-message-id (mail-fetch-field "resent-message-id") + ;;resent-reply-to (mail-fetch-field "resent-reply-to" nil t) + ;;resent-cc (and (not just-sender) + ;; (mail-fetch-field "resent-cc" nil t)) + ;;resent-to (or (mail-fetch-field "resent-to" nil t) "") + ;;resent-subject (mail-fetch-field "resent-subject") + ;;resent-date (mail-fetch-field "resent-date") + ;;resent-message-id (mail-fetch-field "resent-message-id") ) (unless just-sender (if (mail-fetch-field "mail-followup-to" nil t) @@ -3820,17 +3818,18 @@ use \\[mail-yank-original] to yank the original message into it." to (or (mail-fetch-field "to" nil t) "")))))) ;; Merge the resent-to and resent-cc into the to and cc. ;; Bug#512. It's inappropriate to reply to these addresses. -;;; (if (and resent-to (not (equal resent-to ""))) -;;; (if (not (equal to "")) -;;; (setq to (concat to ", " resent-to)) -;;; (setq to resent-to))) -;;; (if (and resent-cc (not (equal resent-cc ""))) -;;; (if (not (equal cc "")) -;;; (setq cc (concat cc ", " resent-cc)) -;;; (setq cc resent-cc))) + ;;(if (and resent-to (not (equal resent-to ""))) + ;; (setq to (if (not (equal to "")) + ;; (concat to ", " resent-to) + ;; resent-to))) + ;;(if (and resent-cc (not (equal resent-cc ""))) + ;; (setq cc (if (not (equal cc "")) + ;; (concat cc ", " resent-cc) + ;; resent-cc))) ;; Add `Re: ' to subject if not there already. (and (stringp subject) - (setq subject + (setq subject (rfc2047-decode-string subject) + subject (concat rmail-reply-prefix (if (let ((case-fold-search t)) (string-match rmail-reply-regexp subject)) @@ -4145,6 +4144,9 @@ The message should be narrowed to just the headers." (declare-function rmail-mime-toggle-raw "rmailmm" (&optional state)) +(defvar rmail-mime-mbox-buffer) +(defvar rmail-mime-view-buffer) + (defun rmail-retry-failure () "Edit a mail message which is based on the contents of the current message. For a message rejected by the mail system, extract the interesting headers and @@ -4421,13 +4423,13 @@ current message into that RMAIL folder." (declare-function dframe-select-attached-frame "dframe" (&optional frame)) (declare-function dframe-maybee-jump-to-attached-frame "dframe" ()) -(defun rmail-speedbar-button (text token indent) +(defun rmail-speedbar-button (_text token _indent) "Execute an rmail command specified by TEXT. The command used is TOKEN. INDENT is not used." (dframe-with-attached-buffer (funcall token t))) -(defun rmail-speedbar-find-file (text token indent) +(defun rmail-speedbar-find-file (text _token _indent) "Load in the rmail file TEXT. TOKEN and INDENT are not used." (dframe-with-attached-buffer @@ -4446,7 +4448,7 @@ TOKEN and INDENT are not used." (forward-char -2) (speedbar-do-function-pointer))))) -(defun rmail-speedbar-move-message (text token indent) +(defun rmail-speedbar-move-message (_text token _indent) "From button TEXT, copy current message to the rmail file specified by TOKEN. TEXT and INDENT are not used." (dframe-with-attached-buffer @@ -4506,9 +4508,78 @@ encoded string (and the same mask) will decode the string." (setq i (1+ i))) (concat string-vector))) +(defun rmail-epa-decrypt-1 (mime) + "Decrypt a single GnuPG encrypted text in a message. +The starting string of the encrypted text should have just been regexp-matched. +Argument MIME is non-nil if this is a mime message." + (let* ((armor-start (match-beginning 0)) + (armor-prefix (buffer-substring + (line-beginning-position) + armor-start)) + (armor-end-regexp) + armor-end after-end + unquote) + (if (string-match "
\\'" armor-prefix) + (setq armor-prefix "")) + + (setq armor-end-regexp + (concat "^" + armor-prefix + "-----END PGP MESSAGE-----$")) + (setq armor-end (re-search-forward armor-end-regexp + nil t)) + + (unless armor-end + (error "Encryption armor beginning has no matching end")) + (goto-char armor-start) + + ;; Because epa--find-coding-system-for-mime-charset not autoloaded. + (require 'epa) + + ;; Advance over this armor. + (goto-char armor-end) + (setq after-end (- (point-max) armor-end)) + + (when mime + (save-excursion + (goto-char armor-start) + (re-search-backward "^--" nil t) + (save-restriction + (narrow-to-region (point) armor-start) + + ;; Use the charset specified in the armor. + (unless coding-system-for-read + (if (re-search-forward "^[ \t]*Charset[ \t\n]*:[ \t\n]*\\(.*\\)" nil t) + (setq coding-system-for-read + (epa--find-coding-system-for-mime-charset + (intern (downcase (match-string 1))))))) + + (goto-char (point-min)) + (if (re-search-forward "^[ \t]*Content-transfer-encoding[ \t\n]*:[ \t\n]*quoted-printable[ \t]*$" nil t) + (setq unquote t))))) + + (when unquote + (let ((inhibit-read-only t)) + (mail-unquote-printable-region armor-start + (- (point-max) after-end)))) + + ;; Decrypt it, maybe in place, maybe making new buffer. + (epa-decrypt-region + armor-start (- (point-max) after-end) + ;; Call back this function to prepare the output. + (lambda () + (let ((inhibit-read-only t)) + (delete-region armor-start (- (point-max) after-end)) + (goto-char armor-start) + (current-buffer)))) + + (list armor-start (- (point-max) after-end) mime + armor-end-regexp))) + ;; Should this have a key-binding, or be in a menu? ;; There doesn't really seem to be an appropriate menu. ;; Eg the edit command is not in a menu either. + (defun rmail-epa-decrypt () "Decrypt GnuPG or OpenPGP armors in current message." (interactive) @@ -4517,12 +4588,14 @@ encoded string (and the same mask) will decode the string." ;; change it in one of the calls to `epa-decrypt-region'. (save-excursion - (let (decrypts (mime (rmail-mime-message-p))) + (let (decrypts (mime (rmail-mime-message-p)) + mime-disabled) (goto-char (point-min)) ;; Turn off mime processing. (when (and mime (not (get-text-property (point-min) 'rmail-mime-hidden))) + (setq mime-disabled t) (rmail-mime)) ;; Now find all armored messages in the buffer @@ -4530,74 +4603,12 @@ encoded string (and the same mask) will decode the string." (goto-char (point-min)) (while (re-search-forward "-----BEGIN PGP MESSAGE-----$" nil t) (let ((coding-system-for-read coding-system-for-read) - (case-fold-search t) - unquote - armor-start armor-prefix armor-end-regexp armor-end after-end) - - (setq armor-start (match-beginning 0) - armor-prefix (buffer-substring - (line-beginning-position) - armor-start)) - (if (string-match "\\'" armor-prefix) - (setq armor-prefix "")) - - (setq armor-end-regexp - (concat "^" - armor-prefix - "-----END PGP MESSAGE-----$")) - (setq armor-end (re-search-forward armor-end-regexp - nil t)) - - (unless armor-end - (error "Encryption armor beginning has no matching end")) - (goto-char armor-start) - - ;; Because epa--find-coding-system-for-mime-charset not autoloaded. - (require 'epa) - - ;; Advance over this armor. - (goto-char armor-end) - (setq after-end (- (point-max) armor-end)) - - (when mime - (save-excursion - (goto-char armor-start) - (re-search-backward "^--" nil t) - (save-restriction - (narrow-to-region (point) armor-start) - - ;; Use the charset specified in the armor. - (unless coding-system-for-read - (if (re-search-forward "^[ \t]*Charset[ \t\n]*:[ \t\n]*\\(.*\\)" nil t) - (setq coding-system-for-read - (epa--find-coding-system-for-mime-charset - (intern (downcase (match-string 1))))))) - - (goto-char (point-min)) - (if (re-search-forward "^[ \t]*Content-transfer-encoding[ \t\n]*:[ \t\n]*quoted-printable[ \t]*$" nil t) - (setq unquote t))))) - - (when unquote - (let ((inhibit-read-only t)) - (mail-unquote-printable-region armor-start - (- (point-max) after-end)))) - - ;; Decrypt it, maybe in place, maybe making new buffer. - (epa-decrypt-region - armor-start (- (point-max) after-end) - ;; Call back this function to prepare the output. - (lambda () - (let ((inhibit-read-only t)) - (delete-region armor-start (- (point-max) after-end)) - (goto-char armor-start) - (current-buffer)))) - - (push (list armor-start (- (point-max) after-end) mime - armor-end-regexp) - decrypts))) + (case-fold-search t)) - (unless decrypts - (error "Nothing to decrypt")) + (push (rmail-epa-decrypt-1 mime) decrypts))) + + (when (and decrypts (eq major-mode 'rmail-mode)) + (rmail-add-label "decrypt")) (when (and decrypts (rmail-buffers-swapped-p)) (when (y-or-n-p "Replace the original message? ") @@ -4637,18 +4648,41 @@ encoded string (and the same mask) will decode the string." (let ((value (match-string 0))) (unless (member value '("text/plain" "text/html")) (replace-match "text/plain")))))))) - )))))))))) - + ))))))) + + (when (and (null decrypts) + mime mime-disabled) + ;; Re-enable mime processing. + (rmail-mime) + ;; Find each Show button and show that part. + (while (search-forward " Show " nil t) + (forward-char -2) + (let ((rmail-mime-render-html-function nil) + (entity (get-text-property (point) 'rmail-mime-entity))) + (unless (and (not (stringp entity)) + (rmail-mime-entity-truncated entity)) + (push-button)))) + (goto-char (point-min)) + (while (re-search-forward "-----BEGIN PGP MESSAGE-----$" nil t) + (let ((coding-system-for-read coding-system-for-read) + (case-fold-search t)) + (push (rmail-epa-decrypt-1 mime) decrypts))) + + ) + + (unless decrypts + (error "Nothing to decrypt"))))) + ;;;; Desktop support -(defun rmail-restore-desktop-buffer (desktop-buffer-file-name - desktop-buffer-name - desktop-buffer-misc) +(defun rmail-restore-desktop-buffer (file-name + _buffer-name + _buffer-misc) "Restore an rmail buffer specified in a desktop file." - (condition-case error + (condition-case nil (progn - (rmail-input desktop-buffer-file-name) + (rmail-input file-name) (if (eq major-mode 'rmail-mode) (current-buffer) rmail-buffer)) @@ -4664,7 +4698,7 @@ encoded string (and the same mask) will decode the string." (defvar rmail-message-encoding nil) ;; Used in `write-region-annotate-functions' to write rmail files. -(defun rmail-write-region-annotate (start end) +(defun rmail-write-region-annotate (start _end) (when (and (null start) rmail-buffer-swapped) (unless (buffer-live-p rmail-view-buffer) (error "Buffer `%s' with real text of `%s' has disappeared" @@ -4691,7 +4725,7 @@ encoded string (and the same mask) will decode the string." ;;; Start of automatically extracted autoloads. -;;;### (autoloads nil "rmailedit" "rmailedit.el" "f6da7267316d02c90b9d314ce95b3c22") +;;;### (autoloads nil "rmailedit" "rmailedit.el" "1ed1c211e6e9c254ba3e0dd8d546e745") ;;; Generated autoloads from rmailedit.el (autoload 'rmail-edit-current-message "rmailedit" "\ @@ -4744,7 +4778,7 @@ With prefix argument N moves forward N messages with these labels. ;;;*** -;;;### (autoloads nil "rmailmm" "rmailmm.el" "a17df5ef8968113c8f6a78cf85c82da4") +;;;### (autoloads nil "rmailmm" "rmailmm.el" "e5b89eed8afb278cc8881f2208382c7c") ;;; Generated autoloads from rmailmm.el (autoload 'rmail-mime "rmailmm" "\ @@ -4841,7 +4875,7 @@ If prefix argument REVERSE is non-nil, sorts in reverse order. ;;;*** -;;;### (autoloads nil "rmailsum" "rmailsum.el" "3203e61425330fc20f3154b559f8b539") +;;;### (autoloads nil "rmailsum" "rmailsum.el" "4bc0d1a65aede332348200e1937c84d4") ;;; Generated autoloads from rmailsum.el (autoload 'rmail-summary "rmailsum" "\ @@ -4860,7 +4894,7 @@ Display a summary of all messages with the given RECIPIENTS. Normally checks the To, From and Cc fields of headers; but if PRIMARY-ONLY is non-nil (prefix arg given), only look in the To and From fields. -RECIPIENTS is a string of regexps separated by commas. +RECIPIENTS is a regular expression. \(fn RECIPIENTS &optional PRIMARY-ONLY)" t nil) @@ -4876,13 +4910,13 @@ Emacs will list the message in the summary. Display a summary of all messages with the given SUBJECT. Normally checks just the Subject field of headers; but with prefix argument WHOLE-MESSAGE is non-nil, looks in the whole message. -SUBJECT is a string of regexps separated by commas. +SUBJECT is a regular expression. \(fn SUBJECT &optional WHOLE-MESSAGE)" t nil) (autoload 'rmail-summary-by-senders "rmailsum" "\ Display a summary of all messages whose \"From\" field matches SENDERS. -SENDERS is a string of regexps separated by commas. +SENDERS is a regular expression. \(fn SENDERS)" t nil)