]> git.llucax.com Git - software/mutt-debian.git/blobdiff - send.c
Sidebar patch replaced with the one written by Stuart Henderson (Closes: 619822)
[software/mutt-debian.git] / send.c
diff --git a/send.c b/send.c
index cd4d3617dc45b7994cb9d1aeaee4e0485c89e73c..bc000a7b664c272c30b06be33fbea4df74acadfe 100644 (file)
--- a/send.c
+++ b/send.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1996-2002 Michael R. Elkins <me@mutt.org>
+ * Copyright (C) 1996-2002,2004 Michael R. Elkins <me@mutt.org>
  * 
  *     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
@@ -27,7 +27,6 @@
 #include "mime.h"
 #include "mailbox.h"
 #include "copy.h"
-#include "mx.h"
 #include "mutt_crypt.h"
 #include "mutt_idna.h"
 #include "url.h"
@@ -60,7 +59,7 @@ static void append_signature (FILE *f)
     if (option (OPTSIGDASHES))
       fputs ("\n-- \n", f);
     mutt_copy_stream (tmpfp, f);
-    fclose (tmpfp);
+    safe_fclose (&tmpfp);
     if (thepid != -1)
       mutt_wait_filter (thepid);
   }
@@ -299,7 +298,7 @@ static void process_user_header (ENVELOPE *env)
     }
     else if (ascii_strncasecmp ("message-id:", uh->data, 11) == 0)
     {
-      char *tmp = mutt_extract_message_id (uh->data + 11);
+      char *tmp = mutt_extract_message_id (uh->data + 11, NULL);
       if (rfc822_valid_msgid (tmp) >= 0)
       {
        FREE(&env->message_id);
@@ -310,7 +309,8 @@ static void process_user_header (ENVELOPE *env)
     else if (ascii_strncasecmp ("to:", uh->data, 3) != 0 &&
             ascii_strncasecmp ("cc:", uh->data, 3) != 0 &&
             ascii_strncasecmp ("bcc:", uh->data, 4) != 0 &&
-            ascii_strncasecmp ("subject:", uh->data, 8) != 0)
+            ascii_strncasecmp ("subject:", uh->data, 8) != 0 &&
+            ascii_strncasecmp ("return-path:", uh->data, 12) != 0)
     {
       if (last)
       {
@@ -388,6 +388,10 @@ static int include_forward (CONTEXT *ctx, HEADER *cur, FILE *out)
   if (option (OPTFORWQUOTE))
     cmflags |= M_CM_PREFIX;
 
+  /* wrapping headers for forwarding is considered a display
+   * rather than send action */
+  chflags |= CH_DISPLAY;
+
   mutt_copy_message (out, ctx, cur, cmflags, chflags);
   mutt_forward_trailer (out);
   return 0;
@@ -452,7 +456,7 @@ static int default_to (ADDRESS **to, ENVELOPE *env, int flags, int hmfupto)
 
   if (flags && env->mail_followup_to && hmfupto == M_YES) 
   {
-    rfc822_append (to, env->mail_followup_to);
+    rfc822_append (to, env->mail_followup_to, 1);
     return 0;
   }
 
@@ -465,7 +469,7 @@ static int default_to (ADDRESS **to, ENVELOPE *env, int flags, int hmfupto)
   if (!option(OPTREPLYSELF) && mutt_addr_is_user (env->from))
   {
     /* mail is from the user, assume replying to recipients */
-    rfc822_append (to, env->to);
+    rfc822_append (to, env->to, 1);
   }
   else if (env->reply_to)
   {
@@ -483,7 +487,7 @@ static int default_to (ADDRESS **to, ENVELOPE *env, int flags, int hmfupto)
        * in his From header.
        * 
        */
-      rfc822_append (to, env->from);
+      rfc822_append (to, env->from, 0);
     }
     else if (!(mutt_addrcmp (env->from, env->reply_to) && 
               !env->reply_to->next) &&
@@ -500,11 +504,11 @@ static int default_to (ADDRESS **to, ENVELOPE *env, int flags, int hmfupto)
       switch (query_quadoption (OPT_REPLYTO, prompt))
       {
       case M_YES:
-       rfc822_append (to, env->reply_to);
+       rfc822_append (to, env->reply_to, 0);
        break;
 
       case M_NO:
-       rfc822_append (to, env->from);
+       rfc822_append (to, env->from, 0);
        break;
 
       default:
@@ -512,10 +516,10 @@ static int default_to (ADDRESS **to, ENVELOPE *env, int flags, int hmfupto)
       }
     }
     else
-      rfc822_append (to, env->reply_to);
+      rfc822_append (to, env->reply_to, 0);
   }
   else
-    rfc822_append (to, env->from);
+    rfc822_append (to, env->from, 0);
 
   return (0);
 }
@@ -539,7 +543,7 @@ int mutt_fetch_recips (ENVELOPE *out, ENVELOPE *in, int flags)
   if (flags & SENDLISTREPLY)
   {
     tmp = find_mailing_lists (in->to, in->cc);
-    rfc822_append (&out->to, tmp);
+    rfc822_append (&out->to, tmp, 0);
     rfc822_free_address (&tmp);
 
     if (in->mail_followup_to && hmfupto == M_YES &&
@@ -554,8 +558,8 @@ int mutt_fetch_recips (ENVELOPE *out, ENVELOPE *in, int flags)
     if ((flags & SENDGROUPREPLY) && (!in->mail_followup_to || hmfupto != M_YES))
     {
       /* if(!mutt_addr_is_user(in->to)) */
-      rfc822_append (&out->cc, in->to);
-      rfc822_append (&out->cc, in->cc);
+      rfc822_append (&out->cc, in->to, 1);
+      rfc822_append (&out->cc, in->cc, 1);
     }
   }
   return 0;
@@ -676,6 +680,12 @@ mutt_make_reference_headers (ENVELOPE *curenv, ENVELOPE *env, CONTEXT *ctx)
   }
   else
     mutt_add_to_reference_headers (env, curenv, NULL, NULL);
+
+  /* if there's more than entry in In-Reply-To (i.e. message has
+     multiple parents), don't generate a References: header as it's
+     discouraged by RfC2822, sect. 3.6.4 */
+  if (ctx->tagged > 0 && env->in_reply_to && env->in_reply_to->next)
+    mutt_free_list (&env->references);
 }
 
 static int
