diff --git a/NEWS.org b/NEWS.org index d94c2a48..d9976b15 100644 --- a/NEWS.org +++ b/NEWS.org @@ -16,6 +16,11 @@ 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) + - ~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 - added new ~--eval~ command-line option, so you can do e.g. diff --git a/mu4e/mu4e-compose.el b/mu4e/mu4e-compose.el index ead967b6..b559314c 100644 --- a/mu4e/mu4e-compose.el +++ b/mu4e/mu4e-compose.el @@ -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 diff --git a/mu4e/mu4e-draft.el b/mu4e/mu4e-draft.el index ac333831..c0e48695 100644 --- a/mu4e/mu4e-draft.el +++ b/mu4e/mu4e-draft.el @@ -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', diff --git a/mu4e/mu4e.texi b/mu4e/mu4e.texi index 483ec852..b167669f 100644 --- a/mu4e/mu4e.texi +++ b/mu4e/mu4e.texi @@ -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