]> granicus.if.org Git - neomutt/commitdiff
Add $forward_attachments quadoption for inline-forward mode
authorKevin McCarthy <kevin@8t8.us>
Fri, 26 Apr 2019 02:41:04 +0000 (19:41 -0700)
committerRichard Russon <rich@flatcap.org>
Sun, 5 May 2019 00:00:38 +0000 (01:00 +0100)
When set or answered yes, non text-decodable parts will be attached to
the new message.  The default value is "ask-yes", because I believe
this is something people will want to use, and should be made aware of
the new possible behavior.

The option presents a nice middle ground between previous
inline-forwarding behavior (where all the non-text parts were
dropped), and $mime_forward where the entire email was included as an
attachment.

This was previously difficult to achieve, but after the
recv-attachment refactoring: (a19e5266^..faabd621)
it became possible to use the ATTACH_CONTEXT and the recvattach.c
helper mutt_generate_recvattach_list() to properly deal with nesting
and multiple file-handles.

Co-authored-by: Richard Russon <rich@flatcap.org>
doc/manual.xml.head
globals.h
init.h
recvattach.c
recvattach.h
send.c

index 8257ffae7ddf4bd080f8b3d452347e98cec92b8d..db6d129e003083ff93150eaca8ef5f86cdd6a6bc 100644 (file)
@@ -3177,6 +3177,14 @@ color sidebar_divider   color8  default     <emphasis role="comment"># Dark grey
         <link linkend="mime-forward">$mime_forward</link> is a quadoption
         which, for example, can be set to <quote>ask-no</quote>.
       </para>
+      <para>
+        Mutt's default (<link linkend="mime-forward">$mime_forward</link>=<quote>no</quote> and
+        <link linkend="forward-decode">$forward_decode</link>=<quote>yes</quote>) is
+        to use standard inline forwarding.  In that mode all text-decodable
+        parts are included in the new message body.  Other attachments from
+        the original email can also attached to the new message, based on the
+        quadoption <link linkend="forward-attachments">$forward_attachments</link>.
+      </para>
       <para>
         The inclusion of headers is controlled by the current setting of the
         <link linkend="weed">$weed</link> variable, unless
@@ -3193,7 +3201,8 @@ color sidebar_divider   color8  default     <emphasis role="comment"># Dark grey
       </para>
       <para>
         Editing the message to forward follows the same procedure as sending or
-        replying to a message does.
+        replying to a message does, but can be disabled via the quadoption
+        <link linkend="forward-edit">$forward_edit</link>.
       </para>
     </sect1>
 
index f9d6b78faa74970f17e26ce5e0c0eab77d2dd0de..64dbc1b8a4dd6b9fb29a9ae3cce9154bc55773c9 100644 (file)
--- a/globals.h
+++ b/globals.h
@@ -180,6 +180,7 @@ WHERE struct Regex *C_QuoteRegex;            ///< Config: Regex to match quoted
 WHERE unsigned char C_Bounce;                ///< Config: Confirm before bouncing a message
 WHERE unsigned char C_Copy;                  ///< Config: Save outgoing emails to $record
 WHERE unsigned char C_Delete;                ///< Config: Really delete messages, when the mailbox is closed
+WHERE unsigned char C_ForwardAttachments;    ///< Config: Forward attachments when forwarding a message
 WHERE unsigned char C_MimeForward;           ///< Config: Forward a message as a 'message/RFC822' MIME part
 WHERE unsigned char C_Print;                 ///< Config: Confirm before printing a message
 WHERE unsigned char C_Quit;                  ///< Config: Prompt before exiting NeoMutt
