NeoMutt  2021-02-05-89-gabe350
Teaching an old dog new tricks
DOXYGEN
send.c File Reference
#include "config.h"
#include <errno.h>
#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "alias/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "send.h"
#include "lib.h"
#include "compose/lib.h"
#include "ncrypt/lib.h"
#include "pattern/lib.h"
#include "context.h"
#include "copy.h"
#include "handler.h"
#include "hdrline.h"
#include "hook.h"
#include "maillist.h"
#include "mutt_attach.h"
#include "mutt_body.h"
#include "mutt_globals.h"
#include "mutt_header.h"
#include "mutt_logging.h"
#include "mutt_parse.h"
#include "muttlib.h"
#include "options.h"
#include "protos.h"
#include "recvattach.h"
#include "rfc3676.h"
#include "sort.h"
#include "nntp/lib.h"
#include "mx.h"
#include "nntp/mdata.h"
#include "remailer.h"
#include "notmuch/lib.h"
#include "imap/lib.h"
#include "autocrypt/lib.h"
+ Include dependency graph for send.c:

Go to the source code of this file.

Functions

static void append_signature (FILE *fp, struct ConfigSubset *sub)
 Append a signature to an email. More...
 
static void remove_user (struct AddressList *al, bool leave_only)
 Remove any address which matches the current user. More...
 
static void add_mailing_lists (struct AddressList *out, const struct AddressList *t, const struct AddressList *c)
 Search Address lists for mailing lists. More...
 
int mutt_edit_address (struct AddressList *al, const char *field, bool expand_aliases)
 Edit an email address. More...
 
static int edit_envelope (struct Envelope *en, SendFlags flags, struct ConfigSubset *sub)
 Edit Envelope fields. More...
 
static char * nntp_get_header (const char *s)
 Get the trimmed header. More...
 
static void process_user_recips (struct Envelope *env)
 Process the user headers. More...
 
static void process_user_header (struct Envelope *env)
 Process the user headers. More...
 
void mutt_forward_intro (struct Mailbox *m, struct Email *e, FILE *fp, struct ConfigSubset *sub)
 Add the "start of forwarded message" text. More...
 
void mutt_forward_trailer (struct Mailbox *m, struct Email *e, FILE *fp, struct ConfigSubset *sub)
 Add a "end of forwarded message" text. More...
 
static int include_forward (struct Mailbox *m, struct Email *e, FILE *fp_out, struct ConfigSubset *sub)
 Write out a forwarded message. More...
 
static int inline_forward_attachments (struct Mailbox *m, struct Email *e, struct Body ***plast, enum QuadOption *forwardq, struct ConfigSubset *sub)
 Add attachments to an email, inline. More...
 
void mutt_make_attribution (struct Mailbox *m, struct Email *e, FILE *fp_out, struct ConfigSubset *sub)
 Add "on DATE, PERSON wrote" header. More...
 
void mutt_make_post_indent (struct Mailbox *m, struct Email *e, FILE *fp_out, struct ConfigSubset *sub)
 Add suffix to replied email text. More...
 
static int include_reply (struct Mailbox *m, struct Email *e, FILE *fp_out, struct ConfigSubset *sub)
 Generate the reply text for an email. More...
 
static const struct AddressList * choose_default_to (const struct Address *from, const struct Envelope *env, struct ConfigSubset *sub)
 Pick the best 'to:' value. More...
 
static int default_to (struct AddressList *to, struct Envelope *env, SendFlags flags, int hmfupto, struct ConfigSubset *sub)
 Generate default email addresses. More...
 
int mutt_fetch_recips (struct Envelope *out, struct Envelope *in, SendFlags flags, struct ConfigSubset *sub)
 Generate recpients for a reply email. More...
 
static void add_references (struct ListHead *head, struct Envelope *env)
 Add the email's references to a list. More...
 
static void add_message_id (struct ListHead *head, struct Envelope *env)
 Add the email's message ID to a list. More...
 
void mutt_fix_reply_recipients (struct Envelope *env, struct ConfigSubset *sub)
 Remove duplicate recipients. More...
 
void mutt_make_forward_subject (struct Envelope *env, struct Mailbox *m, struct Email *e, struct ConfigSubset *sub)
 Create a subject for a forwarded email. More...
 
void mutt_make_misc_reply_headers (struct Envelope *env, struct Envelope *curenv, struct ConfigSubset *sub)
 Set subject for a reply. More...
 
void mutt_add_to_reference_headers (struct Envelope *env, struct Envelope *curenv, struct ConfigSubset *sub)
 Generate references for a reply email. More...
 
static void make_reference_headers (struct EmailList *el, struct Envelope *env, struct ConfigSubset *sub)
 Generate reference headers for an email. More...
 
static int envelope_defaults (struct Envelope *env, struct Mailbox *m, struct EmailList *el, SendFlags flags, struct ConfigSubset *sub)
 Fill in some defaults for a new email. More...
 
static int generate_body (FILE *fp_tmp, struct Email *e, SendFlags flags, struct Mailbox *m, struct EmailList *el, struct ConfigSubset *sub)
 Create a new email body. More...
 
void mutt_set_followup_to (struct Envelope *env, struct ConfigSubset *sub)
 Set followup-to field. More...
 
static void set_reverse_name (struct AddressList *al, struct Envelope *env, struct ConfigSubset *sub)
 Try to set the 'from' field from the recipients. More...
 
struct Addressmutt_default_from (struct ConfigSubset *sub)
 Get a default 'from' Address. More...
 
static int invoke_mta (struct Mailbox *m, struct Email *e, struct ConfigSubset *sub)
 Send an email. More...
 
void mutt_encode_descriptions (struct Body *b, bool recurse, struct ConfigSubset *sub)
 rfc2047 encode the content-descriptions More...
 
static void decode_descriptions (struct Body *b)
 rfc2047 decode them in case of an error More...
 
static void fix_end_of_file (const char *data)
 Ensure a file ends with a linefeed. More...
 
int mutt_resend_message (FILE *fp, struct Context *ctx, struct Email *e_cur, struct ConfigSubset *sub)
 Resend an email. More...
 
static bool is_reply (struct Email *reply, struct Email *orig)
 Is one email a reply to another? More...
 
static bool search_attach_keyword (char *filename, struct ConfigSubset *sub)
 Search an email for 'attachment' keywords. More...
 
static int save_fcc (struct Email *e, struct Buffer *fcc, struct Body *clear_content, char *pgpkeylist, SendFlags flags, char **finalpath, struct ConfigSubset *sub)
 Save an Email to a 'sent mail' folder. More...
 
static int postpone_message (struct Email *e_post, struct Email *e_cur, const char *fcc, SendFlags flags, struct ConfigSubset *sub)
 Save an Email for another day. More...
 
static bool is_text_plain (const struct Body *b)
 is a Body a text/plain MIME part? More...
 
static bool abort_for_missing_attachments (const struct Body *b, struct ConfigSubset *sub)
 Should we abort sending because of missing attachments? More...
 
int mutt_send_message (SendFlags flags, struct Email *e_templ, const char *tempfile, struct Context *ctx, struct EmailList *el, struct ConfigSubset *sub)
 Send an email. More...
 

Detailed Description

Prepare and send an email

Authors
  • Michael R. Elkins
  • Pietro Cerutti

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file send.c.

Function Documentation

◆ append_signature()

static void append_signature ( FILE *  fp,
struct ConfigSubset sub 
)
static

Append a signature to an email.

Parameters
fpFile to write to
subConfig Subset

Definition at line 93 of file send.c.

