mu4e-compose: allow including parent mime parts

mu4e-compose-reply-include-mime-types specifies the mime-types for
message attachments that should be included in replies, with the default
set to "text/x-patch" -- i.e., patches are included in replies, so you
can comment on them.

As mentioned in #2896.
This commit is contained in:
Dirk-Jan C. Binnema
2026-03-18 00:28:49 +02:00
committed by Seth Ladygo
parent 339cf0bd65
commit 8c067f8726
4 changed files with 68 additions and 0 deletions

View File

@ -16,6 +16,11 @@
is the maximum number of addresses to show. This can be useful if you have is the maximum number of addresses to show. This can be useful if you have
some many personal addresses that the clutter up the main view. (1.14.0) some many personal addresses that the clutter up the main view. (1.14.0)
- ~mu4e-compose-reply-include-mime-types~ specifies the mime-types for message
attachments that should be included in replies, with the default set to
"text/x-patch" -- i.e., patches are included in replies, so you can comment
on them. Set to nil to disable.
*** scm *** scm
- added new ~--eval~ command-line option, so you can do e.g. - added new ~--eval~ command-line option, so you can do e.g.

View File

@ -380,6 +380,8 @@ non-nil, make it a \"wide\" reply (a.k.a. \"reply-to-all\")."
(with-current-buffer (mu4e--message-call #'message-reply to wide) (with-current-buffer (mu4e--message-call #'message-reply to wide)
(message-goto-body) (message-goto-body)
(insert (mu4e--compose-cite parent)) (insert (mu4e--compose-cite parent))
;; include matching MIME parts from the parent
(mu4e--reply-insert-mime-parts parent)
(current-buffer)))))) (current-buffer))))))
;;;###autoload ;;;###autoload

View File

@ -26,6 +26,7 @@
;; look a little convoluted since we need to subvert the gnus/message ;; look a little convoluted since we need to subvert the gnus/message
;; functions a bit to work with mu4e. ;; functions a bit to work with mu4e.
(require 'message) (require 'message)
(require 'mm-decode)
(require 'mu4e-config) (require 'mu4e-config)
(require 'mu4e-helpers) (require 'mu4e-helpers)
(require 'mu4e-contacts) (require 'mu4e-contacts)
@ -186,6 +187,17 @@ you don't consider that reasonable, set to nil."
:safe 'booleanp :safe 'booleanp
:group 'mu4e-compose) :group 'mu4e-compose)
(defcustom mu4e-compose-reply-include-mime-types '("text/x-patch")
"MIME types from the parent message to include when replying.
When replying to a message, MIME parts with content-types in this
list are automatically included in the the reply message. This is
useful for carrying over patches or other structured text parts.
Set to nil to disable."
:type '(repeat string)
:group 'mu4e-compose)
;; ;;
;; display the ready-to-go display buffer in the desired way. ;; display the ready-to-go display buffer in the desired way.
;; ;;
@ -774,6 +786,50 @@ Returns the new buffer."
(mu4e--prepare-post oldframe oldwinconf) (mu4e--prepare-post oldframe oldwinconf)
draft-buffer))) draft-buffer)))
(defun mu4e--collect-mime-parts (handles types)
"Collect MIME parts from HANDLES with content-types in TYPES.
HANDLES is as returned by `mm-dissect-buffer'. TYPES is a list of
MIME type strings.
Returns a list of matching leaf handles."
(cond
;; Leaf handle (buffer in car).
((bufferp (car handles))
(when (member (mm-handle-media-type handles) types)
(list handles)))
;; Composite handle, e.g. multipart/* (type string in car).
((stringp (car handles))
(mapcan (lambda (h) (mu4e--collect-mime-parts h types))
(cdr handles)))
;; Plain list of handles.
(t
(mapcan (lambda (h) (mu4e--collect-mime-parts h types))
handles))))
(defun mu4e--reply-insert-mime-parts (msg)
"Insert MIME parts from MSG matching `mu4e-compose-reply-include-mime-types'.
Matching parts are inserted inline at point so that the user can
comment on them directly."
(when mu4e-compose-reply-include-mime-types
(let ((handles
(with-temp-buffer
(insert-file-contents-literally
(mu4e-message-readable-path msg))
(mm-dissect-buffer t t))))
(when handles
(unwind-protect
(dolist (part (mu4e--collect-mime-parts
handles mu4e-compose-reply-include-mime-types))
(let ((filename (mm-handle-filename part))
(content (mm-get-part part)))
(insert "\n")
(when filename
(insert filename ":\n"))
(insert content)
(unless (bolp) (insert "\n"))))
(mm-destroy-parts handles))))))
(defun mu4e--draft-with-parent (compose-type parent compose-func) (defun mu4e--draft-with-parent (compose-type parent compose-func)
"Draft a message based on some parent message. "Draft a message based on some parent message.
COMPOSE-TYPE, COMPOSE-FUNC and PARENT are as in `mu4e--draft', COMPOSE-TYPE, COMPOSE-FUNC and PARENT are as in `mu4e--draft',

View File

@ -1814,6 +1814,11 @@ that, you can set (or @code{let}-bind) @code{message-cite-function} to
See @ref{(message) Reply} and @ref{(message) Wide Reply} for further details. See @ref{(message) Reply} and @ref{(message) Wide Reply} for further details.
@code{mu4e-compose-reply-include-mime-types} specifies the MIME-types for
message attachments that should be included in replies, with the default set to
@code{"text/x-patch"}-- i.e., patches are included in replies, so you can
comment on them. Set to @code{nil} to disable.
@subsubsection Interactively deciding whom to reply to @subsubsection Interactively deciding whom to reply to
In older @t{mu4e} versions, @code{mu4e-compose-reply} would @emph{ask} whether In older @t{mu4e} versions, @code{mu4e-compose-reply} would @emph{ask} whether