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