94 {
95  const char *c_signature = cs_subset_path(sub, "signature");
96  if (!c_signature)
97  return;
98 
99  pid_t pid = 0;
100  FILE *fp_tmp = mutt_open_read(c_signature, &pid);
101  if (!fp_tmp)
102  {
103  mutt_perror(c_signature);
104  return;
105  }
106 
107  const bool c_sig_dashes = cs_subset_bool(sub, "sig_dashes");
108  if (c_sig_dashes)
109  fputs("\n-- \n", fp);
110  mutt_file_copy_stream(fp_tmp, fp);
111  mutt_file_fclose(&fp_tmp);
112  if (pid != -1)
113  filter_wait(pid);
114 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ remove_user()

static void remove_user ( struct AddressList *  al,
bool  leave_only 
)
static

Remove any address which matches the current user.

Parameters
alList of addresses
leave_onlyIf set, don't remove the user's address if it it the only one in the list

Definition at line 122 of file send.c.

123 {
124  struct Address *a = NULL, *tmp = NULL;
125  TAILQ_FOREACH_SAFE(a, al, entries, tmp)
126  {
127  if (mutt_addr_is_user(a) && (!leave_only || TAILQ_NEXT(a, entries)))
128  {
129  TAILQ_REMOVE(al, a, entries);
130  mutt_addr_free(&a);
131  }
132  }
133 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ add_mailing_lists()

static void add_mailing_lists ( struct AddressList *  out,
const struct AddressList *  t,
const struct AddressList *  c 
)
static

Search Address lists for mailing lists.

Parameters
outAddress list where to append matching mailing lists
t'To' Address list
c'Cc' Address list

Definition at line 141 of file send.c.

143 {
144  const struct AddressList *const als[] = { t, c };
145 
146  for (size_t i = 0; i < mutt_array_size(als); ++i)
147  {
148  const struct AddressList *al = als[i];
149  struct Address *a = NULL;
150  TAILQ_FOREACH(a, al, entries)
151  {
152  if (!a->group && mutt_is_mail_list(a))
153  {
155  }
156  }
157  }
158 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_edit_address()

int mutt_edit_address ( struct AddressList *  al,
const char *  field,
bool  expand_aliases 
)

Edit an email address.

Parameters
[in,out]alAddressList to edit
[in]fieldPrompt for user
[in]expand_aliasesIf true, expand Address aliases
Return values
0Success
-1Failure

Definition at line 168 of file send.c.

169 {
170  char buf[8192];
171  char *err = NULL;
172  int idna_ok = 0;
173 
174  do
175  {
176  buf[0] = '\0';
178  mutt_addrlist_write(al, buf, sizeof(buf), false);
179  if (mutt_get_field(field, buf, sizeof(buf), MUTT_ALIAS, false, NULL, NULL) != 0)
180  return -1;
182  mutt_addrlist_parse2(al, buf);
183  if (expand_aliases)
185  idna_ok = mutt_addrlist_to_intl(al, &err);
186  if (idna_ok != 0)
187  {
188  mutt_error(_("Bad IDN: '%s'"), err);
189  FREE(&err);
190  }
191  } while (idna_ok != 0);
192  return 0;
193 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ edit_envelope()

static int edit_envelope ( struct Envelope en,
SendFlags  flags,
struct ConfigSubset sub 
)
static

Edit Envelope fields.

Parameters
enEnvelope to edit
flagsFlags, see SendFlags
subConfig Subset
Return values
0Success
-1Failure

Definition at line 203 of file send.c.

204 {
205  char buf[8192];
206 
207 #ifdef USE_NNTP
208  if (OptNewsSend)
209  {
210  if (en->newsgroups)
211  mutt_str_copy(buf, en->newsgroups, sizeof(buf));
212  else
213  buf[0] = '\0';
214  if (mutt_get_field("Newsgroups: ", buf, sizeof(buf), MUTT_COMP_NO_FLAGS,
215  false, NULL, NULL) != 0)
216  {
217  return -1;
218  }
219  FREE(&en->newsgroups);
220  en->newsgroups = mutt_str_dup(buf);
221 
222  if (en->followup_to)
223  mutt_str_copy(buf, en->followup_to, sizeof(buf));
224  else
225  buf[0] = '\0';
226 
227  const bool c_ask_follow_up = cs_subset_bool(sub, "ask_follow_up");
228  if (c_ask_follow_up && (mutt_get_field("Followup-To: ", buf, sizeof(buf),
229  MUTT_COMP_NO_FLAGS, false, NULL, NULL) != 0))
230  {
231  return -1;
232  }
233  FREE(&en->followup_to);
234  en->followup_to = mutt_str_dup(buf);
235 
236  if (en->x_comment_to)
237  mutt_str_copy(buf, en->x_comment_to, sizeof(buf));
238  else
239  buf[0] = '\0';
240 
241  const bool c_x_comment_to = cs_subset_bool(sub, "x_comment_to");
242  const bool c_ask_x_comment_to = cs_subset_bool(sub, "ask_x_comment_to");
243  if (c_x_comment_to && c_ask_x_comment_to &&
244  (mutt_get_field("X-Comment-To: ", buf, sizeof(buf), MUTT_COMP_NO_FLAGS,
245  false, NULL, NULL) != 0))
246  {
247  return -1;
248  }
249  FREE(&en->x_comment_to);
250  en->x_comment_to = mutt_str_dup(buf);
251  }
252  else
253 #endif
254  {
255  if ((mutt_edit_address(&en->to, _("To: "), true) == -1) || TAILQ_EMPTY(&en->to))
256  return -1;
257 
258  const bool c_ask_cc = cs_subset_bool(sub, "ask_cc");
259  if (c_ask_cc && (mutt_edit_address(&en->cc, _("Cc: "), true) == -1))
260  return -1;
261 
262  const bool c_ask_bcc = cs_subset_bool(sub, "ask_bcc");
263  if (c_ask_bcc && (mutt_edit_address(&en->bcc, _("Bcc: "), true) == -1))
264  return -1;
265 
266  const bool c_reply_with_xorig = cs_subset_bool(sub, "reply_with_xorig");
267  if (c_reply_with_xorig && (flags & (SEND_REPLY | SEND_LIST_REPLY | SEND_GROUP_REPLY)) &&
268  (mutt_edit_address(&en->from, "From: ", true) == -1))
269  {
270  return -1;
271  }
272  }
273 
274  if (en->subject)
275  {
276  const bool c_fast_reply = cs_subset_bool(sub, "fast_reply");
277  if (c_fast_reply)
278  return 0;
279  mutt_str_copy(buf, en->subject, sizeof(buf));
280  }
281  else
282  {
283  const char *p = NULL;
284 
285  buf[0] = '\0';
286  struct ListNode *uh = NULL;
287  STAILQ_FOREACH(uh, &UserHeader, entries)
288  {
289  size_t plen = mutt_istr_startswith(uh->data, "subject:");
290  if (plen)
291  {
292  p = mutt_str_skip_email_wsp(uh->data + plen);
293  mutt_str_copy(buf, p, sizeof(buf));
294  }
295  }
296  }
297 
298  const enum QuadOption c_abort_nosubject =
299  cs_subset_quad(sub, "abort_nosubject");
300  if ((mutt_get_field(_("Subject: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS,
301  false, NULL, NULL) != 0) ||
302  ((buf[0] == '\0') &&
303  (query_quadoption(c_abort_nosubject, _("No subject, abort?")) != MUTT_NO)))
304  {
305  mutt_message(_("No subject, aborting"));
306  return -1;
307  }
308  mutt_str_replace(&en->subject, buf);
309 
310  return 0;
311 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_get_header()

static char* nntp_get_header ( const char *  s)
static

Get the trimmed header.

Parameters
sHeader line with leading whitespace
Return values
ptrCopy of string
Note
The caller should free the returned string.

Definition at line 321 of file send.c.

322 {
323  SKIPWS(s);
324  return mutt_str_dup(s);
325 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_user_recips()

static void process_user_recips ( struct Envelope env)
static

Process the user headers.

Parameters
envEnvelope to populate

Definition at line 332 of file send.c.

333 {
334  struct ListNode *uh = NULL;
335  STAILQ_FOREACH(uh, &UserHeader, entries)
336  {
337  size_t plen;
338  if ((plen = mutt_istr_startswith(uh->data, "to:")))
339  mutt_addrlist_parse(&env->to, uh->data + plen);
340  else if ((plen = mutt_istr_startswith(uh->data, "cc:")))
341  mutt_addrlist_parse(&env->cc, uh->data + plen);
342  else if ((plen = mutt_istr_startswith(uh->data, "bcc:")))
343  mutt_addrlist_parse(&env->bcc, uh->data + plen);
344 #ifdef USE_NNTP
345  else if ((plen = mutt_istr_startswith(uh->data, "newsgroups:")))
346  env->newsgroups = nntp_get_header(uh->data + plen);
347  else if ((plen = mutt_istr_startswith(uh->data, "followup-to:")))
348  env->followup_to = nntp_get_header(uh->data + plen);
349  else if ((plen = mutt_istr_startswith(uh->data, "x-comment-to:")))
350  env->x_comment_to = nntp_get_header(uh->data + plen);
351 #endif
352  }
353 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_user_header()

static void process_user_header ( struct Envelope env)
static

Process the user headers.

Parameters
envEnvelope to populate

Definition at line 359 of file send.c.

360 {
361  struct ListNode *uh = NULL;
362  STAILQ_FOREACH(uh, &UserHeader, entries)
363  {
364  size_t plen;
365  if ((plen = mutt_istr_startswith(uh->data, "from:")))
366  {
367  /* User has specified a default From: address. Remove default address */
368  mutt_addrlist_clear(&env->from);
369  mutt_addrlist_parse(&env->from, uh->data + plen);
370  }
371  else if ((plen = mutt_istr_startswith(uh->data, "reply-to:")))
372  {
374  mutt_addrlist_parse(&env->reply_to, uh->data + plen);
375  }
376  else if ((plen = mutt_istr_startswith(uh->data, "message-id:")))
377  {
378  char *tmp = mutt_extract_message_id(uh->data + plen, NULL);
379  if (mutt_addr_valid_msgid(tmp))
380  {
381  FREE(&env->message_id);
382  env->message_id = tmp;
383  }
384  else
385  FREE(&tmp);
386  }
387  else if (!mutt_istr_startswith(uh->data, "to:") &&
388  !mutt_istr_startswith(uh->data, "cc:") &&
389  !mutt_istr_startswith(uh->data, "bcc:") &&
390 #ifdef USE_NNTP
391  !mutt_istr_startswith(uh->data, "newsgroups:") &&
392  !mutt_istr_startswith(uh->data, "followup-to:") &&
393  !mutt_istr_startswith(uh->data, "x-comment-to:") &&
394 #endif
395  !mutt_istr_startswith(uh->data, "supersedes:") &&
396  !mutt_istr_startswith(uh->data, "subject:") &&
397  !mutt_istr_startswith(uh->data, "return-path:"))
398  {
400  }
401  }
402 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_forward_intro()

void mutt_forward_intro ( struct Mailbox m,
struct Email e,
FILE *  fp,
struct ConfigSubset sub 
)

Add the "start of forwarded message" text.

Parameters
mMailbox
eEmail
subConfig Subset
fpFile to write to

Definition at line 411 of file send.c.

412 {
413  const char *c_forward_attribution_intro =
414  cs_subset_string(sub, "forward_attribution_intro");
415  if (!c_forward_attribution_intro || !fp)
416  return;
417 
418  const char *c_attribution_locale =
419  cs_subset_string(sub, "attribution_locale");
420 
421  char buf[1024];
422  setlocale(LC_TIME, NONULL(c_attribution_locale));
423  mutt_make_string(buf, sizeof(buf), 0, c_forward_attribution_intro, m, -1, e,
424  MUTT_FORMAT_NO_FLAGS, NULL);
425  setlocale(LC_TIME, "");
426  fputs(buf, fp);
427  fputs("\n\n", fp);
428 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_forward_trailer()

void mutt_forward_trailer ( struct Mailbox m,
struct Email e,
FILE *  fp,
struct ConfigSubset sub 
)

Add a "end of forwarded message" text.

Parameters
mMailbox
eEmail
subConfig Subset
fpFile to write to

Definition at line 437 of file send.c.

439 {
440  const char *c_forward_attribution_trailer =
441  cs_subset_string(sub, "forward_attribution_trailer");
442  if (!c_forward_attribution_trailer || !fp)
443  return;
444 
445  const char *c_attribution_locale =
446  cs_subset_string(sub, "attribution_locale");
447 
448  char buf[1024];
449  setlocale(LC_TIME, NONULL(c_attribution_locale));
450  mutt_make_string(buf, sizeof(buf), 0, c_forward_attribution_trailer, m, -1, e,
451  MUTT_FORMAT_NO_FLAGS, NULL);
452  setlocale(LC_TIME, "");
453  fputc('\n', fp);
454  fputs(buf, fp);
455  fputc('\n', fp);
456 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ include_forward()

static int include_forward ( struct Mailbox m,
struct Email e,
FILE *  fp_out,
struct ConfigSubset sub 
)
static

Write out a forwarded message.

Parameters
mMailbox
eEmail
fp_outFile to write to
subConfig Subset
Return values
0Success
-1Failure

Definition at line 467 of file send.c.

469 {
470  CopyHeaderFlags chflags = CH_DECODE;
472 
475 
476  const bool c_forward_decode = cs_subset_bool(sub, "forward_decode");
477  if ((WithCrypto != 0) && (e->security & SEC_ENCRYPT) && c_forward_decode)
478  {
479  /* make sure we have the user's passphrase before proceeding... */
481  return -1;
482  }
483 
484  mutt_forward_intro(m, e, fp_out, sub);
485 
486  if (c_forward_decode)
487  {
488  cmflags |= MUTT_CM_DECODE | MUTT_CM_CHARCONV;
489 
490  const bool c_weed = cs_subset_bool(sub, "weed");
491  if (c_weed)
492  {
493  chflags |= CH_WEED | CH_REORDER;
494  cmflags |= MUTT_CM_WEED;
495  }
496  }
497 
498  const bool c_forward_quote = cs_subset_bool(sub, "forward_quote");
499  if (c_forward_quote)
500  cmflags |= MUTT_CM_PREFIX;
501 
502  mutt_copy_message(fp_out, m, e, cmflags, chflags, 0);
503  mutt_forward_trailer(m, e, fp_out, sub);
504  return 0;
505 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inline_forward_attachments()

static int inline_forward_attachments ( struct Mailbox m,
struct Email e,
struct Body ***  plast,
enum QuadOption forwardq,
struct ConfigSubset sub 
)
static

Add attachments to an email, inline.

Parameters
[in]mMailbox
[in]eCurrent Email
[out]plastPointer to the last Attachment
[out]forwardqResult of asking the user to forward the attachments, e.g. MUTT_YES
[in]subConfig Subset
Return values
0Success
-1Error

Definition at line 517 of file send.c.

520 {
521  struct Body **last = *plast;
522  struct Body *body = NULL;
523  struct Message *msg = NULL;
524  struct AttachCtx *actx = NULL;
525  int rc = 0, i;
526 
529 
530  msg = mx_msg_open(m, e->msgno);
531  if (!msg)
532  return -1;
533 
534  actx = mutt_mem_calloc(1, sizeof(*actx));
535  actx->email = e;
536  actx->fp_root = msg->fp;
537 
538  mutt_generate_recvattach_list(actx, actx->email, actx->email->body,
539  actx->fp_root, -1, 0, 0);
540 
541  for (i = 0; i < actx->idxlen; i++)
542  {
543  body = actx->idx[i]->body;
544  if ((body->type != TYPE_MULTIPART) && !mutt_can_decode(body) &&
545  !((body->type == TYPE_APPLICATION) &&
546  (mutt_istr_equal(body->subtype, "pgp-signature") ||
547  mutt_istr_equal(body->subtype, "x-pkcs7-signature") ||
548  mutt_istr_equal(body->subtype, "pkcs7-signature"))))
549  {
550  /* Ask the quadoption only once */
551  if (*forwardq == MUTT_ABORT)
552  {
553  const enum QuadOption c_forward_attachments =
554  cs_subset_quad(sub, "forward_attachments");
555  *forwardq = query_quadoption(c_forward_attachments,
556  /* L10N: This is the prompt for $forward_attachments.
557  When inline forwarding ($mime_forward answered "no"), this prompts
558  whether to add non-decodable attachments from the original email.
559  Text/plain parts and the like will already be included in the
560  message contents, but other attachment, such as PDF files, will also
561  be added as attachments to the new mail, if this is answered yes. */
562  _("Forward attachments?"));
563  if (*forwardq != MUTT_YES)
564  {
565  if (*forwardq == -1)
566  rc = -1;
567  goto cleanup;
568  }
569  }
570  if (mutt_body_copy(actx->idx[i]->fp, last, body) == -1)
571  {
572  rc = -1;
573  goto cleanup;
574  }
575  last = &((*last)->next);
576  }
577  }
578 
579 cleanup:
580  *plast = last;
581  mx_msg_close(m, &msg);
582  mutt_actx_free(&actx);
583  return rc;
584 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_make_attribution()

void mutt_make_attribution ( struct Mailbox m,
struct Email e,
FILE *  fp_out,
struct ConfigSubset sub 
)

Add "on DATE, PERSON wrote" header.

Parameters
mMailbox
eEmail
fp_outFile to write to
subConfig Subset

Definition at line 593 of file send.c.

595 {
596  const char *c_attribution = cs_subset_string(sub, "attribution");
597  if (!c_attribution || !fp_out)
598  return;
599 
600  const char *c_attribution_locale =
601  cs_subset_string(sub, "attribution_locale");
602 
603  char buf[1024];
604  setlocale(LC_TIME, NONULL(c_attribution_locale));
605  mutt_make_string(buf, sizeof(buf), 0, c_attribution, m, -1, e, MUTT_FORMAT_NO_FLAGS, NULL);
606  setlocale(LC_TIME, "");
607  fputs(buf, fp_out);
608  fputc('\n', fp_out);
609 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_make_post_indent()

void mutt_make_post_indent ( struct Mailbox m,
struct Email e,
FILE *  fp_out,
struct ConfigSubset sub 
)

Add suffix to replied email text.

Parameters
mMailbox
eEmail
fp_outFile to write to
subConfig Subset

Definition at line 618 of file send.c.

620 {
621  const char *c_post_indent_string =
622  cs_subset_string(sub, "post_indent_string");
623  if (!c_post_indent_string || !fp_out)
624  return;
625 
626  char buf[256];
627  mutt_make_string(buf, sizeof(buf), 0, c_post_indent_string, m, -1, e,
628  MUTT_FORMAT_NO_FLAGS, NULL);
629  fputs(buf, fp_out);
630  fputc('\n', fp_out);
631 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ include_reply()

static int include_reply ( struct Mailbox m,
struct Email e,
FILE *  fp_out,
struct ConfigSubset sub 
)
static

Generate the reply text for an email.

Parameters
mMailbox
eEmail
fp_outFile to write to
subConfig Subset
Return values
0Success
-1Failure

Definition at line 642 of file send.c.

644 {
645  CopyMessageFlags cmflags =
647  CopyHeaderFlags chflags = CH_DECODE;
648 
649  if ((WithCrypto != 0) && (e->security & SEC_ENCRYPT))
650  {
651  /* make sure we have the user's passphrase before proceeding... */
653  return -1;
654  }
655 
658 
659  mutt_make_attribution(m, e, fp_out, sub);
660 
661  const bool c_header = cs_subset_bool(sub, "header");
662  if (!c_header)
663  cmflags |= MUTT_CM_NOHEADER;
664 
665  const bool c_weed = cs_subset_bool(sub, "weed");
666  if (c_weed)
667  {
668  chflags |= CH_WEED | CH_REORDER;
669  cmflags |= MUTT_CM_WEED;
670  }
671 
672  mutt_copy_message(fp_out, m, e, cmflags, chflags, 0);
673 
674  mutt_make_post_indent(m, e, fp_out, sub);
675 
676  return 0;
677 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ choose_default_to()

static const struct AddressList* choose_default_to ( const struct Address from,
const struct Envelope env,
struct ConfigSubset sub 
)
static

Pick the best 'to:' value.

Parameters
fromFrom Address
envEnvelope
subConfig Subset
Return values
ptrAddresses to use

Definition at line 686 of file send.c.

689 {
690  const bool c_reply_self = cs_subset_bool(sub, "reply_self");
691  if (!c_reply_self && mutt_addr_is_user(from))
692  {
693  /* mail is from the user, assume replying to recipients */
694  return &env->to;
695  }
696  else
697  {
698  return &env->from;
699  }
700 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ default_to()

static int default_to ( struct AddressList *  to,
struct Envelope env,
SendFlags  flags,
int  hmfupto,
struct ConfigSubset sub 
)
static

Generate default email addresses.

Parameters
[in,out]to'To' address
[in]envEnvelope to populate
[in]flagsFlags, see SendFlags
[in]hmfuptoIf true, add 'followup-to' address to 'to' address
[in]subConfig Subset
Return values
0Success
-1Aborted

Definition at line 712 of file send.c.

714 {
715  const struct Address *from = TAILQ_FIRST(&env->from);
716  const struct Address *reply_to = TAILQ_FIRST(&env->reply_to);
717 
718  if (flags && !TAILQ_EMPTY(&env->mail_followup_to) && (hmfupto == MUTT_YES))
719  {
720  mutt_addrlist_copy(to, &env->mail_followup_to, true);
721  return 0;
722  }
723 
724  /* Exit now if we're setting up the default Cc list for list-reply
725  * (only set if Mail-Followup-To is present and honoured). */
726  if (flags & SEND_LIST_REPLY)
727  return 0;
728 
729  const struct AddressList *default_to = choose_default_to(from, env, sub);
730 
731  if (reply_to)
732  {
733  const bool from_is_reply_to = mutt_addr_cmp(from, reply_to);
734  const bool multiple_reply_to =
735  reply_to && TAILQ_NEXT(TAILQ_FIRST(&env->reply_to), entries);
736 
737  const bool c_ignore_list_reply_to =
738  cs_subset_bool(sub, "ignore_list_reply_to");
739  const enum QuadOption c_reply_to = cs_subset_quad(sub, "reply_to");
740  if ((from_is_reply_to && !multiple_reply_to && !reply_to->personal) ||
741  (c_ignore_list_reply_to && mutt_is_mail_list(reply_to) &&
742  (mutt_addrlist_search(&env->to, reply_to) || mutt_addrlist_search(&env->cc, reply_to))))
743  {
744  /* If the Reply-To: address is a mailing list, assume that it was
745  * put there by the mailing list, and use the From: address
746  *
747  * We also take the from header if our correspondent has a reply-to
748  * header which is identical to the electronic mail address given
749  * in his From header, and the reply-to has no display-name. */
750  mutt_addrlist_copy(to, &env->from, false);
751  }
752  else if (!(from_is_reply_to && !multiple_reply_to) && (c_reply_to != MUTT_YES))
753  {
754  char prompt[256];
755  /* There are quite a few mailing lists which set the Reply-To:
756  * header field to the list address, which makes it quite impossible
757  * to send a message to only the sender of the message. This
758  * provides a way to do that. */
759  /* L10N: Asks whether the user respects the reply-to header.
760  If she says no, neomutt will reply to the from header's address instead. */
761  snprintf(prompt, sizeof(prompt), _("Reply to %s%s?"), reply_to->mailbox,
762  multiple_reply_to ? ",..." : "");
763  switch (query_quadoption(c_reply_to, prompt))
764  {
765  case MUTT_YES:
766  mutt_addrlist_copy(to, &env->reply_to, false);
767  break;
768 
769  case MUTT_NO:
770  mutt_addrlist_copy(to, default_to, false);
771  break;
772 
773  default:
774  return -1; /* abort */
775  }
776  }
777  else
778  {
779  mutt_addrlist_copy(to, &env->reply_to, false);
780  }
781  }
782  else
783  {
784  mutt_addrlist_copy(to, default_to, false);
785  }
786 
787  return 0;
788 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_fetch_recips()

int mutt_fetch_recips ( struct Envelope out,
struct Envelope in,
SendFlags  flags,
struct ConfigSubset sub 
)

Generate recpients for a reply email.

Parameters
outEnvelope to populate
inEnvelope of source email
flagsFlags, see SendFlags
subConfig Subset
Return values
0Success
-1Failure

Definition at line 799 of file send.c.

801 {
802  enum QuadOption hmfupto = MUTT_ABORT;
803  const struct Address *followup_to = TAILQ_FIRST(&in->mail_followup_to);
804 
805  if ((flags & (SEND_LIST_REPLY | SEND_GROUP_REPLY | SEND_GROUP_CHAT_REPLY)) && followup_to)
806  {
807  char prompt[256];
808  snprintf(prompt, sizeof(prompt), _("Follow-up to %s%s?"), followup_to->mailbox,
809  TAILQ_NEXT(TAILQ_FIRST(&in->mail_followup_to), entries) ? ",..." : "");
810 
811  const enum QuadOption c_honor_followup_to =
812  cs_subset_quad(sub, "honor_followup_to");
813  hmfupto = query_quadoption(c_honor_followup_to, prompt);
814  if (hmfupto == MUTT_ABORT)
815  return -1;
816  }
817 
818  if (flags & SEND_LIST_REPLY)
819  {
820  add_mailing_lists(&out->to, &in->to, &in->cc);
821 
822  if (followup_to && (hmfupto == MUTT_YES) &&
823  (default_to(&out->cc, in, flags & SEND_LIST_REPLY, (hmfupto == MUTT_YES), sub) == MUTT_ABORT))
824  {
825  return -1; /* abort */
826  }
827  }
828  else if (flags & SEND_TO_SENDER)
829  {
830  mutt_addrlist_copy(&out->to, &in->from, false);
831  }
832  else
833  {
834  if (default_to(&out->to, in, flags & (SEND_GROUP_REPLY | SEND_GROUP_CHAT_REPLY),
835  (hmfupto == MUTT_YES), sub) == -1)
836  return -1; /* abort */
837 
838  if ((flags & (SEND_GROUP_REPLY | SEND_GROUP_CHAT_REPLY)) &&
839  (!followup_to || (hmfupto != MUTT_YES)))
840  {
841  /* if(!mutt_addr_is_user(in->to)) */
842  if (flags & SEND_GROUP_REPLY)
843  mutt_addrlist_copy(&out->cc, &in->to, true);
844  else
845  mutt_addrlist_copy(&out->to, &in->to, true);
846  mutt_addrlist_copy(&out->cc, &in->cc, true);
847  }
848  }
849  return 0;
850 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ add_references()

static void add_references ( struct ListHead *  head,
struct Envelope env 
)
static

Add the email's references to a list.

Parameters
headList of references
envEnvelope of message

Definition at line 857 of file send.c.

858 {
859  struct ListNode *np = NULL;
860 
861  struct ListHead *src = STAILQ_EMPTY(&env->references) ? &env->in_reply_to : &env->references;
862  STAILQ_FOREACH(np, src, entries)
863  {
865  }
866 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ add_message_id()

static void add_message_id ( struct ListHead *  head,
struct Envelope env 
)
static

Add the email's message ID to a list.

Parameters
headList of message IDs
envEnvelope of message

Definition at line 873 of file send.c.

874 {
875  if (env->message_id)
876  {
878  }
879 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_fix_reply_recipients()

void mutt_fix_reply_recipients ( struct Envelope env,
struct ConfigSubset sub 
)

Remove duplicate recipients.

Parameters
envEnvelope to fix
subConfig Subset

Definition at line 886 of file send.c.

887 {
888  const bool c_me_too = cs_subset_bool(sub, "me_too");
889  if (!c_me_too)
890  {
891  const bool c_reply_self = cs_subset_bool(sub, "reply_self");
892 
893  /* the order is important here. do the CC: first so that if the
894  * the user is the only recipient, it ends up on the TO: field */
895  remove_user(&env->cc, TAILQ_EMPTY(&env->to));
896  remove_user(&env->to, TAILQ_EMPTY(&env->cc) || c_reply_self);
897  }
898 
899  /* the CC field can get cluttered, especially with lists */
900  mutt_addrlist_dedupe(&env->to);
901  mutt_addrlist_dedupe(&env->cc);
902  mutt_addrlist_remove_xrefs(&env->to, &env->cc);
903 
904  if (!TAILQ_EMPTY(&env->cc) && TAILQ_EMPTY(&env->to))
905  {
906  TAILQ_SWAP(&env->to, &env->cc, Address, entries);
907  }
908 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_make_forward_subject()

void mutt_make_forward_subject ( struct Envelope env,
struct Mailbox m,
struct Email e,
struct ConfigSubset sub 
)

Create a subject for a forwarded email.

Parameters
envEnvelope for result
mMailbox
eEmail
subConfig Subset

Definition at line 917 of file send.c.

919 {
920  if (!env)
921  return;
922 
923  const char *c_forward_format = cs_subset_string(sub, "forward_format");
924 
925  char buf[256];
926  /* set the default subject for the message. */
927  mutt_make_string(buf, sizeof(buf), 0, NONULL(c_forward_format), m, -1, e,
928  MUTT_FORMAT_NO_FLAGS, NULL);
929  mutt_str_replace(&env->subject, buf);
930 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_make_misc_reply_headers()

void mutt_make_misc_reply_headers ( struct Envelope env,
struct Envelope curenv,
struct ConfigSubset sub 
)

Set subject for a reply.

Parameters
envEnvelope for result
curenvEnvelope of source email
subConfig Subset

Definition at line 938 of file send.c.

940 {
941  if (!env || !curenv)
942  return;
943 
944  /* This takes precedence over a subject that might have
945  * been taken from a List-Post header. Is that correct? */
946  if (curenv->real_subj)
947  {
948  FREE(&env->subject);
949  env->subject = mutt_mem_malloc(mutt_str_len(curenv->real_subj) + 5);
950  sprintf(env->subject, "Re: %s", curenv->real_subj);
951  }
952  else if (!env->subject)
953  {
954  const char *c_empty_subject = cs_subset_string(sub, "empty_subject");
955  env->subject = mutt_str_dup(c_empty_subject);
956  }
957 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_add_to_reference_headers()

void mutt_add_to_reference_headers ( struct Envelope env,
struct Envelope curenv,
struct ConfigSubset sub 
)

Generate references for a reply email.

Parameters
envEnvelope for result
curenvEnvelope of source email
subConfig Subset

Definition at line 965 of file send.c.

967 {
968  add_references(&env->references, curenv);
969  add_message_id(&env->references, curenv);
970  add_message_id(&env->in_reply_to, curenv);
971 
972 #ifdef USE_NNTP
973  const bool c_x_comment_to = cs_subset_bool(sub, "x_comment_to");
974  if (OptNewsSend && c_x_comment_to && !TAILQ_EMPTY(&curenv->from))
976 #endif
977 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ make_reference_headers()

static void make_reference_headers ( struct EmailList *  el,
struct Envelope env,
struct ConfigSubset sub 
)
static

Generate reference headers for an email.

Parameters
elList of source Emails
envEnvelope for result
subConfig Subset

Definition at line 985 of file send.c.

987 {
988  if (!el || !env || STAILQ_EMPTY(el))
989  return;
990 
991  struct EmailNode *en = STAILQ_FIRST(el);
992  bool single = !STAILQ_NEXT(en, entries);
993 
994  if (!single)
995  {
996  STAILQ_FOREACH(en, el, entries)
997  {
998  mutt_add_to_reference_headers(env, en->email->env, sub);
999  }
1000  }
1001  else
1002  mutt_add_to_reference_headers(env, en->email->env, sub);
1003 
1004  /* if there's more than entry in In-Reply-To (i.e. message has multiple
1005  * parents), don't generate a References: header as it's discouraged by
1006  * RFC2822, sect. 3.6.4 */
1007  if (!single && !STAILQ_EMPTY(&env->in_reply_to) &&
1008  STAILQ_NEXT(STAILQ_FIRST(&env->in_reply_to), entries))
1009  {
1010  mutt_list_free(&env->references);
1011  }
1012 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ envelope_defaults()

static int envelope_defaults ( struct Envelope env,
struct Mailbox m,
struct EmailList *  el,
SendFlags  flags,
struct ConfigSubset sub 
)
static

Fill in some defaults for a new email.

Parameters
envEnvelope for result
mMailbox
elList of Emails to use
flagsFlags, see SendFlags
subConfig Subset
Return values
0Success
-1Failure

Definition at line 1024 of file send.c.

1026 {
1027  if (!el || STAILQ_EMPTY(el))
1028  return -1;
1029 
1030  struct EmailNode *en = STAILQ_FIRST(el);
1031  bool single = !STAILQ_NEXT(en, entries);
1032 
1033  struct Envelope *curenv = en->email->env;
1034  if (!curenv)
1035  return -1;
1036 
1037  if (flags & (SEND_REPLY | SEND_TO_SENDER))
1038  {
1039 #ifdef USE_NNTP
1040  if ((flags & SEND_NEWS))
1041  {
1042  /* in case followup set Newsgroups: with Followup-To: if it present */
1043  if (!env->newsgroups && !mutt_istr_equal(curenv->followup_to, "poster"))
1044  {
1045  env->newsgroups = mutt_str_dup(curenv->followup_to);
1046  }
1047  }
1048  else
1049 #endif
1050  if (!single)
1051  {
1052  STAILQ_FOREACH(en, el, entries)
1053  {
1054  if (mutt_fetch_recips(env, en->email->env, flags, sub) == -1)
1055  return -1;
1056  }
1057  }
1058  else if (mutt_fetch_recips(env, curenv, flags, sub) == -1)
1059  return -1;
1060 
1061  if ((flags & SEND_LIST_REPLY) && TAILQ_EMPTY(&env->to))
1062  {
1063  mutt_error(_("No mailing lists found"));
1064  return -1;
1065  }
1066 
1067  if (flags & SEND_REPLY)
1068  {
1069  mutt_make_misc_reply_headers(env, curenv, sub);
1070  make_reference_headers(el, env, sub);
1071  }
1072  }
1073  else if (flags & SEND_FORWARD)
1074  {
1075  mutt_make_forward_subject(env, m, en->email, sub);
1076 
1077  const bool c_forward_references = cs_subset_bool(sub, "forward_references");
1078  if (c_forward_references)
1079  make_reference_headers(el, env, sub);
1080  }
1081 
1082  return 0;
1083 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generate_body()

static int generate_body ( FILE *  fp_tmp,
struct Email e,
SendFlags  flags,
struct Mailbox m,
struct EmailList *  el,
struct ConfigSubset sub 
)
static

Create a new email body.

Parameters
fp_tmpStream for outgoing message
eEmail for outgoing message
flagsCompose mode, see SendFlags
mMailbox
elList of Emails to use
subConfig Subset
Return values
0Success
-1Error

Definition at line 1096 of file send.c.

1098 {
1099  /* An EmailList is required for replying and forwarding */
1100  if (!el && (flags & (SEND_REPLY | SEND_FORWARD)))
1101  return -1;
1102 
1103  if (flags & SEND_REPLY)
1104  {
1105  const enum QuadOption c_include = cs_subset_quad(sub, "include");
1106  enum QuadOption ans =
1107  query_quadoption(c_include, _("Include message in reply?"));
1108  if (ans == MUTT_ABORT)
1109  return -1;
1110 
1111  if (ans == MUTT_YES)
1112  {
1113  mutt_message(_("Including quoted message..."));
1114  struct EmailNode *en = NULL;
1115  STAILQ_FOREACH(en, el, entries)
1116  {
1117  if (include_reply(m, en->email, fp_tmp, sub) == -1)
1118  {
1119  mutt_error(_("Could not include all requested messages"));
1120  return -1;
1121  }
1122  if (STAILQ_NEXT(en, entries) != NULL)
1123  {
1124  fputc('\n', fp_tmp);
1125  }
1126  }
1127  }
1128  }
1129  else if (flags & SEND_FORWARD)
1130  {
1131  const enum QuadOption c_mime_forward = cs_subset_quad(sub, "mime_forward");
1132  enum QuadOption ans =
1133  query_quadoption(c_mime_forward, _("Forward as attachment?"));
1134  if (ans == MUTT_YES)
1135  {
1136  struct Body *last = e->body;
1137 
1138  mutt_message(_("Preparing forwarded message..."));
1139 
1140  while (last && last->next)
1141  last = last->next;
1142 
1143  struct EmailNode *en = NULL;
1144  STAILQ_FOREACH(en, el, entries)
1145  {
1146  struct Body *tmp = mutt_make_message_attach(m, en->email, false, sub);
1147  if (last)
1148  {
1149  last->next = tmp;
1150  last = tmp;
1151  }
1152  else
1153  {
1154  last = tmp;
1155  e->body = tmp;
1156  }
1157  }
1158  }
1159  else if (ans != MUTT_ABORT)
1160  {
1161  enum QuadOption forwardq = MUTT_ABORT;
1162  struct Body **last = NULL;
1163  struct EmailNode *en = NULL;
1164 
1165  const bool c_forward_decode = cs_subset_bool(sub, "forward_decode");
1166  const enum QuadOption c_forward_attachments =
1167  cs_subset_quad(sub, "forward_attachments");
1168  if (c_forward_decode && (c_forward_attachments != MUTT_NO))
1169  {
1170  last = &e->body;
1171  while (*last)
1172  last = &((*last)->next);
1173  }
1174 
1175  STAILQ_FOREACH(en, el, entries)
1176  {
1177  struct Email *e_cur = en->email;
1178  include_forward(m, e_cur, fp_tmp, sub);
1179  if (c_forward_decode && (c_forward_attachments != MUTT_NO))
1180  {
1181  if (inline_forward_attachments(m, e_cur, &last, &forwardq, sub) != 0)
1182  return -1;
1183  }
1184  }
1185  }
1186  else
1187  return -1;
1188  }
1189  /* if (WithCrypto && (flags & SEND_KEY)) */
1190  else if (((WithCrypto & APPLICATION_PGP) != 0) && (flags & SEND_KEY))
1191  {
1192  struct Body *b = NULL;
1193 
1194  if (((WithCrypto & APPLICATION_PGP) != 0) && !(b = crypt_pgp_make_key_attachment()))
1195  {
1196  return -1;
1197  }
1198 
1199  b->next = e->body;
1200  e->body = b;
1201  }
1202 
1203  mutt_clear_error();
1204 
1205  return 0;
1206 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_set_followup_to()

void mutt_set_followup_to ( struct Envelope env,
struct ConfigSubset sub 
)

Set followup-to field.

Parameters
envEnvelope to modify
subConfig Subset

Definition at line 1213 of file send.c.

1214 {
1215  /* Only generate the Mail-Followup-To if the user has requested it, and
1216  * it hasn't already been set */
1217 
1218  const bool c_followup_to = cs_subset_bool(sub, "followup_to");
1219  if (!c_followup_to)
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_dup(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 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ set_reverse_name()

static void set_reverse_name ( struct AddressList *  al,
struct Envelope env,
struct ConfigSubset sub 
)
static

Try to set the 'from' field from the recipients.

Parameters
alAddressList to prepend the found address
envEnvelope to use
subConfig Subset

Look through the recipients of the message we are replying to, and if we find an address that matches $alternates, we use that as the default from field

Definition at line 1286 of file send.c.

1288 {
1289  struct Address *a = NULL;
1290  if (TAILQ_EMPTY(al))
1291  {
1292  TAILQ_FOREACH(a, &env->to, entries)
1293  {
1294  if (mutt_addr_is_user(a))
1295  {
1297  break;
1298  }
1299  }
1300  }
1301 
1302  if (TAILQ_EMPTY(al))
1303  {
1304  TAILQ_FOREACH(a, &env->cc, entries)
1305  {
1306  if (mutt_addr_is_user(a))
1307  {
1309  break;
1310  }
1311  }
1312  }
1313 
1314  if (TAILQ_EMPTY(al))
1315  {
1316  struct Address *from = TAILQ_FIRST(&env->from);
1317  if (from && mutt_addr_is_user(from))
1318  {
1320  }
1321  }
1322 
1323  if (!TAILQ_EMPTY(al))
1324  {
1325  /* when $reverse_real_name is not set, clear the personal name so that it
1326  * may be set via a reply- or send-hook. */
1327 
1328  const bool c_reverse_real_name = cs_subset_bool(sub, "reverse_real_name");
1329  if (!c_reverse_real_name)
1330  FREE(&TAILQ_FIRST(al)->personal);
1331  }
1332 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_default_from()

struct Address* mutt_default_from ( struct ConfigSubset sub)

Get a default 'from' Address.

Return values
ptrNewly allocated Address

Definition at line 1338 of file send.c.

1339 {
1340  /* Note: We let $from override $real_name here.
1341  * Is this the right thing to do?
1342  */
1343 
1344  const struct Address *c_from = cs_subset_address(sub, "from");
1345  const bool c_use_domain = cs_subset_bool(sub, "use_domain");
1346  if (c_from)
1347  {
1348  return mutt_addr_copy(c_from);
1349  }
1350  else if (c_use_domain)
1351  {
1352  struct Address *addr = mutt_addr_new();
1353  mutt_str_asprintf(&addr->mailbox, "%s@%s", NONULL(Username),
1354  NONULL(mutt_fqdn(true, sub)));
1355  return addr;
1356  }
1357  else
1358  {
1359  return mutt_addr_create(NULL, Username);
1360  }
1361 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ invoke_mta()

static int invoke_mta ( struct Mailbox m,
struct Email e,
struct ConfigSubset sub 
)
static

Send an email.

Parameters
mMailbox
eEmail
subConfig Subset
Return values
0Success
-1Failure

Definition at line 1371 of file send.c.

1372 {
1373  struct Buffer *tempfile = NULL;
1374  int rc = -1;
1375 #ifdef USE_SMTP
1376  short old_write_bcc;
1377 #endif
1378 
1379  /* Write out the message in MIME form. */
1380  tempfile = mutt_buffer_pool_get();
1381  mutt_buffer_mktemp(tempfile);
1382  FILE *fp_tmp = mutt_file_fopen(mutt_buffer_string(tempfile), "w");
1383  if (!fp_tmp)
1384  goto cleanup;
1385 
1386 #ifdef USE_SMTP
1387  const bool c_write_bcc = cs_subset_bool(sub, "write_bcc");
1388  const char *c_smtp_url = cs_subset_string(sub, "smtp_url");
1389  old_write_bcc = c_write_bcc;
1390  if (c_smtp_url)
1391  cs_subset_str_native_set(sub, "write_bcc", false, NULL);
1392 #endif
1393 #ifdef MIXMASTER
1395  !STAILQ_EMPTY(&e->chain),
1397 #endif
1398 #ifndef MIXMASTER
1400  false, mutt_should_hide_protected_subject(e), sub);
1401 #endif
1402 #ifdef USE_SMTP
1403  if (old_write_bcc)
1404  cs_subset_str_native_set(sub, "write_bcc", true, NULL);
1405 #endif
1406 
1407  fputc('\n', fp_tmp); /* tie off the header. */
1408 
1409  if ((mutt_write_mime_body(e->body, fp_tmp, sub) == -1))
1410  goto cleanup;
1411 
1412  if (mutt_file_fclose(&fp_tmp) != 0)
1413  {
1414  mutt_perror(mutt_buffer_string(tempfile));
1415  unlink(mutt_buffer_string(tempfile));
1416  goto cleanup;
1417  }
1418 
1419 #ifdef MIXMASTER
1420  if (!STAILQ_EMPTY(&e->chain))
1421  {
1422  rc = mix_send_message(&e->chain, mutt_buffer_string(tempfile));
1423  goto cleanup;
1424  }
1425 #endif
1426 
1427 #ifdef USE_NNTP
1428  if (OptNewsSend)
1429  goto sendmail;
1430 #endif
1431 
1432 #ifdef USE_SMTP
1433  if (c_smtp_url)
1434  {
1435  rc = mutt_smtp_send(&e->env->from, &e->env->to, &e->env->cc, &e->env->bcc,
1436  mutt_buffer_string(tempfile),
1437  (e->body->encoding == ENC_8BIT), sub);
1438  goto cleanup;
1439  }
1440 #endif
1441 
1442 sendmail:
1443  rc = mutt_invoke_sendmail(m, &e->env->from, &e->env->to, &e->env->cc,
1444  &e->env->bcc, mutt_buffer_string(tempfile),
1445  (e->body->encoding == ENC_8BIT), sub);
1446 cleanup:
1447  if (fp_tmp)
1448  {
1449  mutt_file_fclose(&fp_tmp);
1450  unlink(mutt_buffer_string(tempfile));
1451  }
1452  mutt_buffer_pool_release(&tempfile);
1453  return rc;
1454 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_encode_descriptions()

void mutt_encode_descriptions ( struct Body b,
bool  recurse,
struct ConfigSubset sub 
)

rfc2047 encode the content-descriptions

Parameters
bBody of email
recurseIf true, encode children parts
subConfig Subset

Definition at line 1462 of file send.c.

1463 {
1464  for (struct Body *t = b; t; t = t->next)
1465  {
1466  if (t->description)
1467  {
1468  const char *c_send_charset = cs_subset_string(sub, "send_charset");
1469  rfc2047_encode(&t->description, NULL, sizeof("Content-Description:"), c_send_charset);
1470  }
1471  if (recurse && t->parts)
1472  mutt_encode_descriptions(t->parts, recurse, sub);
1473  }
1474 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ decode_descriptions()

static void decode_descriptions ( struct Body b)
static

rfc2047 decode them in case of an error

Parameters
bMIME parts to decode

Definition at line 1480 of file send.c.

1481 {
1482  for (struct Body *t = b; t; t = t->next)
1483  {
1484  if (t->description)
1485  {
1486  rfc2047_decode(&t->description);
1487  }
1488  if (t->parts)
1489  decode_descriptions(t->parts);
1490  }
1491 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fix_end_of_file()

static void fix_end_of_file ( const char *  data)
static

Ensure a file ends with a linefeed.

Parameters
dataName of file to fix

Definition at line 1497 of file send.c.

1498 {
1499  FILE *fp = mutt_file_fopen(data, "a+");
1500  if (!fp)
1501  return;
1502  if (fseek(fp, -1, SEEK_END) >= 0)
1503  {
1504  int c = fgetc(fp);
1505  if (c != '\n')
1506  fputc('\n', fp);
1507  }
1508  mutt_file_fclose(&fp);
1509 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_resend_message()

int mutt_resend_message ( FILE *  fp,
struct Context ctx,
struct Email e_cur,
struct ConfigSubset sub 
)

Resend an email.

Parameters
fpFile containing email
ctxMailbox
e_curEmail to resend
subConfig Subset
Return values
0Message was successfully sent
-1Message was aborted or an error occurred
1Message was postponed

Definition at line 1521 of file send.c.

1523 {
1524  struct Email *e_new = email_new();
1525 
1526  if (mutt_prepare_template(fp, ctx->mailbox, e_new, e_cur, true) < 0)
1527  {
1528  email_free(&e_new);
1529  return -1;
1530  }
1531 
1532  if (WithCrypto)
1533  {
1534  /* mutt_prepare_template doesn't always flip on an application bit.
1535  * so fix that here */
1536  if (!(e_new->security & (APPLICATION_SMIME | APPLICATION_PGP)))
1537  {
1538  const bool c_smime_is_default = cs_subset_bool(sub, "smime_is_default");
1539  if (((WithCrypto & APPLICATION_SMIME) != 0) && c_smime_is_default)
1540  e_new->security |= APPLICATION_SMIME;
1541  else if (WithCrypto & APPLICATION_PGP)
1542  e_new->security |= APPLICATION_PGP;
1543  else
1544  e_new->security |= APPLICATION_SMIME;
1545  }
1546 
1547  const bool c_crypt_opportunistic_encrypt =
1548  cs_subset_bool(sub, "crypt_opportunistic_encrypt");
1549  if (c_crypt_opportunistic_encrypt)
1550  {
1551  e_new->security |= SEC_OPPENCRYPT;
1553  }
1554  }
1555 
1556  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
1557  emaillist_add_email(&el, e_cur);
1558  int rc = mutt_send_message(SEND_RESEND, e_new, NULL, ctx, &el, sub);
1559  emaillist_clear(&el);
1560 
1561  return rc;
1562 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ is_reply()

static bool is_reply ( struct Email reply,
struct Email orig 
)
static

Is one email a reply to another?

Parameters
replyEmail to test
origOriginal email
Return values
trueIt is a reply
falseIt is not a reply

Definition at line 1571 of file send.c.

1572 {
1573  if (!reply || !reply->env || !orig || !orig->env)
1574  return false;
1575  return mutt_list_find(&orig->env->references, reply->env->message_id) ||
1576  mutt_list_find(&orig->env->in_reply_to, reply->env->message_id);
1577 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ search_attach_keyword()

static bool search_attach_keyword ( char *  filename,
struct ConfigSubset sub 
)
static

Search an email for 'attachment' keywords.

Parameters
filenameFilename
subConfig Subset
Return values
trueIf the regex matches in the email

Search an email for the regex in $abort_noattach_regex. A match might indicate that the user should have attached something.

Note
Quoted lines (as defined by $quote_regex) are ignored

Definition at line 1590 of file send.c.

1591 {
1592  const struct Regex *c_abort_noattach_regex =
1593  cs_subset_regex(sub, "abort_noattach_regex");
1594  const struct Regex *c_quote_regex = cs_subset_regex(sub, "quote_regex");
1595 
1596  /* Search for the regex in `$abort_noattach_regex` within a file */
1597  if (!c_abort_noattach_regex || !c_abort_noattach_regex->regex ||
1598  !c_quote_regex || !c_quote_regex->regex)
1599  {
1600  return false;
1601  }
1602 
1603  FILE *fp_att = mutt_file_fopen(filename, "r");
1604  if (!fp_att)
1605  return false;
1606 
1607  char *inputline = mutt_mem_malloc(1024);
1608  bool found = false;
1609  while (!feof(fp_att))
1610  {
1611  fgets(inputline, 1024, fp_att);
1612  if (!mutt_is_quote_line(inputline, NULL) &&
1613  mutt_regex_match(c_abort_noattach_regex, inputline))
1614  {
1615  found = true;
1616  break;
1617  }
1618  }
1619  FREE(&inputline);
1620  mutt_file_fclose(&fp_att);
1621  return found;
1622 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ save_fcc()

static int save_fcc ( struct Email e,
struct Buffer fcc,
struct Body clear_content,
char *  pgpkeylist,
SendFlags  flags,
char **  finalpath,
struct ConfigSubset sub 
)
static

Save an Email to a 'sent mail' folder.

Parameters
[in]eEmail to save
[in]fccFolder to save to (can be comma-separated list)
[in]clear_contentCleartext content of Email
[in]pgpkeylistList of pgp keys
[in]flagsSend mode, see SendFlags
[out]finalpathPath of final folder
[in]subConfig Subset
Return values
0Success
-1Error

Definition at line 1636 of file send.c.

1639 {
1640  int rc = 0;
1641  struct Body *save_content = NULL;
1642 
1644 
1645  /* Don't save a copy when we are in batch-mode, and the FCC
1646  * folder is on an IMAP server: This would involve possibly lots
1647  * of user interaction, which is not available in batch mode.
1648  *
1649  * Note: A patch to fix the problems with the use of IMAP servers
1650  * from non-curses mode is available from Brendan Cully. However,
1651  * I'd like to think a bit more about this before including it. */
1652 
1653 #ifdef USE_IMAP
1654  if ((flags & SEND_BATCH) && !mutt_buffer_is_empty(fcc) &&
1655  (imap_path_probe(mutt_buffer_string(fcc), NULL) == MUTT_IMAP))
1656  {
1657  mutt_error(
1658  _("Warning: Fcc to an IMAP mailbox is not supported in batch mode"));
1659  /* L10N: Printed after the "Fcc to an IMAP mailbox is not supported" message.
1660  To make it clearer that the message doesn't mean NeoMutt is aborting
1661  sending the mail too.
1662  %s is the full mailbox URL, including imap(s)://
1663  */
1664  mutt_error(_("Skipping Fcc to %s"), mutt_buffer_string(fcc));
1665  mutt_buffer_reset(fcc);
1666  return rc;
1667  }
1668 #endif
1669 
1670  if (mutt_buffer_is_empty(fcc) || mutt_str_equal("/dev/null", mutt_buffer_string(fcc)))
1671  return rc;
1672 
1673  struct Body *tmpbody = e->body;
1674  struct Body *save_sig = NULL;
1675  struct Body *save_parts = NULL;
1676 
1677  const bool c_fcc_before_send = cs_subset_bool(sub, "fcc_before_send");
1678  /* Before sending, we don't allow message manipulation because it
1679  * will break message signatures. This is especially complicated by
1680  * Protected Headers. */
1681  if (!c_fcc_before_send)
1682  {
1683  const bool c_fcc_clear = cs_subset_bool(sub, "fcc_clear");
1684  if ((WithCrypto != 0) &&
1685  (e->security & (SEC_ENCRYPT | SEC_SIGN | SEC_AUTOCRYPT)) && c_fcc_clear)
1686  {
1687  e->body = clear_content;
1690  }
1691 
1692  const enum QuadOption c_fcc_attach = cs_subset_quad(sub, "fcc_attach");
1693 
1694  /* check to see if the user wants copies of all attachments */
1695  bool save_atts = true;
1696  if (e->body->type == TYPE_MULTIPART)
1697  {
1698  /* In batch mode, save attachments if the quadoption is yes or ask-yes */
1699  if (flags & SEND_BATCH)
1700  {
1701  if ((c_fcc_attach == MUTT_NO) || (c_fcc_attach == MUTT_ASKNO))
1702  save_atts = false;
1703  }
1704  else if (query_quadoption(c_fcc_attach, _("Save attachments in Fcc?")) != MUTT_YES)
1705  save_atts = false;
1706  }
1707  if (!save_atts)
1708  {
1709  if ((WithCrypto != 0) && (e->security & (SEC_ENCRYPT | SEC_SIGN | SEC_AUTOCRYPT)) &&
1710  (mutt_str_equal(e->body->subtype, "encrypted") ||
1711  mutt_str_equal(e->body->subtype, "signed")))
1712  {
1713  if ((clear_content->type == TYPE_MULTIPART) &&
1714  (query_quadoption(c_fcc_attach, _("Save attachments in Fcc?")) == MUTT_NO))
1715  {
1716  if (!(e->security & SEC_ENCRYPT) && (e->security & SEC_SIGN))
1717  {
1718  /* save initial signature and attachments */
1719  save_sig = e->body->parts->next;
1720  save_parts = clear_content->parts->next;
1721  }
1722 
1723  /* this means writing only the main part */
1724  e->body = clear_content->parts;
1725 
1726  if (mutt_protect(e, pgpkeylist, false) == -1)
1727  {
1728  /* we can't do much about it at this point, so
1729  * fallback to saving the whole thing to fcc */
1730  e->body = tmpbody;
1731  save_sig = NULL;
1732  goto full_fcc;
1733  }
1734 
1735  save_content = e->body;
1736  }
1737  }
1738  else
1739  {
1740  if (query_quadoption(c_fcc_attach, _("Save attachments in Fcc?")) == MUTT_NO)
1741  e->body = e->body->parts;
1742  }
1743  }
1744  }
1745 
1746 full_fcc:
1747  if (e->body)
1748  {
1749  /* update received time so that when storing to a mbox-style folder
1750  * the From_ line contains the current time instead of when the
1751  * message was first postponed. */
1752  e->received = mutt_date_epoch();
1753  rc = mutt_write_multiple_fcc(mutt_buffer_string(fcc), e, NULL, false, NULL,
1754  finalpath, sub);
1755  while (rc && !(flags & SEND_BATCH))
1756  {
1757  mutt_clear_error();
1758  int choice = mutt_multi_choice(
1759  /* L10N: Called when saving to $record or Fcc failed after sending.
1760  (r)etry tries the same mailbox again.
1761  alternate (m)ailbox prompts for a different mailbox to try.
1762  (s)kip aborts saving. */
1763  _("Fcc failed. (r)etry, alternate (m)ailbox, or (s)kip?"),
1764  /* L10N: These correspond to the "Fcc failed" multi-choice prompt
1765  (r)etry, alternate (m)ailbox, or (s)kip.
1766  Any similarity to famous leaders of the FSF is coincidental. */
1767  _("rms"));
1768  switch (choice)
1769  {
1770  case 2: /* alternate (m)ailbox */
1771  /* L10N: This is the prompt to enter an "alternate (m)ailbox" when the
1772  initial Fcc fails. */
1773  rc = mutt_buffer_enter_fname(_("Fcc mailbox"), fcc, true, ctx_mailbox(Context),
1774  false, NULL, NULL, MUTT_SEL_NO_FLAGS);
1775  if ((rc == -1) || mutt_buffer_is_empty(fcc))
1776  {
1777  rc = 0;
1778  break;
1779  }
1780  /* fall through */
1781 
1782  case 1: /* (r)etry */
1783  rc = mutt_write_multiple_fcc(mutt_buffer_string(fcc), e, NULL, false,
1784  NULL, finalpath, sub);
1785  break;
1786 
1787  case -1: /* abort */
1788  case 3: /* (s)kip */
1789  rc = 0;
1790  break;
1791  }
1792  }
1793  }
1794 
1795  if (!c_fcc_before_send)
1796  {
1797  e->body = tmpbody;
1798 
1799  if ((WithCrypto != 0) && save_sig)
1800  {
1801  /* cleanup the second signature structures */
1802  if (save_content->parts)
1803  {
1804  mutt_body_free(&save_content->parts->next);
1805  save_content->parts = NULL;
1806  }
1807  mutt_body_free(&save_content);
1808 
1809  /* restore old signature and attachments */
1810  e->body->parts->next = save_sig;
1811  e->body->parts->parts->next = save_parts;
1812  }
1813  else if ((WithCrypto != 0) && save_content)
1814  {
1815  /* destroy the new encrypted body. */
1816  mutt_body_free(&save_content);
1817  }
1818  }
1819 
1820  return 0;
1821 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ postpone_message()

static int postpone_message ( struct Email e_post,
struct Email e_cur,
const char *  fcc,
SendFlags  flags,
struct ConfigSubset sub 
)
static

Save an Email for another day.

Parameters
e_postEmail to postpone
e_curCurrent Email in the index
fccFolder for 'sent mail'
flagsSend mode, see SendFlags
subConfig Subset
Return values
0Success
-1Error

Definition at line 1833 of file send.c.

1835 {
1836  char *pgpkeylist = NULL;
1837  const char *encrypt_as = NULL;
1838  struct Body *clear_content = NULL;
1839 
1840  const char *c_postponed = cs_subset_string(sub, "postponed");
1841  if (!c_postponed)
1842  {
1843  mutt_error(_("Can't postpone. $postponed is unset"));
1844  return -1;
1845  }
1846 
1847  if (e_post->body->next)
1848  e_post->body = mutt_make_multipart(e_post->body);
1849 
1850  mutt_encode_descriptions(e_post->body, true, sub);
1851 
1852  const bool c_postpone_encrypt = cs_subset_bool(sub, "postpone_encrypt");
1853  if ((WithCrypto != 0) && c_postpone_encrypt &&
1854  (e_post->security & (SEC_ENCRYPT | SEC_AUTOCRYPT)))
1855  {
1856  if (((WithCrypto & APPLICATION_PGP) != 0) && (e_post->security & APPLICATION_PGP))
1857  {
1858  const char *c_pgp_default_key = cs_subset_string(sub, "pgp_default_key");
1859  encrypt_as = c_pgp_default_key;
1860  }
1861  else if (((WithCrypto & APPLICATION_SMIME) != 0) && (e_post->security & APPLICATION_SMIME))
1862  {
1863  const char *c_smime_default_key =
1864  cs_subset_string(sub, "smime_default_key");
1865  encrypt_as = c_smime_default_key;
1866  }
1867  if (!encrypt_as)
1868  {
1869  const char *c_postpone_encrypt_as =
1870  cs_subset_string(sub, "postpone_encrypt_as");
1871  encrypt_as = c_postpone_encrypt_as;
1872  }
1873 
1874 #ifdef USE_AUTOCRYPT
1875  if (e_post->security & SEC_AUTOCRYPT)
1876  {
1877  struct Mailbox *m = ctx_mailbox(Context);
1879  {
1880  e_post->body = mutt_remove_multipart(e_post->body);
1881  decode_descriptions(e_post->body);
1882  mutt_error(_("Error encrypting message. Check your crypt settings."));
1883  return -1;
1884  }
1885  encrypt_as = AutocryptDefaultKey;
1886  }
1887 #endif
1888 
1889  if (encrypt_as)
1890  {
1891  pgpkeylist = mutt_str_dup(encrypt_as);
1892  clear_content = e_post->body;
1893  if (mutt_protect(e_post, pgpkeylist, true) == -1)
1894  {
1895  FREE(&pgpkeylist);
1896  e_post->body = mutt_remove_multipart(e_post->body);
1897  decode_descriptions(e_post->body);
1898  mutt_error(_("Error encrypting message. Check your crypt settings."));
1899  return -1;
1900  }
1901 
1902  FREE(&pgpkeylist);
1903 
1904  mutt_encode_descriptions(e_post->body, false, sub);
1905  }
1906  }
1907 
1908  /* make sure the message is written to the right part of a maildir
1909  * postponed folder. */
1910  e_post->read = false;
1911  e_post->old = false;
1912 
1913  mutt_prepare_envelope(e_post->env, false, sub);
1914  mutt_env_to_intl(e_post->env, NULL, NULL); /* Handle bad IDNAs the next time. */
1915 
1916  if (mutt_write_fcc(NONULL(c_postponed), e_post,
1917  (e_cur && (flags & SEND_REPLY)) ? e_cur->env->message_id : NULL,
1918  true, fcc, NULL, sub) < 0)
1919  {
1920  if (clear_content)
1921  {
1922  mutt_body_free(&e_post->body);
1923  e_post->body = clear_content;
1924  }
1925  mutt_env_free(&e_post->body->mime_headers); /* protected headers */
1926  e_post->body = mutt_remove_multipart(e_post->body);
1927  decode_descriptions(e_post->body);
1928  mutt_unprepare_envelope(e_post->env);
1929  return -1;
1930  }
1931 
1933 
1934  if (clear_content)
1935  mutt_body_free(&clear_content);
1936 
1937  return 0;
1938 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ is_text_plain()

static bool is_text_plain ( const struct Body b)
static

is a Body a text/plain MIME part?

Parameters
bBody to check
Return values
trueif it's text/plain
falseif it's not

Definition at line 1946 of file send.c.

1947 {
1948  return (b->type == TYPE_TEXT) && mutt_istr_equal(b->subtype, "plain");
1949 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ abort_for_missing_attachments()

static bool abort_for_missing_attachments ( const struct Body b,
struct ConfigSubset sub 
)
static

Should we abort sending because of missing attachments?

Parameters
bBody
subConfig Subset
Return values
Abortbecause of missing attachments

Definition at line 1957 of file send.c.

1958 {
1959  const enum QuadOption c_abort_noattach =
1960  cs_subset_quad(sub, "abort_noattach");
1961 
1962  if (c_abort_noattach == MUTT_NO)
1963  return false;
1964 
1965  if (b->next)
1966  return false;
1967 
1968  bool has_keyword = false;
1969 
1970  /* search text/plain parts, whether they are main or alternative parts */
1971  if (is_text_plain(b))
1972  {
1973  has_keyword |= search_attach_keyword(b->filename, sub);
1974  }
1975  else
1976  {
1977  for (b = b->parts; b; b = b->next)
1978  {
1979  if (is_text_plain(b))
1980  {
1981  has_keyword |= search_attach_keyword(b->filename, sub);
1982  }
1983  }
1984  }
1985 
1986  if (!has_keyword)
1987  return false;
1988 
1989  if (c_abort_noattach == MUTT_YES)
1990  {
1991  mutt_error(_("Message contains text matching \"$abort_noattach_regex\". "
1992  "Not sending."));
1993  return true;
1994  }
1995 
1996  return query_quadoption(c_abort_noattach,
1997  _("No attachments, cancel sending?")) != MUTT_NO;
1998 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_send_message()

int mutt_send_message ( SendFlags  flags,
struct Email e_templ,
const char *  tempfile,
struct Context ctx,
struct EmailList *  el,
struct ConfigSubset sub 
)

Send an email.

Parameters
flagsSend mode, see SendFlags
e_templTemplate to use for new message
tempfileFile specified by -i or -H
ctxCurrent mailbox
elList of Emails to send
subConfig Subset
Return values
0Message was successfully sent
-1Message was aborted or an error occurred
1Message was postponed

Definition at line 2012 of file send.c.

2014 {
2015  char buf[1024];
2016  struct Buffer fcc = mutt_buffer_make(0); /* where to copy this message */
2017  FILE *fp_tmp = NULL;
2018  struct Body *pbody = NULL;
2019  int i;
2020  bool free_clear_content = false;
2021 
2022  struct Body *clear_content = NULL;
2023  char *pgpkeylist = NULL;
2024  /* save current value of "pgp_sign_as" and "smime_default_key" */
2025  char *pgp_sign_as = NULL;
2026  char *smime_sign_as = NULL;
2027  const char *tag = NULL;
2028  char *err = NULL;
2029  char *ctype = NULL;
2030  char *finalpath = NULL;
2031  struct EmailNode *en = NULL;
2032  struct Email *e_cur = NULL;
2033  struct Mailbox *mailbox = ctx ? ctx->mailbox : NULL;
2034 
2035  if (el)
2036  en = STAILQ_FIRST(el);
2037  if (en)
2038  e_cur = STAILQ_NEXT(en, entries) ? NULL : en->email;
2039 
2040  int rc = -1;
2041 
2042 #ifdef USE_NNTP
2043  if (flags & SEND_NEWS)
2044  OptNewsSend = true;
2045  else
2046  OptNewsSend = false;
2047 #endif
2048 
2049  const enum QuadOption c_recall = cs_subset_quad(sub, "recall");
2050 
2051  if (!flags && !e_templ && (c_recall != MUTT_NO) && mutt_num_postponed(mailbox, true))
2052  {
2053  /* If the user is composing a new message, check to see if there
2054  * are any postponed messages first. */
2055  enum QuadOption ans =
2056  query_quadoption(c_recall, _("Recall postponed message?"));
2057  if (ans == MUTT_ABORT)
2058  return rc;
2059 
2060  if (ans == MUTT_YES)
2061  flags |= SEND_POSTPONED;
2062  }
2063 
2064  /* Allocate the buffer due to the long lifetime, but
2065  * pre-resize it to ensure there are no NULL data field issues */
2066  mutt_buffer_alloc(&fcc, 1024);
2067 
2068  if (flags & SEND_POSTPONED)
2069  {
2071  {
2072  const char *c_pgp_sign_as = cs_subset_string(sub, "pgp_sign_as");
2073  pgp_sign_as = mutt_str_dup(c_pgp_sign_as);
2074  }
2076  {
2077  const char *c_smime_sign_as = cs_subset_string(sub, "smime_sign_as");
2078  smime_sign_as = mutt_str_dup(c_smime_sign_as);
2079  }
2080  }
2081 
2082  /* Delay expansion of aliases until absolutely necessary--shouldn't
2083  * be necessary unless we are prompting the user or about to execute a
2084  * send-hook. */
2085 
2086  if (!e_templ)
2087  {
2088  e_templ = email_new();
2089 
2090  if (flags == SEND_POSTPONED)
2091  {
2092  rc = mutt_get_postponed(ctx, e_templ, &e_cur, &fcc);
2093  if (rc < 0)
2094  {
2096  goto cleanup;
2097  }
2098  flags = rc;
2099 #ifdef USE_NNTP
2100  /* If postponed message is a news article, it have
2101  * a "Newsgroups:" header line, then set appropriate flag. */
2102  if (e_templ->env->newsgroups)
2103  {
2104  flags |= SEND_NEWS;
2105  OptNewsSend = true;
2106  }
2107  else
2108  {
2109  flags &= ~SEND_NEWS;
2110  OptNewsSend = false;
2111  }
2112 #endif
2113  }
2114 
2115  if (flags & (SEND_POSTPONED | SEND_RESEND))
2116  {
2117  fp_tmp = mutt_file_fopen(e_templ->body->filename, "a+");
2118  if (!fp_tmp)
2119  {
2120  mutt_perror(e_templ->body->filename);
2121  goto cleanup;
2122  }
2123  }
2124 
2125  if (!e_templ->env)
2126  e_templ->env = mutt_env_new();
2127  }
2128 
2129  /* Parse and use an eventual list-post header */
2130  if ((flags & SEND_LIST_REPLY) && e_cur && e_cur->env && e_cur->env->list_post)
2131  {
2132  /* Use any list-post header as a template */
2133  mutt_parse_mailto(e_templ->env, NULL, e_cur->env->list_post);
2134  /* We don't let them set the sender's address. */
2135  mutt_addrlist_clear(&e_templ->env->from);
2136  }
2137 
2138  if (!(flags & (SEND_KEY | SEND_POSTPONED | SEND_RESEND)))
2139  {
2140  /* When SEND_DRAFT_FILE is set, the caller has already
2141  * created the "parent" body structure. */
2142  if (!(flags & SEND_DRAFT_FILE))
2143  {
2144  pbody = mutt_body_new();
2145  pbody->next = e_templ->body; /* don't kill command-line attachments */
2146  e_templ->body = pbody;
2147 
2148  const char *c_content_type = cs_subset_string(sub, "content_type");
2149  ctype = mutt_str_dup(c_content_type);
2150  if (!ctype)
2151  ctype = mutt_str_dup("text/plain");
2152  mutt_parse_content_type(ctype, e_templ->body);
2153  FREE(&ctype);
2154  e_templ->body->unlink = true;
2155  e_templ->body->use_disp = false;
2156  e_templ->body->disposition = DISP_INLINE;
2157 
2158  if (tempfile)
2159  {
2160  fp_tmp = mutt_file_fopen(tempfile, "a+");
2161  e_templ->body->filename = mutt_str_dup(tempfile);
2162  }
2163  else
2164  {
2165  mutt_mktemp(buf, sizeof(buf));
2166  fp_tmp = mutt_file_fopen(buf, "w+");
2167  e_templ->body->filename = mutt_str_dup(buf);
2168  }
2169  }
2170  else
2171  fp_tmp = mutt_file_fopen(e_templ->body->filename, "a+");
2172 
2173  if (!fp_tmp)
2174  {
2175  mutt_debug(LL_DEBUG1, "can't create tempfile %s (errno=%d)\n",
2176  e_templ->body->filename, errno);
2177  mutt_perror(e_templ->body->filename);
2178  goto cleanup;
2179  }
2180  }
2181 
2182  const bool c_reverse_name = cs_subset_bool(sub, "reverse_name");
2183  /* this is handled here so that the user can match ~f in send-hook */
2184  if (e_cur && c_reverse_name && !(flags & (SEND_POSTPONED | SEND_RESEND)))
2185  {
2186  /* We shouldn't have to worry about alias expansion here since we are
2187  * either replying to a real or postponed message, therefore no aliases
2188  * should exist since the user has not had the opportunity to add
2189  * addresses to the list. We just have to ensure the postponed messages
2190  * have their aliases expanded. */
2191 
2192  if (!TAILQ_EMPTY(&e_templ->env->from))
2193  {
2194  mutt_debug(LL_DEBUG5, "e_templ->env->from before set_reverse_name: %s\n",
2195  TAILQ_FIRST(&e_templ->env->from)->mailbox);
2196  mutt_addrlist_clear(&e_templ->env->from);
2197  }
2198  set_reverse_name(&e_templ->env->from, e_cur->env, sub);
2199  }
2200 
2201  const bool c_reply_with_xorig = cs_subset_bool(sub, "reply_with_xorig");
2202  if (e_cur && c_reply_with_xorig && !(flags & (SEND_POSTPONED | SEND_RESEND | SEND_FORWARD)))
2203  {
2204  /* We shouldn't have to worry about freeing 'e_templ->env->from' before
2205  * setting it here since this code will only execute when doing some
2206  * sort of reply. The pointer will only be set when using the -H command
2207  * line option.
2208  *
2209  * If there is already a from address recorded in 'e_templ->env->from',
2210  * then it theoretically comes from `$reverse_name` handling, and we don't use
2211  * the 'X-Orig-To header'. */
2212  if (!TAILQ_EMPTY(&e_cur->env->x_original_to) && TAILQ_EMPTY(&e_templ->env->from))
2213  {
2214  mutt_addrlist_copy(&e_templ->env->from, &e_cur->env->x_original_to, false);
2215  mutt_debug(LL_DEBUG5, "e_templ->env->from extracted from X-Original-To: header: %s\n",
2216  TAILQ_FIRST(&e_templ->env->from)->mailbox);
2217  }
2218  }
2219 
2220  const bool c_resume_draft_files = cs_subset_bool(sub, "resume_draft_files");
2221  if (!(flags & (SEND_POSTPONED | SEND_RESEND)) &&
2222  !((flags & SEND_DRAFT_FILE) && c_resume_draft_files))
2223  {
2224  if ((flags & (SEND_REPLY | SEND_FORWARD | SEND_TO_SENDER)) && mailbox &&
2225  (envelope_defaults(e_templ->env, mailbox, el, flags, sub) == -1))
2226  {
2227  goto cleanup;
2228  }
2229 
2230  const bool c_hdrs = cs_subset_bool(sub, "hdrs");
2231  if (c_hdrs)
2232  process_user_recips(e_templ->env);
2233 
2234  /* Expand aliases and remove duplicates/crossrefs */
2235  mutt_expand_aliases_env(e_templ->env);
2236 
2237  if (flags & SEND_REPLY)
2238  mutt_fix_reply_recipients(e_templ->env, sub);
2239 
2240 #ifdef USE_NNTP
2241  if ((flags & SEND_NEWS) && (mailbox && mailbox->type == MUTT_NNTP) &&
2242  !e_templ->env->newsgroups)
2243  {
2244  e_templ->env->newsgroups =
2245  mutt_str_dup(((struct NntpMboxData *) mailbox->mdata)->group);
2246  }
2247 #endif
2248 
2249  const bool c_auto_edit = cs_subset_bool(sub, "auto_edit");
2250  const bool c_edit_headers = cs_subset_bool(sub, "edit_headers");
2251  const bool c_fast_reply = cs_subset_bool(sub, "fast_reply");
2252  if (!(flags & SEND_BATCH) && !(c_auto_edit && c_edit_headers) &&
2253  !((flags & SEND_REPLY) && c_fast_reply))
2254  {
2255  if (edit_envelope(e_templ->env, flags, sub) == -1)
2256  goto cleanup;
2257  }
2258 
2259  /* the from address must be set here regardless of whether or not
2260  * $use_from is set so that the '~P' (from you) operator in send-hook
2261  * patterns will work. if $use_from is unset, the from address is killed
2262  * after send-hooks are evaluated */
2263 
2264  const bool killfrom = TAILQ_EMPTY(&e_templ->env->from);
2265  if (killfrom)
2266  {
2268  }
2269 
2270  if ((flags & SEND_REPLY) && e_cur)
2271  {
2272  /* change setting based upon message we are replying to */
2273  mutt_message_hook(mailbox, e_cur, MUTT_REPLY_HOOK);
2274 
2275  /* set the replied flag for the message we are generating so that the
2276  * user can use ~Q in a send-hook to know when reply-hook's are also
2277  * being used. */
2278  e_templ->replied = true;
2279  }
2280 
2281  /* change settings based upon recipients */
2282 
2283  mutt_message_hook(NULL, e_templ, MUTT_SEND_HOOK);
2284 
2285  /* Unset the replied flag from the message we are composing since it is
2286  * no longer required. This is done here because the FCC'd copy of
2287  * this message was erroneously get the 'R'eplied flag when stored in
2288  * a maildir-style mailbox. */
2289  e_templ->replied = false;
2290 
2291  /* $use_from and/or $from might have changed in a send-hook */
2292  if (killfrom)
2293  {
2294  mutt_addrlist_clear(&e_templ->env->from);
2295 
2296  const bool c_use_from = cs_subset_bool(sub, "use_from");
2297  if (c_use_from && !(flags & (SEND_POSTPONED | SEND_RESEND)))
2299  }
2300 
2301  if (c_hdrs)
2302  process_user_header(e_templ->env);
2303 
2304  if (flags & SEND_BATCH)
2305  {
2306  if (mutt_file_copy_stream(stdin, fp_tmp) < 1)
2307  {
2308  mutt_error(_("Refusing to send an empty email"));
2309  mutt_message(_("Try: echo | neomutt -s 'subject' user@example.com"));
2310  goto cleanup;
2311  }
2312  }
2313 
2314  const bool c_sig_on_top = cs_subset_bool(sub, "sig_on_top");
2315  const char *c_editor = cs_subset_string(sub, "editor");
2316  if (c_sig_on_top && !(flags & (SEND_KEY | SEND_BATCH)) && c_editor)
2317  {
2318  append_signature(fp_tmp, sub);
2319  }
2320 
2321  /* include replies/forwarded messages, unless we are given a template */
2322  if (!tempfile && (mailbox || !(flags & (SEND_REPLY | SEND_FORWARD))) &&
2323  (generate_body(fp_tmp, e_templ, flags, mailbox, el, sub) == -1))
2324  {
2325  goto cleanup;
2326  }
2327 
2328  if (!c_sig_on_top && !(flags & (SEND_KEY | SEND_BATCH)) && c_editor)
2329  {
2330  append_signature(fp_tmp, sub);
2331  }
2332  }
2333 
2334  /* Only set format=flowed for new messages. postponed/resent/draftfiles
2335  * should respect the original email.
2336  *
2337  * This is set here so that send-hook can be used to turn the option on. */
2339  {
2340  const bool c_text_flowed = cs_subset_bool(sub, "text_flowed");
2341  if (c_text_flowed && is_text_plain(e_templ->body))
2342  {
2343  mutt_param_set(&e_templ->body->parameter, "format", "flowed");
2344  }
2345  }
2346 
2347  /* This hook is even called for postponed messages, and can, e.g., be used
2348  * for setting the editor, the sendmail path, or the envelope sender. */
2349  mutt_message_hook(NULL, e_templ, MUTT_SEND2_HOOK);
2350 
2351  /* wait until now to set the real name portion of our return address so
2352  * that $real_name can be set in a send-hook */
2353  {
2354  struct Address *from = TAILQ_FIRST(&e_templ->env->from);
2355  if (from && !from->personal && !(flags & (SEND_RESEND | SEND_POSTPONED)))
2356  {
2357  const char *c_real_name = cs_subset_string(sub, "real_name");
2358  from->personal = mutt_str_dup(c_real_name);
2359  }
2360  }
2361 
2362  if (!(((WithCrypto & APPLICATION_PGP) != 0) && (flags & SEND_KEY)))
2363  mutt_file_fclose(&fp_tmp);
2364 
2365  if (!(flags & SEND_BATCH))
2366  {
2367  struct stat st;
2368  time_t mtime = mutt_file_decrease_mtime(e_templ->body->filename, NULL);
2369  if (mtime == (time_t) -1)
2370  {
2371  mutt_perror(e_templ->body->filename);
2372  goto cleanup;
2373  }
2374 
2375  mutt_update_encoding(e_templ->body, sub);
2376 
2377  const bool c_edit_headers = cs_subset_bool(sub, "edit_headers");
2378  const bool c_auto_edit = cs_subset_bool(sub, "auto_edit");
2379  const enum QuadOption c_forward_edit = cs_subset_quad(sub, "forward_edit");
2380 
2381  /* Select whether or not the user's editor should be called now. We
2382  * don't want to do this when:
2383  * 1) we are sending a key/cert
2384  * 2) we are forwarding a message and the user doesn't want to edit it.
2385  * This is controlled by the quadoption $forward_edit. However, if
2386  * both $edit_headers and $auto_edit are set, we want to ignore the
2387  * setting of $forward_edit because the user probably needs to add the
2388  * recipients. */
2389  if (!(flags & SEND_KEY) &&
2390  (((flags & SEND_FORWARD) == 0) || (c_edit_headers && c_auto_edit) ||
2391  (query_quadoption(c_forward_edit, _("Edit forwarded message?")) == MUTT_YES)))
2392  {
2393  /* If the this isn't a text message, look for a mailcap edit command */
2394  const char *c_editor = cs_subset_string(sub, "editor");
2395  if (mutt_needs_mailcap(e_templ->body))
2396  {
2397  if (!mutt_edit_attachment(e_templ->body))
2398  goto cleanup;
2399  }
2400  else if (c_edit_headers)
2401  {
2402  mutt_env_to_local(e_templ->env);
2403  mutt_edit_headers(c_editor, e_templ->body->filename, e_templ, &fcc);
2404  mutt_env_to_intl(e_templ->env, NULL, NULL);
2405  }
2406  else
2407  {
2408  mutt_edit_file(c_editor, e_templ->body->filename);
2409  if (stat(e_templ->body->filename, &st) == 0)
2410  {
2411  if (mtime != st.st_mtime)
2412  fix_end_of_file(e_templ->body->filename);
2413  }
2414  else
2415  mutt_perror(e_templ->body->filename);
2416  }
2417 
2418  mutt_message_hook(NULL, e_templ, MUTT_SEND2_HOOK);
2419  }
2420 
2422  {
2423  if (stat(e_templ->body->filename, &st) == 0)
2424  {
2425  const enum QuadOption c_abort_unmodified =
2426  cs_subset_quad(sub, "abort_unmodified");
2427 
2428  /* if the file was not modified, bail out now */
2429  if ((mtime == st.st_mtime) && !e_templ->body->next &&
2430  (query_quadoption(c_abort_unmodified,
2431  _("Abort unmodified message?")) == MUTT_YES))
2432  {
2433  mutt_message(_("Aborted unmodified message"));
2434  goto cleanup;
2435  }
2436  }
2437  else
2438  mutt_perror(e_templ->body->filename);
2439  }
2440  }
2441 
2442  /* Set the message security unless:
2443  * 1) crypto support is not enabled (WithCrypto==0)
2444  * 2) pgp: header field was present during message editing with $edit_headers (e_templ->security != 0)
2445  * 3) we are resending a message
2446  * 4) we are recalling a postponed message (don't override the user's saved settings)
2447  * 5) we are in batch mode
2448  *
2449  * This is done after allowing the user to edit the message so that security
2450  * settings can be configured with send2-hook and $edit_headers. */
2451  if ((WithCrypto != 0) && (e_templ->security == 0) &&
2452  !(flags & (SEND_BATCH | SEND_POSTPONED | SEND_RESEND)))
2453  {
2454  bool c_autocrypt = false;
2455  bool c_autocrypt_reply = false;
2456 
2457 #ifdef USE_AUTOCRYPT
2458  c_autocrypt = cs_subset_bool(sub, "autocrypt");
2459  c_autocrypt_reply = cs_subset_bool(sub, "autocrypt_reply");
2460 #endif
2461 
2462  if (c_autocrypt && c_autocrypt_reply && e_cur && (e_cur->security & SEC_AUTOCRYPT))
2463  {
2465  }
2466  else
2467  {
2468  const bool c_crypt_auto_sign = cs_subset_bool(sub, "crypt_auto_sign");
2469  const bool c_crypt_auto_encrypt =
2470  cs_subset_bool(sub, "crypt_auto_encrypt");
2471  const bool c_crypt_reply_encrypt =
2472  cs_subset_bool(sub, "crypt_reply_encrypt");
2473  const bool c_crypt_reply_sign = cs_subset_bool(sub, "crypt_reply_sign");
2474  const bool c_crypt_reply_sign_encrypted =
2475  cs_subset_bool(sub, "crypt_reply_sign_encrypted");
2476 
2477  if (c_crypt_auto_sign)
2478  e_templ->security |= SEC_SIGN;
2479  if (c_crypt_auto_encrypt)
2480  e_templ->security |= SEC_ENCRYPT;
2481  if (c_crypt_reply_encrypt && e_cur && (e_cur->security & SEC_ENCRYPT))
2482  e_templ->security |= SEC_ENCRYPT;
2483  if (c_crypt_reply_sign && e_cur && (e_cur->security & SEC_SIGN))
2484  e_templ->security |= SEC_SIGN;
2485  if (c_crypt_reply_sign_encrypted && e_cur && (e_cur->security & SEC_ENCRYPT))
2486  e_templ->security |= SEC_SIGN;
2487 
2488  const bool c_crypt_opportunistic_encrypt =
2489  cs_subset_bool(sub, "crypt_opportunistic_encrypt");
2490 
2491  if (((WithCrypto & APPLICATION_PGP) != 0) &&
2492  ((e_templ->security & (SEC_ENCRYPT | SEC_SIGN)) || c_crypt_opportunistic_encrypt))
2493  {
2494  const bool c_pgp_auto_inline = cs_subset_bool(sub, "pgp_auto_inline");
2495  const bool c_pgp_reply_inline = cs_subset_bool(sub, "pgp_reply_inline");
2496 
2497  if (c_pgp_auto_inline)
2498  e_templ->security |= SEC_INLINE;
2499  if (c_pgp_reply_inline && e_cur && (e_cur->security & SEC_INLINE))
2500  e_templ->security |= SEC_INLINE;
2501  }
2502  }
2503 
2504  const bool c_crypt_opportunistic_encrypt =
2505  cs_subset_bool(sub, "crypt_opportunistic_encrypt");
2506 
2507  if (e_templ->security || c_crypt_opportunistic_encrypt)
2508  {
2509  const bool c_crypt_auto_pgp = cs_subset_bool(sub, "crypt_auto_pgp");
2510  const bool c_crypt_auto_smime = cs_subset_bool(sub, "crypt_auto_smime");
2511 
2512  /* When replying / forwarding, use the original message's
2513  * crypto system. According to the documentation,
2514  * smime_is_default should be disregarded here.
2515  *
2516  * Problem: At least with forwarding, this doesn't really
2517  * make much sense. Should we have an option to completely
2518  * disable individual mechanisms at run-time? */
2519  if (e_cur)
2520  {
2521  if (((WithCrypto & APPLICATION_PGP) != 0) && c_crypt_auto_pgp &&
2522  (e_cur->security & APPLICATION_PGP))
2523  {
2524  e_templ->security |= APPLICATION_PGP;
2525  }
2526  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
2527  c_crypt_auto_smime && (e_cur->security & APPLICATION_SMIME))
2528  {
2529  e_templ->security |= APPLICATION_SMIME;
2530  }
2531  }
2532 
2533  const bool c_smime_is_default = cs_subset_bool(sub, "smime_is_default");
2534 
2535  /* No crypto mechanism selected? Use availability + smime_is_default
2536  * for the decision. */
2537  if (!(e_templ->security & (APPLICATION_SMIME | APPLICATION_PGP)))
2538  {
2539  if (((WithCrypto & APPLICATION_SMIME) != 0) && c_crypt_auto_smime && c_smime_is_default)
2540  {
2541  e_templ->security |= APPLICATION_SMIME;
2542  }
2543  else if (((WithCrypto & APPLICATION_PGP) != 0) && c_crypt_auto_pgp)
2544  {
2545  e_templ->security |= APPLICATION_PGP;
2546  }
2547  else if (((WithCrypto & APPLICATION_SMIME) != 0) && c_crypt_auto_smime)
2548  {
2549  e_templ->security |= APPLICATION_SMIME;
2550  }
2551  }
2552  }
2553 
2554  /* opportunistic encrypt relies on SMIME or PGP already being selected */
2555  if (c_crypt_opportunistic_encrypt)
2556  {
2557  /* If something has already enabled encryption, e.g. `$crypt_auto_encrypt`
2558  * or `$crypt_reply_encrypt`, then don't enable opportunistic encrypt for
2559  * the message. */
2560  if (!(e_templ->security & (SEC_ENCRYPT | SEC_AUTOCRYPT)))
2561  {
2562  e_templ->security |= SEC_OPPENCRYPT;
2563  crypt_opportunistic_encrypt(e_templ);
2564  }
2565  }
2566 
2567  /* No permissible mechanisms found. Don't sign or encrypt. */
2568  if (!(e_templ->security & (APPLICATION_SMIME | APPLICATION_PGP)))
2569  e_templ->security = SEC_NO_FLAGS;
2570  }
2571 
2572  /* Deal with the corner case where the crypto module backend is not available.
2573  * This can happen if configured without PGP/SMIME and with GPGME, but
2574  * $crypt_use_gpgme is unset. */
2575  if (e_templ->security && !crypt_has_module_backend(e_templ->security))
2576  {
2577  mutt_error(_(
2578  "No crypto backend configured. Disabling message security setting."));
2579  e_templ->security = SEC_NO_FLAGS;
2580  }
2581 
2582  /* specify a default fcc. if we are in batchmode, only save a copy of
2583  * the message if the value of $copy is yes or ask-yes */
2584 
2585  const enum QuadOption c_copy = cs_subset_quad(sub, "copy");
2586 
2587  if (mutt_buffer_is_empty(&fcc) && !(flags & SEND_POSTPONED_FCC) &&
2588  (!(flags & SEND_BATCH) || (c_copy & 0x1)))
2589  {
2590  /* set the default FCC */
2591  const bool killfrom = TAILQ_EMPTY(&e_templ->env->from);
2592  if (killfrom)
2593  {
2594  mutt_addrlist_append(&e_templ->env->from, mutt_default_from(sub));
2595  }
2596  mutt_select_fcc(&fcc, e_templ);
2597  if (killfrom)
2598  {
2599  mutt_addrlist_clear(&e_templ->env->from);
2600  }
2601  }
2602 
2603  mutt_rfc3676_space_stuff(e_templ);
2604 
2605  mutt_update_encoding(e_templ->body, sub);
2606 
2607  if (!(flags & SEND_BATCH))
2608  {
2609  main_loop:
2610 
2612  i = mutt_compose_menu(
2613  e_templ, &fcc, e_cur,
2614  ((flags & SEND_NO_FREE_HEADER) ? MUTT_COMPOSE_NOFREEHEADER : 0), sub);
2615  if (i == -1)
2616  {
2617 /* abort */
2618 #ifdef USE_NNTP
2619  if (flags & SEND_NEWS)
2620  mutt_message(_("Article not posted"));
2621  else
2622 #endif
2623  mutt_message(_("Mail not sent"));
2624  goto cleanup;
2625  }
2626  else if (i == 1)
2627  {
2628  if (postpone_message(e_templ, e_cur, mutt_buffer_string(&fcc), flags, sub) != 0)
2629  goto main_loop;
2630  mutt_message(_("Message postponed"));
2631  rc = 1;
2632  goto cleanup;
2633  }
2634  }
2635 
2636 #ifdef USE_NNTP
2637  if (!(flags & SEND_NEWS))
2638 #endif
2639  if ((mutt_addrlist_count_recips(&e_templ->env->to) == 0) &&
2640  (mutt_addrlist_count_recips(&e_templ->env->cc) == 0) &&
2641  (mutt_addrlist_count_recips(&e_templ->env->bcc) == 0))
2642  {
2643  if (flags & SEND_BATCH)
2644  {
2645  puts(_("No recipients specified"));
2646  goto cleanup;
2647  }
2648 
2649  mutt_error(_("No recipients specified"));
2650  goto main_loop;
2651  }
2652 
2653  if (mutt_env_to_intl(e_templ->env, &tag, &err))
2654  {
2655  mutt_error(_("Bad IDN in '%s': '%s'"), tag, err);
2656  FREE(&err);
2657  if (flags & SEND_BATCH)
2658  goto cleanup;
2659  goto main_loop;
2660  }
2661 
2662  const enum QuadOption c_abort_nosubject =
2663  cs_subset_quad(sub, "abort_nosubject");
2664 
2665  if (!e_templ->env->subject && !(flags & SEND_BATCH) &&
2666  (query_quadoption(c_abort_nosubject, _("No subject, abort sending?")) != MUTT_NO))
2667  {
2668  /* if the abort is automatic, print an error message */
2669  if (c_abort_nosubject == MUTT_YES)
2670  mutt_error(_("No subject specified"));
2671  goto main_loop;
2672  }
2673 #ifdef USE_NNTP
2674  if ((flags & SEND_NEWS) && !e_templ->env->subject)
2675  {
2676  mutt_error(_("No subject specified"));
2677  goto main_loop;
2678  }
2679 
2680  if ((flags & SEND_NEWS) && !e_templ->env->newsgroups)
2681  {
2682  mutt_error(_("No newsgroup specified"));
2683  goto main_loop;
2684  }
2685 #endif
2686 
2687  if (!(flags & SEND_BATCH) && abort_for_missing_attachments(e_templ->body, sub))
2688  {
2689  goto main_loop;
2690  }
2691 
2692  if (e_templ->body->next)
2693  e_templ->body = mutt_make_multipart(e_templ->body);
2694 
2695  /* Ok, we need to do it this way instead of handling all fcc stuff in
2696  * one place in order to avoid going to main_loop with encoded "env"
2697  * in case of error. Ugh. */
2698 
2699  mutt_encode_descriptions(e_templ->body, true, sub);
2700 
2701  /* Make sure that clear_content and free_clear_content are
2702  * properly initialized -- we may visit this particular place in
2703  * the code multiple times, including after a failed call to
2704  * mutt_protect(). */
2705 
2706  clear_content = NULL;
2707  free_clear_content = false;
2708 
2709  if (WithCrypto)
2710  {
2711  if (e_templ->security & (SEC_ENCRYPT | SEC_SIGN | SEC_AUTOCRYPT))
2712  {
2713  /* save the decrypted attachments */
2714  clear_content = e_templ->body;
2715 
2716  if ((crypt_get_keys(e_templ, &pgpkeylist, 0) == -1) ||
2717  (mutt_protect(e_templ, pgpkeylist, false) == -1))
2718  {
2719  e_templ->body = mutt_remove_multipart(e_templ->body);
2720 
2721  FREE(&pgpkeylist);
2722 
2723  decode_descriptions(e_templ->body);
2724  goto main_loop;
2725  }
2726  mutt_encode_descriptions(e_templ->body, false, sub);
2727  }
2728 
2729  /* at this point, e_templ->body is one of the following three things:
2730  * - multipart/signed. In this case, clear_content is a child
2731  * - multipart/encrypted. In this case, clear_content exists independently
2732  * - application/pgp. In this case, clear_content exists independently
2733  * - something else. In this case, it's the same as clear_content */
2734 
2735  /* This is ugly -- lack of "reporting back" from mutt_protect(). */
2736 
2737  if (clear_content && (e_templ->body != clear_content) &&
2738  (e_templ->body->parts != clear_content))
2739  free_clear_content = true;
2740  }
2741 
2742  if (!OptNoCurses)
2743  mutt_message(_("Sending message..."));
2744 
2745  mutt_prepare_envelope(e_templ->env, true, sub);
2746 
2747  const bool c_fcc_before_send = cs_subset_bool(sub, "fcc_before_send");
2748  if (c_fcc_before_send)
2749  save_fcc(e_templ, &fcc, clear_content, pgpkeylist, flags, &finalpath, sub);
2750 
2751  i = invoke_mta(mailbox, e_templ, sub);
2752  if (i < 0)
2753  {
2754  if (!(flags & SEND_BATCH))
2755  {
2756  if (!WithCrypto)
2757  ; // do nothing
2758  else if ((e_templ->security & (SEC_ENCRYPT | SEC_AUTOCRYPT)) ||
2759  ((e_templ->security & SEC_SIGN) && (e_templ->body->type == TYPE_APPLICATION)))
2760  {
2761  if (e_templ->body != clear_content)
2762  {
2763  mutt_body_free(&e_templ->body); /* destroy PGP data */
2764  e_templ->body = clear_content; /* restore clear text. */
2765  }
2766  }
2767  else if ((e_templ->security & SEC_SIGN) && (e_templ->body->type == TYPE_MULTIPART))
2768  {
2769  mutt_body_free(&e_templ->body->parts->next); /* destroy sig */
2770  e_templ->body = mutt_remove_multipart(e_templ->body);
2771  }
2772 
2773  FREE(&pgpkeylist);
2774  mutt_env_free(&e_templ->body->mime_headers); /* protected headers */
2775  e_templ->body = mutt_remove_multipart(e_templ->body);
2776  decode_descriptions(e_templ->body);
2777  mutt_unprepare_envelope(e_templ->env);
2778  FREE(&finalpath);
2779  goto main_loop;
2780  }
2781  else
2782  {
2783  puts(_("Could not send the message"));
2784  goto cleanup;
2785  }
2786  }
2787 
2788  if (!c_fcc_before_send)
2789  save_fcc(e_templ, &fcc, clear_content, pgpkeylist, flags, &finalpath, sub);
2790 
2791  if (!OptNoCurses)
2792  {
2793  mutt_message((i != 0) ? _("Sending in background") :
2794  (flags & SEND_NEWS) ? _("Article posted") : /* USE_NNTP */
2795  _("Mail sent"));
2796 #ifdef USE_NOTMUCH
2797  const bool c_nm_record = cs_subset_bool(sub, "nm_record");
2798  if (c_nm_record)
2799  nm_record_message(mailbox, finalpath, e_cur);
2800 #endif
2801  mutt_sleep(0);
2802  }
2803 
2804  if (WithCrypto)
2805  FREE(&pgpkeylist);
2806 
2807  if ((WithCrypto != 0) && free_clear_content)
2808  mutt_body_free(&clear_content);
2809 
2810  /* set 'replied' flag only if the user didn't change/remove
2811  * In-Reply-To: and References: headers during edit */
2812  if (flags & SEND_REPLY)
2813  {
2814  if (!(flags & SEND_POSTPONED) && mailbox)
2815  {
2816  STAILQ_FOREACH(en, el, entries)
2817  {
2818  mutt_set_flag(mailbox, en->email, MUTT_REPLIED, is_reply(en->email, e_templ));
2819  }
2820  }
2821  }
2822 
2823  rc = 0;
2824 
2825 cleanup:
2826  mutt_buffer_dealloc(&fcc);
2827 
2828  if (flags & SEND_POSTPONED)
2829  {
2831  {
2832  cs_subset_str_string_set(sub, "pgp_sign_as", pgp_sign_as, NULL);
2833  }
2835  {
2836  cs_subset_str_string_set(sub, "smime_sign_as", smime_sign_as, NULL);
2837  }
2838  }
2839 
2840  mutt_file_fclose(&fp_tmp);
2841  if (!(flags & SEND_NO_FREE_HEADER))
2842  email_free(&e_templ);
2843 
2844  FREE(&finalpath);
2845  return rc;
2846 }
+ Here is the caller graph for this function:
Envelope
The header of an Email.
Definition: envelope.h:54
mutt_expand_aliases_env
void mutt_expand_aliases_env(struct Envelope *env)
Expand aliases in all the fields of an Envelope.
Definition: alias.c:308
CopyHeaderFlags
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:49
Email::msgno
int msgno
Number displayed to the user.
Definition: email.h:87
Envelope::subject
char * subject
Email's subject.
Definition: envelope.h:66
AttachCtx
A set of attachments.
Definition: attach.h:49
SEND_GROUP_CHAT_REPLY
#define SEND_GROUP_CHAT_REPLY
Reply to all recipients preserving To/Cc.
Definition: send.h:53
mix_send_message
int mix_send_message(struct ListHead *chain, const char *tempfile)
Send an email via Mixmaster.
Definition: remailer.c:846
mutt_open_read
FILE * mutt_open_read(const char *path, pid_t *thepid)
Run a command to read from.
Definition: muttlib.c:1306
Envelope::bcc
struct AddressList bcc
Email's 'Bcc' list.
Definition: envelope.h:60
crypt_pgp_make_key_attachment
struct Body * crypt_pgp_make_key_attachment(void)
Wrapper for CryptModuleSpecs::pgp_make_key_attachment()
Definition: cryptglue.c:305
mutt_message_hook
void mutt_message_hook(struct Mailbox *m, struct Email *e, HookFlags type)
Perform a message hook.
Definition: hook.c:574
QuadOption
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
SEND_REPLY
#define SEND_REPLY
Reply to sender.
Definition: send.h:41
AttachCtx::fp_root
FILE * fp_root
Used by recvattach for updating.
Definition: attach.h:52
Envelope::followup_to
char * followup_to
List of 'followup-to' fields.
Definition: envelope.h:77
CH_REORDER
#define CH_REORDER
Re-order output of headers (specified by 'hdr_order')
Definition: copy.h:58
make_reference_headers
static void make_reference_headers(struct EmailList *el, struct Envelope *env, struct ConfigSubset *sub)
Generate reference headers for an email.
Definition: send.c:985
mutt_mem_calloc
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
MUTT_CM_CHARCONV
#define MUTT_CM_CHARCONV
Perform character set conversions.
Definition: copy.h:41
_
#define _(a)
Definition: message.h:28
NONULL
#define NONULL(x)
Definition: string2.h:37
Mailbox
A mailbox.
Definition: mailbox.h:81
Envelope::x_original_to
struct AddressList x_original_to
Email's 'X-Orig-to'.
Definition: envelope.h:64
mutt_file_decrease_mtime
time_t mutt_file_decrease_mtime(const char *fp, struct stat *st)
Decrease a file's modification time by 1 second.
Definition: file.c:963
Envelope::in_reply_to
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:82
Envelope::message_id
char * message_id
Message ID.
Definition: envelope.h:69
mutt_make_string
void mutt_make_string(char *buf, size_t buflen, int cols, const char *s, struct Mailbox *m, int inpgr, struct Email *e, MuttFormatFlags flags, const char *progress)
Create formatted strings using mailbox expandos.
Definition: hdrline.c:1427
APPLICATION_SMIME
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:98
MUTT_SEND2_HOOK
#define MUTT_SEND2_HOOK
send2-hook: when changing fields in the compose menu
Definition: hook.h:56
mutt_addrlist_dedupe
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1405
invoke_mta
static int invoke_mta(struct Mailbox *m, struct Email *e, struct ConfigSubset *sub)
Send an email.
Definition: send.c:1371
SEND_BATCH
#define SEND_BATCH
Send email in batch mode (without user interaction)
Definition: send.h:46
Address::personal
char * personal
Real name of address.
Definition: address.h:36
mutt_env_to_intl
int mutt_env_to_intl(struct Envelope *env, const char **tag, char **err)
Convert an Envelope's Address fields to Punycode format.
Definition: envelope.c:309
ListNode
A List node for strings.
Definition: list.h:34
Buffer
String manipulation buffer.
Definition: buffer.h:33
mutt_list_find
struct ListNode * mutt_list_find(const struct ListHead *h, const char *data)
Find a string in a List.
Definition: list.c:102
mutt_addrlist_append
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1488
mutt_addrlist_to_intl
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1304
ctx_mailbox
struct Mailbox * ctx_mailbox(struct Context *ctx)
wrapper to get the mailbox in a Context, or NULL
Definition: context.c:429
mutt_update_encoding
void mutt_update_encoding(struct Body *a, struct ConfigSubset *sub)
Update the encoding type.
Definition: sendlib.c:905
mutt_get_name
const char * mutt_get_name(const struct Address *a)
Pick the best name to display from an address.
Definition: sort.c:158
SEC_OPPENCRYPT
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:93
mutt_file_fclose
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
mutt_buffer_pretty_mailbox
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:599
SEC_AUTOCRYPT_OVERRIDE
#define SEC_AUTOCRYPT_OVERRIDE
(Autocrypt) Indicates manual set/unset of encryption
Definition: lib.h:95
Body::next
struct Body * next
next attachment in the list
Definition: body.h:53
mutt_buffer_is_empty
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
mutt_buffer_dealloc
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
is_text_plain
static bool is_text_plain(const struct Body *b)
is a Body a text/plain MIME part?
Definition: send.c:1946
Body
The body of an email.
Definition: body.h:34
SEC_ENCRYPT
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:85
AttachPtr::fp
FILE * fp
Used in the recvattach menu.
Definition: attach.h:37
MUTT_CM_NOHEADER
#define MUTT_CM_NOHEADER
Don't copy the message header.
Definition: copy.h:35
mutt_remove_multipart
struct Body * mutt_remove_multipart(struct Body *b)
Extract the multipart body if it exists.
Definition: multipart.c:126
mutt_add_to_reference_headers
void mutt_add_to_reference_headers(struct Envelope *env, struct Envelope *curenv, struct ConfigSubset *sub)
Generate references for a reply email.
Definition: send.c:965
SEC_SIGN
#define SEC_SIGN
Email is signed.
Definition: lib.h:86
SEND_KEY
#define SEND_KEY
Mail a PGP public key.
Definition: send.h:47
default_to
static int default_to(struct AddressList *to, struct Envelope *env, SendFlags flags, int hmfupto, struct ConfigSubset *sub)
Generate default email addresses.
Definition: send.c:712
mutt_addrlist_write
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:1150
envelope_defaults
static int envelope_defaults(struct Envelope *env, struct Mailbox *m, struct EmailList *el, SendFlags flags, struct ConfigSubset *sub)
Fill in some defaults for a new email.
Definition: send.c:1024
MUTT_SEL_NO_FLAGS
#define MUTT_SEL_NO_FLAGS
No flags are set.
Definition: browser.h:41
generate_body
static int generate_body(FILE *fp_tmp, struct Email *e, SendFlags flags, struct Mailbox *m, struct EmailList *el, struct ConfigSubset *sub)
Create a new email body.
Definition: send.c:1096
MUTT_SEND_HOOK
#define MUTT_SEND_HOOK
send-hook: when composing a new email
Definition: hook.h:47
mutt_buffer_mktemp
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
mutt_multi_choice
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: curs_lib.c:937
cs_subset_bool
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:69
TAILQ_EMPTY
#define TAILQ_EMPTY(head)
Definition: queue.h:714
CH_WEED
#define CH_WEED
Weed the headers?
Definition: copy.h:52
mutt_is_quote_line
int mutt_is_quote_line(char *line, regmatch_t *pmatch)
Is a line of message text a quote?
Definition: pager.c:1047
SEND_RESEND
#define SEND_RESEND
Reply using the current email as a template.
Definition: send.h:48
EmailNode::email
struct Email * email
Email in the list.
Definition: email.h:127
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
crypt_has_module_backend
bool crypt_has_module_backend(SecurityFlags type)
Is there a crypto backend for a given type?
Definition: cryptglue.c:169
Regex
Cached regular expression.
Definition: regex3.h:89
mutt_prepare_envelope
void mutt_prepare_envelope(struct Envelope *env, bool final, struct ConfigSubset *sub)
Prepare an email header.
Definition: sendlib.c:1238
mutt_make_multipart
struct Body * mutt_make_multipart(struct Body *b)
Create a multipart email.
Definition: multipart.c:100
MUTT_YES
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:40
mutt_expand_aliases
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:294
Context
The "current" mailbox.
Definition: context.h:38
mutt_str_dup
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
mutt_is_subscribed_list_recipient
int mutt_is_subscribed_list_recipient(bool all_addr, struct Envelope *e)
Matches subscribed mailing lists.
Definition: exec.c:427
mutt_file_fopen
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
LL_DEBUG1
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
Mailbox::flags
uint8_t flags
e.g. MB_NORMAL
Definition: mailbox.h:134
Envelope::x_comment_to
char * x_comment_to
List of 'X-comment-to' fields.
Definition: envelope.h:78
FREE
#define FREE(x)
Definition: memory.h:40
mutt_should_hide_protected_subject
bool mutt_should_hide_protected_subject(struct Email *e)
Should NeoMutt hide the protected subject?
Definition: crypt.c:1076
EmailNode
List of Emails.
Definition: email.h:125
mutt_make_attribution
void mutt_make_attribution(struct Mailbox *m, struct Email *e, FILE *fp_out, struct ConfigSubset *sub)
Add "on DATE, PERSON wrote" header.
Definition: send.c:593
STAILQ_FIRST
#define STAILQ_FIRST(head)
Definition: queue.h:347
Body::disposition
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:67
mutt_perror
#define mutt_perror(...)
Definition: logging.h:85
mutt_addrlist_parse
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:458
decode_descriptions
static void decode_descriptions(struct Body *b)
rfc2047 decode them in case of an error
Definition: send.c:1480
Body::encoding
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
LL_DEBUG5
@ LL_DEBUG5
Log at debug level 5.
Definition: logging.h:44
mutt_parse_mailto
bool mutt_parse_mailto(struct Envelope *e, char **body, const char *src)
Parse a mailto:// url.
Definition: parse.c:1593
SEND_DRAFT_FILE
#define SEND_DRAFT_FILE
Used by the -H flag.
Definition: send.h:51
MUTT_ABORT
@ MUTT_ABORT
User aborted the question (with Ctrl-G)
Definition: quad.h:38
set_reverse_name
static void set_reverse_name(struct AddressList *al, struct Envelope *env, struct ConfigSubset *sub)
Try to set the 'from' field from the recipients.
Definition: send.c:1286
OptNoCurses
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:48
mutt_buffer_reset
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
mutt_sleep
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:1448
mutt_buffer_pool_release
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
STAILQ_EMPTY
#define STAILQ_EMPTY(head)
Definition: queue.h:345
MUTT_FORMAT_NO_FLAGS
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
Username
WHERE char * Username
User's login name.
Definition: mutt_globals.h:52
mutt_make_post_indent
void mutt_make_post_indent(struct Mailbox *m, struct Email *e, FILE *fp_out, struct ConfigSubset *sub)
Add suffix to replied email text.
Definition: send.c:618
mutt_get_postponed
int mutt_get_postponed(struct Context *ctx, struct Email *hdr, struct Email **cur, struct Buffer *fcc)
Recall a postponed message.
Definition: postpone.c:331
mutt_addrlist_prepend
void mutt_addrlist_prepend(struct AddressList *al, struct Address *a)
Prepend an Address to an AddressList.
Definition: address.c:1499
Envelope::real_subj
char * real_subj
Offset of the real subject.
Definition: envelope.h:67
email_new
struct Email * email_new(void)
Create a new Email.
Definition: email.c:72
mutt_body_free
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
Body::subtype
char * subtype
content-type subtype
Definition: body.h:37
mutt_list_insert_tail
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
mutt_array_size
#define mutt_array_size(x)
Definition: memory.h:33
STAILQ_FOREACH
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
mutt_write_fcc
int mutt_write_fcc(const char *path, struct Email *e, const char *msgid, bool post, const char *fcc, char **finalpath, struct ConfigSubset *sub)
Write email to FCC mailbox.
Definition: sendlib.c:1510
mutt_autocrypt_set_sign_as_default_key
int mutt_autocrypt_set_sign_as_default_key(struct Mailbox *m, struct Email *e)
Set the Autocrypt default key for signing.
Definition: autocrypt.c:697
cs_subset_str_native_set
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition: subset.c:292
mutt_edit_address
int mutt_edit_address(struct AddressList *al, const char *field, bool expand_aliases)
Edit an email address.
Definition: send.c:168
mutt_buffer_alloc
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
save_fcc
static int save_fcc(struct Email *e, struct Buffer *fcc, struct Body *clear_content, char *pgpkeylist, SendFlags flags, char **finalpath, struct ConfigSubset *sub)
Save an Email to a 'sent mail' folder.
Definition: send.c:1636
crypt_get_keys
int crypt_get_keys(struct Email *e, char **keylist, bool oppenc_mode)
Check we have all the keys we need.
Definition: crypt.c:945
mutt_edit_headers
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:170
mutt_invoke_sendmail
int mutt_invoke_sendmail(struct Mailbox *m, struct AddressList *from, struct AddressList *to, struct AddressList *cc, struct AddressList *bcc, const char *msg, bool eightbit, struct ConfigSubset *sub)
Run sendmail.
Definition: sendmail.c:287
mutt_parse_mime_message
void mutt_parse_mime_message(struct Mailbox *m, struct Email *e)
Parse a MIME email.
Definition: mutt_parse.c:49
SKIPWS
#define SKIPWS(ch)
Definition: string2.h:46
mutt_istr_equal
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
mutt_unprepare_envelope
void mutt_unprepare_envelope(struct Envelope *env)
Undo the encodings of mutt_prepare_envelope()
Definition: sendlib.c:1277
mutt_is_mail_list
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list? - Implements addr_predicate_t.
Definition: maillist.c:45
mutt_str_equal
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
MUTT_CM_REPLYING
#define MUTT_CM_REPLYING
Replying the message.
Definition: copy.h:43
mutt_write_multiple_fcc
int mutt_write_multiple_fcc(const char *path, struct Email *e, const char *msgid, bool post, char *fcc, char **finalpath, struct ConfigSubset *sub)
Handle FCC with multiple, comma separated entries.
Definition: sendlib.c:1462
MUTT_ALIAS
#define MUTT_ALIAS
Do alias "completion" by calling up the alias-menu.
Definition: mutt.h:57
TAILQ_SWAP
#define TAILQ_SWAP(head1, head2, type, field)
Definition: queue.h:852
Envelope::reply_to
struct AddressList reply_to
Email's 'reply-to'.
Definition: envelope.h:62
mutt_is_list_recipient
int mutt_is_list_recipient(bool all_addr, struct Envelope *e)
Matches known mailing lists.
Definition: exec.c:440
SEND_NEWS
#define SEND_NEWS
Reply to a news article.
Definition: send.h:54
Email::old
bool old
Email is seen, but unread.
Definition: email.h:50
TAILQ_REMOVE
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:834
Email::received
time_t received
Time when the message was placed in the mailbox.
Definition: email.h:83
MUTT_CM_WEED
#define MUTT_CM_WEED
Weed message/rfc822 attachment headers.
Definition: copy.h:40
mutt_rfc822_write_header
int mutt_rfc822_write_header(FILE *fp, struct Envelope *env, struct Body *attach, enum MuttWriteHeaderMode mode, bool privacy, bool hide_protected_subject, struct ConfigSubset *sub)
Write out one RFC822 header line.
Definition: header.c:574
TAILQ_FIRST
#define TAILQ_FIRST(head)
Definition: queue.h:716
mutt_parse_content_type
void mutt_parse_content_type(const char *s, struct Body *ct)
Parse a content type.
Definition: parse.c:426
cs_subset_address
const struct Address * cs_subset_address(const struct ConfigSubset *sub, const char *name)
Get an Address config item by name.
Definition: helpers.c:48
Envelope::cc
struct AddressList cc
Email's 'Cc' list.
Definition: envelope.h:59
query_quadoption
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: curs_lib.c:518
mutt_body_new
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
SEND_FORWARD
#define SEND_FORWARD
Forward email.
Definition: send.h:44
mutt_env_free
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
mutt_buffer_pool_get
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
MUTT_NNTP
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
Definition: mailbox.h:52
mutt_can_decode
bool mutt_can_decode(struct Body *a)
Will decoding the attachment produce any output.
Definition: handler.c:1805
mutt_edit_file
void mutt_edit_file(const char *editor, const char *file)
Let the user edit a file.
Definition: curs_lib.c:356
Mailbox::type
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
CH_DECODE
#define CH_DECODE
Do RFC2047 header decoding.
Definition: copy.h:53
Mailbox::mdata
void * mdata
Driver specific data.
Definition: mailbox.h:136
SEND_POSTPONED
#define SEND_POSTPONED
Recall a postponed email.
Definition: send.h:45
SEND_POSTPONED_FCC
#define SEND_POSTPONED_FCC
Used by mutt_get_postponed() to signal that the x-mutt-fcc header field was present.
Definition: send.h:49
SEND_TO_SENDER
#define SEND_TO_SENDER
Compose new email to sender.
Definition: send.h:52
AutocryptDefaultKey
char * AutocryptDefaultKey
Autocrypt default key id (used for postponing messages)
Definition: config.c:43
TAILQ_FOREACH_REVERSE
#define TAILQ_FOREACH_REVERSE(var, head, headname, field)
Definition: queue.h:738
mutt_file_copy_stream
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
mutt_protect
int mutt_protect(struct Email *e, char *keylist, bool postpone)
Encrypt and/or sign a message.
Definition: crypt.c:160
rfc2047_decode
void rfc2047_decode(char **pd)
Decode any RFC2047-encoded header fields.
Definition: rfc2047.c:639
Address::group
bool group
Group mailbox?
Definition: address.h:38
mutt_extract_message_id
char * mutt_extract_message_id(const char *s, size_t *len)
Find a message-id.
Definition: parse.c:362
mutt_write_mime_body
int mutt_write_mime_body(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Write a MIME part.
Definition: body.c:314
include_reply
static int include_reply(struct Mailbox *m, struct Email *e, FILE *fp_out, struct ConfigSubset *sub)
Generate the reply text for an email.
Definition: send.c:642
ENC_8BIT
@ ENC_8BIT
8-bit text
Definition: mime.h:50
APPLICATION_PGP
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:97
MUTT_CM_NO_FLAGS
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:34
mutt_list_insert_head
struct ListNode * mutt_list_insert_head(struct ListHead *h, char *s)
Insert a string at the beginning of a List.
Definition: list.c:45
cs_subset_str_string_set
int cs_subset_str_string_set(const struct ConfigSubset *sub, const char *name, const char *value, struct Buffer *err)
Set a config item by string.
Definition: subset.c:395
cs_subset_path
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:133
mutt_make_message_attach
struct Body * mutt_make_message_attach(struct Mailbox *m, struct Email *e, bool attach_msg, struct ConfigSubset *sub)
Create a message attachment.
Definition: sendlib.c:937
cs_subset_regex
const struct Regex * cs_subset_regex(const struct ConfigSubset *sub, const char *name)
Get a regex config item by name.
Definition: helpers.c:176
add_mailing_lists
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:141
mutt_clear_error
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
mutt_str_skip_email_wsp
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:743
rfc2047_encode
void rfc2047_encode(char **pd, const char *specials, int col, const char *charsets)
RFC-2047-encode a string.
Definition: rfc2047.c:615
mutt_env_to_local
void mutt_env_to_local(struct Envelope *env)
Convert an Envelope's Address fields to local format.
Definition: envelope.c:271
add_references
static void add_references(struct ListHead *head, struct Envelope *env)
Add the email's references to a list.
Definition: send.c:857
mutt_send_message
int mutt_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Context *ctx, struct EmailList *el, struct ConfigSubset *sub)
Send an email.
Definition: send.c:2012
mutt_addrlist_clear
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1468
postpone_message
static int postpone_message(struct Email *e_post, struct Email *e_cur, const char *fcc, SendFlags flags, struct ConfigSubset *sub)
Save an Email for another day.
Definition: send.c:1833
mutt_addrlist_parse2
int mutt_addrlist_parse2(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:616
mutt_encode_descriptions
void mutt_encode_descriptions(struct Body *b, bool recurse, struct ConfigSubset *sub)
rfc2047 encode the content-descriptions
Definition: send.c:1462
MUTT_IMAP
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:53
mutt_param_set
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
Envelope::to
struct AddressList to
Email's 'To' list.
Definition: envelope.h:58
Body::parts
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
mutt_addrlist_remove_xrefs
void mutt_addrlist_remove_xrefs(const struct AddressList *a, struct AddressList *b)
Remove cross-references.
Definition: address.c:1441
process_user_header
static void process_user_header(struct Envelope *env)
Process the user headers.
Definition: send.c:359
AttachPtr::body
struct Body * body
Attachment.
Definition: attach.h:36
Context::mailbox
struct Mailbox * mailbox
Definition: context.h:50
emaillist_add_email
int emaillist_add_email(struct EmailList *el, struct Email *e)
Add an Email to a list.
Definition: email.c:151
MUTT_WRITE_HEADER_NORMAL
@ MUTT_WRITE_HEADER_NORMAL
A normal Email, write full header + MIME headers.
Definition: header.h:40
abort_for_missing_attachments
static bool abort_for_missing_attachments(const struct Body *b, struct ConfigSubset *sub)
Should we abort sending because of missing attachments?
Definition: send.c:1957
Email::env
struct Envelope * env
Envelope information.
Definition: email.h:90
mutt_update_num_postponed
void mutt_update_num_postponed(void)
Force the update of the number of postponed messages.
Definition: postpone.c:203
mutt_debug
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
MUTT_REPLIED
@ MUTT_REPLIED
Messages that have been replied to.
Definition: mutt.h:95
SEND_GROUP_REPLY
#define SEND_GROUP_REPLY
Reply to all.
Definition: send.h:42
MUTT_NO
@ MUTT_NO
User answered 'No', or assume 'No'.
Definition: quad.h:39
mutt_make_forward_subject
void mutt_make_forward_subject(struct Envelope *env, struct Mailbox *m, struct Email *e, struct ConfigSubset *sub)
Create a subject for a forwarded email.
Definition: send.c:917
mutt_addr_free
void mutt_addr_free(struct Address **ptr)
Free a single Address.
Definition: address.c:440
edit_envelope
static int edit_envelope(struct Envelope *en, SendFlags flags, struct ConfigSubset *sub)
Edit Envelope fields.
Definition: send.c:203
mutt_buffer_expand_path
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:323
Message::fp
FILE * fp
pointer to the message data
Definition: mx.h:96
mutt_str_len
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
mutt_regex_match
bool mutt_regex_match(const struct Regex *regex, const char *str)
Shorthand to mutt_regex_capture()
Definition: regex.c:611
mutt_prepare_template
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:664
TAILQ_FOREACH_SAFE
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:728
mutt_buffer_string
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
mutt_addr_new
struct Address * mutt_addr_new(void)
Create a new Address.
Definition: address.c:385
Email::chain
struct ListHead chain
Mixmaster chain.
Definition: email.h:102
mutt_env_new
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
Email::security
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition: email.h:39
mutt_date_epoch
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:416
cs_subset_quad
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition: helpers.c:154
mutt_forward_trailer
void mutt_forward_trailer(struct Mailbox *m, struct Email *e, FILE *fp, struct ConfigSubset *sub)
Add a "end of forwarded message" text.
Definition: send.c:437
mutt_str_replace
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
filter_wait
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
remove_user
static void remove_user(struct AddressList *al, bool leave_only)
Remove any address which matches the current user.
Definition: send.c:122
inline_forward_attachments
static int inline_forward_attachments(struct Mailbox *m, struct Email *e, struct Body ***plast, enum QuadOption *forwardq, struct ConfigSubset *sub)
Add attachments to an email, inline.
Definition: send.c:517
WithCrypto
#define WithCrypto
Definition: lib.h:123
Address::mailbox
char * mailbox
Mailbox and host address.
Definition: address.h:37
Envelope::newsgroups
char * newsgroups
List of newsgroups.
Definition: envelope.h:75
mutt_edit_attachment
int mutt_edit_attachment(struct Body *a)
Edit an attachment.
Definition: mutt_attach.c:259
STAILQ_HEAD_INITIALIZER
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:321
mutt_addr_copy
struct Address * mutt_addr_copy(const struct Address *addr)
Copy the real address.
Definition: address.c:716
cs_subset_string
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:241
mutt_mktemp
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:74
Envelope::userhdrs
struct ListHead userhdrs
user defined headers
Definition: envelope.h:83
Envelope::from
struct AddressList from
Email's 'From' list.
Definition: envelope.h:57
search_attach_keyword
static bool search_attach_keyword(char *filename, struct ConfigSubset *sub)
Search an email for 'attachment' keywords.
Definition: send.c:1590
TYPE_APPLICATION
@ TYPE_APPLICATION
Type: 'application/*'.
Definition: mime.h:33
mutt_make_misc_reply_headers
void mutt_make_misc_reply_headers(struct Envelope *env, struct Envelope *curenv, struct ConfigSubset *sub)
Set subject for a reply.
Definition: send.c:938
process_user_recips
static void process_user_recips(struct Envelope *env)
Process the user headers.
Definition: send.c:332
TAILQ_NEXT
#define TAILQ_NEXT(elm, field)
Definition: queue.h:825
mutt_mem_malloc
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
TYPE_TEXT
@ TYPE_TEXT
Type: 'text/*'.
Definition: mime.h:38
is_reply
static bool is_reply(struct Email *reply, struct Email *orig)
Is one email a reply to another?
Definition: send.c:1571
MUTT_MESSAGE_HOOK
#define MUTT_MESSAGE_HOOK
message-hook: run before displaying a message
Definition: hook.h:52
mutt_generate_recvattach_list
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:1363
MUTT_COMPOSE_NOFREEHEADER
#define MUTT_COMPOSE_NOFREEHEADER
Definition: lib.h:43
mutt_forward_intro
void mutt_forward_intro(struct Mailbox *m, struct Email *e, FILE *fp, struct ConfigSubset *sub)
Add the "start of forwarded message" text.
Definition: send.c:411
nntp_get_header
static char * nntp_get_header(const char *s)
Get the trimmed header.
Definition: send.c:321
DISP_INLINE
@ DISP_INLINE
Content is inline.
Definition: mime.h:62
SEC_INLINE
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:92
crypt_opportunistic_encrypt
void crypt_opportunistic_encrypt(struct Email *e)
Can all recipients be determined.
Definition: crypt.c:1024
mutt_istr_startswith
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:172
AttachCtx::email
struct Email * email
Used by recvattach for updating.
Definition: attach.h:51
Body::type
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
mutt_num_postponed
int mutt_num_postponed(struct Mailbox *m, bool force)
Return the number of postponed messages.
Definition: postpone.c:89
fix_end_of_file
static void fix_end_of_file(const char *data)
Ensure a file ends with a linefeed.
Definition: send.c:1497
imap_path_probe
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2372
mutt_actx_free
void mutt_actx_free(struct AttachCtx **ptr)
Free an Attachment Context.
Definition: attach.c:140
mutt_compose_menu
int mutt_compose_menu(struct Email *e, struct Buffer *fcc, struct Email *e_cur, uint8_t flags, struct ConfigSubset *sub)
Allow the user to edit the message envelope.
Definition: compose.c:1474
Regex::regex
regex_t * regex
compiled expression
Definition: regex3.h:92
Envelope::list_post
char * list_post
This stores a mailto URL, or nothing.
Definition: envelope.h:65
ListNode::data
char * data
String.
Definition: list.h:36
mutt_default_from
struct Address * mutt_default_from(struct ConfigSubset *sub)
Get a default 'from' Address.
Definition: send.c:1338
AttachCtx::idx
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
mutt_body_copy
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
MUTT_CM_DECODE
#define MUTT_CM_DECODE
Decode the message body into text/plain.
Definition: copy.h:37
mutt_select_fcc
void mutt_select_fcc(struct Buffer *path, struct Email *e)
Select the FCC path for an email.
Definition: hook.c:693
email_free
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:43
Body::use_disp
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
plen
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
SEND_LIST_REPLY
#define SEND_LIST_REPLY
Reply to mailing list.
Definition: send.h:43
mutt_needs_mailcap
bool mutt_needs_mailcap(struct Body *m)
Does this type need a mailcap entry do display.
Definition: muttlib.c:405
STAILQ_NEXT
#define STAILQ_NEXT(elm, field)
Definition: queue.h:397
OptNewsSend
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:46
append_signature
static void append_signature(FILE *fp, struct ConfigSubset *sub)
Append a signature to an email.
Definition: send.c:93
mutt_addrlist_to_local
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1386
mutt_get_field
int mutt_get_field(const char *field, char *buf, size_t buflen, CompletionFlags complete, bool multiple, char ***files, int *numfiles)
Ask the user for a string.
Definition: curs_lib.c:311
mutt_rfc3676_space_stuff
void mutt_rfc3676_space_stuff(struct Email *e)
Perform RFC3676 space stuffing on an Email.
Definition: rfc3676.c:479
nm_record_message
int nm_record_message(struct Mailbox *m, char *path, struct Email *e)
Add a message to the Notmuch database.
Definition: notmuch.c:1965
Body::unlink
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
mutt_buffer_enter_fname
int mutt_buffer_enter_fname(const char *prompt, struct Buffer *fname, bool mailbox, struct Mailbox *m, bool multiple, char ***files, int *numfiles, SelectFileFlags flags)
Ask the user to select a file.
Definition: curs_lib.c:772
Body::parameter
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
mutt_addrlist_count_recips
int mutt_addrlist_count_recips(const struct AddressList *al)
Count the number of Addresses with valid recipients.
Definition: address.c:844
mutt_fqdn
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:1182
mx_msg_close
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1204
Mailbox::sub
struct ConfigSubset * sub
Inherited config items.
Definition: mailbox.h:86
Email::replied
bool replied
Email has been replied to.
Definition: email.h:54
Buffer::data
char * data
Pointer to data.
Definition: buffer.h:35
MUTT_ASKNO
@ MUTT_ASKNO
Ask the user, defaulting to 'No'.
Definition: quad.h:41
mutt_addr_cmp
bool mutt_addr_cmp(const struct Address *a, const struct Address *b)
Compare two e-mail addresses.
Definition: address.c:864
TYPE_MULTIPART
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition: mime.h:37
Email
The envelope/body of an email.
Definition: email.h:37
MUTT_CM_PREFIX
#define MUTT_CM_PREFIX
Quote the header and body.
Definition: copy.h:36
mutt_message
#define mutt_message(...)
Definition: logging.h:83
mutt_set_flag
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:67
mutt_addr_create
struct Address * mutt_addr_create(const char *personal, const char *mailbox)
Create and populate a new Address.
Definition: address.c:398
mutt_str_asprintf
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:1095
emaillist_clear
void emaillist_clear(struct EmailList *el)
Drop a private list of Emails.
Definition: email.c:130
Envelope::mail_followup_to
struct AddressList mail_followup_to
Email's 'mail-followup-to'.
Definition: envelope.h:63
mutt_smtp_send
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, struct ConfigSubset *sub)
Send a message using SMTP.
Definition: smtp.c:880
mutt_addrlist_search
bool mutt_addrlist_search(const struct AddressList *haystack, const struct Address *needle)
Search for an e-mail address in a list.
Definition: address.c:881
Envelope::references
struct ListHead references
message references (in reverse order)
Definition: envelope.h:81
mutt_addrlist_copy
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:737
mutt_copy_message
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:835
mutt_buffer_make
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
mutt_list_free
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
crypt_valid_passphrase
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:135
Email::read
bool read
Email is read.
Definition: email.h:51
mutt_addr_valid_msgid
bool mutt_addr_valid_msgid(const char *msgid)
Is this a valid Message ID?
Definition: address.c:764
SEC_NO_FLAGS
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:84
include_forward
static int include_forward(struct Mailbox *m, struct Email *e, FILE *fp_out, struct ConfigSubset *sub)
Write out a forwarded message.
Definition: send.c:467
mutt_fetch_recips
int mutt_fetch_recips(struct Envelope *out, struct Envelope *in, SendFlags flags, struct ConfigSubset *sub)
Generate recpients for a reply email.
Definition: send.c:799
mutt_fix_reply_recipients
void mutt_fix_reply_recipients(struct Envelope *env, struct ConfigSubset *sub)
Remove duplicate recipients.
Definition: send.c:886
MUTT_REPLY_HOOK
#define MUTT_REPLY_HOOK
reply-hook: when replying to an email
Definition: hook.h:55
AttachCtx::idxlen
short idxlen
Number of attachmentes.
Definition: attach.h:55
SEC_AUTOCRYPT
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:94
mutt_addr_is_user
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition: alias.c:556
Address
An email address.
Definition: address.h:34
NntpMboxData
NNTP-specific Mailbox data -.
Definition: mdata.h:31
add_message_id
static void add_message_id(struct ListHead *head, struct Envelope *env)
Add the email's message ID to a list.
Definition: send.c:873
Message
A local copy of an email.
Definition: mx.h:94
Body::mime_headers
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
SEND_NO_FREE_HEADER
#define SEND_NO_FREE_HEADER
Used by the -E flag.
Definition: send.h:50
Body::filename
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
Email::body
struct Body * body
List of MIME parts.
Definition: email.h:91
mx_msg_open
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
return a stream pointer for a message
Definition: mx.c:1158
choose_default_to
static const struct AddressList * choose_default_to(const struct Address *from, const struct Envelope *env, struct ConfigSubset *sub)
Pick the best 'to:' value.
Definition: send.c:686
mutt_error
#define mutt_error(...)
Definition: logging.h:84
CopyMessageFlags
uint16_t CopyMessageFlags
Flags for mutt_copy_message(), e.g. MUTT_CM_NOHEADER.
Definition: copy.h:31
mutt_str_copy
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:716
MUTT_COMP_NO_FLAGS
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56