NeoMutt  2019-12-07-168-gc45f47
Teaching an old dog new tricks
DOXYGEN
send.c
Go to the documentation of this file.
1 
30 #include "config.h"
31 #include <errno.h>
32 #include <locale.h>
33 #include <stdbool.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <sys/stat.h>
37 #include <time.h>
38 #include <unistd.h>
39 #include "mutt/lib.h"
40 #include "address/lib.h"
41 #include "config/lib.h"
42 #include "email/lib.h"
43 #include "core/lib.h"
44 #include "gui/lib.h"
45 #include "mutt.h"
46 #include "send.h"
47 #include "alias.h"
48 #include "compose.h"
49 #include "context.h"
50 #include "copy.h"
51 #include "edit.h"
52 #include "globals.h"
53 #include "handler.h"
54 #include "hdrline.h"
55 #include "hook.h"
56 #include "mutt_attach.h"
57 #include "mutt_body.h"
58 #include "mutt_header.h"
59 #include "mutt_logging.h"
60 #include "mutt_parse.h"
61 #include "muttlib.h"
62 #include "options.h"
63 #include "pattern.h"
64 #include "protos.h"
65 #include "recvattach.h"
66 #include "rfc3676.h"
67 #include "sendlib.h"
68 #include "smtp.h"
69 #include "sort.h"
70 #include "ncrypt/lib.h"
71 #ifdef USE_NNTP
72 #include "mx.h"
73 #include "nntp/lib.h"
74 #endif
75 #ifdef MIXMASTER
76 #include "remailer.h"
77 #endif
78 #ifdef USE_NOTMUCH
79 #include "notmuch/lib.h"
80 #endif
81 #ifdef USE_IMAP
82 #include "imap/lib.h"
83 #endif
84 #ifdef USE_AUTOCRYPT
85 #include "autocrypt/lib.h"
86 #endif
87 
88 /* These Config Variables are only used in send.c */
89 unsigned char C_AbortNoattach;
91 unsigned char C_AbortNosubject;
92 unsigned char C_AbortUnmodified;
105 unsigned char C_FccAttach;
111 unsigned char C_ForwardEdit;
114 bool C_Hdrs;
115 unsigned char C_HonorFollowupTo;
117 unsigned char C_Include;
118 bool C_Metoo;
124 unsigned char C_Recall;
126 unsigned char C_ReplyTo;
131 char *C_Signature;
133 bool C_UseFrom;
134 
139 static void append_signature(FILE *fp)
140 {
141  FILE *fp_tmp = NULL;
142  pid_t pid;
143 
144  if (C_Signature && (fp_tmp = mutt_open_read(C_Signature, &pid)))
145  {
146  if (C_SigDashes)
147  fputs("\n-- \n", fp);
148  mutt_file_copy_stream(fp_tmp, fp);
149  mutt_file_fclose(&fp_tmp);
150  if (pid != -1)
151  filter_wait(pid);
152  }
153 }
154 
161 static void remove_user(struct AddressList *al, bool leave_only)
162 {
163  struct Address *a = NULL, *tmp = NULL;
164  TAILQ_FOREACH_SAFE(a, al, entries, tmp)
165  {
166  if (mutt_addr_is_user(a) && (!leave_only || TAILQ_NEXT(a, entries)))
167  {
168  TAILQ_REMOVE(al, a, entries);
169  mutt_addr_free(&a);
170  }
171  }
172 }
173 
180 static void add_mailing_lists(struct AddressList *out, const struct AddressList *t,
181  const struct AddressList *c)
182 {
183  const struct AddressList *const als[] = { t, c };
184 
185  for (size_t i = 0; i < mutt_array_size(als); ++i)
186  {
187  const struct AddressList *al = als[i];
188  struct Address *a = NULL;
189  TAILQ_FOREACH(a, al, entries)
190  {
191  if (!a->group && mutt_is_mail_list(a))
192  {
194  }
195  }
196  }
197 }
198 
207 int mutt_edit_address(struct AddressList *al, const char *field, bool expand_aliases)
208 {
209  char buf[8192];
210  char *err = NULL;
211  int idna_ok = 0;
212 
213  do
214  {
215  buf[0] = '\0';
217  mutt_addrlist_write(al, buf, sizeof(buf), false);
218  if (mutt_get_field(field, buf, sizeof(buf), MUTT_ALIAS) != 0)
219  return -1;
221  mutt_addrlist_parse2(al, buf);
222  if (expand_aliases)
224  idna_ok = mutt_addrlist_to_intl(al, &err);
225  if (idna_ok != 0)
226  {
227  mutt_error(_("Bad IDN: '%s'"), err);
228  FREE(&err);
229  }
230  } while (idna_ok != 0);
231  return 0;
232 }
233 
241 static int edit_envelope(struct Envelope *en, SendFlags flags)
242 {
243  char buf[8192];
244 
245 #ifdef USE_NNTP
246  if (OptNewsSend)
247  {
248  if (en->newsgroups)
249  mutt_str_strfcpy(buf, en->newsgroups, sizeof(buf));
250  else
251  buf[0] = '\0';
252  if (mutt_get_field("Newsgroups: ", buf, sizeof(buf), MUTT_COMP_NO_FLAGS) != 0)
253  return -1;
254  FREE(&en->newsgroups);
255  en->newsgroups = mutt_str_strdup(buf);
256 
257  if (en->followup_to)
258  mutt_str_strfcpy(buf, en->followup_to, sizeof(buf));
259  else
260  buf[0] = '\0';
261  if (C_AskFollowUp &&
262  (mutt_get_field("Followup-To: ", buf, sizeof(buf), MUTT_COMP_NO_FLAGS) != 0))
263  {
264  return -1;
265  }
266  FREE(&en->followup_to);
267  en->followup_to = mutt_str_strdup(buf);
268 
269  if (en->x_comment_to)
270  mutt_str_strfcpy(buf, en->x_comment_to, sizeof(buf));
271  else
272  buf[0] = '\0';
273  if (C_XCommentTo && C_AskXCommentTo &&
274  (mutt_get_field("X-Comment-To: ", buf, sizeof(buf), MUTT_COMP_NO_FLAGS) != 0))
275  {
276  return -1;
277  }
278  FREE(&en->x_comment_to);
279  en->x_comment_to = mutt_str_strdup(buf);
280  }
281  else
282 #endif
283  {
284  if ((mutt_edit_address(&en->to, _("To: "), true) == -1) || TAILQ_EMPTY(&en->to))
285  return -1;
286  if (C_Askcc && (mutt_edit_address(&en->cc, _("Cc: "), true) == -1))
287  return -1;
288  if (C_Askbcc && (mutt_edit_address(&en->bcc, _("Bcc: "), true) == -1))
289  return -1;
291  (mutt_edit_address(&en->from, "From: ", true) == -1))
292  {
293  return -1;
294  }
295  }
296 
297  if (en->subject)
298  {
299  if (C_FastReply)
300  return 0;
301  mutt_str_strfcpy(buf, en->subject, sizeof(buf));
302  }
303  else
304  {
305  const char *p = NULL;
306 
307  buf[0] = '\0';
308  struct ListNode *uh = NULL;
309  STAILQ_FOREACH(uh, &UserHeader, entries)
310  {
311  size_t plen = mutt_str_startswith(uh->data, "subject:", CASE_IGNORE);
312  if (plen)
313  {
314  p = mutt_str_skip_email_wsp(uh->data + plen);
315  mutt_str_strfcpy(buf, p, sizeof(buf));
316  }
317  }
318  }
319 
320  if ((mutt_get_field(_("Subject: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS) != 0) ||
321  (!buf[0] &&
322  (query_quadoption(C_AbortNosubject, _("No subject, abort?")) != MUTT_NO)))
323  {
324  mutt_message(_("No subject, aborting"));
325  return -1;
326  }
327  mutt_str_replace(&en->subject, buf);
328 
329  return 0;
330 }
331 
332 #ifdef USE_NNTP
333 
340 static char *nntp_get_header(const char *s)
341 {
342  SKIPWS(s);
343  return mutt_str_strdup(s);
344 }
345 #endif
346 
351 static void process_user_recips(struct Envelope *env)
352 {
353  struct ListNode *uh = NULL;
354  STAILQ_FOREACH(uh, &UserHeader, entries)
355  {
356  size_t plen;
357  if ((plen = mutt_str_startswith(uh->data, "to:", CASE_IGNORE)))
358  mutt_addrlist_parse(&env->to, uh->data + plen);
359  else if ((plen = mutt_str_startswith(uh->data, "cc:", CASE_IGNORE)))
360  mutt_addrlist_parse(&env->cc, uh->data + plen);
361  else if ((plen = mutt_str_startswith(uh->data, "bcc:", CASE_IGNORE)))
362  mutt_addrlist_parse(&env->bcc, uh->data + plen);
363 #ifdef USE_NNTP
364  else if ((plen = mutt_str_startswith(uh->data, "newsgroups:", CASE_IGNORE)))
365  env->newsgroups = nntp_get_header(uh->data + plen);
366  else if ((plen = mutt_str_startswith(uh->data, "followup-to:", CASE_IGNORE)))
367  env->followup_to = nntp_get_header(uh->data + plen);
368  else if ((plen = mutt_str_startswith(uh->data, "x-comment-to:", CASE_IGNORE)))
369  env->x_comment_to = nntp_get_header(uh->data + plen);
370 #endif
371  }
372 }
373 
378 static void process_user_header(struct Envelope *env)
379 {
380  struct ListNode *uh = NULL;
381  STAILQ_FOREACH(uh, &UserHeader, entries)
382  {
383  size_t plen;
384  if ((plen = mutt_str_startswith(uh->data, "from:", CASE_IGNORE)))
385  {
386  /* User has specified a default From: address. Remove default address */
387  mutt_addrlist_clear(&env->from);
388  mutt_addrlist_parse(&env->from, uh->data + plen);
389  }
390  else if ((plen = mutt_str_startswith(uh->data, "reply-to:", CASE_IGNORE)))
391  {
393  mutt_addrlist_parse(&env->reply_to, uh->data + plen);
394  }
395  else if ((plen = mutt_str_startswith(uh->data, "message-id:", CASE_IGNORE)))
396  {
397  char *tmp = mutt_extract_message_id(uh->data + plen, NULL);
398  if (mutt_addr_valid_msgid(tmp))
399  {
400  FREE(&env->message_id);
401  env->message_id = tmp;
402  }
403  else
404  FREE(&tmp);
405  }
406  else if (!mutt_str_startswith(uh->data, "to:", CASE_IGNORE) &&
407  !mutt_str_startswith(uh->data, "cc:", CASE_IGNORE) &&
408  !mutt_str_startswith(uh->data, "bcc:", CASE_IGNORE) &&
409 #ifdef USE_NNTP
410  !mutt_str_startswith(uh->data, "newsgroups:", CASE_IGNORE) &&
411  !mutt_str_startswith(uh->data, "followup-to:", CASE_IGNORE) &&
412  !mutt_str_startswith(uh->data, "x-comment-to:", CASE_IGNORE) &&
413 #endif
414  !mutt_str_startswith(uh->data, "supersedes:", CASE_IGNORE) &&
415  !mutt_str_startswith(uh->data, "subject:", CASE_IGNORE) &&
416  !mutt_str_startswith(uh->data, "return-path:", CASE_IGNORE))
417  {
419  }
420  }
421 }
422 
429 void mutt_forward_intro(struct Mailbox *m, struct Email *e, FILE *fp)
430 {
431  if (!C_ForwardAttributionIntro || !fp)
432  return;
433 
434  char buf[1024];
435  setlocale(LC_TIME, NONULL(C_AttributionLocale));
436  mutt_make_string(buf, sizeof(buf), 0, C_ForwardAttributionIntro, NULL, m, e);
437  setlocale(LC_TIME, "");
438  fputs(buf, fp);
439  fputs("\n\n", fp);
440 }
441 
448 void mutt_forward_trailer(struct Mailbox *m, struct Email *e, FILE *fp)
449 {
450  if (!C_ForwardAttributionTrailer || !fp)
451  return;
452 
453  char buf[1024];
454  setlocale(LC_TIME, NONULL(C_AttributionLocale));
455  mutt_make_string(buf, sizeof(buf), 0, C_ForwardAttributionTrailer, NULL, m, e);
456  setlocale(LC_TIME, "");
457  fputc('\n', fp);
458  fputs(buf, fp);
459  fputc('\n', fp);
460 }
461 
470 static int include_forward(struct Mailbox *m, struct Email *e, FILE *fp_out)
471 {
472  CopyHeaderFlags chflags = CH_DECODE;
474 
477 
478  if ((WithCrypto != 0) && (e->security & SEC_ENCRYPT) && C_ForwardDecode)
479  {
480  /* make sure we have the user's passphrase before proceeding... */
482  return -1;
483  }
484 
485  mutt_forward_intro(m, e, fp_out);
486 
487  if (C_ForwardDecode)
488  {
489  cmflags |= MUTT_CM_DECODE | MUTT_CM_CHARCONV;
490  if (C_Weed)
491  {
492  chflags |= CH_WEED | CH_REORDER;
493  cmflags |= MUTT_CM_WEED;
494  }
495  }
496  if (C_ForwardQuote)
497  cmflags |= MUTT_CM_PREFIX;
498 
499  mutt_copy_message(fp_out, m, e, cmflags, chflags, 0);
500  mutt_forward_trailer(m, e, fp_out);
501  return 0;
502 }
503 
513 static int inline_forward_attachments(struct Mailbox *m, struct Email *e,
514  struct Body ***plast, int *forwardq)
515 {
516  struct Body **last = *plast;
517  struct Body *body = NULL;
518  struct Message *msg = NULL;
519  struct AttachCtx *actx = NULL;
520  int rc = 0, i;
521 
524 
525  msg = mx_msg_open(m, e->msgno);
526  if (!msg)
527  return -1;
528 
529  actx = mutt_mem_calloc(1, sizeof(*actx));
530  actx->email = e;
531  actx->fp_root = msg->fp;
532 
533  mutt_generate_recvattach_list(actx, actx->email, actx->email->content,
534  actx->fp_root, -1, 0, 0);
535 
536  for (i = 0; i < actx->idxlen; i++)
537  {
538  body = actx->idx[i]->content;
539  if ((body->type != TYPE_MULTIPART) && !mutt_can_decode(body) &&
540  !((body->type == TYPE_APPLICATION) &&
541  ((mutt_str_strcasecmp(body->subtype, "pgp-signature") == 0) ||
542  (mutt_str_strcasecmp(body->subtype, "x-pkcs7-signature") == 0) ||
543  (mutt_str_strcasecmp(body->subtype, "pkcs7-signature") == 0))))
544  {
545  /* Ask the quadoption only once */
546  if (*forwardq == -1)
547  {
549  /* L10N:
550  This is the prompt for $forward_attachments.
551  When inline forwarding ($mime_forward answered "no"), this prompts
552  whether to add non-decodable attachments from the original email.
553  Text/plain parts and the like will already be included in the
554  message contents, but other attachment, such as PDF files, will also
555  be added as attachments to the new mail, if this is answered yes.
556  */
557  _("Forward attachments?"));
558  if (*forwardq != MUTT_YES)
559  {
560  if (*forwardq == -1)
561  rc = -1;
562  goto cleanup;
563  }
564  }
565  if (mutt_body_copy(actx->idx[i]->fp, last, body) == -1)
566  {
567  rc = -1;
568  goto cleanup;
569  }
570  last = &((*last)->next);
571  }
572  }
573 
574 cleanup:
575  *plast = last;
576  mx_msg_close(m, &msg);
577  mutt_actx_free(&actx);
578  return rc;
579 }
580 
590 static int mutt_inline_forward(struct Mailbox *m, struct Email *e_edit,
591  struct Email *e_cur, FILE *out)
592 {
593  int forwardq = -1;
594  struct Body **last = NULL;
595 
596  if (e_cur)
597  include_forward(m, e_cur, out);
598  else
599  {
600  for (int i = 0; i < m->vcount; i++)
601  {
602  struct Email *e = mutt_get_virt_email(m, i);
603  if (!e)
604  continue;
605  if (e->tagged)
606  include_forward(m, e, out);
607  }
608  }
609 
611  {
612  last = &e_edit->content;
613  while (*last)
614  last = &((*last)->next);
615 
616  if (e_cur)
617  {
618  if (inline_forward_attachments(m, e_cur, &last, &forwardq) != 0)
619  return -1;
620  }
621  else
622  {
623  for (int i = 0; i < m->vcount; i++)
624  {
625  struct Email *e = mutt_get_virt_email(m, i);
626  if (!e)
627  continue;
628  if (e->tagged)
629  {
630  if (inline_forward_attachments(m, e, &last, &forwardq) != 0)
631  return -1;
632  if (forwardq == MUTT_NO)
633  break;
634  }
635  }
636  }
637  }
638 
639  return 0;
640 }
641 
648 void mutt_make_attribution(struct Mailbox *m, struct Email *e, FILE *fp_out)
649 {
650  if (!C_Attribution || !fp_out)
651  return;
652 
653  char buf[1024];
654  setlocale(LC_TIME, NONULL(C_AttributionLocale));
655  mutt_make_string(buf, sizeof(buf), 0, C_Attribution, NULL, m, e);
656  setlocale(LC_TIME, "");
657  fputs(buf, fp_out);
658  fputc('\n', fp_out);
659 }
660 
667 void mutt_make_post_indent(struct Mailbox *m, struct Email *e, FILE *fp_out)
668 {
669  if (!C_PostIndentString || !fp_out)
670  return;
671 
672  char buf[256];
673  mutt_make_string(buf, sizeof(buf), 0, C_PostIndentString, NULL, m, e);
674  fputs(buf, fp_out);
675  fputc('\n', fp_out);
676 }
677 
686 static int include_reply(struct Mailbox *m, struct Email *e, FILE *fp_out)
687 {
688  CopyMessageFlags cmflags =
690  CopyHeaderFlags chflags = CH_DECODE;
691 
692  if ((WithCrypto != 0) && (e->security & SEC_ENCRYPT))
693  {
694  /* make sure we have the user's passphrase before proceeding... */
696  return -1;
697  }
698 
701 
702  mutt_make_attribution(m, e, fp_out);
703 
704  if (!C_Header)
705  cmflags |= MUTT_CM_NOHEADER;
706  if (C_Weed)
707  {
708  chflags |= CH_WEED | CH_REORDER;
709  cmflags |= MUTT_CM_WEED;
710  }
711 
712  mutt_copy_message(fp_out, m, e, cmflags, chflags, 0);
713 
714  mutt_make_post_indent(m, e, fp_out);
715 
716  return 0;
717 }
718 
725 static const struct AddressList *choose_default_to(const struct Address *from,
726  const struct Envelope *env)
727 {
728  if (!C_ReplySelf && mutt_addr_is_user(from))
729  {
730  /* mail is from the user, assume replying to recipients */
731  return &env->to;
732  }
733  else
734  {
735  return &env->from;
736  }
737 }
738 
748 static int default_to(struct AddressList *to, struct Envelope *env, SendFlags flags, int hmfupto)
749 {
750  char prompt[256];
751  const struct Address *from = TAILQ_FIRST(&env->from);
752  const struct Address *reply_to = TAILQ_FIRST(&env->reply_to);
753 
754  if (flags && !TAILQ_EMPTY(&env->mail_followup_to) && (hmfupto == MUTT_YES))
755  {
756  mutt_addrlist_copy(to, &env->mail_followup_to, true);
757  return 0;
758  }
759 
760  /* Exit now if we're setting up the default Cc list for list-reply
761  * (only set if Mail-Followup-To is present and honoured). */
762  if (flags & SEND_LIST_REPLY)
763  return 0;
764 
765  const struct AddressList *default_to = choose_default_to(from, env);
766 
767  if (reply_to)
768  {
769  const bool from_is_reply_to = mutt_addr_cmp(from, reply_to);
770  const bool multiple_reply_to =
771  reply_to && TAILQ_NEXT(TAILQ_FIRST(&env->reply_to), entries);
772  if ((from_is_reply_to && !multiple_reply_to && !reply_to->personal) ||
773  (C_IgnoreListReplyTo && mutt_is_mail_list(reply_to) &&
774  (mutt_addrlist_search(&env->to, reply_to) || mutt_addrlist_search(&env->cc, reply_to))))
775  {
776  /* If the Reply-To: address is a mailing list, assume that it was
777  * put there by the mailing list, and use the From: address
778  *
779  * We also take the from header if our correspondent has a reply-to
780  * header which is identical to the electronic mail address given
781  * in his From header, and the reply-to has no display-name. */
782  mutt_addrlist_copy(to, &env->from, false);
783  }
784  else if (!(from_is_reply_to && !multiple_reply_to) && (C_ReplyTo != MUTT_YES))
785  {
786  /* There are quite a few mailing lists which set the Reply-To:
787  * header field to the list address, which makes it quite impossible
788  * to send a message to only the sender of the message. This
789  * provides a way to do that. */
790  /* L10N: Asks whether the user respects the reply-to header.
791  If she says no, neomutt will reply to the from header's address instead. */
792  snprintf(prompt, sizeof(prompt), _("Reply to %s%s?"), reply_to->mailbox,
793  multiple_reply_to ? ",..." : "");
794  switch (query_quadoption(C_ReplyTo, prompt))
795  {
796  case MUTT_YES:
797  mutt_addrlist_copy(to, &env->reply_to, false);
798  break;
799 
800  case MUTT_NO:
801  mutt_addrlist_copy(to, default_to, false);
802  break;
803 
804  default:
805  return -1; /* abort */
806  }
807  }
808  else
809  {
810  mutt_addrlist_copy(to, &env->reply_to, false);
811  }
812  }
813  else
814  {
815  mutt_addrlist_copy(to, default_to, false);
816  }
817 
818  return 0;
819 }
820 
829 int mutt_fetch_recips(struct Envelope *out, struct Envelope *in, SendFlags flags)
830 {
831  enum QuadOption hmfupto = MUTT_ABORT;
832  const struct Address *followup_to = TAILQ_FIRST(&in->mail_followup_to);
833 
834  if ((flags & (SEND_LIST_REPLY | SEND_GROUP_REPLY | SEND_GROUP_CHAT_REPLY)) && followup_to)
835  {
836  char prompt[256];
837  snprintf(prompt, sizeof(prompt), _("Follow-up to %s%s?"), followup_to->mailbox,
838  TAILQ_NEXT(TAILQ_FIRST(&in->mail_followup_to), entries) ? ",..." : "");
839 
840  hmfupto = query_quadoption(C_HonorFollowupTo, prompt);
841  if (hmfupto == MUTT_ABORT)
842  return -1;
843  }
844 
845  if (flags & SEND_LIST_REPLY)
846  {
847  add_mailing_lists(&out->to, &in->to, &in->cc);
848 
849  if (followup_to && (hmfupto == MUTT_YES) &&
850  (default_to(&out->cc, in, flags & SEND_LIST_REPLY, (hmfupto == MUTT_YES)) == MUTT_ABORT))
851  {
852  return -1; /* abort */
853  }
854  }
855  else if (flags & SEND_TO_SENDER)
856  {
857  mutt_addrlist_copy(&out->to, &in->from, false);
858  }
859  else
860  {
861  if (default_to(&out->to, in, flags & (SEND_GROUP_REPLY | SEND_GROUP_CHAT_REPLY),
862  (hmfupto == MUTT_YES)) == -1)
863  return -1; /* abort */
864 
865  if ((flags & (SEND_GROUP_REPLY | SEND_GROUP_CHAT_REPLY)) &&
866  (!followup_to || (hmfupto != MUTT_YES)))
867  {
868  /* if(!mutt_addr_is_user(in->to)) */
869  if (flags & SEND_GROUP_REPLY)
870  mutt_addrlist_copy(&out->cc, &in->to, true);
871  else
872  mutt_addrlist_copy(&out->to, &in->cc, true);
873  mutt_addrlist_copy(&out->cc, &in->cc, true);
874  }
875  }
876  return 0;
877 }
878 
884 static void add_references(struct ListHead *head, struct Envelope *env)
885 {
886  struct ListNode *np = NULL;
887 
888  struct ListHead *src = !STAILQ_EMPTY(&env->references) ? &env->references : &env->in_reply_to;
889  STAILQ_FOREACH(np, src, entries)
890  {
892  }
893 }
894 
900 static void add_message_id(struct ListHead *head, struct Envelope *env)
901 {
902  if (env->message_id)
903  {
905  }
906 }
907 
913 {
914  if (!C_Metoo)
915  {
916  /* the order is important here. do the CC: first so that if the
917  * the user is the only recipient, it ends up on the TO: field */
918  remove_user(&env->cc, TAILQ_EMPTY(&env->to));
919  remove_user(&env->to, TAILQ_EMPTY(&env->cc) || C_ReplySelf);
920  }
921 
922  /* the CC field can get cluttered, especially with lists */
923  mutt_addrlist_dedupe(&env->to);
924  mutt_addrlist_dedupe(&env->cc);
925  mutt_addrlist_remove_xrefs(&env->to, &env->cc);
926 
927  if (!TAILQ_EMPTY(&env->cc) && TAILQ_EMPTY(&env->to))
928  {
929  TAILQ_SWAP(&env->to, &env->cc, Address, entries);
930  }
931 }
932 
939 void mutt_make_forward_subject(struct Envelope *env, struct Mailbox *m, struct Email *e)
940 {
941  if (!env)
942  return;
943 
944  char buf[256];
945 
946  /* set the default subject for the message. */
947  mutt_make_string(buf, sizeof(buf), 0, NONULL(C_ForwardFormat), NULL, m, e);
948  mutt_str_replace(&env->subject, buf);
949 }
950 
956 void mutt_make_misc_reply_headers(struct Envelope *env, struct Envelope *curenv)
957 {
958  if (!env || !curenv)
959  return;
960 
961  /* This takes precedence over a subject that might have
962  * been taken from a List-Post header. Is that correct? */
963  if (curenv->real_subj)
964  {
965  FREE(&env->subject);
966  env->subject = mutt_mem_malloc(mutt_str_strlen(curenv->real_subj) + 5);
967  sprintf(env->subject, "Re: %s", curenv->real_subj);
968  }
969  else if (!env->subject)
971 }
972 
978 void mutt_add_to_reference_headers(struct Envelope *env, struct Envelope *curenv)
979 {
980  add_references(&env->references, curenv);
981  add_message_id(&env->references, curenv);
982  add_message_id(&env->in_reply_to, curenv);
983 
984 #ifdef USE_NNTP
985  if (OptNewsSend && C_XCommentTo && !TAILQ_EMPTY(&curenv->from))
987 #endif
988 }
989 
995 static void make_reference_headers(struct EmailList *el, struct Envelope *env)
996 {
997  if (!el || !env || STAILQ_EMPTY(el))
998  return;
999 
1000  struct EmailNode *en = STAILQ_FIRST(el);
1001  bool single = !STAILQ_NEXT(en, entries);
1002 
1003  if (!single)
1004  {
1005  STAILQ_FOREACH(en, el, entries)
1006  {
1008  }
1009  }
1010  else
1012 
1013  /* if there's more than entry in In-Reply-To (i.e. message has multiple
1014  * parents), don't generate a References: header as it's discouraged by
1015  * RFC2822, sect. 3.6.4 */
1016  if (!single && !STAILQ_EMPTY(&env->in_reply_to) &&
1017  STAILQ_NEXT(STAILQ_FIRST(&env->in_reply_to), entries))
1018  {
1019  mutt_list_free(&env->references);
1020  }
1021 }
1022 
1032 static int envelope_defaults(struct Envelope *env, struct Mailbox *m,
1033  struct EmailList *el, SendFlags flags)
1034 {
1035  if (!el || STAILQ_EMPTY(el))
1036  return -1;
1037 
1038  struct EmailNode *en = STAILQ_FIRST(el);
1039  bool single = !STAILQ_NEXT(en, entries);
1040 
1041  struct Envelope *curenv = en->email->env;
1042  if (!curenv)
1043  return -1;
1044 
1045  if (flags & (SEND_REPLY | SEND_TO_SENDER))
1046  {
1047 #ifdef USE_NNTP
1048  if ((flags & SEND_NEWS))
1049  {
1050  /* in case followup set Newsgroups: with Followup-To: if it present */
1051  if (!env->newsgroups &&
1052  (mutt_str_strcasecmp(curenv->followup_to, "poster") != 0))
1053  {
1054  env->newsgroups = mutt_str_strdup(curenv->followup_to);
1055  }
1056  }
1057  else
1058 #endif
1059  if (!single)
1060  {
1061  STAILQ_FOREACH(en, el, entries)
1062  {
1063  if (mutt_fetch_recips(env, en->email->env, flags) == -1)
1064  return -1;
1065  }
1066  }
1067  else if (mutt_fetch_recips(env, curenv, flags) == -1)
1068  return -1;
1069 
1070  if ((flags & SEND_LIST_REPLY) && TAILQ_EMPTY(&env->to))
1071  {
1072  mutt_error(_("No mailing lists found"));
1073  return -1;
1074  }
1075 
1076  if (flags & SEND_REPLY)
1077  {
1078  mutt_make_misc_reply_headers(env, curenv);
1079  make_reference_headers(el, env);
1080  }
1081  }
1082  else if (flags & SEND_FORWARD)
1083  {
1084  mutt_make_forward_subject(env, m, en->email);
1085  if (C_ForwardReferences)
1086  make_reference_headers(el, env);
1087  }
1088 
1089  return 0;
1090 }
1091 
1102 static int generate_body(FILE *fp_tmp, struct Email *e, SendFlags flags,
1103  struct Mailbox *m, struct EmailList *el)
1104 {
1105  struct Body *tmp = NULL;
1106  struct EmailNode *en = NULL;
1107  bool single = true;
1108 
1109  if (el)
1110  en = STAILQ_FIRST(el);
1111  if (en)
1112  single = !STAILQ_NEXT(en, entries);
1113 
1114  /* An EmailList is required for replying and forwarding */
1115  if (!el && (flags & (SEND_REPLY | SEND_FORWARD)))
1116  return -1;
1117 
1118  if (flags & SEND_REPLY)
1119  {
1120  enum QuadOption ans =
1121  query_quadoption(C_Include, _("Include message in reply?"));
1122  if (ans == MUTT_ABORT)
1123  return -1;
1124 
1125  if (ans == MUTT_YES)
1126  {
1127  mutt_message(_("Including quoted message..."));
1128  if (single && en)
1129  include_reply(m, en->email, fp_tmp);
1130  else
1131  {
1132  STAILQ_FOREACH(en, el, entries)
1133  {
1134  if (include_reply(m, en->email, fp_tmp) == -1)
1135  {
1136  mutt_error(_("Could not include all requested messages"));
1137  return -1;
1138  }
1139  fputc('\n', fp_tmp);
1140  }
1141  }
1142  }
1143  }
1144  else if (flags & SEND_FORWARD)
1145  {
1146  enum QuadOption ans =
1147  query_quadoption(C_MimeForward, _("Forward as attachment?"));
1148  if (ans == MUTT_YES)
1149  {
1150  struct Body *last = e->content;
1151 
1152  mutt_message(_("Preparing forwarded message..."));
1153 
1154  while (last && last->next)
1155  last = last->next;
1156 
1157  if (single && en)
1158  {
1159  tmp = mutt_make_message_attach(m, en->email, false);
1160  if (last)
1161  last->next = tmp;
1162  else
1163  e->content = tmp;
1164  }
1165  else
1166  {
1167  STAILQ_FOREACH(en, el, entries)
1168  {
1169  tmp = mutt_make_message_attach(m, en->email, false);
1170  if (last)
1171  {
1172  last->next = tmp;
1173  last = tmp;
1174  }
1175  else
1176  {
1177  last = tmp;
1178  e->content = tmp;
1179  }
1180  }
1181  }
1182  }
1183  else if ((ans != MUTT_ABORT) && en)
1184  {
1185  if (mutt_inline_forward(m, e, en->email, fp_tmp) != 0)
1186  return -1;
1187  }
1188  else
1189  return -1;
1190  }
1191  /* if (WithCrypto && (flags & SEND_KEY)) */
1192  else if (((WithCrypto & APPLICATION_PGP) != 0) && (flags & SEND_KEY))
1193  {
1194  struct Body *b = NULL;
1195 
1196  if (((WithCrypto & APPLICATION_PGP) != 0) && !(b = crypt_pgp_make_key_attachment()))
1197  {
1198  return -1;
1199  }
1200 
1201  b->next = e->content;
1202  e->content = b;
1203  }
1204 
1205  mutt_clear_error();
1206 
1207  return 0;
1208 }
1209 
1215 {
1216  /* Only generate the Mail-Followup-To if the user has requested it, and
1217  * it hasn't already been set */
1218 
1219  if (!C_FollowupTo)
1220  return;
1221 #ifdef USE_NNTP
1222  if (OptNewsSend)
1223  {
1224  if (!env->followup_to && env->newsgroups && (strrchr(env->newsgroups, ',')))
1225  env->followup_to = mutt_str_strdup(env->newsgroups);
1226  return;
1227  }
1228 #endif
1229 
1230  if (TAILQ_EMPTY(&env->mail_followup_to))
1231  {
1232  if (mutt_is_list_recipient(false, env))
1233  {
1234  /* this message goes to known mailing lists, so create a proper
1235  * mail-followup-to header */
1236 
1237  mutt_addrlist_copy(&env->mail_followup_to, &env->to, false);
1238  mutt_addrlist_copy(&env->mail_followup_to, &env->cc, true);
1239  }
1240 
1241  /* remove ourselves from the mail-followup-to header */
1242  remove_user(&env->mail_followup_to, false);
1243 
1244  /* If we are not subscribed to any of the lists in question, re-add
1245  * ourselves to the mail-followup-to header. The mail-followup-to header
1246  * generated is a no-op with group-reply, but makes sure list-reply has the
1247  * desired effect. */
1248 
1249  if (!TAILQ_EMPTY(&env->mail_followup_to) &&
1250  !mutt_is_subscribed_list_recipient(false, env))
1251  {
1252  struct AddressList *al = NULL;
1253  if (!TAILQ_EMPTY(&env->reply_to))
1254  al = &env->reply_to;
1255  else if (!TAILQ_EMPTY(&env->from))
1256  al = &env->from;
1257 
1258  if (al)
1259  {
1260  struct Address *a = NULL;
1261  TAILQ_FOREACH_REVERSE(a, al, AddressList, entries)
1262  {
1264  }
1265  }
1266  else
1267  {
1269  }
1270  }
1271 
1273  }
1274 }
1275 
1285 static void set_reverse_name(struct AddressList *al, struct Envelope *env)
1286 {
1287  struct Address *a = NULL;
1288  if (TAILQ_EMPTY(al))
1289  {
1290  TAILQ_FOREACH(a, &env->to, entries)
1291  {
1292  if (mutt_addr_is_user(a))
1293  {
1295  break;
1296  }
1297  }
1298  }
1299 
1300  if (TAILQ_EMPTY(al))
1301  {
1302  TAILQ_FOREACH(a, &env->cc, entries)
1303  {
1304  if (mutt_addr_is_user(a))
1305  {
1307  break;
1308  }
1309  }
1310  }
1311 
1312  if (TAILQ_EMPTY(al))
1313  {
1314  struct Address *from = TAILQ_FIRST(&env->from);
1315  if (from && mutt_addr_is_user(from))
1316  {
1318  }
1319  }
1320 
1321  if (!TAILQ_EMPTY(al))
1322  {
1323  /* when $reverse_realname is not set, clear the personal name so that it
1324  * may be set via a reply- or send-hook. */
1325  if (!C_ReverseRealname)
1326  FREE(&TAILQ_FIRST(al)->personal);
1327  }
1328 }
1329 
1335 {
1336  /* Note: We let $from override $realname here.
1337  * Is this the right thing to do?
1338  */
1339 
1340  if (C_From)
1341  {
1342  return mutt_addr_copy(C_From);
1343  }
1344  else if (C_UseDomain)
1345  {
1346  struct Address *addr = mutt_addr_new();
1347  mutt_str_asprintf(&addr->mailbox, "%s@%s", NONULL(Username), NONULL(mutt_fqdn(true)));
1348  return addr;
1349  }
1350  else
1351  {
1352  return mutt_addr_create(NULL, Username);
1353  }
1354 }
1355 
1362 static int send_message(struct Email *e)
1363 {
1364  struct Buffer *tempfile = NULL;
1365  int rc = -1;
1366 #ifdef USE_SMTP
1367  short old_write_bcc;
1368 #endif
1369 
1370  /* Write out the message in MIME form. */
1371  tempfile = mutt_buffer_pool_get();
1372  mutt_buffer_mktemp(tempfile);
1373  FILE *fp_tmp = mutt_file_fopen(mutt_b2s(tempfile), "w");
1374  if (!fp_tmp)
1375  goto cleanup;
1376 
1377 #ifdef USE_SMTP
1378  old_write_bcc = C_WriteBcc;
1379  if (C_SmtpUrl)
1380  C_WriteBcc = false;
1381 #endif
1382 #ifdef MIXMASTER
1384  !STAILQ_EMPTY(&e->chain),
1386 #endif
1387 #ifndef MIXMASTER
1390 #endif
1391 #ifdef USE_SMTP
1392  if (old_write_bcc)
1393  C_WriteBcc = true;
1394 #endif
1395 
1396  fputc('\n', fp_tmp); /* tie off the header. */
1397 
1398  if ((mutt_write_mime_body(e->content, fp_tmp) == -1))
1399  goto cleanup;
1400 
1401  if (mutt_file_fclose(&fp_tmp) != 0)
1402  {
1403  mutt_perror(mutt_b2s(tempfile));
1404  unlink(mutt_b2s(tempfile));
1405  goto cleanup;
1406  }
1407 
1408 #ifdef MIXMASTER
1409  if (!STAILQ_EMPTY(&e->chain))
1410  {
1411  rc = mix_send_message(&e->chain, mutt_b2s(tempfile));
1412  goto cleanup;
1413  }
1414 #endif
1415 
1416 #ifdef USE_NNTP
1417  if (OptNewsSend)
1418  goto sendmail;
1419 #endif
1420 
1421 #ifdef USE_SMTP
1422  if (C_SmtpUrl)
1423  {
1424  rc = mutt_smtp_send(&e->env->from, &e->env->to, &e->env->cc, &e->env->bcc,
1425  mutt_b2s(tempfile), (e->content->encoding == ENC_8BIT));
1426  goto cleanup;
1427  }
1428 #endif
1429 
1430 sendmail:
1431  rc = mutt_invoke_sendmail(&e->env->from, &e->env->to, &e->env->cc, &e->env->bcc,
1432  mutt_b2s(tempfile), (e->content->encoding == ENC_8BIT));
1433 cleanup:
1434  if (fp_tmp)
1435  {
1436  mutt_file_fclose(&fp_tmp);
1437  unlink(mutt_b2s(tempfile));
1438  }
1439  mutt_buffer_pool_release(&tempfile);
1440  return rc;
1441 }
1442 
1448 void mutt_encode_descriptions(struct Body *b, bool recurse)
1449 {
1450  for (struct Body *t = b; t; t = t->next)
1451  {
1452  if (t->description)
1453  {
1454  rfc2047_encode(&t->description, NULL, sizeof("Content-Description:"), C_SendCharset);
1455  }
1456  if (recurse && t->parts)
1457  mutt_encode_descriptions(t->parts, recurse);
1458  }
1459 }
1460 
1465 static void decode_descriptions(struct Body *b)
1466 {
1467  for (struct Body *t = b; t; t = t->next)
1468  {
1469  if (t->description)
1470  {
1471  rfc2047_decode(&t->description);
1472  }
1473  if (t->parts)
1474  decode_descriptions(t->parts);
1475  }
1476 }
1477 
1482 static void fix_end_of_file(const char *data)
1483 {
1484  FILE *fp = mutt_file_fopen(data, "a+");
1485  if (!fp)
1486  return;
1487  if (fseek(fp, -1, SEEK_END) >= 0)
1488  {
1489  int c = fgetc(fp);
1490  if (c != '\n')
1491  fputc('\n', fp);
1492  }
1493  mutt_file_fclose(&fp);
1494 }
1495 
1505 int mutt_resend_message(FILE *fp, struct Context *ctx, struct Email *e_cur)
1506 {
1507  struct Email *e_new = email_new();
1508 
1509  if (mutt_prepare_template(fp, ctx->mailbox, e_new, e_cur, true) < 0)
1510  {
1511  email_free(&e_new);
1512  return -1;
1513  }
1514 
1515  if (WithCrypto)
1516  {
1517  /* mutt_prepare_template doesn't always flip on an application bit.
1518  * so fix that here */
1519  if (!(e_new->security & (APPLICATION_SMIME | APPLICATION_PGP)))
1520  {
1521  if (((WithCrypto & APPLICATION_SMIME) != 0) && C_SmimeIsDefault)
1522  e_new->security |= APPLICATION_SMIME;
1523  else if (WithCrypto & APPLICATION_PGP)
1524  e_new->security |= APPLICATION_PGP;
1525  else
1526  e_new->security |= APPLICATION_SMIME;
1527  }
1528 
1530  {
1531  e_new->security |= SEC_OPPENCRYPT;
1533  }
1534  }
1535 
1536  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
1537  emaillist_add_email(&el, e_cur);
1538  int rc = ci_send_message(SEND_RESEND, e_new, NULL, ctx, &el);
1539  emaillist_clear(&el);
1540 
1541  return rc;
1542 }
1543 
1551 static bool is_reply(struct Email *reply, struct Email *orig)
1552 {
1553  if (!reply || !reply->env || !orig || !orig->env)
1554  return false;
1555  return mutt_list_find(&orig->env->references, reply->env->message_id) ||
1556  mutt_list_find(&orig->env->in_reply_to, reply->env->message_id);
1557 }
1558 
1569 static bool search_attach_keyword(char *filename)
1570 {
1571  /* Search for the regex in C_AbortNoattachRegex within a file */
1572  if (!C_AbortNoattachRegex || !C_AbortNoattachRegex->regex || !C_QuoteRegex ||
1573  !C_QuoteRegex->regex)
1574  {
1575  return false;
1576  }
1577 
1578  FILE *fp_att = mutt_file_fopen(filename, "r");
1579  if (!fp_att)
1580  return false;
1581 
1582  char *inputline = mutt_mem_malloc(1024);
1583  bool found = false;
1584  while (!feof(fp_att))
1585  {
1586  fgets(inputline, 1024, fp_att);
1587  if (!mutt_is_quote_line(inputline, NULL) &&
1588  mutt_regex_match(C_AbortNoattachRegex, inputline))
1589  {
1590  found = true;
1591  break;
1592  }
1593  }
1594  FREE(&inputline);
1595  mutt_file_fclose(&fp_att);
1596  return found;
1597 }
1598 
1610 static int save_fcc(struct Email *e, struct Buffer *fcc, struct Body *clear_content,
1611  char *pgpkeylist, SendFlags flags, char **finalpath)
1612 {
1613  int rc = 0;
1614  struct Body *save_content = NULL;
1615 
1617 
1618  /* Don't save a copy when we are in batch-mode, and the FCC
1619  * folder is on an IMAP server: This would involve possibly lots
1620  * of user interaction, which is not available in batch mode.
1621  *
1622  * Note: A patch to fix the problems with the use of IMAP servers
1623  * from non-curses mode is available from Brendan Cully. However,
1624  * I'd like to think a bit more about this before including it. */
1625 
1626 #ifdef USE_IMAP
1627  if ((flags & SEND_BATCH) && !mutt_buffer_is_empty(fcc) &&
1628  (imap_path_probe(mutt_b2s(fcc), NULL) == MUTT_IMAP))
1629  {
1630  mutt_buffer_reset(fcc);
1631  mutt_error(_("Fcc to an IMAP mailbox is not supported in batch mode"));
1632  return rc;
1633  }
1634 #endif
1635 
1636  if (mutt_buffer_is_empty(fcc) || (mutt_str_strcmp("/dev/null", mutt_b2s(fcc)) == 0))
1637  return rc;
1638 
1639  struct Body *tmpbody = e->content;
1640  struct Body *save_sig = NULL;
1641  struct Body *save_parts = NULL;
1642 
1643  /* Before sending, we don't allow message manipulation because it
1644  * will break message signatures. This is especially complicated by
1645  * Protected Headers. */
1646  if (!C_FccBeforeSend)
1647  {
1648  if ((WithCrypto != 0) && (e->security & (SEC_ENCRYPT | SEC_SIGN | SEC_AUTOCRYPT)) && C_FccClear)
1649  {
1650  e->content = clear_content;
1653  }
1654 
1655  /* check to see if the user wants copies of all attachments */
1656  bool save_atts = true;
1657  if (e->content->type == TYPE_MULTIPART)
1658  {
1659  /* In batch mode, save attachments if the quadoption is yes or ask-yes */
1660  if (flags & SEND_BATCH)
1661  {
1662  if ((C_FccAttach == MUTT_NO) || (C_FccAttach == MUTT_ASKNO))
1663  save_atts = false;
1664  }
1665  else if (query_quadoption(C_FccAttach, _("Save attachments in Fcc?")) != MUTT_YES)
1666  save_atts = false;
1667  }
1668  if (!save_atts)
1669  {
1670  if ((WithCrypto != 0) && (e->security & (SEC_ENCRYPT | SEC_SIGN | SEC_AUTOCRYPT)) &&
1671  ((mutt_str_strcmp(e->content->subtype, "encrypted") == 0) ||
1672  (mutt_str_strcmp(e->content->subtype, "signed") == 0)))
1673  {
1674  if ((clear_content->type == TYPE_MULTIPART) &&
1675  (query_quadoption(C_FccAttach, _("Save attachments in Fcc?")) == MUTT_NO))
1676  {
1677  if (!(e->security & SEC_ENCRYPT) && (e->security & SEC_SIGN))
1678  {
1679  /* save initial signature and attachments */
1680  save_sig = e->content->parts->next;
1681  save_parts = clear_content->parts->next;
1682  }
1683 
1684  /* this means writing only the main part */
1685  e->content = clear_content->parts;
1686 
1687  if (mutt_protect(e, pgpkeylist, false) == -1)
1688  {
1689  /* we can't do much about it at this point, so
1690  * fallback to saving the whole thing to fcc */
1691  e->content = tmpbody;
1692  save_sig = NULL;
1693  goto full_fcc;
1694  }
1695 
1696  save_content = e->content;
1697  }
1698  }
1699  else
1700  {
1701  if (query_quadoption(C_FccAttach, _("Save attachments in Fcc?")) == MUTT_NO)
1702  e->content = e->content->parts;
1703  }
1704  }
1705  }
1706 
1707 full_fcc:
1708  if (e->content)
1709  {
1710  /* update received time so that when storing to a mbox-style folder
1711  * the From_ line contains the current time instead of when the
1712  * message was first postponed. */
1713  e->received = mutt_date_epoch();
1714  rc = mutt_write_multiple_fcc(mutt_b2s(fcc), e, NULL, false, NULL, finalpath);
1715  while (rc && !(flags & SEND_BATCH))
1716  {
1717  mutt_clear_error();
1718  int choice = mutt_multi_choice(
1719  /* L10N: Called when saving to $record or Fcc failed after sending.
1720  (r)etry tries the same mailbox again.
1721  alternate (m)ailbox prompts for a different mailbox to try.
1722  (s)kip aborts saving. */
1723  _("Fcc failed. (r)etry, alternate (m)ailbox, or (s)kip?"),
1724  /* L10N: These correspond to the "Fcc failed" multi-choice prompt
1725  (r)etry, alternate (m)ailbox, or (s)kip.
1726  Any similarity to famous leaders of the FSF is coincidental. */
1727  _("rms"));
1728  switch (choice)
1729  {
1730  case 2: /* alternate (m)ailbox */
1731  /* L10N: This is the prompt to enter an "alternate (m)ailbox" when the
1732  initial Fcc fails. */
1733  rc = mutt_buffer_enter_fname(_("Fcc mailbox"), fcc, true);
1734  if ((rc == -1) || mutt_buffer_is_empty(fcc))
1735  {
1736  rc = 0;
1737  break;
1738  }
1739  /* fall through */
1740 
1741  case 1: /* (r)etry */
1742  rc = mutt_write_multiple_fcc(mutt_b2s(fcc), e, NULL, false, NULL, finalpath);
1743  break;
1744 
1745  case -1: /* abort */
1746  case 3: /* (s)kip */
1747  rc = 0;
1748  break;
1749  }
1750  }
1751  }
1752 
1753  if (!C_FccBeforeSend)
1754  {
1755  e->content = tmpbody;
1756 
1757  if ((WithCrypto != 0) && save_sig)
1758  {
1759  /* cleanup the second signature structures */
1760  if (save_content->parts)
1761  {
1762  mutt_body_free(&save_content->parts->next);
1763  save_content->parts = NULL;
1764  }
1765  mutt_body_free(&save_content);
1766 
1767  /* restore old signature and attachments */
1768  e->content->parts->next = save_sig;
1769  e->content->parts->parts->next = save_parts;
1770  }
1771  else if ((WithCrypto != 0) && save_content)
1772  {
1773  /* destroy the new encrypted body. */
1774  mutt_body_free(&save_content);
1775  }
1776  }
1777 
1778  return 0;
1779 }
1780 
1790 static int postpone_message(struct Email *e_post, struct Email *e_cur,
1791  const char *fcc, SendFlags flags)
1792 {
1793  char *pgpkeylist = NULL;
1794  char *encrypt_as = NULL;
1795  struct Body *clear_content = NULL;
1796 
1797  if (!C_Postponed)
1798  {
1799  mutt_error(_("Can't postpone. $postponed is unset"));
1800  return -1;
1801  }
1802 
1803  if (e_post->content->next)
1804  e_post->content = mutt_make_multipart(e_post->content);
1805 
1806  mutt_encode_descriptions(e_post->content, true);
1807 
1808  if ((WithCrypto != 0) && C_PostponeEncrypt &&
1809  (e_post->security & (SEC_ENCRYPT | SEC_AUTOCRYPT)))
1810  {
1811  if (((WithCrypto & APPLICATION_PGP) != 0) && (e_post->security & APPLICATION_PGP))
1812  encrypt_as = C_PgpDefaultKey;
1813  else if (((WithCrypto & APPLICATION_SMIME) != 0) && (e_post->security & APPLICATION_SMIME))
1814  encrypt_as = C_SmimeDefaultKey;
1815  if (!encrypt_as)
1816  encrypt_as = C_PostponeEncryptAs;
1817 
1818 #ifdef USE_AUTOCRYPT
1819  if (e_post->security & SEC_AUTOCRYPT)
1820  {
1822  {
1823  e_post->content = mutt_remove_multipart(e_post->content);
1824  decode_descriptions(e_post->content);
1825  return -1;
1826  }
1827  encrypt_as = AutocryptDefaultKey;
1828  }
1829 #endif
1830 
1831  if (encrypt_as)
1832  {
1833  pgpkeylist = mutt_str_strdup(encrypt_as);
1834  clear_content = e_post->content;
1835  if (mutt_protect(e_post, pgpkeylist, true) == -1)
1836  {
1837  FREE(&pgpkeylist);
1838  e_post->content = mutt_remove_multipart(e_post->content);
1839  decode_descriptions(e_post->content);
1840  return -1;
1841  }
1842 
1843  FREE(&pgpkeylist);
1844 
1845  mutt_encode_descriptions(e_post->content, false);
1846  }
1847  }
1848 
1849  /* make sure the message is written to the right part of a maildir
1850  * postponed folder. */
1851  e_post->read = false;
1852  e_post->old = false;
1853 
1854  mutt_prepare_envelope(e_post->env, false);
1855  mutt_env_to_intl(e_post->env, NULL, NULL); /* Handle bad IDNAs the next time. */
1856 
1857  if (mutt_write_fcc(NONULL(C_Postponed), e_post,
1858  (e_cur && (flags & SEND_REPLY)) ? e_cur->env->message_id : NULL,
1859  true, fcc, NULL) < 0)
1860  {
1861  if (clear_content)
1862  {
1863  mutt_body_free(&e_post->content);
1864  e_post->content = clear_content;
1865  }
1866  mutt_env_free(&e_post->content->mime_headers); /* protected headers */
1867  e_post->content = mutt_remove_multipart(e_post->content);
1868  decode_descriptions(e_post->content);
1869  mutt_unprepare_envelope(e_post->env);
1870  return -1;
1871  }
1872 
1874 
1875  if (clear_content)
1876  mutt_body_free(&clear_content);
1877 
1878  return 0;
1879 }
1880 
1892 int ci_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile,
1893  struct Context *ctx, struct EmailList *el)
1894 {
1895  char buf[1024];
1896  struct Buffer fcc = mutt_buffer_make(0); /* where to copy this message */
1897  FILE *fp_tmp = NULL;
1898  struct Body *pbody = NULL;
1899  int i;
1900  bool free_clear_content = false;
1901 
1902  struct Body *clear_content = NULL;
1903  char *pgpkeylist = NULL;
1904  /* save current value of "pgp_sign_as" and "smime_default_key" */
1905  char *pgp_signas = NULL;
1906  char *smime_signas = NULL;
1907  const char *tag = NULL;
1908  char *err = NULL;
1909  char *ctype = NULL;
1910  char *finalpath = NULL;
1911  struct EmailNode *en = NULL;
1912  struct Email *e_cur = NULL;
1913 
1914  if (el)
1915  en = STAILQ_FIRST(el);
1916  if (en)
1917  e_cur = STAILQ_NEXT(en, entries) ? NULL : en->email;
1918 
1919  int rc = -1;
1920 
1921 #ifdef USE_NNTP
1922  if (flags & SEND_NEWS)
1923  OptNewsSend = true;
1924  else
1925  OptNewsSend = false;
1926 #endif
1927 
1928  if (!flags && !e_templ && (C_Recall != MUTT_NO) &&
1929  mutt_num_postponed(ctx ? ctx->mailbox : NULL, true))
1930  {
1931  /* If the user is composing a new message, check to see if there
1932  * are any postponed messages first. */
1933  enum QuadOption ans =
1934  query_quadoption(C_Recall, _("Recall postponed message?"));
1935  if (ans == MUTT_ABORT)
1936  return rc;
1937 
1938  if (ans == MUTT_YES)
1939  flags |= SEND_POSTPONED;
1940  }
1941 
1942  /* Allocate the buffer due to the long lifetime, but
1943  * pre-resize it to ensure there are no NULL data field issues */
1944  mutt_buffer_alloc(&fcc, 1024);
1945 
1946  if (flags & SEND_POSTPONED)
1947  {
1949  pgp_signas = mutt_str_strdup(C_PgpSignAs);
1951  smime_signas = mutt_str_strdup(C_SmimeSignAs);
1952  }
1953 
1954  /* Delay expansion of aliases until absolutely necessary--shouldn't
1955  * be necessary unless we are prompting the user or about to execute a
1956  * send-hook. */
1957 
1958  if (!e_templ)
1959  {
1960  e_templ = email_new();
1961 
1962  if (flags == SEND_POSTPONED)
1963  {
1964  rc = mutt_get_postponed(ctx, e_templ, &e_cur, &fcc);
1965  if (rc < 0)
1966  {
1967  flags = SEND_POSTPONED;
1968  goto cleanup;
1969  }
1970  flags = rc;
1971 #ifdef USE_NNTP
1972  /* If postponed message is a news article, it have
1973  * a "Newsgroups:" header line, then set appropriate flag. */
1974  if (e_templ->env->newsgroups)
1975  {
1976  flags |= SEND_NEWS;
1977  OptNewsSend = true;
1978  }
1979  else
1980  {
1981  flags &= ~SEND_NEWS;
1982  OptNewsSend = false;
1983  }
1984 #endif
1985  }
1986 
1987  if (flags & (SEND_POSTPONED | SEND_RESEND))
1988  {
1989  fp_tmp = mutt_file_fopen(e_templ->content->filename, "a+");
1990  if (!fp_tmp)
1991  {
1992  mutt_perror(e_templ->content->filename);
1993  goto cleanup;
1994  }
1995  }
1996 
1997  if (!e_templ->env)
1998  e_templ->env = mutt_env_new();
1999  }
2000 
2001  /* Parse and use an eventual list-post header */
2002  if ((flags & SEND_LIST_REPLY) && e_cur && e_cur->env && e_cur->env->list_post)
2003  {
2004  /* Use any list-post header as a template */
2005  mutt_parse_mailto(e_templ->env, NULL, e_cur->env->list_post);
2006  /* We don't let them set the sender's address. */
2007  mutt_addrlist_clear(&e_templ->env->from);
2008  }
2009 
2010  if (!(flags & (SEND_KEY | SEND_POSTPONED | SEND_RESEND)))
2011  {
2012  /* When SEND_DRAFT_FILE is set, the caller has already
2013  * created the "parent" body structure. */
2014  if (!(flags & SEND_DRAFT_FILE))
2015  {
2016  pbody = mutt_body_new();
2017  pbody->next = e_templ->content; /* don't kill command-line attachments */
2018  e_templ->content = pbody;
2019 
2020  ctype = mutt_str_strdup(C_ContentType);
2021  if (!ctype)
2022  ctype = mutt_str_strdup("text/plain");
2023  mutt_parse_content_type(ctype, e_templ->content);
2024  FREE(&ctype);
2025  e_templ->content->unlink = true;
2026  e_templ->content->use_disp = false;
2027  e_templ->content->disposition = DISP_INLINE;
2028 
2029  if (tempfile)
2030  {
2031  fp_tmp = mutt_file_fopen(tempfile, "a+");
2032  e_templ->content->filename = mutt_str_strdup(tempfile);
2033  }
2034  else
2035  {
2036  mutt_mktemp(buf, sizeof(buf));
2037  fp_tmp = mutt_file_fopen(buf, "w+");
2038  e_templ->content->filename = mutt_str_strdup(buf);
2039  }
2040  }
2041  else
2042  fp_tmp = mutt_file_fopen(e_templ->content->filename, "a+");
2043 
2044  if (!fp_tmp)
2045  {
2046  mutt_debug(LL_DEBUG1, "can't create tempfile %s (errno=%d)\n",
2047  e_templ->content->filename, errno);
2048  mutt_perror(e_templ->content->filename);
2049  goto cleanup;
2050  }
2051  }
2052 
2053  /* this is handled here so that the user can match ~f in send-hook */
2054  if (e_cur && C_ReverseName && !(flags & (SEND_POSTPONED | SEND_RESEND)))
2055  {
2056  /* We shouldn't have to worry about alias expansion here since we are
2057  * either replying to a real or postponed message, therefore no aliases
2058  * should exist since the user has not had the opportunity to add
2059  * addresses to the list. We just have to ensure the postponed messages
2060  * have their aliases expanded. */
2061 
2062  if (!TAILQ_EMPTY(&e_templ->env->from))
2063  {
2064  mutt_debug(LL_DEBUG5, "e_templ->env->from before set_reverse_name: %s\n",
2065  TAILQ_FIRST(&e_templ->env->from)->mailbox);
2066  mutt_addrlist_clear(&e_templ->env->from);
2067  }
2068  set_reverse_name(&e_templ->env->from, e_cur->env);
2069  }
2070  if (e_cur && C_ReplyWithXorig && !(flags & (SEND_POSTPONED | SEND_RESEND | SEND_FORWARD)))
2071  {
2072  /* We shouldn't have to worry about freeing 'e_templ->env->from' before
2073  * setting it here since this code will only execute when doing some
2074  * sort of reply. The pointer will only be set when using the -H command
2075  * line option.
2076  *
2077  * If there is already a from address recorded in 'e_templ->env->from',
2078  * then it theoretically comes from C_ReverseName handling, and we don't use
2079  * the 'X-Orig-To header'. */
2080  if (!TAILQ_EMPTY(&e_cur->env->x_original_to) && TAILQ_EMPTY(&e_templ->env->from))
2081  {
2082  mutt_addrlist_copy(&e_templ->env->from, &e_cur->env->x_original_to, false);
2083  mutt_debug(LL_DEBUG5, "e_templ->env->from extracted from X-Original-To: header: %s\n",
2084  TAILQ_FIRST(&e_templ->env->from)->mailbox);
2085  }
2086  }
2087 
2088  if (!(flags & (SEND_POSTPONED | SEND_RESEND)) &&
2089  !((flags & SEND_DRAFT_FILE) && C_ResumeDraftFiles))
2090  {
2091  if ((flags & (SEND_REPLY | SEND_FORWARD | SEND_TO_SENDER)) && ctx &&
2092  (envelope_defaults(e_templ->env, ctx->mailbox, el, flags) == -1))
2093  {
2094  goto cleanup;
2095  }
2096 
2097  if (C_Hdrs)
2098  process_user_recips(e_templ->env);
2099 
2100  /* Expand aliases and remove duplicates/crossrefs */
2101  mutt_expand_aliases_env(e_templ->env);
2102 
2103  if (flags & SEND_REPLY)
2104  mutt_fix_reply_recipients(e_templ->env);
2105 
2106 #ifdef USE_NNTP
2107  if ((flags & SEND_NEWS) && ctx && (ctx->mailbox->magic == MUTT_NNTP) &&
2108  !e_templ->env->newsgroups)
2109  {
2110  e_templ->env->newsgroups =
2111  mutt_str_strdup(((struct NntpMboxData *) ctx->mailbox->mdata)->group);
2112  }
2113 #endif
2114 
2115  if (!(flags & (SEND_MAILX | SEND_BATCH)) &&
2116  !(C_Autoedit && C_EditHeaders) && !((flags & SEND_REPLY) && C_FastReply))
2117  {
2118  if (edit_envelope(e_templ->env, flags) == -1)
2119  goto cleanup;
2120  }
2121 
2122  /* the from address must be set here regardless of whether or not
2123  * $use_from is set so that the '~P' (from you) operator in send-hook
2124  * patterns will work. if $use_from is unset, the from address is killed
2125  * after send-hooks are evaluated */
2126 
2127  const bool killfrom = TAILQ_EMPTY(&e_templ->env->from);
2128  if (killfrom)
2129  {
2131  }
2132 
2133  if ((flags & SEND_REPLY) && e_cur)
2134  {
2135  /* change setting based upon message we are replying to */
2136  mutt_message_hook(ctx ? ctx->mailbox : NULL, e_cur, MUTT_REPLY_HOOK);
2137 
2138  /* set the replied flag for the message we are generating so that the
2139  * user can use ~Q in a send-hook to know when reply-hook's are also
2140  * being used. */
2141  e_templ->replied = true;
2142  }
2143 
2144  /* change settings based upon recipients */
2145 
2146  mutt_message_hook(NULL, e_templ, MUTT_SEND_HOOK);
2147 
2148  /* Unset the replied flag from the message we are composing since it is
2149  * no longer required. This is done here because the FCC'd copy of
2150  * this message was erroneously get the 'R'eplied flag when stored in
2151  * a maildir-style mailbox. */
2152  e_templ->replied = false;
2153 
2154  /* $use_from and/or $from might have changed in a send-hook */
2155  if (killfrom)
2156  {
2157  mutt_addrlist_clear(&e_templ->env->from);
2158  if (C_UseFrom && !(flags & (SEND_POSTPONED | SEND_RESEND)))
2160  }
2161 
2162  if (C_Hdrs)
2163  process_user_header(e_templ->env);
2164 
2165  if (flags & SEND_BATCH)
2166  mutt_file_copy_stream(stdin, fp_tmp);
2167 
2168  if (C_SigOnTop && !(flags & (SEND_MAILX | SEND_KEY | SEND_BATCH)) &&
2169  C_Editor && (mutt_str_strcmp(C_Editor, "builtin") != 0))
2170  {
2171  append_signature(fp_tmp);
2172  }
2173 
2174  /* include replies/forwarded messages, unless we are given a template */
2175  if (!tempfile && (ctx || !(flags & (SEND_REPLY | SEND_FORWARD))) &&
2176  (generate_body(fp_tmp, e_templ, flags, ctx ? ctx->mailbox : NULL, el) == -1))
2177  {
2178  goto cleanup;
2179  }
2180 
2181  if (!C_SigOnTop && !(flags & (SEND_MAILX | SEND_KEY | SEND_BATCH)) &&
2182  C_Editor && (mutt_str_strcmp(C_Editor, "builtin") != 0))
2183  {
2184  append_signature(fp_tmp);
2185  }
2186  }
2187 
2188  /* Only set format=flowed for new messages. postponed/resent/draftfiles
2189  * should respect the original email.
2190  *
2191  * This is set here so that send-hook can be used to turn the option on. */
2192  if (!(flags & (SEND_KEY | SEND_POSTPONED | SEND_RESEND | SEND_DRAFT_FILE)))
2193  {
2194  if (C_TextFlowed && (e_templ->content->type == TYPE_TEXT) &&
2195  (mutt_str_strcasecmp(e_templ->content->subtype, "plain") == 0))
2196  {
2197  mutt_param_set(&e_templ->content->parameter, "format", "flowed");
2198  }
2199  }
2200 
2201  /* This hook is even called for postponed messages, and can, e.g., be
2202  * used for setting the editor, the sendmail path, or the
2203  * envelope sender. */
2204  mutt_message_hook(NULL, e_templ, MUTT_SEND2_HOOK);
2205 
2206  /* wait until now to set the real name portion of our return address so
2207  * that $realname can be set in a send-hook */
2208  {
2209  struct Address *from = TAILQ_FIRST(&e_templ->env->from);
2210  if (from && !from->personal && !(flags & (SEND_RESEND | SEND_POSTPONED)))
2212  }
2213 
2214  if (!(((WithCrypto & APPLICATION_PGP) != 0) && (flags & SEND_KEY)))
2215  mutt_file_fclose(&fp_tmp);
2216 
2217  if (flags & SEND_MAILX)
2218  {
2219  if (mutt_builtin_editor(e_templ->content->filename, e_templ, e_cur) == -1)
2220  goto cleanup;
2221  }
2222  else if (!(flags & SEND_BATCH))
2223  {
2224  struct stat st;
2225  time_t mtime = mutt_file_decrease_mtime(e_templ->content->filename, NULL);
2226 
2227  mutt_update_encoding(e_templ->content);
2228 
2229  /* Select whether or not the user's editor should be called now. We
2230  * don't want to do this when:
2231  * 1) we are sending a key/cert
2232  * 2) we are forwarding a message and the user doesn't want to edit it.
2233  * This is controlled by the quadoption $forward_edit. However, if
2234  * both $edit_headers and $autoedit are set, we want to ignore the
2235  * setting of $forward_edit because the user probably needs to add the
2236  * recipients. */
2237  if (!(flags & SEND_KEY) &&
2238  (((flags & SEND_FORWARD) == 0) || (C_EditHeaders && C_Autoedit) ||
2239  (query_quadoption(C_ForwardEdit, _("Edit forwarded message?")) == MUTT_YES)))
2240  {
2241  /* If the this isn't a text message, look for a mailcap edit command */
2242  if (mutt_needs_mailcap(e_templ->content))
2243  {
2244  if (!mutt_edit_attachment(e_templ->content))
2245  goto cleanup;
2246  }
2247  else if (!C_Editor || (mutt_str_strcmp("builtin", C_Editor) == 0))
2248  mutt_builtin_editor(e_templ->content->filename, e_templ, e_cur);
2249  else if (C_EditHeaders)
2250  {
2251  mutt_env_to_local(e_templ->env);
2252  mutt_edit_headers(C_Editor, e_templ->content->filename, e_templ, &fcc);
2253  mutt_env_to_intl(e_templ->env, NULL, NULL);
2254  }
2255  else
2256  {
2258  if (stat(e_templ->content->filename, &st) == 0)
2259  {
2260  if (mtime != st.st_mtime)
2261  fix_end_of_file(e_templ->content->filename);
2262  }
2263  else
2264  mutt_perror(e_templ->content->filename);
2265  }
2266 
2267  mutt_message_hook(NULL, e_templ, MUTT_SEND2_HOOK);
2268  }
2269 
2270  if (!(flags & (SEND_POSTPONED | SEND_FORWARD | SEND_KEY | SEND_RESEND | SEND_DRAFT_FILE)))
2271  {
2272  if (stat(e_templ->content->filename, &st) == 0)
2273  {
2274  /* if the file was not modified, bail out now */
2275  if ((mtime == st.st_mtime) && !e_templ->content->next &&
2277  _("Abort unmodified message?")) == MUTT_YES))
2278  {
2279  mutt_message(_("Aborted unmodified message"));
2280  goto cleanup;
2281  }
2282  }
2283  else
2284  mutt_perror(e_templ->content->filename);
2285  }
2286  }
2287 
2288  /* Set the message security unless:
2289  * 1) crypto support is not enabled (WithCrypto==0)
2290  * 2) pgp: header field was present during message editing with $edit_headers (e_templ->security != 0)
2291  * 3) we are resending a message
2292  * 4) we are recalling a postponed message (don't override the user's saved settings)
2293  * 5) we are in mailx mode
2294  * 6) we are in batch mode
2295  *
2296  * This is done after allowing the user to edit the message so that security
2297  * settings can be configured with send2-hook and $edit_headers. */
2298  if ((WithCrypto != 0) && (e_templ->security == 0) &&
2299  !(flags & (SEND_BATCH | SEND_MAILX | SEND_POSTPONED | SEND_RESEND)))
2300  {
2301  if (
2302 #ifdef USE_AUTOCRYPT
2304 #else
2305  0
2306 #endif
2307  && e_cur && (e_cur->security & SEC_AUTOCRYPT))
2308  {
2310  }
2311  else
2312  {
2313  if (C_CryptAutosign)
2314  e_templ->security |= SEC_SIGN;
2315  if (C_CryptAutoencrypt)
2316  e_templ->security |= SEC_ENCRYPT;
2317  if (C_CryptReplyencrypt && e_cur && (e_cur->security & SEC_ENCRYPT))
2318  e_templ->security |= SEC_ENCRYPT;
2319  if (C_CryptReplysign && e_cur && (e_cur->security & SEC_SIGN))
2320  e_templ->security |= SEC_SIGN;
2321  if (C_CryptReplysignencrypted && e_cur && (e_cur->security & SEC_ENCRYPT))
2322  e_templ->security |= SEC_SIGN;
2323  if (((WithCrypto & APPLICATION_PGP) != 0) &&
2325  {
2326  if (C_PgpAutoinline)
2327  e_templ->security |= SEC_INLINE;
2328  if (C_PgpReplyinline && e_cur && (e_cur->security & SEC_INLINE))
2329  e_templ->security |= SEC_INLINE;
2330  }
2331  }
2332 
2333  if (e_templ->security || C_CryptOpportunisticEncrypt)
2334  {
2335  /* When replying / forwarding, use the original message's
2336  * crypto system. According to the documentation,
2337  * smime_is_default should be disregarded here.
2338  *
2339  * Problem: At least with forwarding, this doesn't really
2340  * make much sense. Should we have an option to completely
2341  * disable individual mechanisms at run-time? */
2342  if (e_cur)
2343  {
2344  if (((WithCrypto & APPLICATION_PGP) != 0) && C_CryptAutopgp &&
2345  (e_cur->security & APPLICATION_PGP))
2346  {
2347  e_templ->security |= APPLICATION_PGP;
2348  }
2349  else if (((WithCrypto & APPLICATION_SMIME) != 0) && C_CryptAutosmime &&
2350  (e_cur->security & APPLICATION_SMIME))
2351  {
2352  e_templ->security |= APPLICATION_SMIME;
2353  }
2354  }
2355 
2356  /* No crypto mechanism selected? Use availability + smime_is_default
2357  * for the decision. */
2358  if (!(e_templ->security & (APPLICATION_SMIME | APPLICATION_PGP)))
2359  {
2361  {
2362  e_templ->security |= APPLICATION_SMIME;
2363  }
2364  else if (((WithCrypto & APPLICATION_PGP) != 0) && C_CryptAutopgp)
2365  {
2366  e_templ->security |= APPLICATION_PGP;
2367  }
2368  else if (((WithCrypto & APPLICATION_SMIME) != 0) && C_CryptAutosmime)
2369  {
2370  e_templ->security |= APPLICATION_SMIME;
2371  }
2372  }
2373  }
2374 
2375  /* opportunistic encrypt relies on SMIME or PGP already being selected */
2377  {
2378  /* If something has already enabled encryption, e.g. C_CryptAutoencrypt
2379  * or C_CryptReplyencrypt, then don't enable opportunistic encrypt for
2380  * the message. */
2381  if (!(e_templ->security & (SEC_ENCRYPT | SEC_AUTOCRYPT)))
2382  {
2383  e_templ->security |= SEC_OPPENCRYPT;
2384  crypt_opportunistic_encrypt(e_templ);
2385  }
2386  }
2387 
2388  /* No permissible mechanisms found. Don't sign or encrypt. */
2389  if (!(e_templ->security & (APPLICATION_SMIME | APPLICATION_PGP)))
2390  e_templ->security = SEC_NO_FLAGS;
2391  }
2392 
2393  /* Deal with the corner case where the crypto module backend is not available.
2394  * This can happen if configured without pgp/smime and with gpgme, but
2395  * $crypt_use_gpgme is unset. */
2396  if (e_templ->security && !crypt_has_module_backend(e_templ->security))
2397  {
2398  mutt_error(_(
2399  "No crypto backend configured. Disabling message security setting."));
2400  e_templ->security = SEC_NO_FLAGS;
2401  }
2402 
2403  /* specify a default fcc. if we are in batchmode, only save a copy of
2404  * the message if the value of $copy is yes or ask-yes */
2405 
2406  if (mutt_buffer_is_empty(&fcc) && !(flags & SEND_POSTPONED_FCC) &&
2407  (!(flags & SEND_BATCH) || (C_Copy & 0x1)))
2408  {
2409  /* set the default FCC */
2410  const bool killfrom = TAILQ_EMPTY(&e_templ->env->from);
2411  if (killfrom)
2412  {
2414  }
2415  mutt_select_fcc(&fcc, e_templ);
2416  if (killfrom)
2417  {
2418  mutt_addrlist_clear(&e_templ->env->from);
2419  }
2420  }
2421 
2422  mutt_rfc3676_space_stuff(e_templ);
2423 
2424  mutt_update_encoding(e_templ->content);
2425 
2426  if (!(flags & (SEND_MAILX | SEND_BATCH)))
2427  {
2428  main_loop:
2429 
2431  i = mutt_compose_menu(e_templ, &fcc, e_cur,
2433  if (i == -1)
2434  {
2435 /* abort */
2436 #ifdef USE_NNTP
2437  if (flags & SEND_NEWS)
2438  mutt_message(_("Article not posted"));
2439  else
2440 #endif
2441  mutt_message(_("Mail not sent"));
2442  goto cleanup;
2443  }
2444  else if (i == 1)
2445  {
2446  if (postpone_message(e_templ, e_cur, mutt_b2s(&fcc), flags) != 0)
2447  goto main_loop;
2448  mutt_message(_("Message postponed"));
2449  rc = 1;
2450  goto cleanup;
2451  }
2452  }
2453 
2454 #ifdef USE_NNTP
2455  if (!(flags & SEND_NEWS))
2456 #endif
2457  if ((mutt_addrlist_count_recips(&e_templ->env->to) == 0) &&
2458  (mutt_addrlist_count_recips(&e_templ->env->cc) == 0) &&
2459  (mutt_addrlist_count_recips(&e_templ->env->bcc) == 0))
2460  {
2461  if (flags & SEND_BATCH)
2462  {
2463  puts(_("No recipients specified"));
2464  goto cleanup;
2465  }
2466 
2467  mutt_error(_("No recipients specified"));
2468  goto main_loop;
2469  }
2470 
2471  if (mutt_env_to_intl(e_templ->env, &tag, &err))
2472  {
2473  mutt_error(_("Bad IDN in '%s': '%s'"), tag, err);
2474  FREE(&err);
2475  if (flags & SEND_BATCH)
2476  goto cleanup;
2477  goto main_loop;
2478  }
2479 
2480  if (!e_templ->env->subject && !(flags & SEND_BATCH) &&
2481  (query_quadoption(C_AbortNosubject, _("No subject, abort sending?")) != MUTT_NO))
2482  {
2483  /* if the abort is automatic, print an error message */
2484  if (C_AbortNosubject == MUTT_YES)
2485  mutt_error(_("No subject specified"));
2486  goto main_loop;
2487  }
2488 #ifdef USE_NNTP
2489  if ((flags & SEND_NEWS) && !e_templ->env->subject)
2490  {
2491  mutt_error(_("No subject specified"));
2492  goto main_loop;
2493  }
2494 
2495  if ((flags & SEND_NEWS) && !e_templ->env->newsgroups)
2496  {
2497  mutt_error(_("No newsgroup specified"));
2498  goto main_loop;
2499  }
2500 #endif
2501 
2502  if (!(flags & SEND_BATCH) && (C_AbortNoattach != MUTT_NO) &&
2503  !e_templ->content->next && (e_templ->content->type == TYPE_TEXT) &&
2504  (mutt_str_strcasecmp(e_templ->content->subtype, "plain") == 0) &&
2505  search_attach_keyword(e_templ->content->filename) &&
2507  _("No attachments, cancel sending?")) != MUTT_NO))
2508  {
2509  /* if the abort is automatic, print an error message */
2510  if (C_AbortNoattach == MUTT_YES)
2511  {
2512  mutt_error(_("Message contains text matching "
2513  "\"$abort_noattach_regex\". Not sending."));
2514  }
2515  goto main_loop;
2516  }
2517 
2518  if (e_templ->content->next)
2519  e_templ->content = mutt_make_multipart(e_templ->content);
2520 
2521  /* Ok, we need to do it this way instead of handling all fcc stuff in
2522  * one place in order to avoid going to main_loop with encoded "env"
2523  * in case of error. Ugh. */
2524 
2525  mutt_encode_descriptions(e_templ->content, true);
2526 
2527  /* Make sure that clear_content and free_clear_content are
2528  * properly initialized -- we may visit this particular place in
2529  * the code multiple times, including after a failed call to
2530  * mutt_protect(). */
2531 
2532  clear_content = NULL;
2533  free_clear_content = false;
2534 
2535  if (WithCrypto)
2536  {
2537  if (e_templ->security & (SEC_ENCRYPT | SEC_SIGN | SEC_AUTOCRYPT))
2538  {
2539  /* save the decrypted attachments */
2540  clear_content = e_templ->content;
2541 
2542  if ((crypt_get_keys(e_templ, &pgpkeylist, 0) == -1) ||
2543  (mutt_protect(e_templ, pgpkeylist, false) == -1))
2544  {
2545  e_templ->content = mutt_remove_multipart(e_templ->content);
2546 
2547  FREE(&pgpkeylist);
2548 
2549  decode_descriptions(e_templ->content);
2550  goto main_loop;
2551  }
2552  mutt_encode_descriptions(e_templ->content, false);
2553  }
2554 
2555  /* at this point, e_templ->content is one of the following three things:
2556  * - multipart/signed. In this case, clear_content is a child
2557  * - multipart/encrypted. In this case, clear_content exists independently
2558  * - application/pgp. In this case, clear_content exists independently
2559  * - something else. In this case, it's the same as clear_content
2560  */
2561 
2562  /* This is ugly -- lack of "reporting back" from mutt_protect(). */
2563 
2564  if (clear_content && (e_templ->content != clear_content) &&
2565  (e_templ->content->parts != clear_content))
2566  free_clear_content = true;
2567  }
2568 
2569  if (!OptNoCurses && !(flags & SEND_MAILX))
2570  mutt_message(_("Sending message..."));
2571 
2572  mutt_prepare_envelope(e_templ->env, true);
2573 
2574  if (C_FccBeforeSend)
2575  save_fcc(e_templ, &fcc, clear_content, pgpkeylist, flags, &finalpath);
2576 
2577  i = send_message(e_templ);
2578  if (i < 0)
2579  {
2580  if (!(flags & SEND_BATCH))
2581  {
2582  if (!WithCrypto)
2583  ;
2584  else if ((e_templ->security & (SEC_ENCRYPT | SEC_AUTOCRYPT)) ||
2585  ((e_templ->security & SEC_SIGN) && (e_templ->content->type == TYPE_APPLICATION)))
2586  {
2587  if (e_templ->content != clear_content)
2588  {
2589  mutt_body_free(&e_templ->content); /* destroy PGP data */
2590  e_templ->content = clear_content; /* restore clear text. */
2591  }
2592  }
2593  else if ((e_templ->security & SEC_SIGN) && (e_templ->content->type == TYPE_MULTIPART))
2594  {
2595  mutt_body_free(&e_templ->content->parts->next); /* destroy sig */
2596  e_templ->content = mutt_remove_multipart(e_templ->content);
2597  }
2598 
2599  FREE(&pgpkeylist);
2600  mutt_env_free(&e_templ->content->mime_headers); /* protected headers */
2601  e_templ->content = mutt_remove_multipart(e_templ->content);
2602  decode_descriptions(e_templ->content);
2603  mutt_unprepare_envelope(e_templ->env);
2604  FREE(&finalpath);
2605  goto main_loop;
2606  }
2607  else
2608  {
2609  puts(_("Could not send the message"));
2610  goto cleanup;
2611  }
2612  }
2613 
2614  if (!C_FccBeforeSend)
2615  save_fcc(e_templ, &fcc, clear_content, pgpkeylist, flags, &finalpath);
2616 
2617  if (!OptNoCurses && !(flags & SEND_MAILX))
2618  {
2619  mutt_message((i != 0) ? _("Sending in background") :
2620  (flags & SEND_NEWS) ? _("Article posted") : /* USE_NNTP */
2621  _("Mail sent"));
2622 #ifdef USE_NOTMUCH
2623  if (C_NmRecord)
2624  nm_record_message(ctx ? ctx->mailbox : NULL, finalpath, e_cur);
2625 #endif
2626  mutt_sleep(0);
2627  }
2628 
2629  if (WithCrypto)
2630  FREE(&pgpkeylist);
2631 
2632  if ((WithCrypto != 0) && free_clear_content)
2633  mutt_body_free(&clear_content);
2634 
2635  /* set 'replied' flag only if the user didn't change/remove
2636  * In-Reply-To: and References: headers during edit */
2637  if (flags & SEND_REPLY)
2638  {
2639  if (!(flags & SEND_POSTPONED) && ctx && ctx->mailbox)
2640  {
2641  STAILQ_FOREACH(en, el, entries)
2642  {
2643  mutt_set_flag(ctx->mailbox, en->email, MUTT_REPLIED, is_reply(en->email, e_templ));
2644  }
2645  }
2646  }
2647 
2648  rc = 0;
2649 
2650 cleanup:
2651  mutt_buffer_dealloc(&fcc);
2652 
2653  if (flags & SEND_POSTPONED)
2654  {
2655  if (WithCrypto & APPLICATION_PGP)
2656  {
2657  FREE(&C_PgpSignAs);
2658  C_PgpSignAs = pgp_signas;
2659  }
2661  {
2662  FREE(&C_SmimeSignAs);
2663  C_SmimeSignAs = smime_signas;
2664  }
2665  }
2666 
2667  mutt_file_fclose(&fp_tmp);
2668  if (!(flags & SEND_NO_FREE_HEADER))
2669  email_free(&e_templ);
2670 
2671  FREE(&finalpath);
2672  return rc;
2673 }
#define MUTT_SEND_HOOK
send-hook: when composing a new email
Definition: hook.h:47
int nm_record_message(struct Mailbox *m, char *path, struct Email *e)
Add a message to the Notmuch database.
Convenience wrapper for the gui headers.
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:411
void mutt_fix_reply_recipients(struct Envelope *env)
Remove duplicate recipients.
Definition: send.c:912
WHERE char * Username
User&#39;s login name.
Definition: globals.h:52
The "current" mailbox.
Definition: context.h:36
struct Regex * C_AbortNoattachRegex
Config: Regex to match text indicating attachments are expected.
Definition: send.c:90
WHERE char * C_SmtpUrl
Config: (smtp) Url of the SMTP server.
Definition: globals.h:142
static void make_reference_headers(struct EmailList *el, struct Envelope *env)
Generate reference headers for an email.
Definition: send.c:995
bool C_Hdrs
Config: Add custom headers to outgoing mail.
Definition: send.c:114
struct Body * mutt_make_message_attach(struct Mailbox *m, struct Email *e, bool attach_msg)
Create a message attachment.
Definition: sendlib.c:1515
char * C_PostponeEncryptAs
Config: Fallback encryption key for postponed messages.
Definition: send.c:123
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:81
void mutt_actx_free(struct AttachCtx **ptr)
Free an Attachment Context.
Definition: attach.c:140
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
#define NONULL(x)
Definition: string2.h:37
WHERE bool C_Autocrypt
Config: Enables the Autocrypt feature.
Definition: globals.h:198
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
Miscellaneous email parsing routines.
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
struct Body * mutt_remove_multipart(struct Body *b)
Extract the multipart body if it exists.
Definition: sendlib.c:1771
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:70
Representation of the email&#39;s header.
#define WithCrypto
Definition: lib.h:161
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:303
#define SEND_POSTPONED_FCC
Used by mutt_get_postponed() to signal that the x-mutt-fcc header field was present.
Definition: send.h:97
#define SEND_TO_SENDER
Compose new email to sender.
Definition: send.h:100
IMAP network mailbox.
The envelope/body of an email.
Definition: email.h:37
WHERE bool C_WriteBcc
Config: Write out the &#39;Bcc&#39; field when preparing to send a mail.
Definition: globals.h:262
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
struct Email * mutt_get_virt_email(struct Mailbox *m, int vnum)
Get a virtual Email.
Definition: context.c:414
#define TAILQ_FIRST(head)
Definition: queue.h:716
#define mutt_perror(...)
Definition: logging.h:85
char * C_ForwardAttributionIntro
Config: Prefix message for forwarded messages.
Definition: send.c:109
static int postpone_message(struct Email *e_post, struct Email *e_cur, const char *fcc, SendFlags flags)
Save an Email for another day.
Definition: send.c:1790
GUI editor for an email&#39;s headers.
WHERE char * C_AttributionLocale
Config: Locale for dates in the attribution message.
Definition: globals.h:98
static void fix_end_of_file(const char *data)
Ensure a file ends with a linefeed.
Definition: send.c:1482
#define MUTT_ALIAS
Do alias "completion" by calling up the alias-menu.
Definition: mutt.h:63
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2511
struct AddressList mail_followup_to
Email&#39;s &#39;mail-followup-to&#39;.
Definition: envelope.h:63
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
WHERE bool C_AutocryptReply
Config: Replying to an autocrypt email automatically enables autocrypt in the reply.
Definition: globals.h:199
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: mailbox.h:51
bool C_ReplySelf
Config: Really reply to yourself, when replying to your own email.
Definition: send.c:125
Structs that make up an email.
String processing routines to generate the mail index.
void mutt_generate_recvattach_list(struct AttachCtx *actx, struct Email *e, struct Body *parts, FILE *fp, int parent_type, int level, bool decrypted)
Create a list of attachments.
Definition: recvattach.c:1222
The "currently-open" mailbox.
unsigned char C_AbortNoattach
Config: Abort sending the email if attachments are missing.
Definition: send.c:89
struct AddressList reply_to
Email&#39;s &#39;reply-to&#39;.
Definition: envelope.h:62
Autocrypt end-to-end encryption.
static bool search_attach_keyword(char *filename)
Search an email for &#39;attachment&#39; keywords.
Definition: send.c:1569
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:122
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:458
WHERE bool C_ForwardDecode
Config: Decode the message when forwarding it.
Definition: globals.h:212
User aborted the question (with Ctrl-G)
Definition: quad.h:38
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: init.c:1109
#define mutt_message(...)
Definition: logging.h:83
int mutt_parse_mailto(struct Envelope *e, char **body, const char *src)
Parse a mailto:// url.
Definition: parse.c:1595
int emaillist_add_email(struct EmailList *el, struct Email *e)
Add an Email to a list.
Definition: email.c:144
WHERE char * C_SmimeDefaultKey
Config: Default key for SMIME operations.
Definition: globals.h:163
struct Email * email
Used by recvattach for updating.
Definition: attach.h:51
static void add_references(struct ListHead *head, struct Envelope *env)
Add the email&#39;s references to a list.
Definition: send.c:884
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1299
struct AddressList bcc
Email&#39;s &#39;Bcc&#39; list.
Definition: envelope.h:60
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1382
char * C_ForwardFormat
Config: printf-like format string to control the subject when forwarding a message.
Definition: send.c:112
#define SEND_DRAFT_FILE
Used by the -H flag.
Definition: send.h:99
static char * nntp_get_header(const char *s)
Get the trimmed header.
Definition: send.c:340
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:123
#define mutt_make_string(BUF, BUFLEN, COLS, S, CTX, M, E)
Definition: hdrline.h:61
void mutt_expand_aliases_env(struct Envelope *env)
Expand aliases in all the fields of an Envelope.
Definition: alias.c:317
WHERE char * AutocryptDefaultKey
Autocrypt default key id (used for postponing messages)
Definition: globals.h:88
static int envelope_defaults(struct Envelope *env, struct Mailbox *m, struct EmailList *el, SendFlags flags)
Fill in some defaults for a new email.
Definition: send.c:1032
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
A normal Email, write full header + MIME headers.
Definition: sendlib.h:60
static void process_user_header(struct Envelope *env)
Process the user headers.
Definition: send.c:378
bool mutt_should_hide_protected_subject(struct Email *e)
Should NeoMutt hide the protected subject?
Definition: crypt.c:1086
#define SEND_FORWARD
Forward email.
Definition: send.h:91
int mutt_fetch_recips(struct Envelope *out, struct Envelope *in, SendFlags flags)
Generate recpients for a reply email.
Definition: send.c:829
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list?
Definition: hdrline.c:114
NeoMutt Logging.
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:728
bool C_FccBeforeSend
Config: Save FCCs before sending the message.
Definition: send.c:106
regex_t * regex
compiled expression
Definition: regex3.h:60
struct Body * content
List of MIME parts.
Definition: email.h:90
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
int mutt_edit_attachment(struct Body *a)
Edit an attachment.
Definition: mutt_attach.c:257
FILE * fp_root
Used by recvattach for updating.
Definition: attach.h:52
void mutt_forward_intro(struct Mailbox *m, struct Email *e, FILE *fp)
Add the "start of forwarded message" text.
Definition: send.c:429
#define MUTT_CM_WEED
Weed message/rfc822 attachment headers.
Definition: copy.h:40
String manipulation buffer.
Definition: buffer.h:33
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:728
void mutt_parse_mime_message(struct Mailbox *m, struct Email *e)
Parse a MIME email.
Definition: mutt_parse.c:49
int mutt_copy_message(FILE *fp_out, struct Mailbox *m, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags, int wraplen)
Copy a message from a Mailbox.
Definition: copy.c:812
struct ListHead userhdrs
user defined headers
Definition: envelope.h:83
bool C_PostponeEncrypt
Config: Self-encrypt postponed messages.
Definition: send.c:122
#define _(a)
Definition: message.h:28
unsigned char C_AbortUnmodified
Config: Abort the sending if the message hasn&#39;t been edited.
Definition: send.c:92
struct Address * mutt_addr_new(void)
Create a new Address.
Definition: address.c:385
void mutt_make_misc_reply_headers(struct Envelope *env, struct Envelope *curenv)
Set subject for a reply.
Definition: send.c:956
char * real_subj
Offset of the real subject.
Definition: envelope.h:67
static void add_message_id(struct ListHead *head, struct Envelope *env)
Add the email&#39;s message ID to a list.
Definition: send.c:900
WHERE bool C_PgpAutoinline
Config: Use old-style inline PGP messages (not recommended)
Definition: globals.h:278
struct Body * next
next attachment in the list
Definition: body.h:53
short idxlen
Number of attachmentes.
Definition: attach.h:55
An email address.
Definition: address.h:34
8-bit text
Definition: mime.h:50
unsigned char C_Include
Config: Include a copy of the email that&#39;s being replied to.
Definition: send.c:117
WHERE unsigned char C_Copy
Config: Save outgoing emails to $record.
Definition: globals.h:179
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:47
char * mailbox
Mailbox and host address.
Definition: address.h:37
#define SEC_AUTOCRYPT
Message will be, or was Autocrypt encrypt+signed.
Definition: lib.h:132
bool C_CryptAutosign
Config: Automatically PGP sign all outgoing mail.
Definition: send.c:98
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:689
#define MUTT_MESSAGE_HOOK
message-hook: run before displaying a message
Definition: hook.h:52
uint16_t CopyMessageFlags
Flags for mutt_copy_message(), e.g. MUTT_CM_NOHEADER.
Definition: copy.h:31
static int inline_forward_attachments(struct Mailbox *m, struct Email *e, struct Body ***plast, int *forwardq)
Add attachments to an email, inline.
Definition: send.c:513
bool C_FollowupTo
Config: Add the &#39;Mail-Followup-To&#39; header is generated when sending mail.
Definition: send.c:108
bool C_SigDashes
Config: Insert &#39;– &#39; before the signature.
Definition: send.c:130
bool C_IgnoreListReplyTo
Config: Ignore the &#39;Reply-To&#39; header when using <reply> on a mailing list.
Definition: send.c:116
static int default_to(struct AddressList *to, struct Envelope *env, SendFlags flags, int hmfupto)
Generate default email addresses.
Definition: send.c:748
struct Address * mutt_addr_copy(const struct Address *addr)
Copy the real address.
Definition: address.c:707
int crypt_get_keys(struct Email *e, char **keylist, bool oppenc_mode)
Check we have all the keys we need.
Definition: crypt.c:956
int mutt_addrlist_parse2(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:607
uint16_t SendFlags
Flags for ci_send_message(), e.g. SEND_REPLY.
Definition: send.h:86
int mutt_env_to_intl(struct Envelope *env, const char **tag, char **err)
Convert an Envelope&#39;s Address fields to Punycode format.
Definition: envelope.c:309
void mutt_make_post_indent(struct Mailbox *m, struct Email *e, FILE *fp_out)
Add suffix to replied email text.
Definition: send.c:667
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:34
void mutt_addr_free(struct Address **ptr)
Free a single Address.
Definition: address.c:440
struct Address * mutt_addr_create(const char *personal, const char *mailbox)
Create and populate a new Address.
Definition: address.c:398
#define SEND_POSTPONED
Recall a postponed email.
Definition: send.h:92
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:702
bool C_CryptReplysign
Config: Sign replies to signed messages.
Definition: send.c:101
int mutt_write_fcc(const char *path, struct Email *e, const char *msgid, bool post, const char *fcc, char **finalpath)
Write email to FCC mailbox.
Definition: sendlib.c:3257
Representation of a single alias to an email address.
#define MUTT_CM_REPLYING
Replying the message.
Definition: copy.h:43
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:123
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:90
Messages that have been replied to.
Definition: mutt.h:99
int vcount
The number of virtual messages.
Definition: mailbox.h:101
The body of an email.
Definition: body.h:34
void mutt_prepare_envelope(struct Envelope *env, bool final)
Prepare an email header.
Definition: sendlib.c:3002
unsigned int disposition
content-disposition
Definition: body.h:67
Convenience wrapper for the config headers.
Prepare and send an email.
char * C_ForwardAttributionTrailer
Config: Suffix message for forwarded messages.
Definition: send.c:110
Hundreds of global variables to back the user variables.
int mutt_rfc822_write_header(FILE *fp, struct Envelope *env, struct Body *attach, enum MuttWriteHeaderMode mode, bool privacy, bool hide_protected_subject)
Write out one RFC822 header line.
Definition: sendlib.c:2324
Email Address Handling.
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:130
unsigned char C_HonorFollowupTo
Config: Honour the &#39;Mail-Followup-To&#39; header when group replying.
Definition: send.c:115
Assorted sorting methods.
Some miscellaneous functions.
WHERE bool C_SmimeIsDefault
Config: Use SMIME rather than PGP by default.
Definition: globals.h:274
#define mutt_array_size(x)
Definition: memory.h:33
bool C_CryptAutosmime
Config: Allow automatic SMIME functions.
Definition: send.c:99
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1163
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:145
bool tagged
Email is tagged.
Definition: email.h:44
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1319
bool read
Email is read.
Definition: email.h:51
WHERE bool C_UseDomain
Config: Qualify local addresses using this domain.
Definition: globals.h:259
#define SEND_MAILX
Send email in Mailx compatibility mode.
Definition: send.h:94
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:1544
char * C_SendCharset
Config: Character sets for outgoing mail.
Definition: email_globals.c:38
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:82
char * message_id
Message ID.
Definition: envelope.h:69
WHERE bool C_EditHeaders
Config: Let the user edit the email headers whilst editing an email.
Definition: globals.h:210
struct Mailbox * mailbox
Definition: context.h:50
unsigned char C_Recall
Config: Recall postponed mesaages when asked to compose a message.
Definition: send.c:124
Parse and execute user-defined hooks.
int mutt_invoke_sendmail(struct AddressList *from, struct AddressList *to, struct AddressList *cc, struct AddressList *bcc, const char *msg, int eightbit)
Run sendmail.
Definition: sendlib.c:2822
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
Many unsorted constants and some structs.
API for mailboxes.
unsigned char C_ReplyTo
Config: Address to use as a &#39;Reply-To&#39; header.
Definition: send.c:126
bool old
Email is seen, but unread.
Definition: email.h:50
#define TAILQ_FOREACH_REVERSE(var, head, headname, field)
Definition: queue.h:738
void rfc2047_decode(char **pd)
Decode any RFC2047-encoded header fields.
Definition: rfc2047.c:651
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:62
unsigned char C_AbortNosubject
Config: Abort creating the email if subject is missing.
Definition: send.c:91
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
enum MailboxType magic
Mailbox type.
Definition: mailbox.h:104
WHERE unsigned char C_MimeForward
Config: Forward a message as a &#39;message/RFC822&#39; MIME part.
Definition: globals.h:182
void mutt_update_encoding(struct Body *a)
Update the encoding type.
Definition: sendlib.c:1484
static void process_user_recips(struct Envelope *env)
Process the user headers.
Definition: send.c:351
#define CH_WEED
Weed the headers?
Definition: copy.h:52
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
WHERE struct Address * C_From
Config: Default &#39;From&#39; address to use, if isn&#39;t otherwise set.
Definition: globals.h:94
struct Envelope * env
Envelope information.
Definition: email.h:89
Convenience wrapper for the core headers.
int mutt_body_copy(FILE *fp, struct Body **tgt, struct Body *src)
Create a send-mode duplicate from a receive-mode body.
Definition: mutt_body.c:48
static void decode_descriptions(struct Body *b)
rfc2047 decode them in case of an error
Definition: send.c:1465
struct ListNode * mutt_list_find(const struct ListHead *h, const char *data)
Find a string in a List.
Definition: list.c:103
#define SKIPWS(ch)
Definition: string2.h:47
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
WHERE bool C_Autoedit
Config: Skip the initial compose menu and edit the email.
Definition: globals.h:201
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
#define SEND_LIST_REPLY
Reply to mailing list.
Definition: send.h:90
static bool is_reply(struct Email *reply, struct Email *orig)
Is one email a reply to another?
Definition: send.c:1551
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
void * mdata
Driver specific data.
Definition: mailbox.h:135
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
Usenet network mailbox type; talk to an NNTP server.
int mutt_write_multiple_fcc(const char *path, struct Email *e, const char *msgid, bool post, char *fcc, char **finalpath)
Handle FCC with multiple, comma separated entries.
Definition: sendlib.c:3210
struct Body * mutt_make_multipart(struct Body *b)
Create a multipart email.
Definition: sendlib.c:1745
#define SEND_KEY
Mail a PGP public key.
Definition: send.h:95
int mutt_autocrypt_set_sign_as_default_key(struct Email *e)
Set the Autocrypt default key for signing.
Definition: autocrypt.c:681
char * subtype
content-type subtype
Definition: body.h:37
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:834
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:65
#define mutt_b2s(buf)
Definition: buffer.h:41
bool C_FastReply
Config: Don&#39;t prompt for the recipients and subject when replying/forwarding.
Definition: send.c:104
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:136
WHERE bool C_Header
Config: Include the message headers in the reply email (Weed applies)
Definition: globals.h:219
#define MUTT_CM_PREFIX
Quote the header and body.
Definition: copy.h:36
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: curs_lib.c:906
Prototypes for many functions.
char * x_comment_to
List of &#39;X-comment-to&#39; fields.
Definition: envelope.h:78
#define SEND_RESEND
Reply using the current email as a template.
Definition: send.h:96
struct ListHead chain
Mixmaster chain.
Definition: email.h:99
Representation of the body of an email.
void mutt_set_followup_to(struct Envelope *env)
Set followup-to field.
Definition: send.c:1214
void mutt_unprepare_envelope(struct Envelope *env)
Undo the encodings of mutt_prepare_envelope()
Definition: sendlib.c:3041
Notmuch virtual mailbox type.
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:78
bool C_AskXCommentTo
Config: (nntp) Ask the user for the &#39;X-Comment-To&#39; field before editing.
Definition: send.c:94
struct Address * mutt_default_from(void)
Get a default &#39;from&#39; Address.
Definition: send.c:1334
unsigned char C_FccAttach
Config: Save send message with all their attachments.
Definition: send.c:105
WHERE bool C_CryptOpportunisticEncrypt
Config: Enable encryption when the recipient&#39;s key is available.
Definition: globals.h:269
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:135
A local copy of an email.
Definition: mx.h:83
static int include_forward(struct Mailbox *m, struct Email *e, FILE *fp_out)
Write out a forwarded message.
Definition: send.c:470
bool C_ReverseName
Config: Set the &#39;From&#39; from the address the email was sent to.
Definition: send.c:128
A mailbox.
Definition: mailbox.h:80
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:39
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define MUTT_CM_DECODE
Decode the message body into text/plain.
Definition: copy.h:37
void mutt_encode_descriptions(struct Body *b, bool recurse)
rfc2047 encode the content-descriptions
Definition: send.c:1448
void mutt_select_fcc(struct Buffer *path, struct Email *e)
Select the FCC path for an email.
Definition: hook.c:699
#define CH_REORDER
Re-order output of headers (specified by &#39;hdr_order&#39;)
Definition: copy.h:58
#define SEC_AUTOCRYPT_OVERRIDE
Indicates manual set/unset of encryption.
Definition: lib.h:133
Type: &#39;text/*&#39;.
Definition: mime.h:38
static int generate_body(FILE *fp_tmp, struct Email *e, SendFlags flags, struct Mailbox *m, struct EmailList *el)
Create a new email body.
Definition: send.c:1102
int mutt_write_mime_body(struct Body *a, FILE *fp)
Write a MIME part.
Definition: sendlib.c:554
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
#define MUTT_CM_CHARCONV
Perform character set conversions.
Definition: copy.h:41
bool mutt_can_decode(struct Body *a)
Will decoding the attachment produce any output.
Definition: handler.c:1752
char * data
Pointer to data.
Definition: buffer.h:35
static int include_reply(struct Mailbox *m, struct Email *e, FILE *fp_out)
Generate the reply text for an email.
Definition: send.c:686
bool mutt_addr_cmp(const struct Address *a, const struct Address *b)
Compare two e-mail addresses.
Definition: address.c:855
#define CH_DECODE
Do RFC2047 header decoding.
Definition: copy.h:53
int mutt_protect(struct Email *e, char *keylist, bool postpone)
Encrypt and/or sign a message.
Definition: crypt.c:170
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:773
WHERE struct Regex * C_QuoteRegex
Config: Regex to match quoted text in a reply.
Definition: globals.h:174
RFC3676 Format Flowed routines.
FILE * fp
Used in the recvattach menu.
Definition: attach.h:37
void mutt_addrlist_prepend(struct AddressList *al, struct Address *a)
Prepend an Address to an AddressList.
Definition: address.c:1413
API for encryption/signing of emails.
bool C_ReverseRealname
Config: Set the &#39;From&#39; from the full &#39;To&#39; address the email was sent to.
Definition: send.c:129
Ignore case when comparing strings.
Definition: string2.h:68
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:799
#define SEND_NEWS
Reply to a news article.
Definition: send.h:102
int ci_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Context *ctx, struct EmailList *el)
Send an email.
Definition: send.c:1892
Handling of email attachments.
bool C_FccClear
Config: Save sent messages unencrypted and unsigned.
Definition: send.c:107
struct ListNode * mutt_list_insert_head(struct ListHead *h, char *s)
Insert a string at the beginning of a List.
Definition: list.c:46
int mix_send_message(struct ListHead *chain, const char *tempfile)
Send an email via Mixmaster.
Definition: remailer.c:902
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
bool mutt_addrlist_search(const struct AddressList *haystack, const struct Address *needle)
Search for an e-mail address in a list.
Definition: address.c:872
static void set_reverse_name(struct AddressList *al, struct Envelope *env)
Try to set the &#39;from&#39; field from the recipients.
Definition: send.c:1285
void mutt_update_num_postponed(void)
Force the update of the number of postponed messages.
Definition: postpone.c:199
#define STAILQ_NEXT(elm, field)
Definition: queue.h:397
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
bool C_PgpReplyinline
Config: Reply using old-style inline PGP messages (not recommended)
Definition: send.c:120
#define SEND_REPLY
Reply to sender.
Definition: send.h:88
NNTP-specific Mailbox data -.
Definition: lib.h:140
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:453
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:131
bool C_SigOnTop
Config: Insert the signature before the quoted text.
Definition: send.c:132
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2530
bool C_AskFollowUp
Config: (nntp) Ask the user for follow-up groups before editing.
Definition: send.c:93
#define SEND_NO_FREE_HEADER
Used by the -E flag.
Definition: send.h:98
static const struct AddressList * choose_default_to(const struct Address *from, const struct Envelope *env)
Pick the best &#39;to:&#39; value.
Definition: send.c:725
void mutt_forward_trailer(struct Mailbox *m, struct Email *e, FILE *fp)
Add a "end of forwarded message" text.
Definition: send.c:448
unsigned char C_ForwardEdit
Config: Automatically start the editor when forwarding a message.
Definition: send.c:111
void rfc2047_encode(char **pd, const char *specials, int col, const char *charsets)
RFC-2047-encode a string.
Definition: rfc2047.c:627
unsigned int type
content-type primary type
Definition: body.h:65
char * list_post
This stores a mailto URL, or nothing.
Definition: envelope.h:65
bool C_CryptReplyencrypt
Config: Encrypt replies to encrypted messages.
Definition: send.c:100
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
#define SEC_SIGN
Email is signed.
Definition: lib.h:124
int mutt_addrlist_count_recips(const struct AddressList *al)
Count the number of Addresses with valid recipients.
Definition: address.c:835
bool crypt_has_module_backend(SecurityFlags type)
Is there a crypto backend for a given type?
Definition: cryptglue.c:163
char * personal
Real name of address.
Definition: address.h:36
int mutt_num_postponed(struct Mailbox *m, bool force)
Return the number of postponed messages.
Definition: postpone.c:86
WHERE bool C_TextFlowed
Config: Generate &#39;format=flowed&#39; messages.
Definition: globals.h:257
void mutt_parse_content_type(const char *s, struct Body *ct)
Parse a content type.
Definition: parse.c:456
void mutt_env_to_local(struct Envelope *env)
Convert an Envelope&#39;s Address fields to local format.
Definition: envelope.c:271
void mutt_edit_headers(const char *editor, const char *body, struct Email *e, struct Buffer *fcc)
Let the user edit the message header and body.
Definition: mutt_header.c:168
void crypt_opportunistic_encrypt(struct Email *e)
Can all recipients be determined.
Definition: crypt.c:1034
WHERE bool C_ResumeDraftFiles
Config: Process draft files like postponed messages.
Definition: globals.h:247
struct Body * crypt_pgp_make_key_attachment(void)
Wrapper for CryptModuleSpecs::pgp_make_key_attachment()
Definition: cryptglue.c:299
Send email to an SMTP server.
#define SEND_GROUP_REPLY
Reply to all.
Definition: send.h:89
GUI basic built-in text editor.
char * data
String.
Definition: list.h:35
char * subject
Email&#39;s subject.
Definition: envelope.h:66
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
Duplicate the structure of an entire email.
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:341
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1217
Routines for managing attachments.
Log at debug level 1.
Definition: logging.h:40
bool group
Group mailbox?
Definition: address.h:38
char * newsgroups
List of newsgroups.
Definition: envelope.h:75
#define MUTT_SEND2_HOOK
send2-hook: when changing fields in the compose menu
Definition: hook.h:56
void emaillist_clear(struct EmailList *el)
Drop a private list of Emails.
Definition: email.c:123
bool C_Metoo
Config: Remove the user&#39;s address from the list of recipients.
Definition: send.c:118
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:270
WHERE bool C_XCommentTo
Config: (nntp) Add &#39;X-Comment-To&#39; header that contains article author.
Definition: globals.h:284
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
Ask the user, defaulting to &#39;No&#39;.
Definition: quad.h:41
static void add_mailing_lists(struct AddressList *out, const struct AddressList *t, const struct AddressList *c)
Search Address lists for mailing lists.
Definition: send.c:180
struct Body * content
Attachment.
Definition: attach.h:36
struct Email * email
Email in the list.
Definition: email.h:116
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:49
Cached regular expression.
Definition: regex3.h:57
#define mutt_error(...)
Definition: logging.h:84
bool mutt_needs_mailcap(struct Body *m)
Does this type need a mailcap entry do display.
Definition: muttlib.c:423
int mutt_builtin_editor(const char *path, struct Email *e_new, struct Email *e_cur)
Show the user the built-in editor.
Definition: edit.c:401
bool mutt_addr_valid_msgid(const char *msgid)
Is this a valid Message ID?
Definition: address.c:755
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
bool replied
Email has been replied to.
Definition: email.h:54
void mutt_rfc3676_space_stuff(struct Email *e)
Perform RFC3676 space stuffing on an Email.
Definition: rfc3676.c:463
static int edit_envelope(struct Envelope *en, SendFlags flags)
Edit Envelope fields.
Definition: send.c:241
char * followup_to
List of &#39;followup-to&#39; fields.
Definition: envelope.h:77
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:651
bool mutt_regex_match(const struct Regex *regex, const char *str)
Shorthand to mutt_regex_capture()
Definition: regex.c:610
WHERE char * C_Editor
Config: External command to use as an email editor.
Definition: globals.h:109
bool C_UseFrom
Config: Set the &#39;From&#39; header for outgoing mail.
Definition: send.c:133
FILE * fp
pointer to the message data
Definition: mx.h:85
time_t mutt_file_decrease_mtime(const char *fp, struct stat *st)
Decrease a file&#39;s modification time by 1 second.
Definition: file.c:961
#define MUTT_REPLY_HOOK
reply-hook: when replying to an email
Definition: hook.h:55
WHERE bool C_ForwardQuote
Config: Automatically quote a forwarded message using C_IndentString.
Definition: globals.h:213
void mutt_make_forward_subject(struct Envelope *env, struct Mailbox *m, struct Email *e)
Create a subject for a forwarded email.
Definition: send.c:939
int mutt_is_subscribed_list_recipient(bool all_addr, struct Envelope *e)
Matches subscribed mailing lists.
Definition: pattern.c:1816
void mutt_addrlist_remove_xrefs(const struct AddressList *a, struct AddressList *b)
Remove cross-references.
Definition: address.c:1355
WHERE char * C_PgpDefaultKey
Config: Default key to use for PGP operations.
Definition: globals.h:159
#define FREE(x)
Definition: memory.h:40
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition: alias.c:686
#define MUTT_COMPOSE_NOFREEHEADER
Definition: compose.h:35
static int mutt_inline_forward(struct Mailbox *m, struct Email *e_edit, struct Email *e_cur, FILE *out)
Forward attachments, inline.
Definition: send.c:590
#define STAILQ_EMPTY(head)
Definition: queue.h:345
static int save_fcc(struct Email *e, struct Buffer *fcc, struct Body *clear_content, char *pgpkeylist, SendFlags flags, char **finalpath)
Save an Email to a &#39;sent mail&#39; folder.
Definition: send.c:1610
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:321
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
int mutt_smtp_send(const struct AddressList *from, const struct AddressList *to, const struct AddressList *cc, const struct AddressList *bcc, const char *msgfile, bool eightbit)
Send a message using SMTP.
Definition: smtp.c:763
List of Emails.
Definition: email.h:114
struct Email * email_new(void)
Create a new Email.
Definition: email.c:68
#define TAILQ_NEXT(elm, field)
Definition: queue.h:825
WHERE char * C_Realname
Config: Real name of the user.
Definition: globals.h:138
int mutt_is_quote_line(char *line, regmatch_t *pmatch)
Is a line of message text a quote?
Definition: pager.c:937
Handling of global boolean variables.
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Miscellaneous functions for sending an email.
bool C_ForwardReferences
Config: Set the &#39;In-Reply-To&#39; and &#39;References&#39; headers when forwarding a message. ...
Definition: send.c:113
void mutt_message_hook(struct Mailbox *m, struct Email *e, HookFlags type)
Perform a message hook.
Definition: hook.c:578
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
#define TAILQ_EMPTY(head)
Definition: queue.h:714
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:1217
#define SEND_GROUP_CHAT_REPLY
Reply to all recipients preserving To/Cc.
Definition: send.h:101
#define MUTT_CM_NOHEADER
Don&#39;t copy the message header.
Definition: copy.h:35
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:45
WHERE char * C_Postponed
Config: Folder to store postponed messages.
Definition: globals.h:134
WHERE char * C_Attribution
Config: Message to start a reply, "On DATE, PERSON wrote:".
Definition: globals.h:97
Log at debug level 5.
Definition: logging.h:44
WHERE char * C_PgpSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:160
Convenience wrapper for the library headers.
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:585
static void remove_user(struct AddressList *al, bool leave_only)
Remove any address which matches the current user.
Definition: send.c:161
struct ListHead references
message references (in reverse order)
Definition: envelope.h:81
WHERE char * C_SmimeSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:164
static void append_signature(FILE *fp)
Append a signature to an email.
Definition: send.c:139
A List node for strings.
Definition: list.h:33
#define TAILQ_SWAP(head1, head2, type, field)
Definition: queue.h:852
Match patterns to emails.
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:41
FILE * mutt_open_read(const char *path, pid_t *thepid)
Run a command to read from.
Definition: muttlib.c:1402
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
Decide how to display email content.
char * C_ContentType
Config: Default "Content-Type" for newly composed messages.
Definition: send.c:95
Content is inline.
Definition: mime.h:62
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
char * C_EmptySubject
Config: Subject to use when replying to an email with none.
Definition: send.c:103
int mutt_resend_message(FILE *fp, struct Context *ctx, struct Email *e_cur)
Resend an email.
Definition: send.c:1505
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:52
struct AddressList x_original_to
Email&#39;s &#39;X-Orig-to&#39;.
Definition: envelope.h:64
#define STAILQ_FIRST(head)
Definition: queue.h:347
int mutt_is_list_recipient(bool all_addr, struct Envelope *e)
Matches known mailing lists.
Definition: pattern.c:1828
A set of attachments.
Definition: attach.h:49
WHERE bool C_Askbcc
Config: Ask the user for the blind-carbon-copy recipients.
Definition: globals.h:195
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
void mutt_edit_file(const char *editor, const char *file)
Let the user edit a file.
Definition: curs_lib.c:352
char * mutt_extract_message_id(const char *s, const char **saveptr)
Find a message-id.
Definition: parse.c:359
size_t mutt_addrlist_write(const struct AddressList *al, char *buf, size_t buflen, bool display)
Write an Address to a buffer.
Definition: address.c:1138
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:638
static int send_message(struct Email *e)
Send an email.
Definition: send.c:1362
#define mutt_buffer_enter_fname(prompt, fname, mailbox)
Definition: curs_lib.h:87
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
return a stream pointer for a message
Definition: mx.c:1115
int mutt_get_postponed(struct Context *ctx, struct Email *hdr, struct Email **cur, struct Buffer *fcc)
Recall a postponed message.
Definition: postpone.c:328
Type: &#39;application/*&#39;.
Definition: mime.h:33
int mutt_prepare_template(FILE *fp, struct Mailbox *m, struct Email *e_new, struct Email *e, bool resend)
Prepare a message template.
Definition: postpone.c:644
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
int mutt_edit_address(struct AddressList *al, const char *field, bool expand_aliases)
Edit an email address.
Definition: send.c:207
int mutt_compose_menu(struct Email *e, struct Buffer *fcc, struct Email *e_cur, int flags)
Allow the user to edit the message envelope.
Definition: compose.c:1125
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
Support of Mixmaster anonymous remailer.
time_t received
Time when the message was placed in the mailbox.
Definition: email.h:82
char * C_Signature
Config: File containing a signature to append to all mail.
Definition: send.c:131
WHERE bool C_Askcc
Config: Ask the user for the carbon-copy recipients.
Definition: globals.h:196
#define SEND_BATCH
Send email in batch mode (without user interaction)
Definition: send.h:93
The header of an Email.
Definition: envelope.h:54
void mutt_make_attribution(struct Mailbox *m, struct Email *e, FILE *fp_out)
Add "on DATE, PERSON wrote" header.
Definition: send.c:648
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: email_globals.c:40
bool C_CryptReplysignencrypted
Config: Sign replies to encrypted messages.
Definition: send.c:102
bool C_NmRecord
Config: (notmuch) If the &#39;record&#39; mailbox (sent mail) should be indexed.
Definition: send.c:119
int msgno
Number displayed to the user.
Definition: email.h:86
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1402
void mutt_add_to_reference_headers(struct Envelope *env, struct Envelope *curenv)
Generate references for a reply email.
Definition: send.c:978
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:265
bool C_CryptAutopgp
Config: Allow automatic PGP functions.
Definition: send.c:97
const char * mutt_get_name(const struct Address *a)
Pick the best name to display from an address.
Definition: sort.c:157
WHERE unsigned char C_ForwardAttachments
Config: Forward attachments when forwarding a message.
Definition: globals.h:181
char * C_PostIndentString
Config: Suffix message to add after reply text.
Definition: send.c:121
bool C_CryptAutoencrypt
Config: Automatically PGP encrypt all outgoing mail.
Definition: send.c:96
bool C_ReplyWithXorig
Config: Create &#39;From&#39; header from &#39;X-Original-To&#39; header.
Definition: send.c:127