mutt stable branch with some hacks
at master 1936 lines 51 kB view raw
1/* 2 * Copyright (C) 1996-2002,2004,2010,2012-2013 Michael R. Elkins <me@mutt.org> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 */ 18 19#if HAVE_CONFIG_H 20# include "config.h" 21#endif 22 23#include "mutt.h" 24#include "mutt_curses.h" 25#include "rfc2047.h" 26#include "keymap.h" 27#include "mime.h" 28#include "mailbox.h" 29#include "copy.h" 30#include "mutt_crypt.h" 31#include "mutt_idna.h" 32#include "url.h" 33#include "rfc3676.h" 34 35#include <ctype.h> 36#include <stdlib.h> 37#include <locale.h> 38#include <unistd.h> 39#include <string.h> 40#include <errno.h> 41#include <sys/stat.h> 42#include <sys/wait.h> 43#include <dirent.h> 44#include <time.h> 45#include <sys/types.h> 46#include <utime.h> 47 48#ifdef MIXMASTER 49#include "remailer.h" 50#endif 51 52 53static void append_signature (FILE *f) 54{ 55 FILE *tmpfp; 56 pid_t thepid; 57 58 if (Signature && (tmpfp = mutt_open_read (Signature, &thepid))) 59 { 60 if (option (OPTSIGDASHES)) 61 fputs ("\n-- \n", f); 62 mutt_copy_stream (tmpfp, f); 63 safe_fclose (&tmpfp); 64 if (thepid != -1) 65 mutt_wait_filter (thepid); 66 } 67} 68 69/* compare two e-mail addresses and return 1 if they are equivalent */ 70static int mutt_addrcmp (ADDRESS *a, ADDRESS *b) 71{ 72 if (!a->mailbox || !b->mailbox) 73 return 0; 74 if (ascii_strcasecmp (a->mailbox, b->mailbox)) 75 return 0; 76 return 1; 77} 78 79/* search an e-mail address in a list */ 80static int mutt_addrsrc (ADDRESS *a, ADDRESS *lst) 81{ 82 for (; lst; lst = lst->next) 83 { 84 if (mutt_addrcmp (a, lst)) 85 return (1); 86 } 87 return (0); 88} 89 90/* removes addresses from "b" which are contained in "a" */ 91ADDRESS *mutt_remove_xrefs (ADDRESS *a, ADDRESS *b) 92{ 93 ADDRESS *top, *p, *prev = NULL; 94 95 top = b; 96 while (b) 97 { 98 for (p = a; p; p = p->next) 99 { 100 if (mutt_addrcmp (p, b)) 101 break; 102 } 103 if (p) 104 { 105 if (prev) 106 { 107 prev->next = b->next; 108 b->next = NULL; 109 rfc822_free_address (&b); 110 b = prev; 111 } 112 else 113 { 114 top = top->next; 115 b->next = NULL; 116 rfc822_free_address (&b); 117 b = top; 118 } 119 } 120 else 121 { 122 prev = b; 123 b = b->next; 124 } 125 } 126 return top; 127} 128 129/* remove any address which matches the current user. if `leave_only' is 130 * nonzero, don't remove the user's address if it is the only one in the list 131 */ 132static ADDRESS *remove_user (ADDRESS *a, int leave_only) 133{ 134 ADDRESS *top = NULL, *last = NULL; 135 136 while (a) 137 { 138 if (!mutt_addr_is_user (a)) 139 { 140 if (top) 141 { 142 last->next = a; 143 last = last->next; 144 } 145 else 146 last = top = a; 147 a = a->next; 148 last->next = NULL; 149 } 150 else 151 { 152 ADDRESS *tmp = a; 153 154 a = a->next; 155 if (!leave_only || a || last) 156 { 157 tmp->next = NULL; 158 rfc822_free_address (&tmp); 159 } 160 else 161 last = top = tmp; 162 } 163 } 164 return top; 165} 166 167static ADDRESS *find_mailing_lists (ADDRESS *t, ADDRESS *c) 168{ 169 ADDRESS *top = NULL, *ptr = NULL; 170 171 for (; t || c; t = c, c = NULL) 172 { 173 for (; t; t = t->next) 174 { 175 if (mutt_is_mail_list (t) && !t->group) 176 { 177 if (top) 178 { 179 ptr->next = rfc822_cpy_adr_real (t); 180 ptr = ptr->next; 181 } 182 else 183 ptr = top = rfc822_cpy_adr_real (t); 184 } 185 } 186 } 187 return top; 188} 189 190static int edit_address (ADDRESS **a, /* const */ char *field) 191{ 192 char buf[HUGE_STRING]; 193 char *err = NULL; 194 int idna_ok = 0; 195 196 do 197 { 198 buf[0] = 0; 199 mutt_addrlist_to_local (*a); 200 rfc822_write_address (buf, sizeof (buf), *a, 0); 201 if (mutt_get_field (field, buf, sizeof (buf), MUTT_ALIAS) != 0) 202 return (-1); 203 rfc822_free_address (a); 204 *a = mutt_expand_aliases (mutt_parse_adrlist (NULL, buf)); 205 if ((idna_ok = mutt_addrlist_to_intl (*a, &err)) != 0) 206 { 207 mutt_error (_("Error: '%s' is a bad IDN."), err); 208 mutt_refresh (); 209 mutt_sleep (2); 210 FREE (&err); 211 } 212 } 213 while (idna_ok != 0); 214 return 0; 215} 216 217static int edit_envelope (ENVELOPE *en) 218{ 219 char buf[HUGE_STRING]; 220 LIST *uh = UserHeader; 221 222 if (edit_address (&en->to, "To: ") == -1 || en->to == NULL) 223 return (-1); 224 if (option (OPTASKCC) && edit_address (&en->cc, "Cc: ") == -1) 225 return (-1); 226 if (option (OPTASKBCC) && edit_address (&en->bcc, "Bcc: ") == -1) 227 return (-1); 228 229 if (en->subject) 230 { 231 if (option (OPTFASTREPLY)) 232 return (0); 233 else 234 strfcpy (buf, en->subject, sizeof (buf)); 235 } 236 else 237 { 238 const char *p; 239 240 buf[0] = 0; 241 for (; uh; uh = uh->next) 242 { 243 if (ascii_strncasecmp ("subject:", uh->data, 8) == 0) 244 { 245 p = skip_email_wsp(uh->data + 8); 246 strncpy (buf, p, sizeof (buf)); 247 } 248 } 249 } 250 251 if (mutt_get_field ("Subject: ", buf, sizeof (buf), 0) != 0 || 252 (!buf[0] && query_quadoption (OPT_SUBJECT, _("No subject, abort?")) != MUTT_NO)) 253 { 254 mutt_message _("No subject, aborting."); 255 return (-1); 256 } 257 mutt_str_replace (&en->subject, buf); 258 259 return 0; 260} 261 262static void process_user_recips (ENVELOPE *env) 263{ 264 LIST *uh = UserHeader; 265 266 for (; uh; uh = uh->next) 267 { 268 if (ascii_strncasecmp ("to:", uh->data, 3) == 0) 269 env->to = rfc822_parse_adrlist (env->to, uh->data + 3); 270 else if (ascii_strncasecmp ("cc:", uh->data, 3) == 0) 271 env->cc = rfc822_parse_adrlist (env->cc, uh->data + 3); 272 else if (ascii_strncasecmp ("bcc:", uh->data, 4) == 0) 273 env->bcc = rfc822_parse_adrlist (env->bcc, uh->data + 4); 274 } 275} 276 277static void process_user_header (ENVELOPE *env) 278{ 279 LIST *uh = UserHeader; 280 LIST *last = env->userhdrs; 281 282 if (last) 283 while (last->next) 284 last = last->next; 285 286 for (; uh; uh = uh->next) 287 { 288 if (ascii_strncasecmp ("from:", uh->data, 5) == 0) 289 { 290 /* User has specified a default From: address. Remove default address */ 291 rfc822_free_address (&env->from); 292 env->from = rfc822_parse_adrlist (env->from, uh->data + 5); 293 } 294 else if (ascii_strncasecmp ("reply-to:", uh->data, 9) == 0) 295 { 296 rfc822_free_address (&env->reply_to); 297 env->reply_to = rfc822_parse_adrlist (env->reply_to, uh->data + 9); 298 } 299 else if (ascii_strncasecmp ("message-id:", uh->data, 11) == 0) 300 { 301 char *tmp = mutt_extract_message_id (uh->data + 11, NULL); 302 if (rfc822_valid_msgid (tmp) >= 0) 303 { 304 FREE(&env->message_id); 305 env->message_id = tmp; 306 } else 307 FREE(&tmp); 308 } 309 else if (ascii_strncasecmp ("to:", uh->data, 3) != 0 && 310 ascii_strncasecmp ("cc:", uh->data, 3) != 0 && 311 ascii_strncasecmp ("bcc:", uh->data, 4) != 0 && 312 ascii_strncasecmp ("subject:", uh->data, 8) != 0 && 313 ascii_strncasecmp ("return-path:", uh->data, 12) != 0) 314 { 315 if (last) 316 { 317 last->next = mutt_new_list (); 318 last = last->next; 319 } 320 else 321 last = env->userhdrs = mutt_new_list (); 322 last->data = safe_strdup (uh->data); 323 } 324 } 325} 326 327void mutt_forward_intro (FILE *fp, HEADER *cur) 328{ 329 char buffer[STRING]; 330 331 fputs ("----- Forwarded message from ", fp); 332 buffer[0] = 0; 333 rfc822_write_address (buffer, sizeof (buffer), cur->env->from, 1); 334 fputs (buffer, fp); 335 fputs (" -----\n\n", fp); 336} 337 338void mutt_forward_trailer (FILE *fp) 339{ 340 fputs ("\n----- End forwarded message -----\n", fp); 341} 342 343 344static int include_forward (CONTEXT *ctx, HEADER *cur, FILE *out) 345{ 346 int chflags = CH_DECODE, cmflags = 0; 347 348 mutt_parse_mime_message (ctx, cur); 349 mutt_message_hook (ctx, cur, MUTT_MESSAGEHOOK); 350 351 if (WithCrypto && (cur->security & ENCRYPT) && option (OPTFORWDECODE)) 352 { 353 /* make sure we have the user's passphrase before proceeding... */ 354 crypt_valid_passphrase (cur->security); 355 } 356 357 mutt_forward_intro (out, cur); 358 359 if (option (OPTFORWDECODE)) 360 { 361 cmflags |= MUTT_CM_DECODE | MUTT_CM_CHARCONV; 362 if (option (OPTWEED)) 363 { 364 chflags |= CH_WEED | CH_REORDER; 365 cmflags |= MUTT_CM_WEED; 366 } 367 } 368 if (option (OPTFORWQUOTE)) 369 cmflags |= MUTT_CM_PREFIX; 370 371 /* wrapping headers for forwarding is considered a display 372 * rather than send action */ 373 chflags |= CH_DISPLAY; 374 375 mutt_copy_message (out, ctx, cur, cmflags, chflags); 376 mutt_forward_trailer (out); 377 return 0; 378} 379 380void mutt_make_attribution (CONTEXT *ctx, HEADER *cur, FILE *out) 381{ 382 char buffer[LONG_STRING]; 383 if (Attribution) 384 { 385 setlocale (LC_TIME, NONULL (AttributionLocale)); 386 mutt_make_string (buffer, sizeof (buffer), Attribution, ctx, cur); 387 setlocale (LC_TIME, ""); 388 fputs (buffer, out); 389 fputc ('\n', out); 390 } 391} 392 393void mutt_make_post_indent (CONTEXT *ctx, HEADER *cur, FILE *out) 394{ 395 char buffer[STRING]; 396 if (PostIndentString) 397 { 398 mutt_make_string (buffer, sizeof (buffer), PostIndentString, ctx, cur); 399 fputs (buffer, out); 400 fputc ('\n', out); 401 } 402} 403 404static int include_reply (CONTEXT *ctx, HEADER *cur, FILE *out) 405{ 406 int cmflags = MUTT_CM_PREFIX | MUTT_CM_DECODE | MUTT_CM_CHARCONV | MUTT_CM_REPLYING; 407 int chflags = CH_DECODE; 408 409 if (WithCrypto && (cur->security & ENCRYPT)) 410 { 411 /* make sure we have the user's passphrase before proceeding... */ 412 crypt_valid_passphrase (cur->security); 413 } 414 415 mutt_parse_mime_message (ctx, cur); 416 mutt_message_hook (ctx, cur, MUTT_MESSAGEHOOK); 417 418 mutt_make_attribution (ctx, cur, out); 419 420 if (!option (OPTHEADER)) 421 cmflags |= MUTT_CM_NOHEADER; 422 if (option (OPTWEED)) 423 { 424 chflags |= CH_WEED | CH_REORDER; 425 cmflags |= MUTT_CM_WEED; 426 } 427 428 mutt_copy_message (out, ctx, cur, cmflags, chflags); 429 430 mutt_make_post_indent (ctx, cur, out); 431 432 return 0; 433} 434 435static int default_to (ADDRESS **to, ENVELOPE *env, int flags, int hmfupto) 436{ 437 char prompt[STRING]; 438 439 if (flags && env->mail_followup_to && hmfupto == MUTT_YES) 440 { 441 rfc822_append (to, env->mail_followup_to, 1); 442 return 0; 443 } 444 445 /* Exit now if we're setting up the default Cc list for list-reply 446 * (only set if Mail-Followup-To is present and honoured). 447 */ 448 if (flags & SENDLISTREPLY) 449 return 0; 450 451 if (!option(OPTREPLYSELF) && mutt_addr_is_user (env->from)) 452 { 453 /* mail is from the user, assume replying to recipients */ 454 rfc822_append (to, env->to, 1); 455 } 456 else if (env->reply_to) 457 { 458 if ((mutt_addrcmp (env->from, env->reply_to) && !env->reply_to->next) || 459 (option (OPTIGNORELISTREPLYTO) && 460 mutt_is_mail_list (env->reply_to) && 461 (mutt_addrsrc (env->reply_to, env->to) || 462 mutt_addrsrc (env->reply_to, env->cc)))) 463 { 464 /* If the Reply-To: address is a mailing list, assume that it was 465 * put there by the mailing list, and use the From: address 466 * 467 * We also take the from header if our correspondent has a reply-to 468 * header which is identical to the electronic mail address given 469 * in his From header. 470 * 471 */ 472 rfc822_append (to, env->from, 0); 473 } 474 else if (!(mutt_addrcmp (env->from, env->reply_to) && 475 !env->reply_to->next) && 476 quadoption (OPT_REPLYTO) != MUTT_YES) 477 { 478 /* There are quite a few mailing lists which set the Reply-To: 479 * header field to the list address, which makes it quite impossible 480 * to send a message to only the sender of the message. This 481 * provides a way to do that. 482 */ 483 /* L10N: 484 Asks whether the user respects the reply-to header. 485 If she says no, mutt will reply to the from header's address instead. */ 486 snprintf (prompt, sizeof (prompt), _("Reply to %s%s?"), 487 env->reply_to->mailbox, 488 env->reply_to->next?",...":""); 489 switch (query_quadoption (OPT_REPLYTO, prompt)) 490 { 491 case MUTT_YES: 492 rfc822_append (to, env->reply_to, 0); 493 break; 494 495 case MUTT_NO: 496 rfc822_append (to, env->from, 0); 497 break; 498 499 default: 500 return (-1); /* abort */ 501 } 502 } 503 else 504 rfc822_append (to, env->reply_to, 0); 505 } 506 else 507 rfc822_append (to, env->from, 0); 508 509 return (0); 510} 511 512int mutt_fetch_recips (ENVELOPE *out, ENVELOPE *in, int flags) 513{ 514 char prompt[STRING]; 515 ADDRESS *tmp; 516 int hmfupto = -1; 517 518 if ((flags & (SENDLISTREPLY|SENDGROUPREPLY)) && in->mail_followup_to) 519 { 520 snprintf (prompt, sizeof (prompt), _("Follow-up to %s%s?"), 521 in->mail_followup_to->mailbox, 522 in->mail_followup_to->next ? ",..." : ""); 523 524 if ((hmfupto = query_quadoption (OPT_MFUPTO, prompt)) == -1) 525 return -1; 526 } 527 528 if (flags & SENDLISTREPLY) 529 { 530 tmp = find_mailing_lists (in->to, in->cc); 531 rfc822_append (&out->to, tmp, 0); 532 rfc822_free_address (&tmp); 533 534 if (in->mail_followup_to && hmfupto == MUTT_YES && 535 default_to (&out->cc, in, flags & SENDLISTREPLY, hmfupto) == -1) 536 return (-1); /* abort */ 537 } 538 else 539 { 540 if (default_to (&out->to, in, flags & SENDGROUPREPLY, hmfupto) == -1) 541 return (-1); /* abort */ 542 543 if ((flags & SENDGROUPREPLY) && (!in->mail_followup_to || hmfupto != MUTT_YES)) 544 { 545 /* if(!mutt_addr_is_user(in->to)) */ 546 rfc822_append (&out->cc, in->to, 1); 547 rfc822_append (&out->cc, in->cc, 1); 548 } 549 } 550 return 0; 551} 552 553LIST *mutt_make_references(ENVELOPE *e) 554{ 555 LIST *t = NULL, *l = NULL; 556 557 if (e->references) 558 l = mutt_copy_list (e->references); 559 else 560 l = mutt_copy_list (e->in_reply_to); 561 562 if (e->message_id) 563 { 564 t = mutt_new_list(); 565 t->data = safe_strdup(e->message_id); 566 t->next = l; 567 l = t; 568 } 569 570 return l; 571} 572 573void mutt_fix_reply_recipients (ENVELOPE *env) 574{ 575 if (! option (OPTMETOO)) 576 { 577 /* the order is important here. do the CC: first so that if the 578 * the user is the only recipient, it ends up on the TO: field 579 */ 580 env->cc = remove_user (env->cc, (env->to == NULL)); 581 env->to = remove_user (env->to, (env->cc == NULL)); 582 } 583 584 /* the CC field can get cluttered, especially with lists */ 585 env->to = mutt_remove_duplicates (env->to); 586 env->cc = mutt_remove_duplicates (env->cc); 587 env->cc = mutt_remove_xrefs (env->to, env->cc); 588 589 if (env->cc && !env->to) 590 { 591 env->to = env->cc; 592 env->cc = NULL; 593 } 594} 595 596void mutt_make_forward_subject (ENVELOPE *env, CONTEXT *ctx, HEADER *cur) 597{ 598 char buffer[STRING]; 599 600 /* set the default subject for the message. */ 601 mutt_make_string (buffer, sizeof (buffer), NONULL(ForwFmt), ctx, cur); 602 mutt_str_replace (&env->subject, buffer); 603} 604 605void mutt_make_misc_reply_headers (ENVELOPE *env, CONTEXT *ctx, 606 HEADER *cur, ENVELOPE *curenv) 607{ 608 /* This takes precedence over a subject that might have 609 * been taken from a List-Post header. Is that correct? 610 */ 611 if (curenv->real_subj) 612 { 613 FREE (&env->subject); 614 env->subject = safe_malloc (mutt_strlen (curenv->real_subj) + 5); 615 sprintf (env->subject, "Re: %s", curenv->real_subj); /* __SPRINTF_CHECKED__ */ 616 } 617 else if (!env->subject) 618 env->subject = safe_strdup ("Re: your mail"); 619} 620 621void mutt_add_to_reference_headers (ENVELOPE *env, ENVELOPE *curenv, LIST ***pp, LIST ***qq) 622{ 623 LIST **p = NULL, **q = NULL; 624 625 if (pp) p = *pp; 626 if (qq) q = *qq; 627 628 if (!p) p = &env->references; 629 if (!q) q = &env->in_reply_to; 630 631 while (*p) p = &(*p)->next; 632 while (*q) q = &(*q)->next; 633 634 *p = mutt_make_references (curenv); 635 636 if (curenv->message_id) 637 { 638 *q = mutt_new_list(); 639 (*q)->data = safe_strdup (curenv->message_id); 640 } 641 642 if (pp) *pp = p; 643 if (qq) *qq = q; 644 645} 646 647static void 648mutt_make_reference_headers (ENVELOPE *curenv, ENVELOPE *env, CONTEXT *ctx) 649{ 650 env->references = NULL; 651 env->in_reply_to = NULL; 652 653 if (!curenv) 654 { 655 HEADER *h; 656 LIST **p = NULL, **q = NULL; 657 int i; 658 659 for(i = 0; i < ctx->vcount; i++) 660 { 661 h = ctx->hdrs[ctx->v2r[i]]; 662 if (h->tagged) 663 mutt_add_to_reference_headers (env, h->env, &p, &q); 664 } 665 } 666 else 667 mutt_add_to_reference_headers (env, curenv, NULL, NULL); 668 669 /* if there's more than entry in In-Reply-To (i.e. message has 670 multiple parents), don't generate a References: header as it's 671 discouraged by RfC2822, sect. 3.6.4 */ 672 if (ctx->tagged > 0 && env->in_reply_to && env->in_reply_to->next) 673 mutt_free_list (&env->references); 674} 675 676static int 677envelope_defaults (ENVELOPE *env, CONTEXT *ctx, HEADER *cur, int flags) 678{ 679 ENVELOPE *curenv = NULL; 680 int i = 0, tag = 0; 681 682 if (!cur) 683 { 684 tag = 1; 685 for (i = 0; i < ctx->vcount; i++) 686 if (ctx->hdrs[ctx->v2r[i]]->tagged) 687 { 688 cur = ctx->hdrs[ctx->v2r[i]]; 689 curenv = cur->env; 690 break; 691 } 692 693 if (!cur) 694 { 695 /* This could happen if the user tagged some messages and then did 696 * a limit such that none of the tagged message are visible. 697 */ 698 mutt_error _("No tagged messages are visible!"); 699 return (-1); 700 } 701 } 702 else 703 curenv = cur->env; 704 705 if (flags & SENDREPLY) 706 { 707 if (tag) 708 { 709 HEADER *h; 710 711 for (i = 0; i < ctx->vcount; i++) 712 { 713 h = ctx->hdrs[ctx->v2r[i]]; 714 if (h->tagged && mutt_fetch_recips (env, h->env, flags) == -1) 715 return -1; 716 } 717 } 718 else if (mutt_fetch_recips (env, curenv, flags) == -1) 719 return -1; 720 721 if ((flags & SENDLISTREPLY) && !env->to) 722 { 723 mutt_error _("No mailing lists found!"); 724 return (-1); 725 } 726 727 mutt_make_misc_reply_headers (env, ctx, cur, curenv); 728 mutt_make_reference_headers (tag ? NULL : curenv, env, ctx); 729 } 730 else if (flags & SENDFORWARD) 731 mutt_make_forward_subject (env, ctx, cur); 732 733 return (0); 734} 735 736static int 737generate_body (FILE *tempfp, /* stream for outgoing message */ 738 HEADER *msg, /* header for outgoing message */ 739 int flags, /* compose mode */ 740 CONTEXT *ctx, /* current mailbox */ 741 HEADER *cur) /* current message */ 742{ 743 int i; 744 HEADER *h; 745 BODY *tmp; 746 747 if (flags & SENDREPLY) 748 { 749 if ((i = query_quadoption (OPT_INCLUDE, _("Include message in reply?"))) == -1) 750 return (-1); 751 752 if (i == MUTT_YES) 753 { 754 mutt_message _("Including quoted message..."); 755 if (!cur) 756 { 757 for (i = 0; i < ctx->vcount; i++) 758 { 759 h = ctx->hdrs[ctx->v2r[i]]; 760 if (h->tagged) 761 { 762 if (include_reply (ctx, h, tempfp) == -1) 763 { 764 mutt_error _("Could not include all requested messages!"); 765 return (-1); 766 } 767 fputc ('\n', tempfp); 768 } 769 } 770 } 771 else 772 include_reply (ctx, cur, tempfp); 773 774 } 775 } 776 else if (flags & SENDFORWARD) 777 { 778 if ((i = query_quadoption (OPT_MIMEFWD, _("Forward as attachment?"))) == MUTT_YES) 779 { 780 BODY *last = msg->content; 781 782 mutt_message _("Preparing forwarded message..."); 783 784 while (last && last->next) 785 last = last->next; 786 787 if (cur) 788 { 789 tmp = mutt_make_message_attach (ctx, cur, 0); 790 if (last) 791 last->next = tmp; 792 else 793 msg->content = tmp; 794 } 795 else 796 { 797 for (i = 0; i < ctx->vcount; i++) 798 { 799 if (ctx->hdrs[ctx->v2r[i]]->tagged) 800 { 801 tmp = mutt_make_message_attach (ctx, ctx->hdrs[ctx->v2r[i]], 0); 802 if (last) 803 { 804 last->next = tmp; 805 last = tmp; 806 } 807 else 808 last = msg->content = tmp; 809 } 810 } 811 } 812 } 813 else if (i != -1) 814 { 815 if (cur) 816 include_forward (ctx, cur, tempfp); 817 else 818 for (i=0; i < ctx->vcount; i++) 819 if (ctx->hdrs[ctx->v2r[i]]->tagged) 820 include_forward (ctx, ctx->hdrs[ctx->v2r[i]], tempfp); 821 } 822 else if (i == -1) 823 return -1; 824 } 825 /* if (WithCrypto && (flags & SENDKEY)) */ 826 else if ((WithCrypto & APPLICATION_PGP) && (flags & SENDKEY)) 827 { 828 BODY *tmp; 829 830 if ((WithCrypto & APPLICATION_PGP) 831 && (tmp = crypt_pgp_make_key_attachment (NULL)) == NULL) 832 return -1; 833 834 tmp->next = msg->content; 835 msg->content = tmp; 836 } 837 838 mutt_clear_error (); 839 840 return (0); 841} 842 843void mutt_set_followup_to (ENVELOPE *e) 844{ 845 ADDRESS *t = NULL; 846 ADDRESS *from; 847 848 /* 849 * Only generate the Mail-Followup-To if the user has requested it, and 850 * it hasn't already been set 851 */ 852 853 if (option (OPTFOLLOWUPTO) && !e->mail_followup_to) 854 { 855 if (mutt_is_list_cc (0, e->to, e->cc)) 856 { 857 /* 858 * this message goes to known mailing lists, so create a proper 859 * mail-followup-to header 860 */ 861 862 t = rfc822_append (&e->mail_followup_to, e->to, 0); 863 rfc822_append (&t, e->cc, 1); 864 } 865 866 /* remove ourselves from the mail-followup-to header */ 867 e->mail_followup_to = remove_user (e->mail_followup_to, 0); 868 869 /* 870 * If we are not subscribed to any of the lists in question, 871 * re-add ourselves to the mail-followup-to header. The 872 * mail-followup-to header generated is a no-op with group-reply, 873 * but makes sure list-reply has the desired effect. 874 */ 875 876 if (e->mail_followup_to && !mutt_is_list_recipient (0, e->to, e->cc)) 877 { 878 if (e->reply_to) 879 from = rfc822_cpy_adr (e->reply_to, 0); 880 else if (e->from) 881 from = rfc822_cpy_adr (e->from, 0); 882 else 883 from = mutt_default_from (); 884 885 if (from) 886 { 887 /* Normally, this loop will not even be entered. */ 888 for (t = from; t && t->next; t = t->next) 889 ; 890 891 t->next = e->mail_followup_to; /* t cannot be NULL at this point. */ 892 e->mail_followup_to = from; 893 } 894 } 895 896 e->mail_followup_to = mutt_remove_duplicates (e->mail_followup_to); 897 898 } 899} 900 901 902/* look through the recipients of the message we are replying to, and if 903 we find an address that matches $alternates, we use that as the default 904 from field */ 905static ADDRESS *set_reverse_name (ENVELOPE *env) 906{ 907 ADDRESS *tmp; 908 909 for (tmp = env->to; tmp; tmp = tmp->next) 910 { 911 if (mutt_addr_is_user (tmp)) 912 break; 913 } 914 if (!tmp) 915 { 916 for (tmp = env->cc; tmp; tmp = tmp->next) 917 { 918 if (mutt_addr_is_user (tmp)) 919 break; 920 } 921 } 922 if (!tmp && mutt_addr_is_user (env->from)) 923 tmp = env->from; 924 if (tmp) 925 { 926 tmp = rfc822_cpy_adr_real (tmp); 927 /* when $reverse_realname is not set, clear the personal name so that it 928 * may be set vi a reply- or send-hook. 929 */ 930 if (!option (OPTREVREAL)) 931 FREE (&tmp->personal); 932 } 933 return (tmp); 934} 935 936ADDRESS *mutt_default_from (void) 937{ 938 ADDRESS *adr; 939 const char *fqdn = mutt_fqdn(1); 940 941 /* 942 * Note: We let $from override $realname here. Is this the right 943 * thing to do? 944 */ 945 946 if (From) 947 adr = rfc822_cpy_adr_real (From); 948 else if (option (OPTUSEDOMAIN)) 949 { 950 adr = rfc822_new_address (); 951 adr->mailbox = safe_malloc (mutt_strlen (Username) + mutt_strlen (fqdn) + 2); 952 sprintf (adr->mailbox, "%s@%s", NONULL(Username), NONULL(fqdn)); /* __SPRINTF_CHECKED__ */ 953 } 954 else 955 { 956 adr = rfc822_new_address (); 957 adr->mailbox = safe_strdup (NONULL(Username)); 958 } 959 960 return (adr); 961} 962 963static int send_message (HEADER *msg) 964{ 965 char tempfile[_POSIX_PATH_MAX]; 966 FILE *tempfp; 967 int i; 968#ifdef USE_SMTP 969 short old_write_bcc; 970#endif 971 972 /* Write out the message in MIME form. */ 973 mutt_mktemp (tempfile, sizeof (tempfile)); 974 if ((tempfp = safe_fopen (tempfile, "w")) == NULL) 975 return (-1); 976 977#ifdef USE_SMTP 978 old_write_bcc = option (OPTWRITEBCC); 979 if (SmtpUrl) 980 unset_option (OPTWRITEBCC); 981#endif 982#ifdef MIXMASTER 983 mutt_write_rfc822_header (tempfp, msg->env, msg->content, 0, msg->chain ? 1 : 0); 984#endif 985#ifndef MIXMASTER 986 mutt_write_rfc822_header (tempfp, msg->env, msg->content, 0, 0); 987#endif 988#ifdef USE_SMTP 989 if (old_write_bcc) 990 set_option (OPTWRITEBCC); 991#endif 992 993 fputc ('\n', tempfp); /* tie off the header. */ 994 995 if ((mutt_write_mime_body (msg->content, tempfp) == -1)) 996 { 997 safe_fclose (&tempfp); 998 unlink (tempfile); 999 return (-1); 1000 } 1001 1002 if (fclose (tempfp) != 0) 1003 { 1004 mutt_perror (tempfile); 1005 unlink (tempfile); 1006 return (-1); 1007 } 1008 1009#ifdef MIXMASTER 1010 if (msg->chain) 1011 return mix_send_message (msg->chain, tempfile); 1012#endif 1013 1014#if USE_SMTP 1015 if (SmtpUrl) 1016 return mutt_smtp_send (msg->env->from, msg->env->to, msg->env->cc, 1017 msg->env->bcc, tempfile, 1018 (msg->content->encoding == ENC8BIT)); 1019#endif /* USE_SMTP */ 1020 1021 i = mutt_invoke_sendmail (msg->env->from, msg->env->to, msg->env->cc, 1022 msg->env->bcc, tempfile, 1023 (msg->content->encoding == ENC8BIT)); 1024 return (i); 1025} 1026 1027/* rfc2047 encode the content-descriptions */ 1028void mutt_encode_descriptions (BODY *b, short recurse) 1029{ 1030 BODY *t; 1031 1032 for (t = b; t; t = t->next) 1033 { 1034 if (t->description) 1035 { 1036 rfc2047_encode_string (&t->description); 1037 } 1038 if (recurse && t->parts) 1039 mutt_encode_descriptions (t->parts, recurse); 1040 } 1041} 1042 1043/* rfc2047 decode them in case of an error */ 1044static void decode_descriptions (BODY *b) 1045{ 1046 BODY *t; 1047 1048 for (t = b; t; t = t->next) 1049 { 1050 if (t->description) 1051 { 1052 rfc2047_decode (&t->description); 1053 } 1054 if (t->parts) 1055 decode_descriptions (t->parts); 1056 } 1057} 1058 1059static void fix_end_of_file (const char *data) 1060{ 1061 FILE *fp; 1062 int c; 1063 1064 if ((fp = safe_fopen (data, "a+")) == NULL) 1065 return; 1066 fseek (fp,-1,SEEK_END); 1067 if ((c = fgetc(fp)) != '\n') 1068 fputc ('\n', fp); 1069 safe_fclose (&fp); 1070} 1071 1072int mutt_resend_message (FILE *fp, CONTEXT *ctx, HEADER *cur) 1073{ 1074 HEADER *msg = mutt_new_header (); 1075 1076 if (mutt_prepare_template (fp, ctx, msg, cur, 1) < 0) 1077 return -1; 1078 1079 if (WithCrypto) 1080 { 1081 /* mutt_prepare_template doesn't always flip on an application bit. 1082 * so fix that here */ 1083 if (!(msg->security & (APPLICATION_SMIME | APPLICATION_PGP))) 1084 { 1085 if ((WithCrypto & APPLICATION_SMIME) && option (OPTSMIMEISDEFAULT)) 1086 msg->security |= APPLICATION_SMIME; 1087 else if (WithCrypto & APPLICATION_PGP) 1088 msg->security |= APPLICATION_PGP; 1089 else 1090 msg->security |= APPLICATION_SMIME; 1091 } 1092 1093 if (option (OPTCRYPTOPPORTUNISTICENCRYPT)) 1094 { 1095 msg->security |= OPPENCRYPT; 1096 crypt_opportunistic_encrypt(msg); 1097 } 1098 } 1099 1100 return ci_send_message (SENDRESEND, msg, NULL, ctx, cur); 1101} 1102 1103static int is_reply (HEADER *reply, HEADER *orig) 1104{ 1105 return mutt_find_list (orig->env->references, reply->env->message_id) || 1106 mutt_find_list (orig->env->in_reply_to, reply->env->message_id); 1107} 1108 1109static int has_recips (ADDRESS *a) 1110{ 1111 int c = 0; 1112 1113 for ( ; a; a = a->next) 1114 { 1115 if (!a->mailbox || a->group) 1116 continue; 1117 c++; 1118 } 1119 return c; 1120} 1121 1122/* 1123 * Returns 0 if the message was successfully sent 1124 * -1 if the message was aborted or an error occurred 1125 * 1 if the message was postponed 1126 */ 1127int 1128ci_send_message (int flags, /* send mode */ 1129 HEADER *msg, /* template to use for new message */ 1130 char *tempfile, /* file specified by -i or -H */ 1131 CONTEXT *ctx, /* current mailbox */ 1132 HEADER *cur) /* current message */ 1133{ 1134 char buffer[LONG_STRING]; 1135 char fcc[_POSIX_PATH_MAX] = ""; /* where to copy this message */ 1136 FILE *tempfp = NULL; 1137 BODY *pbody; 1138 int i, killfrom = 0; 1139 int fcc_error = 0; 1140 int free_clear_content = 0; 1141 1142 BODY *save_content = NULL; 1143 BODY *clear_content = NULL; 1144 char *pgpkeylist = NULL; 1145 /* save current value of "pgp_sign_as" and "smime_default_key" */ 1146 char *pgp_signas = NULL; 1147 char *smime_default_key = NULL; 1148 char *tag = NULL, *err = NULL; 1149 char *ctype; 1150 1151 int rv = -1; 1152 1153 if (!flags && !msg && quadoption (OPT_RECALL) != MUTT_NO && 1154 mutt_num_postponed (1)) 1155 { 1156 /* If the user is composing a new message, check to see if there 1157 * are any postponed messages first. 1158 */ 1159 if ((i = query_quadoption (OPT_RECALL, _("Recall postponed message?"))) == -1) 1160 return rv; 1161 1162 if(i == MUTT_YES) 1163 flags |= SENDPOSTPONED; 1164 } 1165 1166 1167 if (flags & SENDPOSTPONED) 1168 { 1169 if (WithCrypto & APPLICATION_PGP) 1170 pgp_signas = safe_strdup(PgpSignAs); 1171 if (WithCrypto & APPLICATION_SMIME) 1172 smime_default_key = safe_strdup(SmimeDefaultKey); 1173 } 1174 1175 /* Delay expansion of aliases until absolutely necessary--shouldn't 1176 * be necessary unless we are prompting the user or about to execute a 1177 * send-hook. 1178 */ 1179 1180 if (!msg) 1181 { 1182 msg = mutt_new_header (); 1183 1184 if (flags == SENDPOSTPONED) 1185 { 1186 if ((flags = mutt_get_postponed (ctx, msg, &cur, fcc, sizeof (fcc))) < 0) 1187 goto cleanup; 1188 } 1189 1190 if (flags & (SENDPOSTPONED|SENDRESEND)) 1191 { 1192 if ((tempfp = safe_fopen (msg->content->filename, "a+")) == NULL) 1193 { 1194 mutt_perror (msg->content->filename); 1195 goto cleanup; 1196 } 1197 } 1198 1199 if (!msg->env) 1200 msg->env = mutt_new_envelope (); 1201 } 1202 1203 /* Parse and use an eventual list-post header */ 1204 if ((flags & SENDLISTREPLY) 1205 && cur && cur->env && cur->env->list_post) 1206 { 1207 /* Use any list-post header as a template */ 1208 url_parse_mailto (msg->env, NULL, cur->env->list_post); 1209 /* We don't let them set the sender's address. */ 1210 rfc822_free_address (&msg->env->from); 1211 } 1212 1213 if (! (flags & (SENDKEY | SENDPOSTPONED | SENDRESEND))) 1214 { 1215 /* When SENDDRAFTFILE is set, the caller has already 1216 * created the "parent" body structure. 1217 */ 1218 if (! (flags & SENDDRAFTFILE)) 1219 { 1220 pbody = mutt_new_body (); 1221 pbody->next = msg->content; /* don't kill command-line attachments */ 1222 msg->content = pbody; 1223 1224 if (!(ctype = safe_strdup (ContentType))) 1225 ctype = safe_strdup ("text/plain"); 1226 mutt_parse_content_type (ctype, msg->content); 1227 FREE (&ctype); 1228 msg->content->unlink = 1; 1229 msg->content->use_disp = 0; 1230 msg->content->disposition = DISPINLINE; 1231 1232 if (!tempfile) 1233 { 1234 mutt_mktemp (buffer, sizeof (buffer)); 1235 tempfp = safe_fopen (buffer, "w+"); 1236 msg->content->filename = safe_strdup (buffer); 1237 } 1238 else 1239 { 1240 tempfp = safe_fopen (tempfile, "a+"); 1241 msg->content->filename = safe_strdup (tempfile); 1242 } 1243 } 1244 else 1245 tempfp = safe_fopen (msg->content->filename, "a+"); 1246 1247 if (!tempfp) 1248 { 1249 dprint(1,(debugfile, "newsend_message: can't create tempfile %s (errno=%d)\n", msg->content->filename, errno)); 1250 mutt_perror (msg->content->filename); 1251 goto cleanup; 1252 } 1253 } 1254 1255 /* this is handled here so that the user can match ~f in send-hook */ 1256 if (cur && option (OPTREVNAME) && !(flags & (SENDPOSTPONED|SENDRESEND))) 1257 { 1258 /* we shouldn't have to worry about freeing `msg->env->from' before 1259 * setting it here since this code will only execute when doing some 1260 * sort of reply. the pointer will only be set when using the -H command 1261 * line option. 1262 * 1263 * We shouldn't have to worry about alias expansion here since we are 1264 * either replying to a real or postponed message, therefore no aliases 1265 * should exist since the user has not had the opportunity to add 1266 * addresses to the list. We just have to ensure the postponed messages 1267 * have their aliases expanded. 1268 */ 1269 1270 msg->env->from = set_reverse_name (cur->env); 1271 } 1272 1273 if (! (flags & (SENDPOSTPONED|SENDRESEND)) && 1274 ! ((flags & SENDDRAFTFILE) && option (OPTRESUMEDRAFTFILES))) 1275 { 1276 if ((flags & (SENDREPLY | SENDFORWARD)) && ctx && 1277 envelope_defaults (msg->env, ctx, cur, flags) == -1) 1278 goto cleanup; 1279 1280 if (option (OPTHDRS)) 1281 process_user_recips (msg->env); 1282 1283 /* Expand aliases and remove duplicates/crossrefs */ 1284 mutt_expand_aliases_env (msg->env); 1285 1286 if (flags & SENDREPLY) 1287 mutt_fix_reply_recipients (msg->env); 1288 1289 if (! (flags & (SENDMAILX|SENDBATCH)) && 1290 ! (option (OPTAUTOEDIT) && option (OPTEDITHDRS)) && 1291 ! ((flags & SENDREPLY) && option (OPTFASTREPLY))) 1292 { 1293 if (edit_envelope (msg->env) == -1) 1294 goto cleanup; 1295 } 1296 1297 /* the from address must be set here regardless of whether or not 1298 * $use_from is set so that the `~P' (from you) operator in send-hook 1299 * patterns will work. if $use_from is unset, the from address is killed 1300 * after send-hooks are evaluated */ 1301 1302 if (!msg->env->from) 1303 { 1304 msg->env->from = mutt_default_from (); 1305 killfrom = 1; 1306 } 1307 1308 if ((flags & SENDREPLY) && cur) 1309 { 1310 /* change setting based upon message we are replying to */ 1311 mutt_message_hook (ctx, cur, MUTT_REPLYHOOK); 1312 1313 /* 1314 * set the replied flag for the message we are generating so that the 1315 * user can use ~Q in a send-hook to know when reply-hook's are also 1316 * being used. 1317 */ 1318 msg->replied = 1; 1319 } 1320 1321 /* change settings based upon recipients */ 1322 1323 mutt_message_hook (NULL, msg, MUTT_SENDHOOK); 1324 1325 /* 1326 * Unset the replied flag from the message we are composing since it is 1327 * no longer required. This is done here because the FCC'd copy of 1328 * this message was erroneously get the 'R'eplied flag when stored in 1329 * a maildir-style mailbox. 1330 */ 1331 msg->replied = 0; 1332 1333 if (! (flags & SENDKEY)) 1334 { 1335 if (option (OPTTEXTFLOWED) && msg->content->type == TYPETEXT && !ascii_strcasecmp (msg->content->subtype, "plain")) 1336 mutt_set_parameter ("format", "flowed", &msg->content->parameter); 1337 } 1338 1339 /* $use_from and/or $from might have changed in a send-hook */ 1340 if (killfrom) 1341 { 1342 rfc822_free_address (&msg->env->from); 1343 if (option (OPTUSEFROM) && !(flags & (SENDPOSTPONED|SENDRESEND))) 1344 msg->env->from = mutt_default_from (); 1345 killfrom = 0; 1346 } 1347 1348 if (option (OPTHDRS)) 1349 process_user_header (msg->env); 1350 1351 if (flags & SENDBATCH) 1352 mutt_copy_stream (stdin, tempfp); 1353 1354 if (option (OPTSIGONTOP) && ! (flags & (SENDMAILX|SENDKEY|SENDBATCH)) 1355 && Editor && mutt_strcmp (Editor, "builtin") != 0) 1356 append_signature (tempfp); 1357 1358 /* include replies/forwarded messages, unless we are given a template */ 1359 if (!tempfile && (ctx || !(flags & (SENDREPLY|SENDFORWARD))) 1360 && generate_body (tempfp, msg, flags, ctx, cur) == -1) 1361 goto cleanup; 1362 1363 if (!option (OPTSIGONTOP) && ! (flags & (SENDMAILX|SENDKEY|SENDBATCH)) 1364 && Editor && mutt_strcmp (Editor, "builtin") != 0) 1365 append_signature (tempfp); 1366 } 1367 1368 /* 1369 * This hook is even called for postponed messages, and can, e.g., be 1370 * used for setting the editor, the sendmail path, or the 1371 * envelope sender. 1372 */ 1373 mutt_message_hook (NULL, msg, MUTT_SEND2HOOK); 1374 1375 /* wait until now to set the real name portion of our return address so 1376 that $realname can be set in a send-hook */ 1377 if (msg->env->from && !msg->env->from->personal 1378 && !(flags & (SENDRESEND|SENDPOSTPONED))) 1379 msg->env->from->personal = safe_strdup (Realname); 1380 1381 if (!((WithCrypto & APPLICATION_PGP) && (flags & SENDKEY))) 1382 safe_fclose (&tempfp); 1383 1384 if (flags & SENDMAILX) 1385 { 1386 if (mutt_builtin_editor (msg->content->filename, msg, cur) == -1) 1387 goto cleanup; 1388 } 1389 else if (! (flags & SENDBATCH)) 1390 { 1391 struct stat st; 1392 time_t mtime = mutt_decrease_mtime (msg->content->filename, NULL); 1393 1394 mutt_update_encoding (msg->content); 1395 1396 /* 1397 * Select whether or not the user's editor should be called now. We 1398 * don't want to do this when: 1399 * 1) we are sending a key/cert 1400 * 2) we are forwarding a message and the user doesn't want to edit it. 1401 * This is controlled by the quadoption $forward_edit. However, if 1402 * both $edit_headers and $autoedit are set, we want to ignore the 1403 * setting of $forward_edit because the user probably needs to add the 1404 * recipients. 1405 */ 1406 if (! (flags & SENDKEY) && 1407 ((flags & SENDFORWARD) == 0 || 1408 (option (OPTEDITHDRS) && option (OPTAUTOEDIT)) || 1409 query_quadoption (OPT_FORWEDIT, _("Edit forwarded message?")) == MUTT_YES)) 1410 { 1411 /* If the this isn't a text message, look for a mailcap edit command */ 1412 if (mutt_needs_mailcap (msg->content)) 1413 { 1414 if (!mutt_edit_attachment (msg->content)) 1415 goto cleanup; 1416 } 1417 else if (!Editor || mutt_strcmp ("builtin", Editor) == 0) 1418 mutt_builtin_editor (msg->content->filename, msg, cur); 1419 else if (option (OPTEDITHDRS)) 1420 { 1421 mutt_env_to_local (msg->env); 1422 mutt_edit_headers (Editor, msg->content->filename, msg, fcc, sizeof (fcc)); 1423 mutt_env_to_intl (msg->env, NULL, NULL); 1424 } 1425 else 1426 { 1427 mutt_edit_file (Editor, msg->content->filename); 1428 if (stat (msg->content->filename, &st) == 0) 1429 { 1430 if (mtime != st.st_mtime) 1431 fix_end_of_file (msg->content->filename); 1432 } 1433 else 1434 mutt_perror (msg->content->filename); 1435 } 1436 1437 /* If using format=flowed, perform space stuffing. Avoid stuffing when 1438 * recalling a postponed message where the stuffing was already 1439 * performed. If it has already been performed, the format=flowed 1440 * parameter will be present. 1441 */ 1442 if (option (OPTTEXTFLOWED) && msg->content->type == TYPETEXT && !ascii_strcasecmp("plain", msg->content->subtype)) 1443 { 1444 char *p = mutt_get_parameter("format", msg->content->parameter); 1445 if (ascii_strcasecmp("flowed", NONULL(p))) 1446 rfc3676_space_stuff (msg); 1447 } 1448 1449 mutt_message_hook (NULL, msg, MUTT_SEND2HOOK); 1450 } 1451 1452 if (! (flags & (SENDPOSTPONED | SENDFORWARD | SENDKEY | SENDRESEND | SENDDRAFTFILE))) 1453 { 1454 if (stat (msg->content->filename, &st) == 0) 1455 { 1456 /* if the file was not modified, bail out now */ 1457 if (mtime == st.st_mtime && !msg->content->next && 1458 query_quadoption (OPT_ABORT, _("Abort unmodified message?")) == MUTT_YES) 1459 { 1460 mutt_message _("Aborted unmodified message."); 1461 goto cleanup; 1462 } 1463 } 1464 else 1465 mutt_perror (msg->content->filename); 1466 } 1467 } 1468 1469 /* 1470 * Set the message security unless: 1471 * 1) crypto support is not enabled (WithCrypto==0) 1472 * 2) pgp: header field was present during message editing with $edit_headers (msg->security != 0) 1473 * 3) we are resending a message 1474 * 4) we are recalling a postponed message (don't override the user's saved settings) 1475 * 5) we are in mailx mode 1476 * 6) we are in batch mode 1477 * 1478 * This is done after allowing the user to edit the message so that security 1479 * settings can be configured with send2-hook and $edit_headers. 1480 */ 1481 if (WithCrypto && (msg->security == 0) && !(flags & (SENDBATCH | SENDMAILX | SENDPOSTPONED | SENDRESEND))) 1482 { 1483 if (option (OPTCRYPTAUTOSIGN)) 1484 msg->security |= SIGN; 1485 if (option (OPTCRYPTAUTOENCRYPT)) 1486 msg->security |= ENCRYPT; 1487 if (option (OPTCRYPTREPLYENCRYPT) && cur && (cur->security & ENCRYPT)) 1488 msg->security |= ENCRYPT; 1489 if (option (OPTCRYPTREPLYSIGN) && cur && (cur->security & SIGN)) 1490 msg->security |= SIGN; 1491 if (option (OPTCRYPTREPLYSIGNENCRYPTED) && cur && (cur->security & ENCRYPT)) 1492 msg->security |= SIGN; 1493 if ((WithCrypto & APPLICATION_PGP) && 1494 ((msg->security & (ENCRYPT | SIGN)) || option (OPTCRYPTOPPORTUNISTICENCRYPT))) 1495 { 1496 if (option (OPTPGPAUTOINLINE)) 1497 msg->security |= INLINE; 1498 if (option (OPTPGPREPLYINLINE) && cur && (cur->security & INLINE)) 1499 msg->security |= INLINE; 1500 } 1501 1502 if (msg->security || option (OPTCRYPTOPPORTUNISTICENCRYPT)) 1503 { 1504 /* 1505 * When replying / forwarding, use the original message's 1506 * crypto system. According to the documentation, 1507 * smime_is_default should be disregarded here. 1508 * 1509 * Problem: At least with forwarding, this doesn't really 1510 * make much sense. Should we have an option to completely 1511 * disable individual mechanisms at run-time? 1512 */ 1513 if (cur) 1514 { 1515 if ((WithCrypto & APPLICATION_PGP) && option (OPTCRYPTAUTOPGP) 1516 && (cur->security & APPLICATION_PGP)) 1517 msg->security |= APPLICATION_PGP; 1518 else if ((WithCrypto & APPLICATION_SMIME) && option (OPTCRYPTAUTOSMIME) 1519 && (cur->security & APPLICATION_SMIME)) 1520 msg->security |= APPLICATION_SMIME; 1521 } 1522 1523 /* 1524 * No crypto mechanism selected? Use availability + smime_is_default 1525 * for the decision. 1526 */ 1527 if (!(msg->security & (APPLICATION_SMIME | APPLICATION_PGP))) 1528 { 1529 if ((WithCrypto & APPLICATION_SMIME) && option (OPTCRYPTAUTOSMIME) 1530 && option (OPTSMIMEISDEFAULT)) 1531 msg->security |= APPLICATION_SMIME; 1532 else if ((WithCrypto & APPLICATION_PGP) && option (OPTCRYPTAUTOPGP)) 1533 msg->security |= APPLICATION_PGP; 1534 else if ((WithCrypto & APPLICATION_SMIME) && option (OPTCRYPTAUTOSMIME)) 1535 msg->security |= APPLICATION_SMIME; 1536 } 1537 } 1538 1539 /* opportunistic encrypt relys on SMIME or PGP already being selected */ 1540 if (option (OPTCRYPTOPPORTUNISTICENCRYPT)) 1541 { 1542 /* If something has already enabled encryption, e.g. OPTCRYPTAUTOENCRYPT 1543 * or OPTCRYPTREPLYENCRYPT, then don't enable opportunistic encrypt for 1544 * the message. 1545 */ 1546 if (! (msg->security & ENCRYPT)) 1547 { 1548 msg->security |= OPPENCRYPT; 1549 crypt_opportunistic_encrypt(msg); 1550 } 1551 } 1552 1553 /* No permissible mechanisms found. Don't sign or encrypt. */ 1554 if (!(msg->security & (APPLICATION_SMIME|APPLICATION_PGP))) 1555 msg->security = 0; 1556 } 1557 1558 /* specify a default fcc. if we are in batchmode, only save a copy of 1559 * the message if the value of $copy is yes or ask-yes */ 1560 1561 if (!fcc[0] && !(flags & (SENDPOSTPONEDFCC)) && (!(flags & SENDBATCH) || (quadoption (OPT_COPY) & 0x1))) 1562 { 1563 /* set the default FCC */ 1564 if (!msg->env->from) 1565 { 1566 msg->env->from = mutt_default_from (); 1567 killfrom = 1; /* no need to check $use_from because if the user specified 1568 a from address it would have already been set by now */ 1569 } 1570 mutt_select_fcc (fcc, sizeof (fcc), msg); 1571 if (killfrom) 1572 { 1573 rfc822_free_address (&msg->env->from); 1574 killfrom = 0; 1575 } 1576 } 1577 1578 1579 mutt_update_encoding (msg->content); 1580 1581 if (! (flags & (SENDMAILX | SENDBATCH))) 1582 { 1583main_loop: 1584 1585 fcc_error = 0; /* reset value since we may have failed before */ 1586 mutt_pretty_mailbox (fcc, sizeof (fcc)); 1587 i = mutt_compose_menu (msg, fcc, sizeof (fcc), cur, 1588 (flags & SENDNOFREEHEADER ? MUTT_COMPOSE_NOFREEHEADER : 0)); 1589 if (i == -1) 1590 { 1591 /* abort */ 1592 mutt_message _("Mail not sent."); 1593 goto cleanup; 1594 } 1595 else if (i == 1) 1596 { 1597 /* postpone the message until later. */ 1598 if (msg->content->next) 1599 msg->content = mutt_make_multipart (msg->content); 1600 1601 if (WithCrypto && option (OPTPOSTPONEENCRYPT) && PostponeEncryptAs 1602 && (msg->security & ENCRYPT)) 1603 { 1604 int is_signed = msg->security & SIGN; 1605 if (is_signed) 1606 msg->security &= ~SIGN; 1607 1608 pgpkeylist = safe_strdup (PostponeEncryptAs); 1609 if (mutt_protect (msg, pgpkeylist) == -1) 1610 { 1611 if (is_signed) 1612 msg->security |= SIGN; 1613 FREE (&pgpkeylist); 1614 msg->content = mutt_remove_multipart (msg->content); 1615 goto main_loop; 1616 } 1617 1618 if (is_signed) 1619 msg->security |= SIGN; 1620 FREE (&pgpkeylist); 1621 } 1622 1623 /* 1624 * make sure the message is written to the right part of a maildir 1625 * postponed folder. 1626 */ 1627 msg->read = 0; msg->old = 0; 1628 1629 mutt_encode_descriptions (msg->content, 1); 1630 mutt_prepare_envelope (msg->env, 0); 1631 mutt_env_to_intl (msg->env, NULL, NULL); /* Handle bad IDNAs the next time. */ 1632 1633 if (!Postponed || mutt_write_fcc (NONULL (Postponed), msg, (cur && (flags & SENDREPLY)) ? cur->env->message_id : NULL, 1, fcc) < 0) 1634 { 1635 msg->content = mutt_remove_multipart (msg->content); 1636 decode_descriptions (msg->content); 1637 mutt_unprepare_envelope (msg->env); 1638 goto main_loop; 1639 } 1640 mutt_update_num_postponed (); 1641 mutt_message _("Message postponed."); 1642 rv = 1; 1643 goto cleanup; 1644 } 1645 } 1646 1647 if (!has_recips (msg->env->to) && !has_recips (msg->env->cc) && 1648 !has_recips (msg->env->bcc)) 1649 { 1650 if (! (flags & SENDBATCH)) 1651 { 1652 mutt_error _("No recipients are specified!"); 1653 goto main_loop; 1654 } 1655 else 1656 { 1657 puts _("No recipients were specified."); 1658 goto cleanup; 1659 } 1660 } 1661 1662 if (mutt_env_to_intl (msg->env, &tag, &err)) 1663 { 1664 mutt_error (_("Bad IDN in \"%s\": '%s'"), tag, err); 1665 FREE (&err); 1666 if (!(flags & SENDBATCH)) 1667 goto main_loop; 1668 else 1669 goto cleanup; 1670 } 1671 1672 if (!msg->env->subject && ! (flags & SENDBATCH) && 1673 (i = query_quadoption (OPT_SUBJECT, _("No subject, abort sending?"))) != MUTT_NO) 1674 { 1675 /* if the abort is automatic, print an error message */ 1676 if (quadoption (OPT_SUBJECT) == MUTT_YES) 1677 mutt_error _("No subject specified."); 1678 goto main_loop; 1679 } 1680 1681 if (msg->content->next) 1682 msg->content = mutt_make_multipart (msg->content); 1683 1684 /* 1685 * Ok, we need to do it this way instead of handling all fcc stuff in 1686 * one place in order to avoid going to main_loop with encoded "env" 1687 * in case of error. Ugh. 1688 */ 1689 1690 mutt_encode_descriptions (msg->content, 1); 1691 1692 /* 1693 * Make sure that clear_content and free_clear_content are 1694 * properly initialized -- we may visit this particular place in 1695 * the code multiple times, including after a failed call to 1696 * mutt_protect(). 1697 */ 1698 1699 clear_content = NULL; 1700 free_clear_content = 0; 1701 1702 if (WithCrypto) 1703 { 1704 if (msg->security & (ENCRYPT | SIGN)) 1705 { 1706 /* save the decrypted attachments */ 1707 clear_content = msg->content; 1708 1709 if ((crypt_get_keys (msg, &pgpkeylist, 0) == -1) || 1710 mutt_protect (msg, pgpkeylist) == -1) 1711 { 1712 msg->content = mutt_remove_multipart (msg->content); 1713 1714 FREE (&pgpkeylist); 1715 1716 decode_descriptions (msg->content); 1717 goto main_loop; 1718 } 1719 mutt_encode_descriptions (msg->content, 0); 1720 } 1721 1722 /* 1723 * at this point, msg->content is one of the following three things: 1724 * - multipart/signed. In this case, clear_content is a child. 1725 * - multipart/encrypted. In this case, clear_content exists 1726 * independently 1727 * - application/pgp. In this case, clear_content exists independently. 1728 * - something else. In this case, it's the same as clear_content. 1729 */ 1730 1731 /* This is ugly -- lack of "reporting back" from mutt_protect(). */ 1732 1733 if (clear_content && (msg->content != clear_content) 1734 && (msg->content->parts != clear_content)) 1735 free_clear_content = 1; 1736 } 1737 1738 if (!option (OPTNOCURSES) && !(flags & SENDMAILX)) 1739 mutt_message _("Sending message..."); 1740 1741 mutt_prepare_envelope (msg->env, 1); 1742 1743 /* save a copy of the message, if necessary. */ 1744 1745 mutt_expand_path (fcc, sizeof (fcc)); 1746 1747 1748 /* Don't save a copy when we are in batch-mode, and the FCC 1749 * folder is on an IMAP server: This would involve possibly lots 1750 * of user interaction, which is not available in batch mode. 1751 * 1752 * Note: A patch to fix the problems with the use of IMAP servers 1753 * from non-curses mode is available from Brendan Cully. However, 1754 * I'd like to think a bit more about this before including it. 1755 */ 1756 1757#ifdef USE_IMAP 1758 if ((flags & SENDBATCH) && fcc[0] && mx_is_imap (fcc)) 1759 fcc[0] = '\0'; 1760#endif 1761 1762 if (*fcc && mutt_strcmp ("/dev/null", fcc) != 0) 1763 { 1764 BODY *tmpbody = msg->content; 1765 BODY *save_sig = NULL; 1766 BODY *save_parts = NULL; 1767 1768 if (WithCrypto && (msg->security & (ENCRYPT | SIGN)) && option (OPTFCCCLEAR)) 1769 msg->content = clear_content; 1770 1771 /* check to see if the user wants copies of all attachments */ 1772 if (query_quadoption (OPT_FCCATTACH, _("Save attachments in Fcc?")) != MUTT_YES && 1773 msg->content->type == TYPEMULTIPART) 1774 { 1775 if (WithCrypto 1776 && (msg->security & (ENCRYPT | SIGN)) 1777 && (mutt_strcmp (msg->content->subtype, "encrypted") == 0 || 1778 mutt_strcmp (msg->content->subtype, "signed") == 0)) 1779 { 1780 if (clear_content->type == TYPEMULTIPART) 1781 { 1782 if(!(msg->security & ENCRYPT) && (msg->security & SIGN)) 1783 { 1784 /* save initial signature and attachments */ 1785 save_sig = msg->content->parts->next; 1786 save_parts = clear_content->parts->next; 1787 } 1788 1789 /* this means writing only the main part */ 1790 msg->content = clear_content->parts; 1791 1792 if (mutt_protect (msg, pgpkeylist) == -1) 1793 { 1794 /* we can't do much about it at this point, so 1795 * fallback to saving the whole thing to fcc 1796 */ 1797 msg->content = tmpbody; 1798 save_sig = NULL; 1799 goto full_fcc; 1800 } 1801 1802 save_content = msg->content; 1803 } 1804 } 1805 else 1806 msg->content = msg->content->parts; 1807 } 1808 1809full_fcc: 1810 if (msg->content) 1811 { 1812 /* update received time so that when storing to a mbox-style folder 1813 * the From_ line contains the current time instead of when the 1814 * message was first postponed. 1815 */ 1816 msg->received = time (NULL); 1817 if (mutt_write_fcc (fcc, msg, NULL, 0, NULL) == -1) 1818 { 1819 /* 1820 * Error writing FCC, we should abort sending. 1821 */ 1822 fcc_error = 1; 1823 } 1824 } 1825 1826 msg->content = tmpbody; 1827 1828 if (WithCrypto && save_sig) 1829 { 1830 /* cleanup the second signature structures */ 1831 if (save_content->parts) 1832 { 1833 mutt_free_body (&save_content->parts->next); 1834 save_content->parts = NULL; 1835 } 1836 mutt_free_body (&save_content); 1837 1838 /* restore old signature and attachments */ 1839 msg->content->parts->next = save_sig; 1840 msg->content->parts->parts->next = save_parts; 1841 } 1842 else if (WithCrypto && save_content) 1843 { 1844 /* destroy the new encrypted body. */ 1845 mutt_free_body (&save_content); 1846 } 1847 1848 } 1849 1850 1851 /* 1852 * Don't attempt to send the message if the FCC failed. Just pretend 1853 * the send failed as well so we give the user a chance to fix the 1854 * error. 1855 */ 1856 if (fcc_error || (i = send_message (msg)) < 0) 1857 { 1858 if (!(flags & SENDBATCH)) 1859 { 1860 if (!WithCrypto) 1861 ; 1862 else if ((msg->security & ENCRYPT) || 1863 ((msg->security & SIGN) 1864 && msg->content->type == TYPEAPPLICATION)) 1865 { 1866 mutt_free_body (&msg->content); /* destroy PGP data */ 1867 msg->content = clear_content; /* restore clear text. */ 1868 } 1869 else if ((msg->security & SIGN) && msg->content->type == TYPEMULTIPART) 1870 { 1871 mutt_free_body (&msg->content->parts->next); /* destroy sig */ 1872 msg->content = mutt_remove_multipart (msg->content); 1873 } 1874 1875 msg->content = mutt_remove_multipart (msg->content); 1876 decode_descriptions (msg->content); 1877 mutt_unprepare_envelope (msg->env); 1878 goto main_loop; 1879 } 1880 else 1881 { 1882 puts _("Could not send the message."); 1883 goto cleanup; 1884 } 1885 } 1886 else if (!option (OPTNOCURSES) && ! (flags & SENDMAILX)) 1887 mutt_message (i == 0 ? _("Mail sent.") : _("Sending in background.")); 1888 1889 if (WithCrypto && (msg->security & ENCRYPT)) 1890 FREE (&pgpkeylist); 1891 1892 if (WithCrypto && free_clear_content) 1893 mutt_free_body (&clear_content); 1894 1895 /* set 'replied' flag only if the user didn't change/remove 1896 In-Reply-To: and References: headers during edit */ 1897 if (flags & SENDREPLY) 1898 { 1899 if (cur && ctx) 1900 mutt_set_flag (ctx, cur, MUTT_REPLIED, is_reply (cur, msg)); 1901 else if (!(flags & SENDPOSTPONED) && ctx && ctx->tagged) 1902 { 1903 for (i = 0; i < ctx->vcount; i++) 1904 if (ctx->hdrs[ctx->v2r[i]]->tagged) 1905 mutt_set_flag (ctx, ctx->hdrs[ctx->v2r[i]], MUTT_REPLIED, 1906 is_reply (ctx->hdrs[ctx->v2r[i]], msg)); 1907 } 1908 } 1909 1910 1911 rv = 0; 1912 1913cleanup: 1914 1915 if (flags & SENDPOSTPONED) 1916 { 1917 if (WithCrypto & APPLICATION_PGP) 1918 { 1919 FREE (&PgpSignAs); 1920 PgpSignAs = pgp_signas; 1921 } 1922 if (WithCrypto & APPLICATION_SMIME) 1923 { 1924 FREE (&SmimeDefaultKey); 1925 SmimeDefaultKey = smime_default_key; 1926 } 1927 } 1928 1929 safe_fclose (&tempfp); 1930 if (! (flags & SENDNOFREEHEADER)) 1931 mutt_free_header (&msg); 1932 1933 return rv; 1934} 1935 1936/* vim: set sw=2: */