@@ -864,8 +874,8 @@ void mutt_set_followup_to (ENVELOPE *e)
        * mail-followup-to header
        */
 
-      t = rfc822_append (&e->mail_followup_to, e->to);
-      rfc822_append (&t, e->cc);
+      t = rfc822_append (&e->mail_followup_to, e->to, 0);
+      rfc822_append (&t, e->cc, 1);
     }
 
     /* remove ourselves from the mail-followup-to header */
@@ -881,9 +891,9 @@ void mutt_set_followup_to (ENVELOPE *e)
     if (e->mail_followup_to && !mutt_is_list_recipient (0, e->to, e->cc))
     {
       if (e->reply_to)
-       from = rfc822_cpy_adr (e->reply_to);
+       from = rfc822_cpy_adr (e->reply_to, 0);
       else if (e->from)
-       from = rfc822_cpy_adr (e->from);
+       from = rfc822_cpy_adr (e->from, 0);
       else
        from = mutt_default_from ();
       
@@ -929,10 +939,11 @@ static ADDRESS *set_reverse_name (ENVELOPE *env)
   if (tmp)
   {
     tmp = rfc822_cpy_adr_real (tmp);
+    /* when $reverse_realname is not set, clear the personal name so that it
+     * may be set vi a reply- or send-hook.
+     */
     if (!option (OPTREVREAL))
       FREE (&tmp->personal);
-    if (!tmp->personal)
-      tmp->personal = safe_strdup (Realname);
   }
   return (tmp);
 }
@@ -974,7 +985,7 @@ static int send_message (HEADER *msg)
 #endif
   
   /* Write out the message in MIME form. */
-  mutt_mktemp (tempfile);
+  mutt_mktemp (tempfile, sizeof (tempfile));
   if ((tempfp = safe_fopen (tempfile, "w")) == NULL)
     return (-1);
 
@@ -998,7 +1009,7 @@ static int send_message (HEADER *msg)
 
   if ((mutt_write_mime_body (msg->content, tempfp) == -1))
   {
-    fclose(tempfp);
+    safe_fclose (&tempfp);
     unlink (tempfile);
     return (-1);
   }
@@ -1083,6 +1094,25 @@ int mutt_resend_message (FILE *fp, CONTEXT *ctx, HEADER *cur)
   return ci_send_message (SENDRESEND, msg, NULL, ctx, cur);
 }
 
