mirror of https://github.com/djcb/mu.git
* when forwarding, include attachments from original
This commit is contained in:
parent
ff04b20712
commit
6e3e425c66
|
@ -275,10 +275,11 @@ updated as well, with all processed sexp data removed."
|
||||||
(funcall mu4e-proc-remove-func (plist-get sexp :remove)))
|
(funcall mu4e-proc-remove-func (plist-get sexp :remove)))
|
||||||
|
|
||||||
;; start composing a new message
|
;; start composing a new message
|
||||||
((plist-get sexp :compose)
|
((plist-get sexp :compose-type)
|
||||||
(funcall mu4e-proc-compose-func
|
(funcall mu4e-proc-compose-func
|
||||||
(plist-get sexp :compose-type)
|
(plist-get sexp :compose-type)
|
||||||
(plist-get sexp :compose)))
|
(plist-get sexp :original)
|
||||||
|
(plist-get sexp :include)))
|
||||||
|
|
||||||
;; get some info
|
;; get some info
|
||||||
((plist-get sexp :info)
|
((plist-get sexp :info)
|
||||||
|
|
|
@ -283,7 +283,7 @@ use the new docid. Returns the full path to the new message."
|
||||||
draft))
|
draft))
|
||||||
|
|
||||||
|
|
||||||
(defun mu4e-send-compose-handler (compose-type &optional msg)
|
(defun mu4e-send-compose-handler (compose-type &optional original-msg includes)
|
||||||
"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
|
||||||
|
@ -293,6 +293,15 @@ editing existing messages.
|
||||||
When COMPOSE-TYPE is `reply' or `forward', MSG should be a message
|
When COMPOSE-TYPE is `reply' or `forward', MSG should be a message
|
||||||
plist. If COMPOSE-TYPE is `new', MSG should be nil.
|
plist. If COMPOSE-TYPE is `new', MSG should be nil.
|
||||||
|
|
||||||
|
Optionally (when forwarding, replying) ORIGINAL-MSG is the original
|
||||||
|
message we will forward / reply to.
|
||||||
|
|
||||||
|
Optionally (when forwarding) INCLUDES contains a list of
|
||||||
|
(:file-name <filename> :mime-type <mime-type> :disposition <disposition>)
|
||||||
|
for the attachements to include; file-name refers to
|
||||||
|
a file which our backend has conveniently saved for us (as a
|
||||||
|
tempfile).
|
||||||
|
|
||||||
The name of the draft folder is constructed from the concatenation
|
The name of the draft folder is constructed from the concatenation
|
||||||
of `mu4e-maildir' and `mu4e-drafts-folder' (therefore, these must be
|
of `mu4e-maildir' and `mu4e-drafts-folder' (therefore, these must be
|
||||||
set).
|
set).
|
||||||
|
@ -307,17 +316,25 @@ using Gnus' `message-mode'."
|
||||||
(unless mu4e-drafts-folder (error "mu4e-drafts-folder not set"))
|
(unless mu4e-drafts-folder (error "mu4e-drafts-folder not set"))
|
||||||
(let ((draft
|
(let ((draft
|
||||||
(if (member compose-type '(reply forward new))
|
(if (member compose-type '(reply forward new))
|
||||||
(mu4e-send-open-draft compose-type msg)
|
(mu4e-send-open-draft compose-type original-msg)
|
||||||
(if (eq compose-type 'edit)
|
(if (eq compose-type 'edit)
|
||||||
(plist-get msg :path)
|
(plist-get original-msg :path)
|
||||||
(error "unsupported compose-type %S" compose-type)))))
|
(error "unsupported compose-type %S" compose-type)))))
|
||||||
|
|
||||||
(unless (file-readable-p draft)
|
(unless (file-readable-p draft)
|
||||||
(error "Cannot read %s" path))
|
(error "Cannot read %s" draft))
|
||||||
|
|
||||||
(find-file draft)
|
(find-file draft)
|
||||||
(message-mode)
|
(message-mode)
|
||||||
|
|
||||||
|
;; include files -- e.g. when forwarding a message with attachments,
|
||||||
|
;; we take those from the original.
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (point-max)) ;; put attachments at the end
|
||||||
|
(dolist (att includes)
|
||||||
|
(mml-attach-file
|
||||||
|
(plist-get att :file-name) (plist-get att :mime-type))))
|
||||||
|
|
||||||
(make-local-variable 'write-file-functions)
|
(make-local-variable 'write-file-functions)
|
||||||
|
|
||||||
;; update the db when the file is saved...]
|
;; update the db when the file is saved...]
|
||||||
|
@ -333,7 +350,7 @@ using Gnus' `message-mode'."
|
||||||
"^User-agent:")))
|
"^User-agent:")))
|
||||||
(message-hide-headers))
|
(message-hide-headers))
|
||||||
|
|
||||||
(if (eq compose-type 'new)
|
(if (member compose-type '(new forward))
|
||||||
(message-goto-to)
|
(message-goto-to)
|
||||||
(message-goto-body))))
|
(message-goto-body))))
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,6 @@ and finally, we receive:
|
||||||
.fi
|
.fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B move
|
.B move
|
||||||
|
|
||||||
|
@ -138,13 +137,21 @@ particular e-mail message.
|
||||||
.TP
|
.TP
|
||||||
.B compose
|
.B compose
|
||||||
|
|
||||||
Using the \fBcompose\fR command, we get the (unchanged) message, and tell what
|
Using the \fBcompose\fR command, we get the (original) message, and tell what
|
||||||
to do with it. The user-interface is then expect to pre-process the message,
|
to do with it. The user-interface is then expected to pre-process the message,
|
||||||
e.g. set the subject, sender and recipient for a reply message.
|
e.g. set the subject, sender and recipient for a reply message.
|
||||||
|
|
||||||
.nf
|
.nf
|
||||||
-> compose <reply|forward|edit> <docid>
|
-> compose <reply|forward|edit> <docid>
|
||||||
<- (:compose <s-exp> :compose-type <reply|forward|edit>)
|
<- (:compose-type <reply|forward|edit> :original <s-exp> :include (<list-of-attachments))
|
||||||
|
.fi
|
||||||
|
|
||||||
|
The <list-of-attachments> is an s-expression describing the attachments to
|
||||||
|
include in the message; this currently only applies to message we are
|
||||||
|
forwarding. This s-exprssion looks like:
|
||||||
|
|
||||||
|
.nf
|
||||||
|
(:file-name <filename> :mime-type <mime-type> :disposition <disposition>)
|
||||||
.fi
|
.fi
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -749,6 +749,72 @@ cmd_view (MuStore *store, MuQuery *query, GSList *args, GError **err)
|
||||||
return MU_OK;
|
return MU_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
each_part (MuMsg *msg, MuMsgPart *part, GSList **attlist)
|
||||||
|
{
|
||||||
|
char *att, *cachefile;
|
||||||
|
GError *err;
|
||||||
|
|
||||||
|
/* exclude things that don't look like proper attachments */
|
||||||
|
if (!mu_msg_part_looks_like_attachment(part, TRUE))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* save the attachment to some temp file */
|
||||||
|
cachefile = mu_msg_part_filepath_cache (msg, part->index);
|
||||||
|
if (!cachefile) {
|
||||||
|
server_error (NULL, MU_ERROR_FILE,
|
||||||
|
"could not determine cachefile name");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = NULL;
|
||||||
|
if (!mu_msg_part_save (msg, cachefile, part->index, FALSE, TRUE, &err)) {
|
||||||
|
server_error (&err, MU_ERROR_FILE,
|
||||||
|
"could not save %s", cachefile);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
att = g_strdup_printf (
|
||||||
|
"(:file-name \"%s\" :mime-type \"%s/%s\" :disposition \"%s\")",
|
||||||
|
cachefile,
|
||||||
|
part->type, part->subtype,
|
||||||
|
part->disposition ? part->disposition : "attachment");
|
||||||
|
|
||||||
|
*attlist = g_slist_append (*attlist, att);
|
||||||
|
|
||||||
|
leave:
|
||||||
|
g_clear_error (&err);
|
||||||
|
g_free (cachefile);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* take the attachments of msg, save them as tmp files, and return
|
||||||
|
* as sexp (as a string) describing them
|
||||||
|
*
|
||||||
|
* ((:name <filename> :mime-type <mime-type> :disposition
|
||||||
|
* <attachment|inline>) ... )
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static gchar*
|
||||||
|
include_attachments (MuMsg *msg)
|
||||||
|
{
|
||||||
|
GSList *attlist, *cur;
|
||||||
|
GString *gstr;
|
||||||
|
|
||||||
|
attlist = NULL;
|
||||||
|
mu_msg_part_foreach (msg,(MuMsgPartForeachFunc)each_part,
|
||||||
|
&attlist);
|
||||||
|
|
||||||
|
gstr = g_string_sized_new (512);
|
||||||
|
gstr = g_string_append_c (gstr, '(');
|
||||||
|
for (cur = attlist; cur; cur = g_slist_next (cur))
|
||||||
|
g_string_append (gstr, (gchar*)cur->data);
|
||||||
|
gstr = g_string_append_c (gstr, ')');
|
||||||
|
|
||||||
|
mu_str_free_list (attlist);
|
||||||
|
|
||||||
|
return g_string_free (gstr, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static MuError
|
static MuError
|
||||||
|
@ -756,7 +822,7 @@ cmd_compose (MuStore *store, GSList *args, GError **err)
|
||||||
{
|
{
|
||||||
MuMsg *msg;
|
MuMsg *msg;
|
||||||
unsigned docid;
|
unsigned docid;
|
||||||
char *sexp;
|
char *sexp, *atts;
|
||||||
const char* ctype;
|
const char* ctype;
|
||||||
|
|
||||||
return_if_fail_param_num (args, 2, 2,
|
return_if_fail_param_num (args, 2, 2,
|
||||||
|
@ -779,11 +845,17 @@ cmd_compose (MuStore *store, GSList *args, GError **err)
|
||||||
"failed to get message");
|
"failed to get message");
|
||||||
|
|
||||||
sexp = mu_msg_to_sexp (msg, docid, NULL, FALSE);
|
sexp = mu_msg_to_sexp (msg, docid, NULL, FALSE);
|
||||||
mu_msg_unref (msg);
|
if (strcmp(ctype, "forward") == 0)
|
||||||
|
atts = include_attachments (msg);
|
||||||
|
else
|
||||||
|
atts = NULL;
|
||||||
|
|
||||||
send_expr ("(:compose %s :compose-type %s)", sexp, ctype);
|
mu_msg_unref (msg);
|
||||||
|
send_expr ("(:compose-type %s :original %s :include %s)",
|
||||||
|
ctype, sexp, atts ? atts : "()");
|
||||||
|
|
||||||
g_free (sexp);
|
g_free (sexp);
|
||||||
|
g_free (atts);
|
||||||
|
|
||||||
return MU_OK;
|
return MU_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -527,7 +527,7 @@ mu_msg_part_looks_like_attachment (MuMsgPart *part, gboolean include_inline)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (part, FALSE);
|
g_return_val_if_fail (part, FALSE);
|
||||||
|
|
||||||
if (!part->disposition)
|
if (!part->disposition||!part->type || !part->file_name)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (g_ascii_strcasecmp (part->disposition,
|
if (g_ascii_strcasecmp (part->disposition,
|
||||||
|
|
Loading…
Reference in New Issue