diff --git a/init.h b/init.h
index 801de6ae1d7676d47d2ee4262a7a481af690fb5e..fa39dcb1c41bf0907ef2ad650598e89af7ef388a 100644 (file)
--- a/init.h
+++ b/init.h
@@ -1187,6 +1187,15 @@ struct ConfigDef MuttVars[] = {
   ** .pp
   ** Also see the $$record variable.
   */
+  { "forward_attachments", DT_QUAD, R_NONE, &C_ForwardAttachments, MUTT_ASKYES },
+  /*
+  ** .pp
+  ** When forwarding inline (i.e. $$mime_forward \fIunset\fP or
+  ** answered with ``no'' and $$forward_decode \fIset\fP), attachments
+  ** which cannot be decoded in a reasonable manner will be attached
+  ** to the newly composed message if this quadoption is \fIset\fP or
+  ** answered with ``yes''.
+  */
   { "forward_attribution_intro", DT_STRING, R_NONE, &C_ForwardAttributionIntro, IP "----- Forwarded message from %f -----" },
   /*
   ** .pp
index cc34b97be533c389c20067bf0a24e974e5f5a27c..bf353570942a1ad673183022e04ed2155b496d5d 100644 (file)
@@ -1137,9 +1137,9 @@ int mutt_attach_display_loop(struct Menu *menu, int op, struct Email *e,
  * @param level       Attachment depth
  * @param decrypted   True if attachment has been decrypted
  */
-static void mutt_generate_recvattach_list(struct AttachCtx *actx, struct Email *e,
-                                          struct Body *parts, FILE *fp,
-                                          int parent_type, int level, bool decrypted)
+void mutt_generate_recvattach_list(struct AttachCtx *actx, struct Email *e,
+                                   struct Body *parts, FILE *fp,
+                                   int parent_type, int level, bool decrypted)
 {
   struct AttachPtr *new = NULL;
   struct Body *m = NULL;
index 0964d6ca05e80dc8b7d414ec95d3f1b36b50e49b..90a98d40aef1183a1dfc01d9fde60716315d9160 100644 (file)
@@ -44,4 +44,6 @@ void mutt_update_tree(struct AttachCtx *actx);
 const char *attach_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, unsigned long data, MuttFormatFlags flags);
 void mutt_view_attachments(struct Email *e);
 
+void mutt_generate_recvattach_list(struct AttachCtx *actx, struct Email *e, struct Body *parts, FILE *fp, int parent_type, int level, bool decrypted);
+
 #endif /* MUTT_RECVATTACH_H */
diff --git a/send.c b/send.c
index 52f84a1765556e6a3fa0257837059d80ff769d88..9b8e21b1a7b5bd7e4e8b1268547512347fd1e5eb 100644 (file)
--- a/send.c
+++ b/send.c
 #include "edit.h"
 #include "filter.h"
 #include "globals.h"
+#include "handler.h"
 #include "hdrline.h"
 #include "hook.h"
 #include "mailbox.h"
 #include "mutt_attach.h"
+#include "mutt_body.h"
 #include "mutt_header.h"
 #include "mutt_logging.h"
 #include "mutt_parse.h"
@@ -63,6 +65,7 @@
 #include "options.h"
 #include "pattern.h"
 #include "protos.h"
+#include "recvattach.h"
 #include "rfc3676.h"
 #include "sendlib.h"
 #include "smtp.h"
@@ -533,6 +536,128 @@ static int include_forward(struct Mailbox *m, struct Email *e, FILE *fp_out)
   return 0;
 }
 
