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

@ -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)
(message-goto-body)
(insert (mu4e--compose-cite parent))
;; include matching MIME parts from the parent
(mu4e--reply-insert-mime-parts parent)
(current-buffer))))))
;;;###autoload

View File

@ -26,6 +26,7 @@
;; look a little convoluted since we need to subvert the gnus/message
;; functions a bit to work with mu4e.
(require 'message)
(require 'mm-decode)
(require 'mu4e-config)
(require 'mu4e-helpers)
(require 'mu4e-contacts)
@ -186,6 +187,17 @@ you don't consider that reasonable, set to nil."
:safe 'booleanp
: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.
;;
@ -774,6 +786,50 @@ Returns the new buffer."
(mu4e--prepare-post oldframe oldwinconf)
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)
"Draft a message based on some parent message.
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.
@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
In older @t{mu4e} versions, @code{mu4e-compose-reply} would @emph{ask} whether