Add post-save actions for Rmail attachments

* lisp/mail/rmailmm.el (rmail-mime-save-action): New user
option.
(rmail-mime-save): Use it.
* doc/emacs/rmail.texi (Rmail Display): Document it (bug#78971).
This commit is contained in:
Paul Nelson 2025-07-07 22:18:39 +02:00 committed by Eli Zaretskii
parent 05dca1f51f
commit c3f30ee204
3 changed files with 65 additions and 1 deletions

View file

@ -1229,6 +1229,27 @@ summarizes the part's index, size, and content type. Depending on the
content type, it may also contain one or more buttons; these perform
actions such as saving the part into a file.
@vindex rmail-mime-save-action
When you save a MIME attachment to a file, Rmail can perform follow-up
actions according to the value of @code{rmail-mime-save-action}. By
default, this value is @code{nil}, which means Rmail does nothing.
Other predefined values are:
@table @code
@item visit-file
Visit the saved file in Emacs.
@item visit-directory
Visit the file's directory in Dired and move point to the file.
@item open-external
Open the file with an external program appropriate for its type.
@end table
You can also set @code{rmail-mime-save-action} to a custom function.
This function will be called with the absolute filename of the saved
attachment as its only argument.
@table @kbd
@findex rmail-mime-toggle-hidden
@item @key{RET}

View file

@ -1344,6 +1344,13 @@ replies.
'rmail-re-abbrevs'. 'rmail-re-abbrevs' is still honored if it was
already set.
+++
*** New user option 'rmail-mime-save-action'.
This option specifies an action to take after saving a MIME attachment.
Predefined values include visiting the file in Emacs, jumping to the
file in Dired, or opening the file with an external program. You can
also provide a custom function.
** Message
+++

View file

@ -242,6 +242,27 @@ TRUNCATED is non-nil if the text of this entity was truncated."))
;;; Buttons
(defcustom rmail-mime-save-action nil
"Action to perform after saving a MIME attachment in Rmail.
The value can be one of the following:
- nil: Do nothing (default).
- `visit-file': Visit the saved file in Emacs.
- `visit-directory': Visit the file's directory in Dired.
- `open-external': Open the file with an external program.
- A function: Call the function with the absolute filename as argument.
Email attachments can be dangerous. When this variable is set to one of
the predefined actions, the user will be prompted to confirm the action
before it is performed. If you set this variable to a function, it will
be called without confirmation. Please exercise caution."
:type '(choice (const :tag "Do nothing" nil)
(const :tag "Visit file in Emacs" visit-file)
(const :tag "Visit directory in Dired" visit-directory)
(const :tag "Open with external program" open-external)
(function :tag "Custom function"))
:version "31.1")
(defun rmail-mime-save (button)
"Save the attachment using info in the BUTTON."
(let* ((rmail-mime-mbox-buffer rmail-view-buffer)
@ -282,7 +303,22 @@ TRUNCATED is non-nil if the text of this entity was truncated."))
(ignore-errors (base64-decode-region (point-min) (point-max))))
((string= transfer-encoding "quoted-printable")
(quoted-printable-decode-region (point-min) (point-max))))))
(write-region nil nil filename nil nil nil t))))
(write-region nil nil filename nil nil nil t))
(pcase rmail-mime-save-action
('nil nil)
('visit-file
(when (yes-or-no-p (format "Visit attachment `%s' in Emacs? "
(file-name-nondirectory filename)))
(find-file filename)))
('visit-directory
(when (yes-or-no-p (format "Visit attachment `%s' in Dired? "
(file-name-nondirectory filename)))
(dired-jump nil filename)))
('open-external
(when (yes-or-no-p (format "Open attachment `%s' with external program? "
(file-name-nondirectory filename)))
(shell-command-do-open (list filename))))
((pred functionp) (funcall rmail-mime-save-action filename)))))
(define-button-type 'rmail-mime-save 'action 'rmail-mime-save)