+/**
+ * inline_forward_attachments - Add attachments to an email, inline
+ * @param[in]  m        Mailbox
+ * @param[in]  cur      Current Email
+ * @param[out] plast    Pointer to the last Attachment
+ * @param[out] forwardq Result of asking the user to forward the attachments, e.g. #MUTT_YES
+ * @retval  0 Success
+ * @retval -1 Error
+ */
+static int inline_forward_attachments(struct Mailbox *m, struct Email *cur,
+                                      struct Body ***plast, int *forwardq)
+{
+  struct Body **last = *plast, *body = NULL;
+  struct Message *msg = NULL;
+  struct AttachCtx *actx = NULL;
+  int rc = 0, i;
+
+  mutt_parse_mime_message(m, cur);
+  mutt_message_hook(m, cur, MUTT_MESSAGE_HOOK);
+
+  msg = mx_msg_open(m, cur->msgno);
+  if (!msg)
+    return -1;
+
+  actx = mutt_mem_calloc(1, sizeof(*actx));
+  actx->email = cur;
+  actx->fp_root = msg->fp;
+
+  mutt_generate_recvattach_list(actx, actx->email, actx->email->content,
+                                actx->fp_root, -1, 0, 0);
+
+  for (i = 0; i < actx->idxlen; i++)
+  {
+    body = actx->idx[i]->content;
+    if ((body->type != TYPE_MULTIPART) && !mutt_can_decode(body) &&
+        !((body->type == TYPE_APPLICATION) &&
+          ((mutt_str_strcasecmp(body->subtype, "pgp-signature") == 0) ||
+           (mutt_str_strcasecmp(body->subtype, "x-pkcs7-signature") == 0) ||
+           (mutt_str_strcasecmp(body->subtype, "pkcs7-signature") == 0))))
+    {
+      /* Ask the quadoption only once */
+      if (*forwardq == -1)
+      {
+        *forwardq = query_quadoption(C_ForwardAttachments,
+                                     /* L10N:
+                                        This is the prompt for $forward_attachments.
+                                        When inline forwarding ($mime_forward answered "no"), this prompts
+                                        whether to add non-decodable attachments from the original email.
+                                        Text/plain parts and the like will be already be included in the
+                                        message contents, but other attachment, such as PDF files, will also
+                                        be added as attachments to the new mail, is this is answered yes.
+                                      */
+                                     _("Forward attachments?"));
+        if (*forwardq != MUTT_YES)
+        {
+          if (*forwardq == -1)
+            rc = -1;
+          goto cleanup;
+        }
+      }
+      if (mutt_body_copy(actx->idx[i]->fp, last, body) == -1)
+      {
+        rc = -1;
+        goto cleanup;
+      }
+      last = &((*last)->next);
+    }
+  }
+
+cleanup:
+  *plast = last;
+  mx_msg_close(m, &msg);
+  mutt_actx_free(&actx);
+  return rc;
+}
+
+/**
+ * mutt_inline_forward - Forward attachments, inline
+ * @param m Mailbox
+ * @param msg Email to alter
+ * @param cur Current Email
+ * @param out File
+ * @retval  0 Success
+ * @retval -1 Error
+ */
+int mutt_inline_forward(struct Mailbox *m, struct Email *msg, struct Email *cur, FILE *out)
+{
+  int i, forwardq = -1;
+  struct Body **last;
+
+  if (cur)
+    include_forward(m, cur, out);
+  else
+    for (i = 0; i < m->vcount; i++)
+      if (m->emails[m->v2r[i]]->tagged)
+        include_forward(m, m->emails[m->v2r[i]], out);
+
+  if (C_ForwardDecode && (C_ForwardAttachments != MUTT_NO))
+  {
+    last = &msg->content;
+    while (*last)
+      last = &((*last)->next);
+
+    if (cur)
+    {
+      if (inline_forward_attachments(m, cur, &last, &forwardq) != 0)
+        return -1;
+    }
+    else
+      for (i = 0; i < m->vcount; i++)
+        if (m->emails[m->v2r[i]]->tagged)
+        {
+          if (inline_forward_attachments(m, m->emails[m->v2r[i]], &last, &forwardq) != 0)
+            return -1;
+          if (forwardq == MUTT_NO)
+            break;
+        }
+  }
+
+  return 0;
+}
+
 /**
  * mutt_make_attribution - Add "on DATE, PERSON wrote" header
  * @param m      Mailbox
@@ -1056,15 +1181,8 @@ static int generate_body(FILE *fp_tmp, struct Email *msg, SendFlags flags,
     }
     else if (ans != MUTT_ABORT)
     {
-      if (single)
-        include_forward(m, en->email, fp_tmp);
-      else
-      {
-        STAILQ_FOREACH(en, el, entries)
-        {
-          include_forward(m, en->email, fp_tmp);
-        }
-      }
+      if (mutt_inline_forward(m, msg, en->email, fp_tmp) != 0)
+        return -1;
     }
     else
       return -1;