Add new flag -E to modify draft/include file. (closes #3799)

Specifying -E with -i will cause mutt to directly edit the include
file.

Specifying -E with -H will cause the draft file to be regenerated from
the latest version of the email on exit.

Improve -H so that it will read (and write) multipart messages.

-- 
Kevin J. McCarthy
GPG Fingerprint: 8975 A9B3 3AA3 7910 385C  5308 ADEF 7684 8031 6BDA
http://www.8t8.us/configs/gpg-key-transition-statement.txt
# HG changeset patch
# User Kevin McCarthy <[email protected]>
# Date 1454619075 28800
#      Thu Feb 04 12:51:15 2016 -0800
# Node ID d566ab7098957fadab9838634eb3416a23fe178c
# Parent  e8f7a08cb7ac463c57484b17fb9143c4c4df6fa5
Add new flag -E to modify draft/include file. (closes #3799)

Specifying -E with -i will cause mutt to directly edit the include
file.

Specifying -E with -H will cause the draft file to be regenerated from
the latest version of the email on exit.

Improve -H so that it will read (and write) multipart messages.

diff --git a/compose.c b/compose.c
--- a/compose.c
+++ b/compose.c
@@ -478,19 +478,20 @@
 
 /* return values:
  *
  * 1   message should be postponed
  * 0   normal exit
  * -1  abort message
  */
 int mutt_compose_menu (HEADER *msg,   /* structure for new message */
-                   char *fcc,     /* where to save a copy of the message */
-                   size_t fcclen,
-                   HEADER *cur)   /* current message */
+                       char *fcc,     /* where to save a copy of the message */
+                       size_t fcclen,
+                       HEADER *cur,   /* current message */
+                       int flags)
 {
   char helpstr[LONG_STRING];
   char buf[LONG_STRING];
   char fname[_POSIX_PATH_MAX];
   MUTTMENU *menu;
   ATTACHPTR **idx = NULL;
   short idxlen = 0;
   short idxmax = 0;
@@ -1154,30 +1155,35 @@
          menu->redraw = menu->tagprefix ? REDRAW_FULL : REDRAW_CURRENT;
         menu->redraw |= REDRAW_STATUS;
         mutt_message_hook (NULL, msg, M_SEND2HOOK);
        break;
 
       case OP_EXIT:
        if ((i = query_quadoption (OPT_POSTPONE, _("Postpone this message?"))) 
== M_NO)
        {
-         while (idxlen-- > 0)
-         {
-           /* avoid freeing other attachments */
-           idx[idxlen]->content->next = NULL;
-           idx[idxlen]->content->parts = NULL;
-            if (idx[idxlen]->unowned)
-              idx[idxlen]->content->unlink = 0;
-           mutt_free_body (&idx[idxlen]->content);
-           FREE (&idx[idxlen]->tree);
-           FREE (&idx[idxlen]);
-         }
-         FREE (&idx);
-         idxlen = 0;
-         idxmax = 0;
+          for (i = 0; i < idxlen; i++)
+            if (idx[i]->unowned)
+              idx[i]->content->unlink = 0;
+
+          if (!(flags & M_COMPOSE_NOFREEHEADER))
+          {
+            while (idxlen-- > 0)
+            {
+              /* avoid freeing other attachments */
+              idx[idxlen]->content->next = NULL;
+              idx[idxlen]->content->parts = NULL;
+              mutt_free_body (&idx[idxlen]->content);
+              FREE (&idx[idxlen]->tree);
+              FREE (&idx[idxlen]);
+            }
+            FREE (&idx);
+            idxlen = 0;
+            idxmax = 0;
+          }
          r = -1;
          loop = 0;
          break;
        }
        else if (i == -1)
          break; /* abort */
 
        /* fall through to postpone! */
diff --git a/doc/manual.xml.head b/doc/manual.xml.head
--- a/doc/manual.xml.head
+++ b/doc/manual.xml.head
@@ -8299,16 +8299,17 @@
 <row><entry>Option</entry><entry>Description</entry></row>
 </thead>
 <tbody>
 <row><entry>-A</entry><entry>expand an alias</entry></row>
 <row><entry>-a</entry><entry>attach a file to a message</entry></row>
 <row><entry>-b</entry><entry>specify a blind carbon-copy (BCC) 
address</entry></row>
 <row><entry>-c</entry><entry>specify a carbon-copy (Cc) address</entry></row>
 <row><entry>-D</entry><entry>print the value of all Mutt variables to 
stdout</entry></row>
+<row><entry>-E</entry><entry>edit the draft (-H) or include (-i) 
file</entry></row>
 <row><entry>-e</entry><entry>specify a config command to be run after 
initialization files are read</entry></row>
 <row><entry>-f</entry><entry>specify a mailbox to load</entry></row>
 <row><entry>-F</entry><entry>specify an alternate file to read initialization 
commands</entry></row>
 <row><entry>-h</entry><entry>print help on command line options</entry></row>
 <row><entry>-H</entry><entry>specify a draft file from which to read a header 
and body</entry></row>
 <row><entry>-i</entry><entry>specify a file to include in a message 
composition</entry></row>
 <row><entry>-m</entry><entry>specify a default mailbox type</entry></row>
 <row><entry>-n</entry><entry>do not read the system Muttrc</entry></row>
@@ -8344,24 +8345,24 @@
 </cmdsynopsis>
 
 <para>
 To compose a new message
 </para>
 
 <cmdsynopsis>
 <command>mutt</command>
-<arg choice="opt"><option>-n</option></arg>
+<arg choice="opt"><option>-En</option></arg>
 <arg choice="opt"><option>-F</option>
 <replaceable>muttrc</replaceable>
 </arg>
 <arg choice="opt"><option>-c</option>
 <replaceable>address</replaceable>
 </arg>
-<arg choice="opt"><option>-i</option>
+<arg choice="opt"><option>-Hi</option>
 <replaceable>filename</replaceable>
 </arg>
 <arg choice="opt"><option>-s</option>
 <replaceable>subject</replaceable>
 </arg>
 <arg choice="opt">
 <option>-a</option>
 <replaceable>file</replaceable>
@@ -8390,16 +8391,34 @@
 <para>
 will send a message to
 <literal>&lt;[email protected]&gt;</literal> with a subject of
 <quote>data set for run #2</quote>.  In the body of the message will be
 the contents of the file <quote>~/run2.dat</quote>.
 </para>
 
 <para>
+An include file passed with <literal>-i</literal> will be used as the
+body of the message.  When combined with <literal>-E</literal>, the
+include file will be directly edited during message composition.  The
+file will be modified regardless of whether the message is sent or
+aborted.
+</para>
+
+<para>
+A draft file passed with <literal>-H</literal> will be used as the
+initial header and body for the message.  Multipart messages can be
+used as a draft file.  When combined with <literal>-E</literal>, the
+draft file will be updated to the final state of the message after
+composition, regardless of whether the message is sent, aborted, or
+even postponed.  Note that if the message is sent encrypted or signed,
+the draft file will be saved that way too.
+</para>
+
+<para>
 All files passed with <literal>-a</literal> <emphasis>file</emphasis>
 will be attached as a MIME part to the message. To attach a single or
 several files, use <quote>--</quote> to separate files and recipient
 addresses:
 </para>
 
 <screen>
 mutt -a image.png -- [email protected]</screen>
diff --git a/doc/mutt.man b/doc/mutt.man
--- a/doc/mutt.man
+++ b/doc/mutt.man
@@ -1,12 +1,12 @@
 .\" -*-nroff-*-
 .\"
 .\"
-.\"     Copyright (C) 1996-2004 Michael R. Elkins <[email protected]>
+.\"     Copyright (C) 1996-2016 Michael R. Elkins <[email protected]>
 .\" 
 .\"     This program is free software; you can redistribute it and/or modify
 .\"     it under the terms of the GNU General Public License as published by
 .\"     the Free Software Foundation; either version 2 of the License, or
 .\"     (at your option) any later version.
 .\" 
 .\"     This program is distributed in the hope that it will be useful,
 .\"     but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -22,17 +22,17 @@
 mutt \- The Mutt Mail User Agent
 .SH SYNOPSIS
 .PP
 .B mutt
 [\-nRyzZ]
 [\-e \fIcmd\fP] [\-F \fIfile\fP] [\-m \fItype\fP] [\-f \fIfile\fP]
 .PP
 .B mutt 
-[\-nx] 
+[\-Enx] 
 [\-e \fIcmd\fP] 
 [\-F \fIfile\fP]
 [\-H \fIfile\fP]
 [\-i \fIfile\fP]
 [\-s \fIsubj\fP]
 [\-b \fIaddr\fP]
 [\-c \fIaddr\fP]
 [\-a \fIfile\fP [...] \-\-]
@@ -89,16 +89,19 @@
 .IP "-c \fIaddress\fP"
 Specify a carbon-copy (CC) recipient
 .IP "-d \fIlevel\fP"
 If mutt was compiled with +DEBUG log debugging output to ~/.muttdebug0.
 \fILevel\fP can range from 1-5 and effects verbosity. A value of 2 is
 recommended.
 .IP "-D"
 Print the value of all configuration options to stdout.
+.IP "-E"
+Causes the draft file specified by -H or include file specified by -i
+to be edited during message composition.
 .IP "-e \fIcommand\fP"
 Specify a configuration command to be run after processing of initialization
 files.
 .IP "-f \fImailbox\fP"
 Specify which mailbox to load.
 .IP "-F \fImuttrc\fP"
 Specify an initialization file to read instead of ~/.muttrc
 .IP "-h"
diff --git a/main.c b/main.c
--- a/main.c
+++ b/main.c
@@ -109,17 +109,17 @@
 }
 
 static void mutt_usage (void)
 {
   puts (mutt_make_version ());
 
   puts _(
 "usage: mutt [<options>] [-z] [-f <file> | -yZ]\n\
-       mutt [<options>] [-x] [-Hi <file>] [-s <subj>] [-bc <addr>] [-a <file> 
[...] --] <addr> [...]\n\
+       mutt [<options>] [-Ex] [-Hi <file>] [-s <subj>] [-bc <addr>] [-a <file> 
[...] --] <addr> [...]\n\
        mutt [<options>] [-x] [-s <subj>] [-bc <addr>] [-a <file> [...] --] 
<addr> [...] < message\n\
        mutt [<options>] -p\n\
        mutt [<options>] -A <alias> [...]\n\
        mutt [<options>] -Q <query> [...]\n\
        mutt [<options>] -D\n\
        mutt -v[v]\n");
 
   puts _("\
@@ -129,17 +129,18 @@
 \t\tthe list of files must be terminated with the \"--\" sequence\n\
   -b <address>\tspecify a blind carbon-copy (BCC) address\n\
   -c <address>\tspecify a carbon-copy (CC) address\n\
   -D\t\tprint the value of all variables to stdout");
 #if DEBUG
   puts _("  -d <level>\tlog debugging output to ~/.muttdebug0");
 #endif
   puts _(
-"  -e <command>\tspecify a command to be executed after initialization\n\
+"  -E\t\tedit the draft (-H) or include (-i) file\n\
+  -e <command>\tspecify a command to be executed after initialization\n\
   -f <file>\tspecify which mailbox to read\n\
   -F <file>\tspecify an alternate muttrc file\n\
   -H <file>\tspecify a draft file to read header and body from\n\
   -i <file>\tspecify a file which Mutt should include in the body\n\
   -m <type>\tspecify a default mailbox type\n\
   -n\t\tcauses Mutt not to read the system Muttrc\n\
   -p\t\trecall a postponed message");
   
@@ -567,16 +568,17 @@
   LIST *queries = NULL;
   LIST *alias_queries = NULL;
   int sendflags = 0;
   int flags = 0;
   int version = 0;
   int i;
   int explicit_folder = 0;
   int dump_variables = 0;
+  int edit_infile = 0;
   extern char *optarg;
   extern int optind;
   int double_dash = argc, nargc = 1;
 
   /* sanity check against stupid administrators */
   
   if(getegid() != getgid())
   {
@@ -620,17 +622,17 @@
 
       /* non-option, either an attachment or address */
       if (attach)
         attach = mutt_add_list (attach, argv[optind]);
       else
         argv[nargc++] = argv[optind];
     }
 
-    if ((i = getopt (argc, argv, "+A:a:b:F:f:c:Dd:e:H:s:i:hm:npQ:RvxyzZ")) != 
EOF)
+    if ((i = getopt (argc, argv, "+A:a:b:F:f:c:Dd:Ee:H:s:i:hm:npQ:RvxyzZ")) != 
EOF)
       switch (i)
       {
       case 'A':
         alias_queries = mutt_add_list (alias_queries, optarg);
         break;
       case 'a':
        attach = mutt_add_list (attach, optarg);
        break;
@@ -668,16 +670,20 @@
          return 1;
        }
        printf (_("Debugging at level %d.\n"), debuglevel);
 #else
        printf _("DEBUG was not defined during compilation.  Ignored.\n");
 #endif
        break;
 
+      case 'E':
+        edit_infile = 1;
+        break;
+
       case 'e':
        commands = mutt_add_list (commands, optarg);
        break;
 
       case 'H':
        draftFile = optarg;
        break;
 
@@ -854,20 +860,22 @@
       mutt_flushinp ();
     ci_send_message (SENDPOSTPONED, NULL, NULL, NULL, NULL);
     mutt_endwin (NULL);
   }
   else if (subject || msg || sendflags || draftFile || includeFile || attach ||
           optind < argc)
   {
     FILE *fin = NULL;
+    FILE *fout = NULL;
     char buf[LONG_STRING];
     char *tempfile = NULL, *infile = NULL;
-    char *bodytext = NULL;
+    char *bodytext = NULL, *bodyfile = NULL;
     int rv = 0;
+    char expanded_infile[_POSIX_PATH_MAX];
     
     if (!option (OPTNOCURSES))
       mutt_flushinp ();
 
     if (!msg)
       msg = mutt_new_header ();
     if (!msg->env)
       msg->env = mutt_new_envelope ();
@@ -895,91 +903,151 @@
       fputs (_("No recipients specified.\n"), stderr);
       exit (1);
     }
 
     if (subject)
       msg->env->subject = safe_strdup (subject);
 
     if (draftFile)
+    {
       infile = draftFile;
+      includeFile = NULL;
+    }
     else if (includeFile)
       infile = includeFile;
+    else
+      edit_infile = 0;
 
     if (infile || bodytext)
     {
+      /* Prepare fin and expanded_infile. */
       if (infile)
       {
        if (mutt_strcmp ("-", infile) == 0)
+        {
+          if (edit_infile)
+          {
+            fputs (_("Cannot use -E flag with stdin\n"), stderr);
+            exit (1);
+          }
          fin = stdin;
-       else 
+        }
+       else
        {
-         char path[_POSIX_PATH_MAX];
-         
-         strfcpy (path, infile, sizeof (path));
-         mutt_expand_path (path, sizeof (path));
-         if ((fin = fopen (path, "r")) == NULL)
+         strfcpy (expanded_infile, infile, sizeof (expanded_infile));
+         mutt_expand_path (expanded_infile, sizeof (expanded_infile));
+         if ((fin = fopen (expanded_infile, "r")) == NULL)
          {
            if (!option (OPTNOCURSES))
              mutt_endwin (NULL);
-           perror (path);
+           perror (expanded_infile);
            exit (1);
          }
        }
+      }
 
-        if (draftFile)
+      /* Copy input to a tempfile, and re-point fin to the tempfile.
+       * Note: stdin is always copied to a tempfile, ensuring draftFile
+       * can stat and get the correct st_size below.
+       */
+      if (!edit_infile)
+      {
+        mutt_mktemp (buf, sizeof (buf));
+        tempfile = safe_strdup (buf);
+
+        if ((fout = safe_fopen (tempfile, "w")) == NULL)
         {
-          ENVELOPE *opts_env = msg->env;
-          msg->env = mutt_read_rfc822_header (fin, NULL, 1, 0);
+          if (!option (OPTNOCURSES))
+            mutt_endwin (NULL);
+          perror (tempfile);
+          safe_fclose (&fin);
+          FREE (&tempfile);
+          exit (1);
+        }
+        if (fin)
+        {
+          mutt_copy_stream (fin, fout);
+          if (fin != stdin)
+            safe_fclose (&fin);
+        }
+        else if (bodytext)
+          fputs (bodytext, fout);
+        safe_fclose (&fout);
 
-          rfc822_append (&msg->env->to, opts_env->to, 0);
-          rfc822_append (&msg->env->cc, opts_env->cc, 0);
-          rfc822_append (&msg->env->bcc, opts_env->bcc, 0);
-          if (opts_env->subject)
-            mutt_str_replace (&msg->env->subject, opts_env->subject);
-
-          mutt_free_envelope (&opts_env);
+        if ((fin = fopen (tempfile, "r")) == NULL)
+        {
+          if (!option (OPTNOCURSES))
+            mutt_endwin (NULL);
+          perror (tempfile);
+          FREE (&tempfile);
+          exit (1);
         }
       }
+      /* If editing the infile, keep it around afterwards so
+       * it doesn't get unlinked, and we can rebuild the draftFile
+       */
+      else
+        sendflags |= SENDNOFREEHEADER;
 
-      mutt_mktemp (buf, sizeof (buf));
-      tempfile = safe_strdup (buf);
+      /* Parse the draftFile into the full HEADER/BODY structure.
+       * Set SENDUSEHDRBODY so ci_send_message doesn't overwrite
+       * our msg->content.
+       */
+      if (draftFile)
+      {
+        HEADER *context_hdr = NULL;
+        ENVELOPE *opts_env = msg->env;
+        struct stat st;
 
-      /* is the following if still needed? */
-      
-      if (tempfile)
-      {
-       FILE *fout;
+        sendflags |= SENDUSEHDRBODY;
 
-       if ((fout = safe_fopen (tempfile, "w")) == NULL)
-       {
-         if (!option (OPTNOCURSES))
-           mutt_endwin (NULL);
-         perror (tempfile);
-         safe_fclose (&fin);
-         FREE (&tempfile);
-         exit (1);
-       }
-       if (fin)
-         mutt_copy_stream (fin, fout);
-       else if (bodytext)
-         fputs (bodytext, fout);
-       safe_fclose (&fout);
+        /* Set up a "context" header with just enough information so that
+         * mutt_prepare_template() can parse the message in fin.
+         */
+        context_hdr = mutt_new_header ();
+        context_hdr->offset = 0;
+        context_hdr->content = mutt_new_body ();
+        fstat (fileno (fin), &st);
+        context_hdr->content->length = st.st_size;
+
+        mutt_prepare_template (fin, NULL, msg, context_hdr, 0);
+
+        rfc822_append (&msg->env->to, opts_env->to, 0);
+        rfc822_append (&msg->env->cc, opts_env->cc, 0);
+        rfc822_append (&msg->env->bcc, opts_env->bcc, 0);
+        if (opts_env->subject)
+          mutt_str_replace (&msg->env->subject, opts_env->subject);
+
+        mutt_free_envelope (&opts_env);
+        mutt_free_header (&context_hdr);
       }
+      /* Editing the includeFile: pass it directly in.
+       * Note that SENDNOFREEHEADER is set above so it isn't unlinked.
+       */
+      else if (edit_infile)
+        bodyfile = expanded_infile;
+      /* For bodytext and unedited includeFile: use the tempfile.
+       */
+      else
+        bodyfile = tempfile;
 
-      if (fin && fin != stdin)
+      if (fin)
         safe_fclose (&fin);
     }
 
     FREE (&bodytext);
-    
+
     if (attach)
     {
       LIST *t = attach;
-      BODY *a = NULL;
+      BODY *a = msg->content;
+
+      while (a && a->next)
+        a = a->next;
 
       while (t)
       {
        if (a)
        {
          a->next = mutt_make_file_attach (t->data);
          a = a->next;
        }
@@ -993,17 +1061,72 @@
          mutt_free_list (&attach);
          exit (1);
        }
        t = t->next;
       }
       mutt_free_list (&attach);
     }
 
-    rv = ci_send_message (sendflags, msg, tempfile, NULL, NULL);
+    rv = ci_send_message (sendflags, msg, bodyfile, NULL, NULL);
+
+    if (edit_infile)
+    {
+      if (includeFile)
+        msg->content->unlink = 0;
+      else if (draftFile)
+      {
+        if (truncate (expanded_infile, 0) == -1)
+        {
+          if (!option (OPTNOCURSES))
+            mutt_endwin (NULL);
+          perror (expanded_infile);
+          exit (1);
+        }
+        if ((fout = safe_fopen (expanded_infile, "a")) == NULL)
+        {
+          if (!option (OPTNOCURSES))
+            mutt_endwin (NULL);
+          perror (expanded_infile);
+          exit (1);
+        }
+
+        /* If the message was sent or postponed, these will already
+         * have been done.
+         */
+        if (rv < 0)
+        {
+          if (msg->content->next)
+            msg->content = mutt_make_multipart (msg->content);
+          mutt_encode_descriptions (msg->content, 1);
+          mutt_prepare_envelope (msg->env, 0);
+          mutt_env_to_intl (msg->env, NULL, NULL);
+        }
+
+        mutt_write_rfc822_header (fout, msg->env, msg->content, -1, 0);
+        fputc ('\n', fout);
+        if ((mutt_write_mime_body (msg->content, fout) == -1))
+        {
+          if (!option (OPTNOCURSES))
+            mutt_endwin (NULL);
+          safe_fclose (&fout);
+          exit (1);
+        }
+        safe_fclose (&fout);
+      }
+
+      mutt_free_header (&msg);
+    }
+
+    /* !edit_infile && draftFile will leave the tempfile around */
+    if (tempfile)
+    {
+      unlink (tempfile);
+      FREE (&tempfile);
+    }
 
     if (!option (OPTNOCURSES))
       mutt_endwin (NULL);
 
     if (rv)
       exit(1);
   }
   else
diff --git a/mutt.h b/mutt.h
--- a/mutt.h
+++ b/mutt.h
@@ -291,16 +291,21 @@
 #define SENDLISTREPLY  (1<<2)
 #define SENDFORWARD    (1<<3)
 #define SENDPOSTPONED  (1<<4)
 #define SENDBATCH      (1<<5)
 #define SENDMAILX      (1<<6)
 #define SENDKEY                (1<<7)
 #define SENDRESEND     (1<<8)
 #define SENDPOSTPONEDFCC       (1<<9) /* used by mutt_get_postponed() to 
signal that the x-mutt-fcc header field was present */
+#define SENDNOFREEHEADER       (1<<10)   /* Used by the -E flag */
+#define SENDUSEHDRBODY         (1<<11)   /* Used by the -H flag */
+
+/* flags for mutt_compose_menu() */
+#define M_COMPOSE_NOFREEHEADER (1<<0)
 
 /* flags to _mutt_select_file() */
 #define M_SEL_BUFFY    (1<<0)
 #define M_SEL_MULTI    (1<<1)
 #define M_SEL_FOLDER   (1<<2)
 
 /* flags for parse_spam_list */
 #define M_SPAM          1
diff --git a/protos.h b/protos.h
--- a/protos.h
+++ b/protos.h
@@ -181,16 +181,17 @@
 void mutt_display_address (ENVELOPE *);
 void mutt_display_sanitize (char *);
 void mutt_edit_content_type (HEADER *, BODY *, FILE *);
 void mutt_edit_file (const char *, const char *);
 void mutt_edit_headers (const char *, const char *, HEADER *, char *, size_t);
 int mutt_filter_unprintable (char **);
 void mutt_curses_error (const char *, ...);
 void mutt_curses_message (const char *, ...);
+void mutt_encode_descriptions (BODY *, short);
 void mutt_encode_path (char *, size_t, const char *);
 void mutt_enter_command (void);
 void mutt_expand_aliases_env (ENVELOPE *);
 void mutt_expand_file_fmt (char *, size_t, const char *, const char *);
 void mutt_expand_fmt (char *, size_t, const char *, const char *);
 void mutt_expand_link (char *, const char *, const char *);
 void mutt_fix_reply_recipients (ENVELOPE *env);
 void mutt_folder_hook (char *);
@@ -353,17 +354,17 @@
 int mutt_search_command (int, int);
 #ifdef USE_SMTP
 int mutt_smtp_send (const ADDRESS *, const ADDRESS *, const ADDRESS *,
                     const ADDRESS *, const char *, int);
 #endif
 int mutt_wstr_trunc (const char *, size_t, size_t, size_t *);
 int mutt_charlen (const char *s, int *);
 int mutt_strwidth (const char *);
-int mutt_compose_menu (HEADER *, char *, size_t, HEADER *);
+int mutt_compose_menu (HEADER *, char *, size_t, HEADER *, int);
 int mutt_thread_set_flag (HEADER *, int, int, int);
 int mutt_user_is_recipient (HEADER *);
 void mutt_update_num_postponed (void);
 int mutt_wait_filter (pid_t);
 int mutt_which_case (const char *);
 int mutt_write_fcc (const char *path, HEADER *hdr, const char *msgid, int, 
char *);
 int mutt_write_mime_body (BODY *, FILE *);
 int mutt_write_mime_header (BODY *, FILE *);
diff --git a/send.c b/send.c
--- a/send.c
+++ b/send.c
@@ -1037,28 +1037,28 @@
 
   i = mutt_invoke_sendmail (msg->env->from, msg->env->to, msg->env->cc, 
                            msg->env->bcc, tempfile,
                             (msg->content->encoding == ENC8BIT));
   return (i);
 }
 
 /* rfc2047 encode the content-descriptions */