+static int is_reply (HEADER *reply, HEADER *orig)
+{
+  return mutt_find_list (orig->env->references, reply->env->message_id) ||
+         mutt_find_list (orig->env->in_reply_to, reply->env->message_id);
+}
+
+static int has_recips (ADDRESS *a)
+{
+  int c = 0;
+
+  for ( ; a; a = a->next)
+  {
+    if (!a->mailbox || a->group)
+      continue;
+    c++;
+  }
+  return c;
+}
+
 int
 ci_send_message (int flags,            /* send mode */
                 HEADER *msg,           /* template to use for new message */
@@ -1181,7 +1211,7 @@ ci_send_message (int flags,               /* send mode */
     
     if (!tempfile)
     {
-      mutt_mktemp (buffer);
+      mutt_mktemp (buffer, sizeof (buffer));
       tempfp = safe_fopen (buffer, "w+");
       msg->content->filename = safe_strdup (buffer);
     }
@@ -1217,24 +1247,7 @@ ci_send_message (int flags,              /* send mode */
     msg->env->from = set_reverse_name (cur->env);
   }
 
-  if (!msg->env->from && option (OPTUSEFROM) && !(flags & (SENDPOSTPONED|SENDRESEND)))
-  {
-    msg->env->from = mutt_default_from ();
-    if (!(flags & SENDBATCH))
-      killfrom = 1;    /* $use_from will be re-checked after send-hooks */
-  }
-
-  if (flags & SENDBATCH) 
-  {
-    mutt_copy_stream (stdin, tempfp);
-    if (option (OPTHDRS))
-    {
-      process_user_recips (msg->env);
-      process_user_header (msg->env);
-    }
-    mutt_expand_aliases_env (msg->env);
-  }
-  else if (! (flags & (SENDPOSTPONED|SENDRESEND)))
+  if (! (flags & (SENDPOSTPONED|SENDRESEND)))
   {
     if ((flags & (SENDREPLY | SENDFORWARD)) && ctx &&
        envelope_defaults (msg->env, ctx, cur, flags) == -1)
@@ -1249,7 +1262,7 @@ ci_send_message (int flags,               /* send mode */
     if (flags & SENDREPLY)
       mutt_fix_reply_recipients (msg->env);
 
-    if (! (flags & SENDMAILX) &&
+    if (! (flags & (SENDMAILX|SENDBATCH)) &&
        ! (option (OPTAUTOEDIT) && option (OPTEDITHDRS)) &&
        ! ((flags & SENDREPLY) && option (OPTFASTREPLY)))
     {
@@ -1305,8 +1318,11 @@ ci_send_message (int flags,              /* send mode */
     if (option (OPTHDRS))
       process_user_header (msg->env);
 
+    if (flags & SENDBATCH)
+       mutt_copy_stream (stdin, tempfp);
 
-    if (option (OPTSIGONTOP) && (! (flags & (SENDMAILX | SENDKEY)) && Editor && mutt_strcmp (Editor, "builtin") != 0))
+    if (option (OPTSIGONTOP) && ! (flags & (SENDMAILX|SENDKEY|SENDBATCH))
+       && Editor && mutt_strcmp (Editor, "builtin") != 0)
       append_signature (tempfp);
 
     /* include replies/forwarded messages, unless we are given a template */
@@ -1314,75 +1330,9 @@ ci_send_message (int flags,              /* send mode */
        && generate_body (tempfp, msg, flags, ctx, cur) == -1)
       goto cleanup;
 
-    if (!option (OPTSIGONTOP) && (! (flags & (SENDMAILX | SENDKEY)) && Editor && mutt_strcmp (Editor, "builtin") != 0))
+    if (!option (OPTSIGONTOP) && ! (flags & (SENDMAILX|SENDKEY|SENDBATCH))
+       && Editor && mutt_strcmp (Editor, "builtin") != 0)
       append_signature (tempfp);
-
-    /* 
-     * this wants to be done _after_ generate_body, so message-hooks
-     * can take effect.
-     */
-
-    if (WithCrypto && !(flags & SENDMAILX))
-    {
-      if (option (OPTCRYPTAUTOSIGN))
-       msg->security |= SIGN;
-      if (option (OPTCRYPTAUTOENCRYPT))
-       msg->security |= ENCRYPT;
-      if (option (OPTCRYPTREPLYENCRYPT) && cur && (cur->security & ENCRYPT))
-       msg->security |= ENCRYPT;
-      if (option (OPTCRYPTREPLYSIGN) && cur && (cur->security & SIGN))
-       msg->security |= SIGN;
-      if (option (OPTCRYPTREPLYSIGNENCRYPTED) && cur && (cur->security & ENCRYPT))
-       msg->security |= SIGN;
-      if (WithCrypto & APPLICATION_PGP && (msg->security & (ENCRYPT | SIGN)))
-      {
-       if (option (OPTPGPAUTOINLINE))
-         msg->security |= INLINE;
-       if (option (OPTPGPREPLYINLINE) && cur && (cur->security & INLINE))
-         msg->security |= INLINE;
-      }
-    }
-
-    if (WithCrypto && msg->security)
-    {
-      /* 
-       * When reypling / forwarding, use the original message's
-       * crypto system.  According to the documentation,
-       * smime_is_default should be disregarded here.
-       * 
-       * Problem: At least with forwarding, this doesn't really
-       * make much sense. Should we have an option to completely
-       * disable individual mechanisms at run-time?
-       */
-      if (cur)
-      {
-       if ((WithCrypto & APPLICATION_PGP) && option (OPTCRYPTAUTOPGP) 
-           && (cur->security & APPLICATION_PGP))
-         msg->security |= APPLICATION_PGP;
-       else if ((WithCrypto & APPLICATION_SMIME) && option (OPTCRYPTAUTOSMIME)
-                && (cur->security & APPLICATION_SMIME))
-         msg->security |= APPLICATION_SMIME;
-      }
-      
-      /*
-       * No crypto mechanism selected? Use availability + smime_is_default
-       * for the decision. 
-       */
-      if (!(msg->security & (APPLICATION_SMIME | APPLICATION_PGP)))
-      {
-       if ((WithCrypto & APPLICATION_SMIME) && option (OPTCRYPTAUTOSMIME) 
-           && option (OPTSMIMEISDEFAULT))
-         msg->security |= APPLICATION_SMIME;
-       else if ((WithCrypto & APPLICATION_PGP) && option (OPTCRYPTAUTOPGP))
-         msg->security |= APPLICATION_PGP;
-       else if ((WithCrypto & APPLICATION_SMIME) && option (OPTCRYPTAUTOSMIME))
-         msg->security |= APPLICATION_SMIME;
-      }
-    }
-    
-    /* No permissible mechanisms found.  Don't sign or encrypt. */
-    if (!(msg->security & (APPLICATION_SMIME|APPLICATION_PGP)))
-      msg->security = 0;
   }
   
   /* 
@@ -1418,7 +1368,7 @@ ci_send_message (int flags,               /* send mode */
      * don't want to do this when:
      * 1) we are sending a key/cert
      * 2) we are forwarding a message and the user doesn't want to edit it.
-     *    This is controled by the quadoption $forward_edit.  However, if
+     *    This is controlled by the quadoption $forward_edit.  However, if
      *    both $edit_headers and $autoedit are set, we want to ignore the
      *    setting of $forward_edit because the user probably needs to add the
      *    recipients.
@@ -1477,6 +1427,80 @@ ci_send_message (int flags,              /* send mode */
     }
   }
 
+  /* 
+   * Set the message security unless:
+   * 1) crypto support is not enabled (WithCrypto==0)
+   * 2) pgp: header field was present during message editing with $edit_headers (msg->security != 0)
+   * 3) we are resending a message
+   * 4) we are recalling a postponed message (don't override the user's saved settings)
+   * 5) we are in mailx mode
+   * 6) we are in batch mode
+   *
+   * This is done after allowing the user to edit the message so that security
+   * settings can be configured with send2-hook and $edit_headers.
+   */
+  if (WithCrypto && (msg->security == 0) && !(flags & (SENDBATCH | SENDMAILX | SENDPOSTPONED | SENDRESEND)))
+  {
+    if (option (OPTCRYPTAUTOSIGN))
+      msg->security |= SIGN;
+    if (option (OPTCRYPTAUTOENCRYPT))
+      msg->security |= ENCRYPT;
+    if (option (OPTCRYPTREPLYENCRYPT) && cur && (cur->security & ENCRYPT))
+      msg->security |= ENCRYPT;
+    if (option (OPTCRYPTREPLYSIGN) && cur && (cur->security & SIGN))
+      msg->security |= SIGN;
+    if (option (OPTCRYPTREPLYSIGNENCRYPTED) && cur && (cur->security & ENCRYPT))
+      msg->security |= SIGN;
+    if (WithCrypto & APPLICATION_PGP && (msg->security & (ENCRYPT | SIGN)))
+    {
+      if (option (OPTPGPAUTOINLINE))
+       msg->security |= INLINE;
+      if (option (OPTPGPREPLYINLINE) && cur && (cur->security & INLINE))
+       msg->security |= INLINE;
+    }
+
+    if (msg->security)
+    {
+      /* 
+       * When replying / forwarding, use the original message's
+       * crypto system.  According to the documentation,
+       * smime_is_default should be disregarded here.
+       * 
+       * Problem: At least with forwarding, this doesn't really
+       * make much sense. Should we have an option to completely
+       * disable individual mechanisms at run-time?
+       */
+      if (cur)
+      {
+       if ((WithCrypto & APPLICATION_PGP) && option (OPTCRYPTAUTOPGP) 
+           && (cur->security & APPLICATION_PGP))
+         msg->security |= APPLICATION_PGP;
+       else if ((WithCrypto & APPLICATION_SMIME) && option (OPTCRYPTAUTOSMIME)
+           && (cur->security & APPLICATION_SMIME))
+         msg->security |= APPLICATION_SMIME;
+      }
+
+      /*
+       * No crypto mechanism selected? Use availability + smime_is_default
+       * for the decision. 
+       */
+      if (!(msg->security & (APPLICATION_SMIME | APPLICATION_PGP)))
+      {
+       if ((WithCrypto & APPLICATION_SMIME) && option (OPTCRYPTAUTOSMIME) 
+           && option (OPTSMIMEISDEFAULT))
+         msg->security |= APPLICATION_SMIME;
+       else if ((WithCrypto & APPLICATION_PGP) && option (OPTCRYPTAUTOPGP))
+         msg->security |= APPLICATION_PGP;
+       else if ((WithCrypto & APPLICATION_SMIME) && option (OPTCRYPTAUTOSMIME))
+         msg->security |= APPLICATION_SMIME;
+      }
+    }
+
+    /* No permissible mechanisms found.  Don't sign or encrypt. */
+    if (!(msg->security & (APPLICATION_SMIME|APPLICATION_PGP)))
+      msg->security = 0;
+  }
+
   /* specify a default fcc.  if we are in batchmode, only save a copy of
    * the message if the value of $copy is yes or ask-yes */
 
@@ -1505,7 +1529,7 @@ ci_send_message (int flags,               /* send mode */
 main_loop:
 
     fcc_error = 0; /* reset value since we may have failed before */
-    mutt_pretty_mailbox (fcc);
+    mutt_pretty_mailbox (fcc, sizeof (fcc));
     i = mutt_compose_menu (msg, fcc, sizeof (fcc), cur);
     if (i == -1)
     {
@@ -1542,7 +1566,8 @@ main_loop:
     }
   }
 
-  if (!msg->env->to && !msg->env->cc && !msg->env->bcc)
+  if (!has_recips (msg->env->to) && !has_recips (msg->env->cc) &&
+      !has_recips (msg->env->bcc))
   {
     if (! (flags & SENDBATCH))
     {
@@ -1666,7 +1691,8 @@ main_loop:
       msg->content = clear_content;
 
     /* check to see if the user wants copies of all attachments */
-    if (!option (OPTFCCATTACH) && msg->content->type == TYPEMULTIPART)
+    if (query_quadoption (OPT_FCCATTACH, _("Save attachments in Fcc?")) != M_YES &&
+       msg->content->type == TYPEMULTIPART)
     {
       if (WithCrypto
           && (mutt_strcmp (msg->content->subtype, "encrypted") == 0 ||
@@ -1748,7 +1774,7 @@ full_fcc:
    * the send failed as well so we give the user a chance to fix the
    * error.
    */
-  if (fcc_error || (i = send_message (msg)) == -1)
+  if (fcc_error || (i = send_message (msg)) < 0)
   {
     if (!(flags & SENDBATCH))
     {
@@ -1787,15 +1813,18 @@ full_fcc:
   if (WithCrypto && free_clear_content)
     mutt_free_body (&clear_content);
 
+  /* set 'replied' flag only if the user didn't change/remove
+     In-Reply-To: and References: headers during edit */
   if (flags & SENDREPLY)
   {
     if (cur && ctx)
-      mutt_set_flag (ctx, cur, M_REPLIED, 1);
+      mutt_set_flag (ctx, cur, M_REPLIED, is_reply (cur, msg));
     else if (!(flags & SENDPOSTPONED) && ctx && ctx->tagged)
     {
       for (i = 0; i < ctx->vcount; i++)
        if (ctx->hdrs[ctx->v2r[i]]->tagged)
-         mutt_set_flag (ctx, ctx->hdrs[ctx->v2r[i]], M_REPLIED, 1);
+         mutt_set_flag (ctx, ctx->hdrs[ctx->v2r[i]], M_REPLIED,
+                        is_reply (ctx->hdrs[ctx->v2r[i]], msg));
     }
   }