diff --git a/mu4e/mu4e-compose.el b/mu4e/mu4e-compose.el index d89ae4b1..b7e19942 100644 --- a/mu4e/mu4e-compose.el +++ b/mu4e/mu4e-compose.el @@ -386,10 +386,10 @@ message-thread by removing the In-Reply-To header." "Create a new draft message, or open an existing one. COMPOSE-TYPE determines the kind of message to compose and is a -symbol, either `reply', `forward', `edit', `new'. `edit' is for -editing existing messages. When COMPOSE-TYPE is `reply' or -`forward', MSG should be a message plist. If COMPOSE-TYPE is -`new', ORIGINAL-MSG should be nil. +symbol, either `reply', `forward', `edit', `resend' `new'. `edit' +is for editing existing (draft) messages. When COMPOSE-TYPE is +`reply' or `forward', MSG should be a message plist. If +COMPOSE-TYPE is `new', ORIGINAL-MSG should be nil. Optionally (when forwarding, replying) ORIGINAL-MSG is the original message we will forward / reply to. @@ -406,7 +406,6 @@ tempfile)." (set (make-local-variable 'mu4e-compose-parent-message) original-msg) (put 'mu4e-compose-parent-message 'permanent-local t) ;; maybe switch the context - (message "Autoswitch") (mu4e~context-autoswitch mu4e-compose-parent-message mu4e-compose-context-policy) (run-hooks 'mu4e-compose-pre-hook) @@ -414,7 +413,7 @@ tempfile)." ;; this opens (or re-opens) a messages with all the basic headers set. (condition-case nil (mu4e-draft-open compose-type original-msg) - (quit (kill-buffer) (message "[mu4e] Operation aborted") + (quit (kill-buffer) (mu4e-message "Operation aborted") (return-from mu4e~compose-handler))) ;; insert mail-header-separator, which is needed by message mode to separate ;; headers and body. will be removed before saving to disk @@ -532,15 +531,15 @@ buffer." (mu4e~proc-move (match-string 1 forwarded-from) nil "+P-N"))))))) (defun mu4e-compose (compose-type) - "Start composing a message of COMPOSE-TYPE, where COMPOSE-TYPE is -a symbol, one of `reply', `forward', `edit', `new'. All but `new' -take the message at point as input. Symbol `edit' is only allowed -for draft messages." + "Start composing a message of COMPOSE-TYPE, where COMPOSE-TYPE +is a symbol, one of `reply', `forward', `edit', `resend' +`new'. All but `new' take the message at point as input. Symbol +`edit' is only allowed for draft messages." (let ((msg (mu4e-message-at-point 'noerror))) ;; some sanity checks (unless (or msg (eq compose-type 'new)) (mu4e-warn "No message at point")) - (unless (member compose-type '(reply forward edit new)) + (unless (member compose-type '(reply forward edit resend new)) (mu4e-error "Invalid compose type '%S'" compose-type)) (when (and (eq compose-type 'edit) (not (member 'draft (mu4e-message-field msg :flags)))) @@ -584,6 +583,11 @@ draft message." (interactive) (mu4e-compose 'edit)) +(defun mu4e-compose-resend () + "Resend the message at point in the headers buffer." + (interactive) + (mu4e-compose 'resend)) + (defun mu4e-compose-new () "Start writing a new message." (interactive) diff --git a/mu4e/mu4e-draft.el b/mu4e/mu4e-draft.el index dd5dd4e7..1158d1d7 100644 --- a/mu4e/mu4e-draft.el +++ b/mu4e/mu4e-draft.el @@ -402,54 +402,69 @@ fields will be the same as in the original." "The drafts-folder for this compose buffer, based on `mu4e-drafts-folder', which is evaluated once.") -(defun mu4e-draft-open (compose-type &optional msg) - "Open a draft file for a new message (when COMPOSE-TYPE is reply, forward or new), -or open an existing draft (when COMPOSE-TYPE is edit). +(defun mu4e~draft-open-file (path) + "Open the the draft file at PATH." + (if (and mu4e-compose-in-new-frame (window-system)) + (find-file-other-frame path) + (find-file path))) -The name of the draft folder is constructed from the concatenation -of `mu4e-maildir' and `mu4e-drafts-folder' (the latter will be -evaluated). The message file name is a unique name determined by -`mu4e-send-draft-file-name'. The initial contents will be created -from either `mu4e~draft-reply-construct', or +(defun mu4e~draft-determine-path (draft-dir) + "Determine the path for a new draft file." + (format "%s/%s/cur/%s" + mu4e-maildir draft-dir (mu4e~draft-message-filename-construct "DS"))) + + +(defun mu4e-draft-open (compose-type &optional msg) + "Open a draft file for a new message (when COMPOSE-TYPE is `reply', `forward' or `new'), +open an existing draft (when COMPOSE-TYPE is `edit'), or re-send +an existing message (when COMPOSE-TYPE is `resend'). + +The name of the draft folder is constructed from the +concatenation of `mu4e-maildir' and `mu4e-drafts-folder' (the +latter will be evaluated). The message file name is a unique name +determined by `mu4e-send-draft-file-name'. The initial contents +will be created from either `mu4e~draft-reply-construct', or `mu4e~draft-forward-construct' or `mu4e~draft-newmsg-construct'." (unless mu4e-maildir (mu4e-error "mu4e-maildir not set")) - (let ((draft-dir)) - (if (eq compose-type 'edit) - ;; case-1: re-editing a draft messages. in this case, we do know the full - ;; path, but we cannot really know 'drafts folder'... we make a guess - (progn + (let ((draft-dir nil)) + (case compose-type + + (edit + ;; case-1: re-editing a draft messages. in this case, we do know the full + ;; path, but we cannot really know 'drafts folder'... we make a guess (setq draft-dir (mu4e~guess-maildir (mu4e-message-field msg :path))) - (if (and mu4e-compose-in-new-frame (window-system)) - (find-file-other-frame (mu4e-message-field msg :path)) - (find-file (mu4e-message-field msg :path)))) - ;; case-2: creating a new message; in this case, we can determing - ;; mu4e-get-drafts-folder - (progn + (mu4e~draft-open-file (mu4e-message-field msg :path))) + + (resend + ;; case-2: copy some exisisting message to a draft message, then edit + ;; that. + (setq draft-dir (mu4e~guess-maildir (mu4e-message-field msg :path))) + (let ((draft-path (mu4e~draft-determine-path draft-dir))) + (copy-file (mu4e-message-field msg :path) draft-path) + (mu4e~draft-open-file draft-path))) + + ((reply forward new) + ;; case-3: creating a new message; in this case, we can determing + ;; mu4e-get-drafts-folder (setq draft-dir (mu4e-get-drafts-folder msg)) - (let ((draft-path - (format "%s/%s/cur/%s" - mu4e-maildir - draft-dir - (mu4e~draft-message-filename-construct "DS"))) - (initial-contents - (case compose-type - (reply (mu4e~draft-reply-construct msg)) - (forward (mu4e~draft-forward-construct msg)) - (new (mu4e~draft-newmsg-construct)) - (t (mu4e-error "unsupported compose-type %S" compose-type))))) - (if (and mu4e-compose-in-new-frame (window-system)) - (find-file-other-frame draft-path) - (find-file draft-path)) - (insert initial-contents)) - (newline) - ;; include the message signature (if it's set) - (if (and mu4e-compose-signature-auto-include mu4e-compose-signature) - (let ((message-signature mu4e-compose-signature)) - (save-excursion - (message-insert-signature) - (mu4e~fontify-signature)))))) - ;; evaluate mu4e~drafts-drafts-folder once, here, and use that value - ;; throughout. + (let ((draft-path (mu4e~draft-determine-path draft-dir)) + (initial-contents + (case compose-type + (reply (mu4e~draft-reply-construct msg)) + (forward (mu4e~draft-forward-construct msg)) + (new (mu4e~draft-newmsg-construct))))) + (mu4e~draft-open-file draft-path) + (insert initial-contents) + (newline) + ;; include the message signature (if it's set) + (if (and mu4e-compose-signature-auto-include mu4e-compose-signature) + (let ((message-signature mu4e-compose-signature)) + (save-excursion + (message-insert-signature) + (mu4e~fontify-signature)))))) + (t (mu4e-error "unsupported compose-type %S" compose-type))) + ;; evaluate mu4e~drafts-drafts-folder once, here, and use that value + ;; throughout. (set (make-local-variable 'mu4e~draft-drafts-folder) draft-dir) (put 'mu4e~draft-drafts-folder 'permanent-local t) (unless mu4e~draft-drafts-folder diff --git a/mu4e/mu4e-proc.el b/mu4e/mu4e-proc.el index 310c3f68..d93af5d2 100644 --- a/mu4e/mu4e-proc.el +++ b/mu4e/mu4e-proc.el @@ -435,13 +435,13 @@ e.g. '/drafts'. (defun mu4e~proc-compose (type decrypt &optional docid) "Start composing a message of certain TYPE (a symbol, either -`forward', `reply', `edit' or `new', based on an original -message (ie, replying to, forwarding, editing) with DOCID or nil -for type `new'. +`forward', `reply', `edit', `resend' or `new', based on an +original message (ie, replying to, forwarding, editing, +resending) with DOCID or nil for type `new'. The result will be delivered to the function registered as `mu4e-compose-func'." - (unless (member type '(forward reply edit new)) + (unless (member type '(forward reply edit resend new)) (mu4e-error "Unsupported compose-type %S" type)) (unless (eq (null docid) (eq type 'new)) (mu4e-error "`new' implies docid not-nil, and vice-versa"))