-static void encode_descriptions (BODY *b, short recurse)
+void mutt_encode_descriptions (BODY *b, short recurse)
 {
   BODY *t;
 
   for (t = b; t; t = t->next)
   {
     if (t->description)
     {
       rfc2047_encode_string (&t->description);
     }
     if (recurse && t->parts)
-      encode_descriptions (t->parts, recurse);
+      mutt_encode_descriptions (t->parts, recurse);
   }
 }
 
 /* rfc2047 decode them in case of an error */
 static void decode_descriptions (BODY *b)
 {
   BODY *t;
   
@@ -1131,16 +1131,21 @@
   {
     if (!a->mailbox || a->group)
       continue;
     c++;
   }
   return c;
 }
 
+/*
+ * Returns 0 if the message was successfully sent
+ *        -1 if the message was aborted or an error occurred
+ *         1 if the message was postponed
+ */
 int
 ci_send_message (int flags,            /* send mode */
                 HEADER *msg,           /* template to use for new message */
                 char *tempfile,        /* file specified by -i or -H */
                 CONTEXT *ctx,          /* current mailbox */
                 HEADER *cur)           /* current message */
 {
   char buffer[LONG_STRING];
@@ -1219,39 +1224,47 @@
     /* Use any list-post header as a template */
     url_parse_mailto (msg->env, NULL, cur->env->list_post);
     /* We don't let them set the sender's address. */
     rfc822_free_address (&msg->env->from);
   }
   
   if (! (flags & (SENDKEY | SENDPOSTPONED | SENDRESEND)))
   {
-    pbody = mutt_new_body ();
-    pbody->next = msg->content; /* don't kill command-line attachments */
-    msg->content = pbody;
+    /* When SENDUSEHDRBODY is set, the caller has already
+     * created the "parent" body structure.
+     */
+    if (! (flags & SENDUSEHDRBODY))
+    {
+      pbody = mutt_new_body ();
+      pbody->next = msg->content; /* don't kill command-line attachments */
+      msg->content = pbody;
 
-    if (!(ctype = safe_strdup (ContentType)))
-      ctype = safe_strdup ("text/plain");
-    mutt_parse_content_type (ctype, msg->content);
-    FREE (&ctype);
-    msg->content->unlink = 1;
-    msg->content->use_disp = 0;
-    msg->content->disposition = DISPINLINE;
-    
-    if (!tempfile)
-    {
-      mutt_mktemp (buffer, sizeof (buffer));
-      tempfp = safe_fopen (buffer, "w+");
-      msg->content->filename = safe_strdup (buffer);
+      if (!(ctype = safe_strdup (ContentType)))
+        ctype = safe_strdup ("text/plain");
+      mutt_parse_content_type (ctype, msg->content);
+      FREE (&ctype);
+      msg->content->unlink = 1;
+      msg->content->use_disp = 0;
+      msg->content->disposition = DISPINLINE;
+
+      if (!tempfile)
+      {
+        mutt_mktemp (buffer, sizeof (buffer));
+        tempfp = safe_fopen (buffer, "w+");
+        msg->content->filename = safe_strdup (buffer);
+      }
+      else
+      {
+        tempfp = safe_fopen (tempfile, "a+");
+        msg->content->filename = safe_strdup (tempfile);
+      }
     }
     else
-    {
-      tempfp = safe_fopen (tempfile, "a+");
-      msg->content->filename = safe_strdup (tempfile);
-    }
+      tempfp = safe_fopen (msg->content->filename, "a+");
 
     if (!tempfp)
     {
       dprint(1,(debugfile, "newsend_message: can't create tempfile %s 
(errno=%d)\n", msg->content->filename, errno));
       mutt_perror (msg->content->filename);
       goto cleanup;
     }
   }
@@ -1581,17 +1594,18 @@
   mutt_update_encoding (msg->content);
 
   if (! (flags & (SENDMAILX | SENDBATCH)))
   {
 main_loop:
 
     fcc_error = 0; /* reset value since we may have failed before */
     mutt_pretty_mailbox (fcc, sizeof (fcc));
-    i = mutt_compose_menu (msg, fcc, sizeof (fcc), cur);
+    i = mutt_compose_menu (msg, fcc, sizeof (fcc), cur,
+                           (flags & SENDNOFREEHEADER ? M_COMPOSE_NOFREEHEADER 
: 0));
     if (i == -1)
     {
       /* abort */
       mutt_message _("Mail not sent.");
       goto cleanup;
     }
     else if (i == 1)
     {
@@ -1622,29 +1636,30 @@
       }
 
       /*
        * make sure the message is written to the right part of a maildir 
        * postponed folder.
        */
       msg->read = 0; msg->old = 0;
 
-      encode_descriptions (msg->content, 1);
+      mutt_encode_descriptions (msg->content, 1);
       mutt_prepare_envelope (msg->env, 0);
       mutt_env_to_intl (msg->env, NULL, NULL); /* Handle bad IDNAs the next 
time. */
 
       if (!Postponed || mutt_write_fcc (NONULL (Postponed), msg, (cur && 
(flags & SENDREPLY)) ? cur->env->message_id : NULL, 1, fcc) < 0)
       {
        msg->content = mutt_remove_multipart (msg->content);
        decode_descriptions (msg->content);
        mutt_unprepare_envelope (msg->env);
        goto main_loop;
       }
       mutt_update_num_postponed ();
       mutt_message _("Message postponed.");
+      rv = 1;
       goto cleanup;
     }
   }
 
   if (!has_recips (msg->env->to) && !has_recips (msg->env->cc) &&
       !has_recips (msg->env->bcc))
   {
     if (! (flags & SENDBATCH))
@@ -1682,17 +1697,17 @@
     msg->content = mutt_make_multipart (msg->content);
 
   /* 
    * Ok, we need to do it this way instead of handling all fcc stuff in
    * one place in order to avoid going to main_loop with encoded "env"
    * in case of error.  Ugh.
    */
 
-  encode_descriptions (msg->content, 1);
+  mutt_encode_descriptions (msg->content, 1);
   
   /*
    * Make sure that clear_content and free_clear_content are
    * properly initialized -- we may visit this particular place in
    * the code multiple times, including after a failed call to
    * mutt_protect().
    */
   
@@ -1711,17 +1726,17 @@
       {
         msg->content = mutt_remove_multipart (msg->content);
         
        FREE (&pgpkeylist);
         
         decode_descriptions (msg->content);
         goto main_loop;
       }
-      encode_descriptions (msg->content, 0);
+      mutt_encode_descriptions (msg->content, 0);
     }
   
     /* 
      * at this point, msg->content is one of the following three things:
      * - multipart/signed.  In this case, clear_content is a child.
      * - multipart/encrypted.  In this case, clear_content exists
      *   independently
      * - application/pgp.  In this case, clear_content exists independently.
@@ -1921,14 +1936,15 @@
     if (WithCrypto & APPLICATION_SMIME)
     {
       FREE (&SmimeDefaultKey);
       SmimeDefaultKey = smime_default_key;
     }
   }
    
   safe_fclose (&tempfp);
-  mutt_free_header (&msg);
+  if (! (flags & SENDNOFREEHEADER))
+    mutt_free_header (&msg);
   
   return rv;
 }
 
 /* vim: set sw=2: */

Attachment: signature.asc
Description: PGP signature

Reply via email to