* when forwarding, include attachments from original

This commit is contained in:
djcb 2012-01-14 12:55:50 +02:00
parent ff04b20712
commit 6e3e425c66
5 changed files with 112 additions and 15 deletions

View File

@ -275,10 +275,11 @@ updated as well, with all processed sexp data removed."
(funcall mu4e-proc-remove-func (plist-get sexp :remove)))
;; start composing a new message
((plist-get sexp :compose)
((plist-get sexp :compose-type)
(funcall mu4e-proc-compose-func
(plist-get sexp :compose-type)
(plist-get sexp :compose)))
(plist-get sexp :original)
(plist-get sexp :include)))
;; get some info
((plist-get sexp :info)

View File

@ -283,7 +283,7 @@ use the new docid. Returns the full path to the new message."
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.
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
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
of `mu4e-maildir' and `mu4e-drafts-folder' (therefore, these must be
set).
@ -307,17 +316,25 @@ using Gnus' `message-mode'."
(unless mu4e-drafts-folder (error "mu4e-drafts-folder not set"))
(let ((draft
(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)
(plist-get msg :path)
(plist-get original-msg :path)
(error "unsupported compose-type %S" compose-type)))))
(unless (file-readable-p draft)
(error "Cannot read %s" path))
(error "Cannot read %s" draft))
(find-file draft)
(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)
;; update the db when the file is saved...]
@ -333,7 +350,7 @@ using Gnus' `message-mode'."
"^User-agent:")))
(message-hide-headers))
(if (eq compose-type 'new)
(if (member compose-type '(new forward))
(message-goto-to)
(message-goto-body))))

View File

@ -64,7 +64,6 @@ and finally, we receive:
.fi
.TP
.B move
@ -138,13 +137,21 @@ particular e-mail message.
.TP
.B compose
Using the \fBcompose\fR command, we get the (unchanged) message, and tell what
to do with it. The user-interface is then expect to pre-process the message,
Using the \fBcompose\fR command, we get the (original) message, and tell what
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.
.nf
-> 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

View File

@ -749,6 +749,72 @@ cmd_view (MuStore *store, MuQuery *query, GSList *args, GError **err)
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
@ -756,7 +822,7 @@ cmd_compose (MuStore *store, GSList *args, GError **err)
{
MuMsg *msg;
unsigned docid;
char *sexp;
char *sexp, *atts;
const char* ctype;
return_if_fail_param_num (args, 2, 2,
@ -779,11 +845,17 @@ cmd_compose (MuStore *store, GSList *args, GError **err)
"failed to get message");
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 (atts);
return MU_OK;
}

View File

@ -527,7 +527,7 @@ mu_msg_part_looks_like_attachment (MuMsgPart *part, gboolean include_inline)
{
g_return_val_if_fail (part, FALSE);
if (!part->disposition)
if (!part->disposition||!part->type || !part->file_name)
return FALSE;
if (g_ascii_strcasecmp (part->disposition,