* mu4e-compose.el: let message-mode FCC take care of saving to sent-messages

- replace the old system with a bit less rube-goldbergesque (only a bit)
    system. Immediate advantage is that attachments are now also present in
    the saved messages, i.e. the copy is now the /same/ as what is sent,
    rather than an approximation.

   'fcc' refers to saving a copy of a sent message to a certain folder. that's
   what these 'Sent mail' folders are for!

   We let message mode take care of this by adding a field
     Fcc: <full-path-to-message-in-target-folder>
   in the "message-send-hook" (ie., just before sending).
   message mode will then take care of the saving when the message is actually
   sent.

   note, where and if you make this copy depends on the value of
    `mu4e-sent-messages-behavior'.

  - also quite a bit of cleanup in particular on mu4e~compose
This commit is contained in:
djcb
2012-04-26 18:08:42 +03:00
parent 084ecc71d2
commit 2f3bd58c03

View File

@ -26,7 +26,7 @@
;; gnus' message mode ;; gnus' message mode
;;; Code: ;;; Code:
;; we use some stuff from gnus.. ;; we use some stuff from gnus..
(require 'cl) (require 'cl)
(require 'message) (require 'message)
(require 'mail-parse) (require 'mail-parse)
@ -69,6 +69,19 @@ sent folder."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun mu4e-compose-attach-captured-message()
"Insert the last captured message file as an attachment."
(interactive)
(unless mu4e-captured-message
(error "No message has been captured"))
(let ((path (plist-get mu4e-captured-message :path)))
(unless (file-exists-p path)
(error "Captured message file not found"))
(mml-attach-file
path
"message/rfc822"
(or (plist-get mu4e-captured-message :subject) "No subject")
"attachment")))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -105,7 +118,6 @@ return nil."
(lambda (msgid) (format "<%s>" msgid)) (lambda (msgid) (format "<%s>" msgid))
refs ",")))) refs ","))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; determine the recipient fields for new messages ;; determine the recipient fields for new messages
@ -151,11 +163,11 @@ field before, goes to the Cc:-list (if we're doing a reply-to-all)."
the original message ORIGMSG, and whether it's a reply-all." the original message ORIGMSG, and whether it's a reply-all."
(when reply-all (when reply-all
(let* ((cc-lst ;; get the cc-field from the original, remove dups (let* ((cc-lst ;; get the cc-field from the original, remove dups
(delete-duplicates (delete-duplicates
(append (append
(plist-get origmsg :to) (plist-get origmsg :to)
(plist-get origmsg :cc)) (plist-get origmsg :cc))
:test #'mu4e~compose-address-cell-equal)) :test #'mu4e~compose-address-cell-equal))
;; now we have the basic list, but we must remove ;; now we have the basic list, but we must remove
;; addresses also in the to list ;; addresses also in the to list
(cc-lst (cc-lst
@ -177,19 +189,19 @@ the original message ORIGMSG, and whether it's a reply-all."
cc-lst)))) cc-lst))))
cc-lst))) cc-lst)))
(defun mu4e~compose-recipients-construct (field origmsg &optional reply-all) (defun mu4e~compose-recipients-construct (field origmsg &optional reply-all)
"Create value (a string) for the recipient field FIELD (a "Create value (a string) for the recipient field FIELD (a
symbol, :to or :cc), based on the original message ORIGMSG, symbol, :to or :cc), based on the original message ORIGMSG,
and (optionally) REPLY-ALL which indicates this is a reply-to-all and (optionally) REPLY-ALL which indicates this is a reply-to-all
message. Return nil if there are no recipients for the particular field." message. Return nil if there are no recipients for the particular field."
(mu4e~compose-recipients-list-to-string (mu4e~compose-recipients-list-to-string
(case field (case field
(:to (:to
(mu4e~compose-create-to-lst origmsg)) (mu4e~compose-create-to-lst origmsg))
(:cc (:cc
(mu4e~compose-create-cc-lst origmsg reply-all)) (mu4e~compose-create-cc-lst origmsg reply-all))
(otherwise (otherwise
(error "Unsupported field"))))) (error "Unsupported field")))))
(defun mu4e~compose-from-construct () (defun mu4e~compose-from-construct ()
@ -202,7 +214,6 @@ nil, function returns nil."
(format "%s" user-mail-address)))) (format "%s" user-mail-address))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun mu4e~compose-insert-mail-header-separator () (defun mu4e~compose-insert-mail-header-separator ()
"Insert `mail-header-separator' in the first empty line of the "Insert `mail-header-separator' in the first empty line of the
message. message-mode needs this line to know where the headers end message. message-mode needs this line to know where the headers end
@ -212,7 +223,7 @@ separator is never written to file. Also see
`mu4e-remove-mail-header-separator'." `mu4e-remove-mail-header-separator'."
(save-excursion (save-excursion
(goto-char (point-min)) (goto-char (point-min))
;; search for the first empty line ;; search for the first empty line
(if (search-forward-regexp (concat "^$")) (if (search-forward-regexp (concat "^$"))
(replace-match (replace-match
(propertize mail-header-separator 'read-only t 'intangible t)) (propertize mail-header-separator 'read-only t 'intangible t))
@ -236,22 +247,40 @@ never hits the disk. Also see `mu4e~compose-insert-mail-header-separator."
are more than 1 (based on ORIGMSG)." are more than 1 (based on ORIGMSG)."
(let* ((recipnum (let* ((recipnum
(+ (length (mu4e~compose-create-to-lst origmsg)) (+ (length (mu4e~compose-create-to-lst origmsg))
(length (mu4e~compose-create-cc-lst origmsg t)))) (length (mu4e~compose-create-cc-lst origmsg t))))
(response (response
(if (= recipnum 1) (if (= recipnum 1)
?a ;; with one recipient, we can reply to 'all'.... ?a ;; with one recipient, we can reply to 'all'....
(mu4e-read-option (mu4e-read-option
"Reply to " "Reply to "
`( (,(format "all %d recipients" recipnum)) `( (,(format "all %d recipients" recipnum))
("sender only")))))) ("sender only"))))))
(= response ?a))) (= response ?a)))
(defun mu4e~compose-message-filename-construct (&optional flagstr)
"Construct a randomized name for a message file with flags FLAGSTR; it looks
something like
<time>-<random>.<hostname>:2,
You can append flags."
(let* ((hostname
(downcase
(save-match-data
(substring system-name
(string-match "^[^.]+" system-name) (match-end 0))))))
(format "%s-%x%x.%s:2,%s"
(format-time-string "%Y%m%d" (current-time))
(emacs-pid) (random t) hostname (or flagstr ""))))
(defun mu4e~compose-common-construct ()
"Construct the common headers for each message."
(mu4e~compose-header "User-agent" (mu4e-user-agent)))
(defun mu4e~compose-reply-construct (origmsg) (defun mu4e~compose-reply-construct (origmsg)
"Create a draft message as a reply to original message ORIGMSG." "Create a draft message as a reply to original message ORIGMSG."
(let* ((recipnum (let* ((recipnum
(+ (length (mu4e~compose-create-to-lst origmsg)) (+ (length (mu4e~compose-create-to-lst origmsg))
(length (mu4e~compose-create-cc-lst origmsg t)))) (length (mu4e~compose-create-cc-lst origmsg t))))
(reply-all (mu4e~compose-user-wants-reply-all origmsg)) (reply-all (mu4e~compose-user-wants-reply-all origmsg))
(old-msgid (plist-get origmsg :message-id)) (old-msgid (plist-get origmsg :message-id))
(subject (or (plist-get origmsg :subject) ""))) (subject (or (plist-get origmsg :subject) "")))
@ -261,11 +290,11 @@ are more than 1 (based on ORIGMSG)."
(mu4e~compose-header "Reply-To" mu4e-reply-to-address) (mu4e~compose-header "Reply-To" mu4e-reply-to-address)
(mu4e~compose-header "To" (mu4e~compose-recipients-construct :to origmsg)) (mu4e~compose-header "To" (mu4e~compose-recipients-construct :to origmsg))
(mu4e~compose-header "Cc" (mu4e~compose-recipients-construct :cc origmsg (mu4e~compose-header "Cc" (mu4e~compose-recipients-construct :cc origmsg
reply-all)) reply-all))
(mu4e~compose-header "User-agent" (mu4e-user-agent))
(mu4e~compose-header "References" (mu4e~compose-header "References"
(mu4e~compose-refererences-construct origmsg)) (mu4e~compose-refererences-construct origmsg))
(mu4e~compose-common-construct)
(when old-msgid (when old-msgid
(mu4e~compose-header "In-reply-to" (format "<%s>" old-msgid))) (mu4e~compose-header "In-reply-to" (format "<%s>" old-msgid)))
@ -280,14 +309,13 @@ are more than 1 (based on ORIGMSG)."
(defun mu4e~compose-forward-construct (origmsg) (defun mu4e~compose-forward-construct (origmsg)
"Create a draft forward message for original message ORIGMSG." "Create a draft forward message for original message ORIGMSG."
(let ((subject (let ((subject
(or (plist-get origmsg :subject) ""))) (or (plist-get origmsg :subject) "")))
(concat (concat
(mu4e~compose-header "From" (or (mu4e~compose-from-construct) "")) (mu4e~compose-header "From" (or (mu4e~compose-from-construct) ""))
(mu4e~compose-header "Reply-To" mu4e-reply-to-address) (mu4e~compose-header "Reply-To" mu4e-reply-to-address)
(mu4e~compose-header "To" "") (mu4e~compose-header "To" "")
(mu4e~compose-header "User-agent" (mu4e-user-agent)) (mu4e~compose-common-construct)
(mu4e~compose-header "References" (mu4e~compose-header "References"
(mu4e~compose-refererences-construct origmsg)) (mu4e~compose-refererences-construct origmsg))
(mu4e~compose-header "Subject" (mu4e~compose-header "Subject"
@ -305,9 +333,8 @@ are more than 1 (based on ORIGMSG)."
(mu4e~compose-header "From" (or (mu4e~compose-from-construct) "")) (mu4e~compose-header "From" (or (mu4e~compose-from-construct) ""))
(mu4e~compose-header "Reply-To" mu4e-reply-to-address) (mu4e~compose-header "Reply-To" mu4e-reply-to-address)
(mu4e~compose-header "To" "") (mu4e~compose-header "To" "")
(mu4e~compose-header "User-agent" (mu4e-user-agent))
(mu4e~compose-header "Subject" "") (mu4e~compose-header "Subject" "")
"\n")) (mu4e~compose-common-construct)))
(defun mu4e~compose-open-new-draft-file (compose-type &optional msg) (defun mu4e~compose-open-new-draft-file (compose-type &optional msg)
@ -316,18 +343,9 @@ already exist, and optionally fill it with STR. Function also adds
the new message to the database. When the draft message is added to the new message to the database. When the draft message is added to
the database, `mu4e-path-docid-map' will be updated, so that we can the database, `mu4e-path-docid-map' will be updated, so that we can
use the new docid. Returns the full path to the new message." use the new docid. Returns the full path to the new message."
(let* ((hostname (let* ((draft
(downcase (concat mu4e-maildir mu4e-drafts-folder "/cur/"
(save-match-data (mu4e~compose-message-filename-construct "DS")))
(substring system-name
(string-match "^[^.]+" system-name) (match-end 0)))))
(draft
(concat mu4e-maildir mu4e-drafts-folder "/cur/"
;; 'D': rarely used, but hey, it's available
;; 'S': because we're looking at the draft as we speak
(format "%s-%x%x.%s:2,DS"
(format-time-string "%Y%m%d" (current-time))
(emacs-pid) (random t) hostname)))
(str (case compose-type (str (case compose-type
(reply (mu4e~compose-reply-construct msg)) (reply (mu4e~compose-reply-construct msg))
(forward (mu4e~compose-forward-construct msg)) (forward (mu4e~compose-forward-construct msg))
@ -336,55 +354,84 @@ use the new docid. Returns the full path to the new message."
(when str (when str
(with-current-buffer (find-file-noselect draft) (with-current-buffer (find-file-noselect draft)
(insert str))) (insert str)))
draft)) ;; return the draft buffer file draft)) ;; return the draft buffer file
;; 'fcc' refers to saving a copy of a sent message to a certain folder. that's
;; what these 'Sent mail' folders are for!
;;
;; We let message mode take care of this by adding a field
;; Fcc: <full-path-to-message-in-target-folder>
;; in the "message-send-hook" (ie., just before sending).
;; message mode will then take care of the saving when the message is actually
;; sent.
;;
;; note, where and if you make this copy depends on the value of
;; `mu4e-sent-messages-behavior'.
(defun mu4e~setup-fcc-maybe ()
"Maybe setup Fcc, based on `mu4e-sent-messages-behavior'. If
needed, set the Fcc header, and register the handler function."
(let* ((mdir
(case mu4e-sent-messages-behavior
(delete nil)
(trash mu4e-trash-folder)
(sent mu4e-sent-folder)
(otherwise
(error "unsupported value '%S' `mu4e-sent-messages-behavior'."
mu4e-sent-messages-behavior))))
(fccfile (and mdir
(concat mu4e-maildir mdir "/cur/"
(mu4e~compose-message-filename-construct "S")))))
;; if there's an fcc header, add it to the file
(when fccfile
(message-add-header (concat "Fcc: " fccfile "\n"))
;; sadly, we cannot define as 'buffer-local'... this will screw up gnus
;; etc. if you run it after mu4e so, (hack hack) we reset it to the old
;; hander after we've done our thing.
(setq message-fcc-handler-function
(lexical-let ((maildir mdir) (old-handler message-fcc-handler-function))
(lambda (file)
(setq message-fcc-handler-function old-handler) ;; reset the fcc handler
(write-file file) ;; writing maildirs files is easy
(mu4e~proc-add file maildir))))))) ;; update the database
(defun mu4e~compose-register-message-save-hooks ()
"Just before saving, we remove the mail-header-separator; just
after saving we restore it; thus, the separator should never
appear on disk."
(add-hook 'before-save-hook
'mu4e~compose-remove-mail-header-separator nil t)
(add-hook 'after-save-hook
(lambda ()
(mu4e~compose-set-friendly-buffer-name)
(mu4e~compose-insert-mail-header-separator)
(set-buffer-modified-p nil)
;; update the file on disk -- ie., without the separator
(mu4e~proc-add (buffer-file-name) mu4e-drafts-folder)) nil t))
(define-derived-mode mu4e-compose-mode message-mode "mu4e:compose" (define-derived-mode mu4e-compose-mode message-mode "mu4e:compose"
"Major mode for the mu4e message composition, derived from `message-mode'. "Major mode for the mu4e message composition, derived from `message-mode'.
\\{message-mode-map}." \\{message-mode-map}."
(let ((message-hidden-headers (let ((message-hidden-headers
`("^References:" "^Face:" "^X-Face:" "^X-Draft-From:" `("^References:" "^Face:" "^X-Face:" "^X-Draft-From:" "^User-agent:")))
"^User-agent:")))
(use-local-map mu4e-compose-mode-map) (use-local-map mu4e-compose-mode-map)
(message-hide-headers) (message-hide-headers)
(make-local-variable 'before-save-hook)
(make-local-variable 'after-save-hook)
(make-local-variable 'message-default-charset) (make-local-variable 'message-default-charset)
;; if the default charset is not set, use UTF-8 ;; if the default charset is not set, use UTF-8
(unless message-default-charset (unless message-default-charset
(setq message-default-charset 'utf-8)) (setq message-default-charset 'utf-8))
;; make sure mu4e is started in the background (ie. we don't want to error ;; make sure mu4e is started in the background (ie. we don't want to error
;; out when sending the message; better to do it now if there's a problem) ;; out when sending the message; better to do it now if there's a problem)
(mu4e :hide-ui t) (mu4e~start) ;; start mu4e in background, if needed
(mu4e~compose-register-message-save-hooks)
;; hack-hack-hack... just before saving, we remove the
;; mail-header-separator; just after saving we restore it; thus, the
;; separator should never appear on disk
(add-hook 'before-save-hook 'mu4e~compose-remove-mail-header-separator)
(add-hook 'after-save-hook
(lambda ()
(mu4e~compose-set-friendly-buffer-name)
(mu4e~compose-insert-mail-header-separator)
(set-buffer-modified-p nil)))
;; update the db when the file is saved...]
(add-hook 'after-save-hook
(lambda()
(mu4e~proc-add (buffer-file-name) mu4e-drafts-folder))))
;; notify the backend that a message has been sent. The backend will respond
;; with (:sent ...) sexp, which is handled in `mu4e~compose-handler'.
(add-hook 'message-sent-hook
(lambda ()
(set-buffer-modified-p t)
(basic-save-buffer)
(mu4e~proc-sent (buffer-file-name) mu4e-drafts-folder)))
;; register the function; this function will be called when the '(:sent...)'
;; message is received (see mu4e-proc.el) with parameters docid and path
(setq mu4e-sent-func 'mu4e-sent-handler)
;; set the default directory to the user's home dir; this is probably more ;; set the default directory to the user's home dir; this is probably more
;; useful e.g. when finding an attachment file the directory the current ;; useful e.g. when finding an attachment file the directory the current
;; mail files lives in... ;; mail files lives in...
(setq default-directory (expand-file-name "~/"))) (setq default-directory (expand-file-name "~/"))))
(defconst mu4e~compose-buffer-max-name-length 30 (defconst mu4e~compose-buffer-max-name-length 30
@ -448,6 +495,7 @@ Gnus' `message-mode'."
;; insert mail-header-separator, which is needed by message mode to separate ;; insert mail-header-separator, which is needed by message mode to separate
;; headers and body. will be removed before saving to disk ;; headers and body. will be removed before saving to disk
(mu4e~compose-insert-mail-header-separator) (mu4e~compose-insert-mail-header-separator)
;; include files -- e.g. when forwarding a message with attachments, ;; include files -- e.g. when forwarding a message with attachments,
;; we take those from the original. ;; we take those from the original.
(save-excursion (save-excursion
@ -455,69 +503,51 @@ Gnus' `message-mode'."
(dolist (att includes) (dolist (att includes)
(mml-attach-file (mml-attach-file
(plist-get att :file-name) (plist-get att :mime-type)))) (plist-get att :file-name) (plist-get att :mime-type))))
;; include the message header if it's set; but not when editing an existing ;; include the message header if it's set; but not when editing an existing
;; message. ;; message.
(unless (eq compose-type 'edit) (unless (eq compose-type 'edit)
(when message-signature (when message-signature
(message-insert-signature))) (message-insert-signature)))
;; setup the fcc-stuff, if needed
(add-hook 'message-send-hook
(lambda ()
;; for safety, always save the draft before sending
(set-buffer-modified-p t)
(save-buffer)
(mu4e~setup-fcc-maybe)) nil t)
;; when the message has been sent.
(add-hook 'message-sent-hook
(lambda ()
(setq mu4e-sent-func 'mu4e-sent-handler)
(mu4e~proc-sent (buffer-file-name) mu4e-drafts-folder)) nil t))
(if (member compose-type '(new forward)) ;; buffer is not user-modified yet
(message-goto-to) (mu4e~compose-set-friendly-buffer-name compose-type)
(message-goto-body)) (set-buffer-modified-p nil)
(mu4e~compose-set-friendly-buffer-name compose-type) ;; now jump to some use positions, and start writing that mail!
;; buffer is not user-modified yet (if (member compose-type '(new forward))
(set-buffer-modified-p nil))) (message-goto-to)
(message-goto-body)))
(defun mu4e-compose-attach-captured-message()
"Insert the last captured message file as an attachment."
(interactive)
(unless mu4e-captured-message
(error "No message has been captured"))
(let ((path (plist-get mu4e-captured-message :path)))
(unless (file-exists-p path)
(error "Captured message file not found"))
(mml-attach-file
path
"message/rfc822"
(or (plist-get mu4e-captured-message :subject) "No subject")
"attachment")))
(defun mu4e-sent-handler (docid path) (defun mu4e-sent-handler (docid path)
"Handler function, called with DOCID and PATH for the just-sent "Handler function, called with DOCID and PATH for the just-sent
message." message."
(with-current-buffer(find-file-noselect path) ;; for Forward ('Passed') and Replied messages, try to set the appropriate
;; for Forward ('Passed') and Replied messages, try to set the appropriate ;; flag at the message forwarded or replied-to
;; flag at the message forwarded or replied-to (mu4e~compose-set-parent-flag path)
(mu4e~compose-set-parent-flag docid path) (kill-buffer) ;; remove the draft
;; handle the draft -- should it be moved to the sent-folder, or elsewhere? (when (file-exists-p path) ;; maybe the draft was not saved at all
(mu4e~compose-save-copy-maybe docid path) (mu4e~proc-remove docid)))
;; now, get rid of the buffer
(kill-buffer)))
(defun mu4e~compose-save-copy-maybe (docid path)
"Handler function, called with DOCID and PATH for the just-sent
message, which will move it to the sent-folder or elsewhere,
depending on the value of `mu4e-sent-messages-behavior'.
Function assumes that it's executed in the context of the message (defun mu4e~compose-set-parent-flag (path)
buffer."
;; first, what to do with the draft message in PATH?
(if (eq mu4e-sent-messages-behavior 'delete)
(mu4e~proc-remove docid) ;; remove it
;; otherwise,
(progn ;; prepare the message for saving
(basic-save-buffer)
;; now either move it to trash or to sent
(if (eq mu4e-sent-messages-behavior 'trash)
(mu4e~proc-move docid mu4e-trash-folder "+T-D+S")
(mu4e~proc-move docid mu4e-sent-folder "-T-D+S")))))
(defun mu4e~compose-set-parent-flag (docid path)
"Set the 'replied' \"R\" flag on messages we replied to, and the "Set the 'replied' \"R\" flag on messages we replied to, and the
'passed' \"F\" flag on message we have forwarded. 'passed' \"F\" flag on message we have forwarded.
If a message has a 'in-reply-to' header, it is considered a reply If a message has an 'in-reply-to' header, it is considered a reply
to the message with the corresponding message id. If it does not to the message with the corresponding message id. If it does not
have an 'in-reply-to' header, but does have a 'references' header, have an 'in-reply-to' header, but does have a 'references' header,
it is considered to be a forward message for the message it is considered to be a forward message for the message
@ -529,26 +559,28 @@ with resp. the 'P' (passed) flag for a forwarded message, or the
'R' flag for a replied message. 'R' flag for a replied message.
Function assumes that it's executed in the context of the message Function assumes that it's executed in the context of the message
buffer. buffer."
" (let ((buf (find-file-noselect path)))
(let ((in-reply-to (message-fetch-field "in-reply-to")) (when buf
(forwarded-from) (with-current-buffer buf
(references (message-fetch-field "references"))) (let ((in-reply-to (message-fetch-field "in-reply-to"))
(unless in-reply-to (forwarded-from)
(when references (references (message-fetch-field "references")))
(with-temp-buffer ;; inspired by `message-shorten-references'. (unless in-reply-to
(insert references) (when references
(goto-char (point-min)) (with-temp-buffer ;; inspired by `message-shorten-references'.
(let ((refs)) (insert references)
(while (re-search-forward "<[^ <]+@[^ <]+>" nil t) (goto-char (point-min))
(push (match-string 0) refs)) (let ((refs))
;; the last will be the first (while (re-search-forward "<[^ <]+@[^ <]+>" nil t)
(setq forwarded-from (first refs)))))) (push (match-string 0) refs))
;; remove the <> ;; the last will be the first
(when (and in-reply-to (string-match "<\\(.*\\)>" in-reply-to)) (setq forwarded-from (first refs))))))
(mu4e~proc-move (match-string 1 in-reply-to) nil "+R")) ;; remove the <>
(when (and forwarded-from (string-match "<\\(.*\\)>" forwarded-from)) (when (and in-reply-to (string-match "<\\(.*\\)>" in-reply-to))
(mu4e~proc-move (match-string 1 forwarded-from) nil "+P")))) (mu4e~proc-move (match-string 1 in-reply-to) nil "+R"))
(when (and forwarded-from (string-match "<\\(.*\\)>" forwarded-from))
(mu4e~proc-move (match-string 1 forwarded-from) nil "+P")))))))
@ -559,21 +591,19 @@ buffer.
(defun mu4e~compose (&optional to subject other-headers continue (defun mu4e~compose (&optional to subject other-headers continue
switch-function yank-action send-actions return-action) switch-function yank-action send-actions return-action)
"mu4e's implementation of `compose-mail'." "mu4e's implementation of `compose-mail'."
;; create a new draft message 'resetting' (as below) is not actually needed in ;; create a new draft message 'resetting' (as below) is not actually needed in
;; this case, but let's prepare for the re-edit case as well ;; this case, but let's prepare for the re-edit case as well
(mu4e~compose-handler 'new) (mu4e~compose-handler 'new)
(when (message-goto-to) ;; reset to-address, if needed (when (message-goto-to) ;; reset to-address, if needed
(message-delete-line)) (message-delete-line))
(insert (concat "To: " to "\n")) (message-add-header (concat "To: " to "\n"))
(when (message-goto-subject) ;; reset subject, if needed (when (message-goto-subject) ;; reset subject, if needed
(message-delete-line)) (message-delete-line))
(insert (concat "Subject: " subject "\n")) (message-add-header (concat "Subject: " subject "\n"))
;; add any other headers specified; FIXME: for some reason, these appear ;; add any other headers specified
;; before any other headers
(when other-headers (when other-headers
(message-add-header other-headers)) (message-add-header other-headers))
@ -595,6 +625,6 @@ buffer.
'message-send-and-exit 'message-send-and-exit
'message-kill-buffer 'message-kill-buffer
'message-send-hook) 'message-send-hook)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(provide 'mu4e-compose) (provide 'mu4e-compose)