NeoMutt  2021-02-05-89-gabe350
Teaching an old dog new tricks
DOXYGEN
sendlib.c File Reference
#include "config.h"
#include <errno.h>
#include <iconv.h>
#include <inttypes.h>
#include <limits.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 "mutt.h"
#include "sendlib.h"
#include "lib.h"
#include "ncrypt/lib.h"
#include "context.h"
#include "copy.h"
#include "handler.h"
#include "mutt_globals.h"
#include "mutt_mailbox.h"
#include "mutt_parse.h"
#include "muttlib.h"
#include "mx.h"
#include "options.h"
#include "state.h"
+ Include dependency graph for sendlib.c:

Go to the source code of this file.

Data Structures

struct  ContentState
 Info about the body of an email. More...
 

Functions

static void update_content_info (struct Content *info, struct ContentState *s, char *buf, size_t buflen)
 Cache some info about an email. More...
 
static size_t convert_file_to (FILE *fp, const char *fromcode, int ncodes, char const *const *tocodes, int *tocode, struct Content *info)
 Change the encoding of a file. More...
 
static size_t convert_file_from_to (FILE *fp, const char *fromcodes, const char *tocodes, char **fromcode, char **tocode, struct Content *info)
 Convert a file between encodings. More...
 
struct Contentmutt_get_content_info (const char *fname, struct Body *b, struct ConfigSubset *sub)
 Analyze file to determine MIME encoding to use. More...
 
enum ContentType mutt_lookup_mime_type (struct Body *att, const char *path)
 Find the MIME type for an attachment. More...
 
static void transform_to_7bit (struct Body *a, FILE *fp_in, struct ConfigSubset *sub)
 Convert MIME parts to 7-bit. More...
 
void mutt_message_to_7bit (struct Body *a, FILE *fp, struct ConfigSubset *sub)
 Convert an email's MIME parts to 7-bit. More...
 
static void set_encoding (struct Body *b, struct Content *info, struct ConfigSubset *sub)
 determine which Content-Transfer-Encoding to use More...
 
void mutt_stamp_attachment (struct Body *a)
 Timestamp an Attachment. More...
 
void mutt_update_encoding (struct Body *a, struct ConfigSubset *sub)
 Update the encoding type. More...
 
struct Bodymutt_make_message_attach (struct Mailbox *m, struct Email *e, bool attach_msg, struct ConfigSubset *sub)
 Create a message attachment. More...
 
static void run_mime_type_query (struct Body *att, struct ConfigSubset *sub)
 Run an external command to determine the MIME type. More...
 
struct Bodymutt_make_file_attach (const char *path, struct ConfigSubset *sub)
 Create a file attachment. More...
 
static void encode_headers (struct ListHead *h, struct ConfigSubset *sub)
 RFC2047-encode a list of headers. More...
 
const char * mutt_fqdn (bool may_hide_host, const struct ConfigSubset *sub)
 Get the Fully-Qualified Domain Name. More...
 
static char * gen_msgid (struct ConfigSubset *sub)
 Generate a unique Message ID. More...
 
void mutt_prepare_envelope (struct Envelope *env, bool final, struct ConfigSubset *sub)
 Prepare an email header. More...
 
void mutt_unprepare_envelope (struct Envelope *env)
 Undo the encodings of mutt_prepare_envelope() More...
 
static int bounce_message (FILE *fp, struct Mailbox *m, struct Email *e, struct AddressList *to, const char *resent_from, struct AddressList *env_from, struct ConfigSubset *sub)
 Bounce an email message. More...
 
int mutt_bounce_message (FILE *fp, struct Mailbox *m, struct Email *e, struct AddressList *to, struct ConfigSubset *sub)
 Bounce an email message. More...
 
static void set_noconv_flags (struct Body *b, bool flag)
 Set/reset the "x-mutt-noconv" flag. More...
 
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. More...
 
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. More...
 

Detailed Description

Miscellaneous functions for sending an email

Authors
  • Michael R. Elkins
  • Pietro Cerutti
  • R Primus

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 sendlib.c.

Function Documentation

◆ update_content_info()

static void update_content_info ( struct Content info,
struct ContentState s,
char *  buf,
size_t  buflen 
)
static

Cache some info about an email.

Parameters
infoInfo about an Attachment
sInfo about the Body of an email
bufBuffer for the result
buflenLength of the buffer

Definition at line 81 of file sendlib.c.

83 {
84  bool from = s->from;
85  int whitespace = s->whitespace;
86  bool dot = s->dot;
87  int linelen = s->linelen;
88  bool was_cr = s->was_cr;
89 
90  if (!buf) /* This signals EOF */
91  {
92  if (was_cr)
93  info->binary = true;
94  if (linelen > info->linemax)
95  info->linemax = linelen;
96 
97  return;
98  }
99 
100  for (; buflen; buf++, buflen--)
101  {
102  char ch = *buf;
103 
104  if (was_cr)
105  {
106  was_cr = false;
107  if (ch == '\n')
108  {
109  if (whitespace)
110  info->space = true;
111  if (dot)
112  info->dot = true;
113  if (linelen > info->linemax)
114  info->linemax = linelen;
115  whitespace = 0;
116  dot = false;
117  linelen = 0;
118  continue;
119  }
120 
121  info->binary = true;
122  }
123 
124  linelen++;
125  if (ch == '\n')
126  {
127  info->crlf++;
128  if (whitespace)
129  info->space = true;
130  if (dot)
131  info->dot = true;
132  if (linelen > info->linemax)
133  info->linemax = linelen;
134  whitespace = 0;
135  linelen = 0;
136  dot = false;
137  }
138  else if (ch == '\r')
139  {
140  info->crlf++;
141  info->cr = true;
142  was_cr = true;
143  continue;
144  }
145  else if (ch & 0x80)
146  info->hibin++;
147  else if ((ch == '\t') || (ch == '\f'))
148  {
149  info->ascii++;
150  whitespace++;
151  }
152  else if (ch == 0)
153  {
154  info->nulbin++;
155  info->lobin++;
156  }
157  else if ((ch < 32) || (ch == 127))
158  info->lobin++;
159  else
160  {
161  if (linelen == 1)
162  {
163  if ((ch == 'F') || (ch == 'f'))
164  from = true;
165  else
166  from = false;
167  if (ch == '.')
168  dot = true;
169  else
170  dot = false;
171  }
172  else if (from)
173  {
174  if ((linelen == 2) && (ch != 'r'))
175  from = false;
176  else if ((linelen == 3) && (ch != 'o'))
177  from = false;
178  else if (linelen == 4)
179  {
180  if (ch == 'm')
181  info->from = true;
182  from = false;
183  }
184  }
185  if (ch == ' ')
186  whitespace++;
187  info->ascii++;
188  }
189 
190  if (linelen > 1)
191  dot = false;
192  if ((ch != ' ') && (ch != '\t'))
193  whitespace = 0;
194  }
195 
196  s->from = from;
197  s->whitespace = whitespace;
198  s->dot = dot;
199  s->linelen = linelen;
200  s->was_cr = was_cr;
201 }
+ Here is the caller graph for this function:

◆ convert_file_to()

static size_t convert_file_to ( FILE *  fp,
const char *  fromcode,
int  ncodes,
char const *const *  tocodes,
int *  tocode,
struct Content info 
)
static

Change the encoding of a file.

Parameters
[in]fpFile to convert
[in]fromcodeOriginal encoding
[in]ncodesNumber of target encodings
[in]tocodesList of target encodings
[out]tocodeChosen encoding
[in]infoEncoding information
Return values
-1Error, no conversion was possible
>0Success, number of bytes converted

Find the best charset conversion of the file from fromcode into one of the tocodes. If successful, set *tocode and Content *info and return the number of characters converted inexactly.

We convert via UTF-8 in order to avoid the condition -1(EINVAL), which would otherwise prevent us from knowing the number of inexact conversions. Where the candidate target charset is UTF-8 we avoid doing the second conversion because iconv_open("UTF-8", "UTF-8") fails with some libraries.

We assume that the output from iconv is never more than 4 times as long as the input for any pair of charsets we might be interested in.

Definition at line 228 of file sendlib.c.

230 {
231  char bufi[256], bufu[512], bufo[4 * sizeof(bufi)];
232  size_t ret;
233 
234  const iconv_t cd1 = mutt_ch_iconv_open("utf-8", fromcode, MUTT_ICONV_NO_FLAGS);
235  if (cd1 == (iconv_t)(-1))
236  return -1;
237 
238  iconv_t *cd = mutt_mem_calloc(ncodes, sizeof(iconv_t));
239  size_t *score = mutt_mem_calloc(ncodes, sizeof(size_t));
240  struct ContentState *states = mutt_mem_calloc(ncodes, sizeof(struct ContentState));
241  struct Content *infos = mutt_mem_calloc(ncodes, sizeof(struct Content));
242 
243  for (int i = 0; i < ncodes; i++)
244  {
245  if (!mutt_istr_equal(tocodes[i], "utf-8"))
246  cd[i] = mutt_ch_iconv_open(tocodes[i], "utf-8", MUTT_ICONV_NO_FLAGS);
247  else
248  {
249  /* Special case for conversion to UTF-8 */
250  cd[i] = (iconv_t)(-1);
251  score[i] = (size_t)(-1);
252  }
253  }
254 
255  rewind(fp);
256  size_t ibl = 0;
257  while (true)
258  {
259  /* Try to fill input buffer */
260  size_t n = fread(bufi + ibl, 1, sizeof(bufi) - ibl, fp);
261  ibl += n;
262 
263  /* Convert to UTF-8 */
264  const char *ib = bufi;
265  char *ob = bufu;
266  size_t obl = sizeof(bufu);
267  n = iconv(cd1, (ICONV_CONST char **) ((ibl != 0) ? &ib : 0), &ibl, &ob, &obl);
268  /* assert(n == (size_t)(-1) || !n); */
269  if ((n == (size_t)(-1)) && (((errno != EINVAL) && (errno != E2BIG)) || (ib == bufi)))
270  {
271  /* assert(errno == EILSEQ || (errno == EINVAL && ib == bufi && ibl < sizeof(bufi))); */
272  ret = (size_t)(-1);
273  break;
274  }
275  const size_t ubl1 = ob - bufu;
276 
277  /* Convert from UTF-8 */
278  for (int i = 0; i < ncodes; i++)
279  {
280  if ((cd[i] != (iconv_t)(-1)) && (score[i] != (size_t)(-1)))
281  {
282  const char *ub = bufu;
283  size_t ubl = ubl1;
284  ob = bufo;
285  obl = sizeof(bufo);
286  n = iconv(cd[i], (ICONV_CONST char **) ((ibl || ubl) ? &ub : 0), &ubl, &ob, &obl);
287  if (n == (size_t)(-1))
288  {
289  /* assert(errno == E2BIG || (BUGGY_ICONV && (errno == EILSEQ || errno == ENOENT))); */
290  score[i] = (size_t)(-1);
291  }
292  else
293  {
294  score[i] += n;
295  update_content_info(&infos[i], &states[i], bufo, ob - bufo);
296  }
297  }
298  else if ((cd[i] == (iconv_t)(-1)) && (score[i] == (size_t)(-1)))
299  {
300  /* Special case for conversion to UTF-8 */
301  update_content_info(&infos[i], &states[i], bufu, ubl1);
302  }
303  }
304 
305  if (ibl)
306  {
307  /* Save unused input */
308  memmove(bufi, ib, ibl);
309  }
310  else if (!ubl1 && (ib < bufi + sizeof(bufi)))
311  {
312  ret = 0;
313  break;
314  }
315  }
316 
317  if (ret == 0)
318  {
319  /* Find best score */
320  ret = (size_t)(-1);
321  for (int i = 0; i < ncodes; i++)
322  {
323  if ((cd[i] == (iconv_t)(-1)) && (score[i] == (size_t)(-1)))
324  {
325  /* Special case for conversion to UTF-8 */
326  *tocode = i;
327  ret = 0;
328  break;
329  }
330  else if ((cd[i] == (iconv_t)(-1)) || (score[i] == (size_t)(-1)))
331  continue;
332  else if ((ret == (size_t)(-1)) || (score[i] < ret))
333  {
334  *tocode = i;
335  ret = score[i];
336  if (ret == 0)
337  break;
338  }
339  }
340  if (ret != (size_t)(-1))
341  {
342  memcpy(info, &infos[*tocode], sizeof(struct Content));
343  update_content_info(info, &states[*tocode], 0, 0); /* EOF */
344  }
345  }
346 
347  for (int i = 0; i < ncodes; i++)
348  if (cd[i] != (iconv_t)(-1))
349  iconv_close(cd[i]);
350 
351  iconv_close(cd1);
352  FREE(&cd);
353  FREE(&infos);
354  FREE(&score);
355  FREE(&states);
356 
357  return ret;
358 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ convert_file_from_to()

static size_t convert_file_from_to ( FILE *  fp,
const char *  fromcodes,
const char *  tocodes,
char **  fromcode,
char **  tocode,
struct Content info 
)
static

Convert a file between encodings.

Parameters
[in]fpFile to read from
[in]fromcodesCharsets to try converting FROM
[in]tocodesCharsets to try converting TO
[out]fromcodeFrom charset selected
[out]tocodeTo charset selected
[out]infoInfo about the file
Return values
numCharacters converted
-1Error (as a size_t)

Find the first of the fromcodes that gives a valid conversion and the best charset conversion of the file into one of the tocodes. If successful, set *fromcode and *tocode to dynamically allocated strings, set Content *info, and return the number of characters converted inexactly. If no conversion was possible, return -1.

Both fromcodes and tocodes may be colon-separated lists of charsets. However, if fromcode is zero then fromcodes is assumed to be the name of a single charset even if it contains a colon.

Definition at line 381 of file sendlib.c.

383 {
384  char *fcode = NULL;
385  char **tcode = NULL;
386  const char *c = NULL, *c1 = NULL;
387  size_t ret;
388  int ncodes, i, cn;
389 
390  /* Count the tocodes */
391  ncodes = 0;
392  for (c = tocodes; c; c = c1 ? c1 + 1 : 0)
393  {
394  c1 = strchr(c, ':');
395  if (c1 == c)
396  continue;
397  ncodes++;
398  }
399 
400  /* Copy them */
401  tcode = mutt_mem_malloc(ncodes * sizeof(char *));
402  for (c = tocodes, i = 0; c; c = c1 ? c1 + 1 : 0, i++)
403  {
404  c1 = strchr(c, ':');
405  if (c1 == c)
406  continue;
407  if (c1)
408  tcode[i] = mutt_strn_dup(c, c1 - c);
409  else
410  tcode[i] = mutt_str_dup(c);
411  }
412 
413  ret = (size_t)(-1);
414  if (fromcode)
415  {
416  /* Try each fromcode in turn */
417  for (c = fromcodes; c; c = c1 ? c1 + 1 : 0)
418  {
419  c1 = strchr(c, ':');
420  if (c1 == c)
421  continue;
422  if (c1)
423  fcode = mutt_strn_dup(c, c1 - c);
424  else
425  fcode = mutt_str_dup(c);
426 
427  ret = convert_file_to(fp, fcode, ncodes, (char const *const *) tcode, &cn, info);
428  if (ret != (size_t)(-1))
429  {
430  *fromcode = fcode;
431  *tocode = tcode[cn];
432  tcode[cn] = 0;
433  break;
434  }
435  FREE(&fcode);
436  }
437  }
438  else
439  {
440  /* There is only one fromcode */
441  ret = convert_file_to(fp, fromcodes, ncodes, (char const *const *) tcode, &cn, info);
442  if (ret != (size_t)(-1))
443  {
444  *tocode = tcode[cn];
445  tcode[cn] = 0;
446  }
447  }
448 
449  /* Free memory */
450  for (i = 0; i < ncodes; i++)
451  FREE(&tcode[i]);
452 
453  FREE(&tcode);
454 
455  return ret;
456 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_get_content_info()

struct Content* mutt_get_content_info ( const char *  fname,
struct Body b,
struct ConfigSubset sub 
)

Analyze file to determine MIME encoding to use.

Parameters
fnameFile to examine
bBody to update
subConfig Subset
Return values
ptrNewly allocated Content

Also set the body charset, sometimes, or not.

Definition at line 467 of file sendlib.c.

469 {
470  struct Content *info = NULL;
471  struct ContentState state = { 0 };
472  FILE *fp = NULL;
473  char *fromcode = NULL;
474  char *tocode = NULL;
475  char buf[100];
476  size_t r;
477 
478  struct stat sb;
479 
480  if (b && !fname)
481  fname = b->filename;
482  if (!fname)
483  return NULL;
484 
485  if (stat(fname, &sb) == -1)
486  {
487  mutt_error(_("Can't stat %s: %s"), fname, strerror(errno));
488  return NULL;
489  }
490 
491  if (!S_ISREG(sb.st_mode))
492  {
493  mutt_error(_("%s isn't a regular file"), fname);
494  return NULL;
495  }
496 
497  fp = fopen(fname, "r");
498  if (!fp)
499  {
500  mutt_debug(LL_DEBUG1, "%s: %s (errno %d)\n", fname, strerror(errno), errno);
501  return NULL;
502  }
503 
504  info = mutt_mem_calloc(1, sizeof(struct Content));
505 
506  const char *c_charset = cs_subset_string(sub, "charset");
507 
508  if (b && (b->type == TYPE_TEXT) && (!b->noconv && !b->force_charset))
509  {
510  const char *c_attach_charset = cs_subset_string(sub, "attach_charset");
511  const char *c_send_charset = cs_subset_string(sub, "send_charset");
512 
513  char *chs = mutt_param_get(&b->parameter, "charset");
514  const char *fchs =
515  b->use_disp ? (c_attach_charset ? c_attach_charset : c_charset) : c_charset;
516  if (c_charset && (chs || c_send_charset) &&
517  (convert_file_from_to(fp, fchs, chs ? chs : c_send_charset, &fromcode,
518  &tocode, info) != (size_t)(-1)))
519  {
520  if (!chs)
521  {
522  char chsbuf[256];
523  mutt_ch_canonical_charset(chsbuf, sizeof(chsbuf), tocode);
524  mutt_param_set(&b->parameter, "charset", chsbuf);
525  }
526  FREE(&b->charset);
527  b->charset = fromcode;
528  FREE(&tocode);
529  mutt_file_fclose(&fp);
530  return info;
531  }
532  }
533 
534  rewind(fp);
535  while ((r = fread(buf, 1, sizeof(buf), fp)))
536  update_content_info(info, &state, buf, r);
537  update_content_info(info, &state, 0, 0);
538 
539  mutt_file_fclose(&fp);
540 
541  if (b && (b->type == TYPE_TEXT) && (!b->noconv && !b->force_charset))
542  {
543  mutt_param_set(&b->parameter, "charset",
544  (!info->hibin ? "us-ascii" :
545  c_charset && !mutt_ch_is_us_ascii(c_charset) ?
546  c_charset :
547  "unknown-8bit"));
548  }
549 
550  return info;
551 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_lookup_mime_type()

enum ContentType mutt_lookup_mime_type ( struct Body att,
const char *  path 
)

Find the MIME type for an attachment.

Parameters
attEmail with attachment
pathPath to attachment
Return values
numMIME type, e.g. TYPE_IMAGE

Given a file at 'path', see if there is a registered MIME type. Returns the major MIME type, and copies the subtype to "d". First look in a system mime.types if we can find one, then look for ~/.mime.types. The longest match is used so that we can match 'ps.gz' when 'gz' also exists.

Definition at line 565 of file sendlib.c.

566 {
567  FILE *fp = NULL;
568  char *p = NULL, *q = NULL, *ct = NULL;
569  char buf[PATH_MAX];
570  char subtype[256] = { 0 };
571  char xtype[256] = { 0 };
572  int sze, cur_sze = 0;
573  bool found_mimetypes = false;
574  enum ContentType type = TYPE_OTHER;
575 
576  int szf = mutt_str_len(path);
577 
578  for (int count = 0; count < 4; count++)
579  {
580  /* can't use strtok() because we use it in an inner loop below, so use
581  * a switch statement here instead. */
582  switch (count)
583  {
584  /* last file with last entry to match wins type/xtype */
585  case 0:
586  /* check default unix mimetypes location first */
587  mutt_str_copy(buf, "/etc/mime.types", sizeof(buf));
588  break;
589  case 1:
590  mutt_str_copy(buf, SYSCONFDIR "/mime.types", sizeof(buf));
591  break;
592  case 2:
593  mutt_str_copy(buf, PKGDATADIR "/mime.types", sizeof(buf));
594  break;
595  case 3:
596  snprintf(buf, sizeof(buf), "%s/.mime.types", NONULL(HomeDir));
597  break;
598  default:
599  mutt_debug(LL_DEBUG1, "Internal error, count = %d\n", count);
600  goto bye; /* shouldn't happen */
601  }
602 
603  fp = fopen(buf, "r");
604  if (fp)
605  {
606  found_mimetypes = true;
607 
608  while (fgets(buf, sizeof(buf) - 1, fp))
609  {
610  /* weed out any comments */
611  p = strchr(buf, '#');
612  if (p)
613  *p = '\0';
614 
615  /* remove any leading space. */
616  ct = buf;
617  SKIPWS(ct);
618 
619  /* position on the next field in this line */
620  p = strpbrk(ct, " \t");
621  if (!p)
622  continue;
623  *p++ = 0;
624  SKIPWS(p);
625 
626  /* cycle through the file extensions */
627  while ((p = strtok(p, " \t\n")))
628  {
629  sze = mutt_str_len(p);
630  if ((sze > cur_sze) && (szf >= sze) && mutt_istr_equal(path + szf - sze, p) &&
631  ((szf == sze) || (path[szf - sze - 1] == '.')))
632  {
633  /* get the content-type */
634 
635  p = strchr(ct, '/');
636  if (!p)
637  {
638  /* malformed line, just skip it. */
639  break;
640  }
641  *p++ = 0;
642 
643  for (q = p; *q && !IS_SPACE(*q); q++)
644  ; // do nothing
645 
646  mutt_strn_copy(subtype, p, q - p, sizeof(subtype));
647 
648  type = mutt_check_mime_type(ct);
649  if (type == TYPE_OTHER)
650  mutt_str_copy(xtype, ct, sizeof(xtype));
651 
652  cur_sze = sze;
653  }
654  p = NULL;
655  }
656  }
657  mutt_file_fclose(&fp);
658  }
659  }
660 
661 bye:
662 
663  /* no mime.types file found */
664  if (!found_mimetypes)
665  {
666  mutt_error(_("Could not find any mime.types file"));
667  }
668 
669  if ((type != TYPE_OTHER) || (*xtype != '\0'))
670  {
671  att->type = type;
672  mutt_str_replace(&att->subtype, subtype);
673  mutt_str_replace(&att->xtype, xtype);
674  }
675 
676  return type;
677 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ transform_to_7bit()

static void transform_to_7bit ( struct Body a,
FILE *  fp_in,
struct ConfigSubset sub 
)
static

Convert MIME parts to 7-bit.

Parameters
aBody of the email
fp_inFile to read
subConfig Subset

Definition at line 685 of file sendlib.c.

686 {
687  struct Buffer *buf = NULL;
688  struct State s = { 0 };
689  struct stat sb;
690 
691  for (; a; a = a->next)
692  {
693  if (a->type == TYPE_MULTIPART)
694  {
695  a->encoding = ENC_7BIT;
696  transform_to_7bit(a->parts, fp_in, sub);
697  }
698  else if (mutt_is_message_type(a->type, a->subtype))
699  {
700  mutt_message_to_7bit(a, fp_in, sub);
701  }
702  else
703  {
704  a->noconv = true;
705  a->force_charset = true;
706 
707  /* Because of the potential recursion in message types, we
708  * restrict the lifetime of the buffer tightly */
709  buf = mutt_buffer_pool_get();
710  mutt_buffer_mktemp(buf);
712  if (!s.fp_out)
713  {
714  mutt_perror("fopen");
716  return;
717  }
718  s.fp_in = fp_in;
719  mutt_decode_attachment(a, &s);
721  FREE(&a->d_filename);
722  a->d_filename = a->filename;
723  a->filename = mutt_buffer_strdup(buf);
725  a->unlink = true;
726  if (stat(a->filename, &sb) == -1)
727  {
728  mutt_perror("stat");
729  return;
730  }
731  a->length = sb.st_size;
732 
733  mutt_update_encoding(a, sub);
734  if (a->encoding == ENC_8BIT)
736  else if (a->encoding == ENC_BINARY)
737  a->encoding = ENC_BASE64;
738  }
739  }
740 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_message_to_7bit()

void mutt_message_to_7bit ( struct Body a,
FILE *  fp,
struct ConfigSubset sub 
)

Convert an email's MIME parts to 7-bit.

Parameters
aBody of the email
fpFile to read (OPTIONAL)
subConfig Subset

Definition at line 748 of file sendlib.c.

749 {
750  struct Buffer temp = mutt_buffer_make(0);
751  FILE *fp_in = NULL;
752  FILE *fp_out = NULL;
753  struct stat sb;
754 
755  if (!a->filename && fp)
756  fp_in = fp;
757  else if (!a->filename || !(fp_in = fopen(a->filename, "r")))
758  {
759  mutt_error(_("Could not open %s"), a->filename ? a->filename : "(null)");
760  return;
761  }
762  else
763  {
764  a->offset = 0;
765  if (stat(a->filename, &sb) == -1)
766  {
767  mutt_perror("stat");
768  mutt_file_fclose(&fp_in);
769  goto cleanup;
770  }
771  a->length = sb.st_size;
772  }
773 
774  /* Avoid buffer pool due to recursion */
775  mutt_buffer_mktemp(&temp);
776  fp_out = mutt_file_fopen(mutt_buffer_string(&temp), "w+");
777  if (!fp_out)
778  {
779  mutt_perror("fopen");
780  goto cleanup;
781  }
782 
783  fseeko(fp_in, a->offset, SEEK_SET);
784  a->parts = mutt_rfc822_parse_message(fp_in, a);
785 
786  transform_to_7bit(a->parts, fp_in, sub);
787 
788  mutt_copy_hdr(fp_in, fp_out, a->offset, a->offset + a->length,
789  CH_MIME | CH_NONEWLINE | CH_XMIT, NULL, 0);
790 
791  fputs("MIME-Version: 1.0\n", fp_out);
792  mutt_write_mime_header(a->parts, fp_out, sub);
793  fputc('\n', fp_out);
794  mutt_write_mime_body(a->parts, fp_out, sub);
795 
796  if (fp_in != fp)
797  mutt_file_fclose(&fp_in);
798  mutt_file_fclose(&fp_out);
799 
800  a->encoding = ENC_7BIT;
801  FREE(&a->d_filename);
802  a->d_filename = a->filename;
803  if (a->filename && a->unlink)
804  unlink(a->filename);
805  a->filename = mutt_buffer_strdup(&temp);
806  a->unlink = true;
807  if (stat(a->filename, &sb) == -1)
808  {
809  mutt_perror("stat");
810  goto cleanup;
811  }
812  a->length = sb.st_size;
813  mutt_body_free(&a->parts);
814  a->email->body = NULL;
815 
816 cleanup:
817  if (fp_in && (fp_in != fp))
818  mutt_file_fclose(&fp_in);
819 
820  if (fp_out)
821  {
822  mutt_file_fclose(&fp_out);
824  }
825 
826  mutt_buffer_dealloc(&temp);
827 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ set_encoding()

static void set_encoding ( struct Body b,
struct Content info,
struct ConfigSubset sub 
)
static

determine which Content-Transfer-Encoding to use

Parameters
[in]bBody of email
[out]infoInfo about the email
[in]subConfig Subset

Definition at line 835 of file sendlib.c.

836 {
837  const bool c_allow_8bit = cs_subset_bool(sub, "allow_8bit");
838  if (b->type == TYPE_TEXT)
839  {
840  const bool c_encode_from = cs_subset_bool(sub, "encode_from");
841  char send_charset[128];
842  char *chsname = mutt_body_get_charset(b, send_charset, sizeof(send_charset));
843  if ((info->lobin && !mutt_istr_startswith(chsname, "iso-2022")) ||
844  (info->linemax > 990) || (info->from && c_encode_from))
845  {
847  }
848  else if (info->hibin)
849  {
850  b->encoding = c_allow_8bit ? ENC_8BIT : ENC_QUOTED_PRINTABLE;
851  }
852  else
853  {
854  b->encoding = ENC_7BIT;
855  }
856  }
857  else if ((b->type == TYPE_MESSAGE) || (b->type == TYPE_MULTIPART))
858  {
859  if (info->lobin || info->hibin)
860  {
861  if (c_allow_8bit && !info->lobin)
862  b->encoding = ENC_8BIT;
863  else
864  mutt_message_to_7bit(b, NULL, sub);
865  }
866  else
867  b->encoding = ENC_7BIT;
868  }
869  else if ((b->type == TYPE_APPLICATION) &&
870  mutt_istr_equal(b->subtype, "pgp-keys"))
871  {
872  b->encoding = ENC_7BIT;
873  }
874  else
875  {
876  /* Determine which encoding is smaller */
877  if (1.33 * (float) (info->lobin + info->hibin + info->ascii) <
878  3.0 * (float) (info->lobin + info->hibin) + (float) info->ascii)
879  {
880  b->encoding = ENC_BASE64;
881  }
882  else
883  {
885  }
886  }
887 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_stamp_attachment()

void mutt_stamp_attachment ( struct Body a)

Timestamp an Attachment.

Parameters
aAttachment

Definition at line 893 of file sendlib.c.

894 {
895  a->stamp = mutt_date_epoch();
896 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_update_encoding()

void mutt_update_encoding ( struct Body a,
struct ConfigSubset sub 
)

Update the encoding type.

Parameters
aBody to update
subConfig Subset

Assumes called from send mode where Body->filename points to actual file

Definition at line 905 of file sendlib.c.

906 {
907  struct Content *info = NULL;
908  char chsbuf[256];
909 
910  /* override noconv when it's us-ascii */
911  if (mutt_ch_is_us_ascii(mutt_body_get_charset(a, chsbuf, sizeof(chsbuf))))
912  a->noconv = false;
913 
914  if (!a->force_charset && !a->noconv)
915  mutt_param_delete(&a->parameter, "charset");
916 
917  info = mutt_get_content_info(a->filename, a, sub);
918  if (!info)
919  return;
920 
921  set_encoding(a, info, sub);
923 
924  FREE(&a->content);
925  a->content = info;
926 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ 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.

Parameters
mMailbox
eEmail
attach_msgtrue if attaching a message
subConfig Subset
Return values
ptrNewly allocated Body
NULLError

Definition at line 937 of file sendlib.c.

939 {
940  struct Body *body = NULL;
941  FILE *fp = NULL;
942  CopyMessageFlags cmflags;
944 
945  const bool c_mime_forward_decode = cs_subset_bool(sub, "mime_forward_decode");
946  const bool c_forward_decrypt = cs_subset_bool(sub, "forward_decrypt");
947  if (WithCrypto)
948  {
949  if ((c_mime_forward_decode || c_forward_decrypt) && (e->security & SEC_ENCRYPT))
950  {
952  return NULL;
953  }
954  }
955 
956  struct Buffer *buf = mutt_buffer_pool_get();
957  mutt_buffer_mktemp(buf);
958  fp = mutt_file_fopen(mutt_buffer_string(buf), "w+");
959  if (!fp)
960  {
962  return NULL;
963  }
964 
965  body = mutt_body_new();
966  body->type = TYPE_MESSAGE;
967  body->subtype = mutt_str_dup("rfc822");
969  body->unlink = true;
970  body->use_disp = false;
971  body->disposition = DISP_INLINE;
972  body->noconv = true;
973 
975 
977 
978  CopyHeaderFlags chflags = CH_XMIT;
979  cmflags = MUTT_CM_NO_FLAGS;
980 
981  /* If we are attaching a message, ignore `$mime_forward_decode` */
982  if (!attach_msg && c_mime_forward_decode)
983  {
984  chflags |= CH_MIME | CH_TXTPLAIN;
985  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
987  pgp &= ~PGP_ENCRYPT;
989  pgp &= ~SMIME_ENCRYPT;
990  }
991  else if ((WithCrypto != 0) && c_forward_decrypt && (e->security & SEC_ENCRYPT))
992  {
994  {
995  chflags |= CH_MIME | CH_NONEWLINE;
996  cmflags = MUTT_CM_DECODE_PGP;
997  pgp &= ~PGP_ENCRYPT;
998  }
999  else if (((WithCrypto & APPLICATION_PGP) != 0) &&
1001  {
1002  chflags |= CH_MIME | CH_TXTPLAIN;
1003  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1004  pgp &= ~PGP_ENCRYPT;
1005  }
1006  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
1008  {
1009  chflags |= CH_MIME | CH_TXTPLAIN;
1010  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1011  pgp &= ~SMIME_ENCRYPT;
1012  }
1013  }
1014 
1015  mutt_copy_message(fp, m, e, cmflags, chflags, 0);
1016 
1017  fflush(fp);
1018  rewind(fp);
1019 
1020  body->email = email_new();
1021  body->email->offset = 0;
1022  /* we don't need the user headers here */
1023  body->email->env = mutt_rfc822_read_header(fp, body->email, false, false);
1024  if (WithCrypto)
1025  body->email->security = pgp;
1026  mutt_update_encoding(body, sub);
1027  body->parts = body->email->body;
1028 
1029  mutt_file_fclose(&fp);
1030 
1031  return body;
1032 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ run_mime_type_query()

static void run_mime_type_query ( struct Body att,
struct ConfigSubset sub 
)
static

Run an external command to determine the MIME type.

Parameters
attAttachment
subConfig Subset

The command in $mime_type_query_command is run.

Definition at line 1041 of file sendlib.c.

1042 {
1043  FILE *fp = NULL, *fp_err = NULL;
1044  char *buf = NULL;
1045  size_t buflen;
1046  pid_t pid;
1047  struct Buffer *cmd = mutt_buffer_pool_get();
1048 
1049  const char *c_mime_type_query_command =
1050  cs_subset_string(sub, "mime_type_query_command");
1051 
1052  mutt_buffer_file_expand_fmt_quote(cmd, c_mime_type_query_command, att->filename);
1053 
1054  pid = filter_create(mutt_buffer_string(cmd), NULL, &fp, &fp_err);
1055  if (pid < 0)
1056  {
1057  mutt_error(_("Error running \"%s\""), mutt_buffer_string(cmd));
1059  return;
1060  }
1062 
1063  buf = mutt_file_read_line(buf, &buflen, fp, NULL, MUTT_RL_NO_FLAGS);
1064  if (buf)
1065  {
1066  if (strchr(buf, '/'))
1067  mutt_parse_content_type(buf, att);
1068  FREE(&buf);
1069  }
1070 
1071  mutt_file_fclose(&fp);
1072  mutt_file_fclose(&fp_err);
1073  filter_wait(pid);
1074 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_make_file_attach()

struct Body* mutt_make_file_attach ( const char *  path,
struct ConfigSubset sub 
)

Create a file attachment.

Parameters
pathFile to attach
subConfig Subset
Return values
ptrNewly allocated Body
NULLError

Definition at line 1083 of file sendlib.c.

1084 {
1085  struct Body *att = mutt_body_new();
1086  att->filename = mutt_str_dup(path);
1087 
1088  const char *c_mime_type_query_command =
1089  cs_subset_string(sub, "mime_type_query_command");
1090  const bool c_mime_type_query_first =
1091  cs_subset_bool(sub, "mime_type_query_first");
1092 
1093  if (c_mime_type_query_command && c_mime_type_query_first)
1094  run_mime_type_query(att, sub);
1095 
1096  /* Attempt to determine the appropriate content-type based on the filename
1097  * suffix. */
1098  if (!att->subtype)
1099  mutt_lookup_mime_type(att, path);
1100 
1101  if (!att->subtype && c_mime_type_query_command && !c_mime_type_query_first)
1102  {
1103  run_mime_type_query(att, sub);
1104  }
1105 
1106  struct Content *info = mutt_get_content_info(path, att, sub);
1107  if (!info)
1108  {
1109  mutt_body_free(&att);
1110  return NULL;
1111  }
1112 
1113  if (!att->subtype)
1114  {
1115  if ((info->nulbin == 0) &&
1116  ((info->lobin == 0) || ((info->lobin + info->hibin + info->ascii) / info->lobin >= 10)))
1117  {
1118  /* Statistically speaking, there should be more than 10% "lobin"
1119  * chars if this is really a binary file... */
1120  att->type = TYPE_TEXT;
1121  att->subtype = mutt_str_dup("plain");
1122  }
1123  else
1124  {
1125  att->type = TYPE_APPLICATION;
1126  att->subtype = mutt_str_dup("octet-stream");
1127  }
1128  }
1129 
1130  FREE(&info);
1131  mutt_update_encoding(att, sub);
1132  return att;
1133 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ encode_headers()

static void encode_headers ( struct ListHead *  h,
struct ConfigSubset sub 
)
static

RFC2047-encode a list of headers.

Parameters
hString List of headers
subConfig Subset

The strings are encoded in-place.

Definition at line 1142 of file sendlib.c.

1143 {
1144  char *tmp = NULL;
1145  char *p = NULL;
1146  int i;
1147 
1148  const char *c_send_charset = cs_subset_string(sub, "send_charset");
1149 
1150  struct ListNode *np = NULL;
1151  STAILQ_FOREACH(np, h, entries)
1152  {
1153  p = strchr(np->data, ':');
1154  if (!p)
1155  continue;
1156 
1157  i = p - np->data;
1158  p = mutt_str_skip_email_wsp(p + 1);
1159  tmp = mutt_str_dup(p);
1160 
1161  if (!tmp)
1162  continue;
1163 
1164  rfc2047_encode(&tmp, NULL, i + 2, c_send_charset);
1165  mutt_mem_realloc(&np->data, i + 2 + mutt_str_len(tmp) + 1);
1166 
1167  sprintf(np->data + i + 2, "%s", tmp);
1168 
1169  FREE(&tmp);
1170  }
1171 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_fqdn()

const char* mutt_fqdn ( bool  may_hide_host,
const struct ConfigSubset sub 
)

Get the Fully-Qualified Domain Name.

Parameters
may_hide_hostIf true, hide the hostname (leaving just the domain)
subConfig Subset
Return values
ptrstring pointer into Hostname
NULLError, e.g no Hostname
Warning
Do not free the returned pointer

Definition at line 1182 of file sendlib.c.

1183 {
1184  const char *c_hostname = cs_subset_string(sub, "hostname");
1185  if (!c_hostname || (c_hostname[0] == '@'))
1186  return NULL;
1187 
1188  const char *p = c_hostname;
1189 
1190  const bool c_hidden_host = cs_subset_bool(sub, "hidden_host");
1191  if (may_hide_host && c_hidden_host)
1192  {
1193  p = strchr(c_hostname, '.');
1194  if (p)
1195  p++;
1196 
1197  // sanity check: don't hide the host if the fqdn is something like example.com
1198  if (!p || !strchr(p, '.'))
1199  p = c_hostname;
1200  }
1201 
1202  return p;
1203 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ gen_msgid()

static char* gen_msgid ( struct ConfigSubset sub)
static

Generate a unique Message ID.

Return values
ptrMessage ID
Note
The caller should free the string

Definition at line 1211 of file sendlib.c.

1212 {
1213  char buf[128];
1214  char rndid[MUTT_RANDTAG_LEN + 1];
1215 
1216  mutt_rand_base32(rndid, sizeof(rndid) - 1);
1217  rndid[MUTT_RANDTAG_LEN] = 0;
1218  const char *fqdn = mutt_fqdn(false, sub);
1219  if (!fqdn)
1220  fqdn = NONULL(ShortHostname);
1221 
1222  struct tm tm = mutt_date_gmtime(MUTT_DATE_NOW);
1223  snprintf(buf, sizeof(buf), "<%d%02d%02d%02d%02d%02d.%s@%s>", tm.tm_year + 1900,
1224  tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, rndid, fqdn);
1225  return mutt_str_dup(buf);
1226 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_prepare_envelope()

void mutt_prepare_envelope ( struct Envelope env,
bool  final,
struct ConfigSubset sub 
)

Prepare an email header.

Parameters
envEnvelope to prepare
finaltrue if this email is going to be sent (not postponed)
subConfig Subset

Encode all the headers prior to sending the email.

For postponing (!final) do the necessary encodings only

Definition at line 1238 of file sendlib.c.

1239 {
1240  if (final)
1241  {
1242  if (!TAILQ_EMPTY(&env->bcc) && TAILQ_EMPTY(&env->to) && TAILQ_EMPTY(&env->cc))
1243  {
1244  /* some MTA's will put an Apparently-To: header field showing the Bcc:
1245  * recipients if there is no To: or Cc: field, so attempt to suppress
1246  * it by using an empty To: field. */
1247  struct Address *to = mutt_addr_new();
1248  to->group = true;
1249  mutt_addrlist_append(&env->to, to);
1251 
1252  char buf[1024];
1253  buf[0] = '\0';
1254  mutt_addr_cat(buf, sizeof(buf), "undisclosed-recipients", AddressSpecials);
1255 
1256  to->mailbox = mutt_str_dup(buf);
1257  }
1258 
1259  mutt_set_followup_to(env, sub);
1260 
1261  if (!env->message_id)
1262  env->message_id = gen_msgid(sub);
1263  }
1264 
1265  /* Take care of 8-bit => 7-bit conversion. */
1267  encode_headers(&env->userhdrs, sub);
1268 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_unprepare_envelope()

void mutt_unprepare_envelope ( struct Envelope env)

Undo the encodings of mutt_prepare_envelope()

Parameters
envEnvelope to unprepare

Decode all the headers of an email, e.g. when the sending failed or was aborted.

Definition at line 1277 of file sendlib.c.

1278 {
1279  struct ListNode *item = NULL;
1280  STAILQ_FOREACH(item, &env->userhdrs, entries)
1281  {
1282  rfc2047_decode(&item->data);
1283  }
1284 
1286 
1287  /* back conversions */
1289 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ bounce_message()

static int bounce_message ( FILE *  fp,
struct Mailbox m,
struct Email e,
struct AddressList *  to,
const char *  resent_from,
struct AddressList *  env_from,
struct ConfigSubset sub 
)
static

Bounce an email message.

Parameters
fpHandle of message
mMailbox
eEmail
toAddress to bounce to
resent_fromAddress of new sender
env_fromEnvelope of original sender
subConfig Subset
Return values
0Success
-1Failure

Definition at line 1303 of file sendlib.c.

1306 {
1307  if (!e)
1308  return -1;
1309 
1310  int rc = 0;
1311 
1312  struct Buffer *tempfile = mutt_buffer_pool_get();
1313  mutt_buffer_mktemp(tempfile);
1314  FILE *fp_tmp = mutt_file_fopen(mutt_buffer_string(tempfile), "w");
1315  if (fp_tmp)
1316  {
1318 
1319  const bool c_bounce_delivered = cs_subset_bool(sub, "bounce_delivered");
1320  if (!c_bounce_delivered)
1321  chflags |= CH_WEED_DELIVERED;
1322 
1323  fseeko(fp, e->offset, SEEK_SET);
1324  fprintf(fp_tmp, "Resent-From: %s\n", resent_from);
1325 
1326  struct Buffer *date = mutt_buffer_pool_get();
1327  mutt_date_make_date(date);
1328  fprintf(fp_tmp, "Resent-Date: %s\n", mutt_buffer_string(date));
1329  mutt_buffer_pool_release(&date);
1330 
1331  char *msgid_str = gen_msgid(sub);
1332  fprintf(fp_tmp, "Resent-Message-ID: %s\n", msgid_str);
1333  FREE(&msgid_str);
1334  fputs("Resent-To: ", fp_tmp);
1335  mutt_addrlist_write_file(to, fp_tmp, 11, false);
1336  mutt_copy_header(fp, e, fp_tmp, chflags, NULL, 0);
1337  fputc('\n', fp_tmp);
1338  mutt_file_copy_bytes(fp, fp_tmp, e->body->length);
1339  if (mutt_file_fclose(&fp_tmp) != 0)
1340  {
1341  mutt_perror(mutt_buffer_string(tempfile));
1342  unlink(mutt_buffer_string(tempfile));
1343  return -1;
1344  }
1345 #ifdef USE_SMTP
1346  const char *c_smtp_url = cs_subset_string(sub, "smtp_url");
1347  if (c_smtp_url)
1348  {
1349  rc = mutt_smtp_send(env_from, to, NULL, NULL, mutt_buffer_string(tempfile),
1350  (e->body->encoding == ENC_8BIT), sub);
1351  }
1352  else
1353 #endif
1354  {
1355  rc = mutt_invoke_sendmail(m, env_from, to, NULL, NULL, mutt_buffer_string(tempfile),
1356  (e->body->encoding == ENC_8BIT), sub);
1357  }
1358  }
1359 
1360  mutt_buffer_pool_release(&tempfile);
1361  return rc;
1362 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_bounce_message()

int mutt_bounce_message ( FILE *  fp,
struct Mailbox m,
struct Email e,
struct AddressList *  to,
struct ConfigSubset sub 
)

Bounce an email message.

Parameters
fpHandle of message
mMailbox
eEmail
toAddressList to bounce to
subConfig Subset
Return values
0Success
-1Failure

Definition at line 1374 of file sendlib.c.

1376 {
1377  if (!fp || !e || !to || TAILQ_EMPTY(to))
1378  return -1;
1379 
1380  const char *fqdn = mutt_fqdn(true, sub);
1381  char resent_from[256];
1382  char *err = NULL;
1383 
1384  resent_from[0] = '\0';
1385  struct Address *from = mutt_default_from(sub);
1386  struct AddressList from_list = TAILQ_HEAD_INITIALIZER(from_list);
1387  mutt_addrlist_append(&from_list, from);
1388 
1389  /* mutt_default_from() does not use $real_name if the real name is not set
1390  * in $from, so we add it here. The reason it is not added in
1391  * mutt_default_from() is that during normal sending, we execute
1392  * send-hooks and set the real_name last so that it can be changed based
1393  * upon message criteria. */
1394  if (!from->personal)
1395  {
1396  const char *c_real_name = cs_subset_string(sub, "real_name");
1397  from->personal = mutt_str_dup(c_real_name);
1398  }
1399 
1400  mutt_addrlist_qualify(&from_list, fqdn);
1401 
1402  rfc2047_encode_addrlist(&from_list, "Resent-From");
1403  if (mutt_addrlist_to_intl(&from_list, &err))
1404  {
1405  mutt_error(_("Bad IDN %s while preparing resent-from"), err);
1406  FREE(&err);
1407  mutt_addrlist_clear(&from_list);
1408  return -1;
1409  }
1410  mutt_addrlist_write(&from_list, resent_from, sizeof(resent_from), false);
1411 
1412 #ifdef USE_NNTP
1413  OptNewsSend = false;
1414 #endif
1415 
1416  /* prepare recipient list. idna conversion appears to happen before this
1417  * function is called, since the user receives confirmation of the address
1418  * list being bounced to. */
1419  struct AddressList resent_to = TAILQ_HEAD_INITIALIZER(resent_to);
1420  mutt_addrlist_copy(&resent_to, to, false);
1421  rfc2047_encode_addrlist(&resent_to, "Resent-To");
1422  int rc = bounce_message(fp, m, e, &resent_to, resent_from, &from_list, sub);
1423  mutt_addrlist_clear(&resent_to);
1424  mutt_addrlist_clear(&from_list);
1425 
1426  return rc;
1427 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ set_noconv_flags()

static void set_noconv_flags ( struct Body b,
bool  flag 
)
static

Set/reset the "x-mutt-noconv" flag.

Parameters
bBody of email
flagIf true, set the flag, otherwise remove it

Definition at line 1434 of file sendlib.c.

1435 {
1436  for (; b; b = b->next)
1437  {
1438  if ((b->type == TYPE_MESSAGE) || (b->type == TYPE_MULTIPART))
1439  set_noconv_flags(b->parts, flag);
1440  else if ((b->type == TYPE_TEXT) && b->noconv)
1441  {
1442  if (flag)
1443  mutt_param_set(&b->parameter, "x-mutt-noconv", "yes");
1444  else
1445  mutt_param_delete(&b->parameter, "x-mutt-noconv");
1446  }
1447  }
1448 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ 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.

Parameters
[in]pathPath to mailboxes (comma separated)
[in]eEmail
[in]msgidMessage id
[in]postIf true, postpone message
[in]fccfcc setting to save (postpone only)
[out]finalpathFinal path of email
[in]subConfig Subset
Return values
0Success
-1Failure

Definition at line 1462 of file sendlib.c.

1464 {
1465  char fcc_tok[PATH_MAX];
1466  char fcc_expanded[PATH_MAX];
1467 
1468  mutt_str_copy(fcc_tok, path, sizeof(fcc_tok));
1469 
1470  char *tok = strtok(fcc_tok, ",");
1471  if (!tok)
1472  return -1;
1473 
1474  mutt_debug(LL_DEBUG1, "Fcc: initial mailbox = '%s'\n", tok);
1475  /* mutt_expand_path already called above for the first token */
1476  int status = mutt_write_fcc(tok, e, msgid, post, fcc, finalpath, sub);
1477  if (status != 0)
1478  return status;
1479 
1480  while ((tok = strtok(NULL, ",")))
1481  {
1482  if (*tok == '\0')
1483  continue;
1484 
1485  /* Only call mutt_expand_path if tok has some data */
1486  mutt_debug(LL_DEBUG1, "Fcc: additional mailbox token = '%s'\n", tok);
1487  mutt_str_copy(fcc_expanded, tok, sizeof(fcc_expanded));
1488  mutt_expand_path(fcc_expanded, sizeof(fcc_expanded));
1489  mutt_debug(LL_DEBUG1, " Additional mailbox expanded = '%s'\n", fcc_expanded);
1490  status = mutt_write_fcc(fcc_expanded, e, msgid, post, fcc, finalpath, sub);
1491  if (status != 0)
1492  return status;
1493  }
1494 
1495  return 0;
1496 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ 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.

Parameters
[in]pathPath to mailbox
[in]eEmail
[in]msgidMessage id
[in]postIf true, postpone message, else fcc mode
[in]fccfcc setting to save (postpone only)
[out]finalpathFinal path of email
[in]subConfig Subset
Return values
0Success
-1Failure

Definition at line 1510 of file sendlib.c.

1512 {
1513  struct Message *msg = NULL;
1514  struct Buffer *tempfile = NULL;
1515  FILE *fp_tmp = NULL;
1516  int rc = -1;
1517  bool need_mailbox_cleanup = false;
1518  struct stat st;
1519  MsgOpenFlags onm_flags;
1520 
1521  if (post)
1522  set_noconv_flags(e->body, true);
1523 
1524 #ifdef RECORD_FOLDER_HOOK
1525  mutt_folder_hook(path, NULL);
1526 #endif
1527  struct Mailbox *m_fcc = mx_path_resolve(path);
1528  bool old_append = m_fcc->append;
1529  struct Context *ctx_fcc = mx_mbox_open(m_fcc, MUTT_APPEND | MUTT_QUIET);
1530  if (!ctx_fcc)
1531  {
1532  mutt_debug(LL_DEBUG1, "unable to open mailbox %s in append-mode, aborting\n", path);
1533  mailbox_free(&m_fcc);
1534  goto done;
1535  }
1536 
1537  /* We need to add a Content-Length field to avoid problems where a line in
1538  * the message body begins with "From " */
1539  if ((ctx_fcc->mailbox->type == MUTT_MMDF) || (ctx_fcc->mailbox->type == MUTT_MBOX))
1540  {
1541  tempfile = mutt_buffer_pool_get();
1542  mutt_buffer_mktemp(tempfile);
1543  fp_tmp = mutt_file_fopen(mutt_buffer_string(tempfile), "w+");
1544  if (!fp_tmp)
1545  {
1546  mutt_perror(mutt_buffer_string(tempfile));
1547  mx_mbox_close(&ctx_fcc);
1548  goto done;
1549  }
1550  /* remember new mail status before appending message */
1551  need_mailbox_cleanup = true;
1552  stat(path, &st);
1553  }
1554 
1555  e->read = !post; /* make sure to put it in the 'cur' directory (maildir) */
1556  onm_flags = MUTT_ADD_FROM;
1557  if (post)
1558  onm_flags |= MUTT_SET_DRAFT;
1559  msg = mx_msg_open_new(ctx_fcc->mailbox, e, onm_flags);
1560  if (!msg)
1561  {
1562  mutt_file_fclose(&fp_tmp);
1563  mx_mbox_close(&ctx_fcc);
1564  goto done;
1565  }
1566 
1567  const bool c_crypt_protected_headers_read =
1568  cs_subset_bool(sub, "crypt_protected_headers_read");
1569 
1570  /* post == 1 => postpone message.
1571  * post == 0 => Normal mode. */
1573  msg->fp, e->env, e->body,
1575  c_crypt_protected_headers_read && mutt_should_hide_protected_subject(e), sub);
1576 
1577  /* (postponement) if this was a reply of some sort, <msgid> contains the
1578  * Message-ID: of message replied to. Save it using a special X-Mutt-
1579  * header so it can be picked up if the message is recalled at a later
1580  * point in time. This will allow the message to be marked as replied if
1581  * the same mailbox is still open. */
1582  if (post && msgid)
1583  fprintf(msg->fp, "X-Mutt-References: %s\n", msgid);
1584 
1585  /* (postponement) save the Fcc: using a special X-Mutt- header so that
1586  * it can be picked up when the message is recalled */
1587  if (post && fcc)
1588  fprintf(msg->fp, "X-Mutt-Fcc: %s\n", fcc);
1589 
1590  if ((ctx_fcc->mailbox->type == MUTT_MMDF) || (ctx_fcc->mailbox->type == MUTT_MBOX))
1591  fprintf(msg->fp, "Status: RO\n");
1592 
1593  /* (postponement) if the mail is to be signed or encrypted, save this info */
1594  if (((WithCrypto & APPLICATION_PGP) != 0) && post && (e->security & APPLICATION_PGP))
1595  {
1596  fputs("X-Mutt-PGP: ", msg->fp);
1597  if (e->security & SEC_ENCRYPT)
1598  fputc('E', msg->fp);
1599  if (e->security & SEC_OPPENCRYPT)
1600  fputc('O', msg->fp);
1601  if (e->security & SEC_SIGN)
1602  {
1603  fputc('S', msg->fp);
1604 
1605  const char *c_pgp_sign_as = cs_subset_string(sub, "pgp_sign_as");
1606  if (c_pgp_sign_as)
1607  fprintf(msg->fp, "<%s>", c_pgp_sign_as);
1608  }
1609  if (e->security & SEC_INLINE)
1610  fputc('I', msg->fp);
1611 #ifdef USE_AUTOCRYPT
1612  if (e->security & SEC_AUTOCRYPT)
1613  fputc('A', msg->fp);
1615  fputc('Z', msg->fp);
1616 #endif
1617  fputc('\n', msg->fp);
1618  }
1619 
1620  /* (postponement) if the mail is to be signed or encrypted, save this info */
1621  if (((WithCrypto & APPLICATION_SMIME) != 0) && post && (e->security & APPLICATION_SMIME))
1622  {
1623  fputs("X-Mutt-SMIME: ", msg->fp);
1624  if (e->security & SEC_ENCRYPT)
1625  {
1626  fputc('E', msg->fp);
1627 
1628  const char *c_smime_encrypt_with =
1629  cs_subset_string(sub, "smime_encrypt_with");
1630  if (c_smime_encrypt_with)
1631  fprintf(msg->fp, "C<%s>", c_smime_encrypt_with);
1632  }
1633  if (e->security & SEC_OPPENCRYPT)
1634  fputc('O', msg->fp);
1635  if (e->security & SEC_SIGN)
1636  {
1637  fputc('S', msg->fp);
1638 
1639  const char *c_smime_sign_as = cs_subset_string(sub, "smime_sign_as");
1640  if (c_smime_sign_as)
1641  fprintf(msg->fp, "<%s>", c_smime_sign_as);
1642  }
1643  if (e->security & SEC_INLINE)
1644  fputc('I', msg->fp);
1645  fputc('\n', msg->fp);
1646  }
1647 
1648 #ifdef MIXMASTER
1649  /* (postponement) if the mail is to be sent through a mixmaster
1650  * chain, save that information */
1651 
1652  if (post && !STAILQ_EMPTY(&e->chain))
1653  {
1654  fputs("X-Mutt-Mix:", msg->fp);
1655  struct ListNode *p = NULL;
1656  STAILQ_FOREACH(p, &e->chain, entries)
1657  {
1658  fprintf(msg->fp, " %s", (char *) p->data);
1659  }
1660 
1661  fputc('\n', msg->fp);
1662  }
1663 #endif
1664 
1665  if (fp_tmp)
1666  {
1667  mutt_write_mime_body(e->body, fp_tmp, sub);
1668 
1669  /* make sure the last line ends with a newline. Emacs doesn't ensure this
1670  * will happen, and it can cause problems parsing the mailbox later. */
1671  fseek(fp_tmp, -1, SEEK_END);
1672  if (fgetc(fp_tmp) != '\n')
1673  {
1674  fseek(fp_tmp, 0, SEEK_END);
1675  fputc('\n', fp_tmp);
1676  }
1677 
1678  fflush(fp_tmp);
1679  if (ferror(fp_tmp))
1680  {
1681  mutt_debug(LL_DEBUG1, "%s: write failed\n", mutt_buffer_string(tempfile));
1682  mutt_file_fclose(&fp_tmp);
1683  unlink(mutt_buffer_string(tempfile));
1684  mx_msg_commit(ctx_fcc->mailbox, msg); /* XXX really? */
1685  mx_msg_close(ctx_fcc->mailbox, &msg);
1686  mx_mbox_close(&ctx_fcc);
1687  goto done;
1688  }
1689 
1690  /* count the number of lines */
1691  int lines = 0;
1692  char line_buf[1024];
1693  rewind(fp_tmp);
1694  while (fgets(line_buf, sizeof(line_buf), fp_tmp))
1695  lines++;
1696  fprintf(msg->fp, "Content-Length: " OFF_T_FMT "\n", (LOFF_T) ftello(fp_tmp));
1697  fprintf(msg->fp, "Lines: %d\n\n", lines);
1698 
1699  /* copy the body and clean up */
1700  rewind(fp_tmp);
1701  rc = mutt_file_copy_stream(fp_tmp, msg->fp);
1702  if (mutt_file_fclose(&fp_tmp) != 0)
1703  rc = -1;
1704  /* if there was an error, leave the temp version */
1705  if (rc >= 0)
1706  {
1707  unlink(mutt_buffer_string(tempfile));
1708  rc = 0;
1709  }
1710  }
1711  else
1712  {
1713  fputc('\n', msg->fp); /* finish off the header */
1714  rc = mutt_write_mime_body(e->body, msg->fp, sub);
1715  }
1716 
1717  if (mx_msg_commit(ctx_fcc->mailbox, msg) != 0)
1718  rc = -1;
1719  else if (finalpath)
1720  *finalpath = mutt_str_dup(msg->committed_path);
1721  mx_msg_close(ctx_fcc->mailbox, &msg);
1722  mx_mbox_close(&ctx_fcc);
1723 
1724  if (!post && need_mailbox_cleanup)
1725  mutt_mailbox_cleanup(path, &st);
1726 
1727  if (post)
1728  set_noconv_flags(e->body, false);
1729 
1730 done:
1731  if (m_fcc)
1732  m_fcc->append = old_append;
1733 #ifdef RECORD_FOLDER_HOOK
1734  /* We ran a folder hook for the destination mailbox,
1735  * now we run it for the user's current mailbox */
1736  const struct Mailbox *m = ctx_mailbox(Context);
1737  if (m)
1738  mutt_folder_hook(m->path, m->desc);
1739 #endif
1740 
1741  if (fp_tmp)
1742  {
1743  mutt_file_fclose(&fp_tmp);
1744  unlink(mutt_buffer_string(tempfile));
1745  }
1746  mutt_buffer_pool_release(&tempfile);
1747 
1748  return rc;
1749 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:
mutt_file_copy_bytes
int mutt_file_copy_bytes(FILE *fp_in, FILE *fp_out, size_t size)
Copy some content from one file to another.
Definition: file.c:241
CopyHeaderFlags
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:49
Envelope::bcc
struct AddressList bcc
Email's 'Bcc' list.
Definition: envelope.h:60
ENC_BINARY
@ ENC_BINARY
Binary.
Definition: mime.h:53
MUTT_WRITE_HEADER_FCC
@ MUTT_WRITE_HEADER_FCC
fcc mode, like normal mode but for Bcc header
Definition: header.h:41
ENC_QUOTED_PRINTABLE
@ ENC_QUOTED_PRINTABLE
Quoted-printable text.
Definition: mime.h:51
update_content_info
static void update_content_info(struct Content *info, struct ContentState *s, char *buf, size_t buflen)
Cache some info about an email.
Definition: sendlib.c:81
Body::noconv
bool noconv
Don't do character set conversion.
Definition: body.h:73
MUTT_MMDF
@ MUTT_MMDF
'mmdf' Mailbox type
Definition: mailbox.h:49
State::fp_in
FILE * fp_in
File to read from.
Definition: state.h:46
mutt_mem_calloc
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
mutt_stamp_attachment
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:893
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
rfc2047_encode_envelope
void rfc2047_encode_envelope(struct Envelope *env)
Encode the fields of an Envelope.
Definition: rfc2047.c:799
mutt_ch_canonical_charset
void mutt_ch_canonical_charset(char *buf, size_t buflen, const char *name)
Canonicalise the charset of a string.
Definition: charset.c:352
Envelope::message_id
char * message_id
Message ID.
Definition: envelope.h:69
APPLICATION_SMIME
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:98
Body::content
struct Content * content
Detailed info about the content of the attachment.
Definition: body.h:51
Mailbox::append
bool append
Mailbox is opened in append mode.
Definition: mailbox.h:113
mutt_addrlist_qualify
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:650
ContentState::linelen
int linelen
Definition: sendlib.c:70
Content::dot
bool dot
Has a line consisting of a single dot?
Definition: content.h:44
CH_NONEWLINE
#define CH_NONEWLINE
Don't output terminating newline after the header.
Definition: copy.h:59
mutt_date_make_date
void mutt_date_make_date(struct Buffer *buf)
Write a date in RFC822 format to a buffer.
Definition: date.c:377
Address::personal
char * personal
Real name of address.
Definition: address.h:36
ListNode
A List node for strings.
Definition: list.h:34
Buffer
String manipulation buffer.
Definition: buffer.h:33
mutt_addrlist_append
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1488
encode_headers
static void encode_headers(struct ListHead *h, struct ConfigSubset *sub)
RFC2047-encode a list of headers.
Definition: sendlib.c:1142
mutt_addrlist_to_intl
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1304
Body::offset
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
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
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
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_dealloc
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
Body
The body of an email.
Definition: body.h:34
mutt_mailbox_cleanup
void mutt_mailbox_cleanup(const char *path, struct stat *st)
Restore the timestamp of a mailbox.
Definition: mutt_mailbox.c:358
SMIME_ENCRYPT
#define SMIME_ENCRYPT
Definition: lib.h:109
SEC_ENCRYPT
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:85
SEC_SIGN
#define SEC_SIGN
Email is signed.
Definition: lib.h:86
MUTT_ICONV_NO_FLAGS
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:73
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
mutt_buffer_mktemp
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
mutt_folder_hook
void mutt_folder_hook(const char *path, const char *desc)
Perform a folder hook.
Definition: hook.c:505
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
Content::from
bool from
Has a line beginning with "From "?
Definition: content.h:43
TAILQ_EMPTY
#define TAILQ_EMPTY(head)
Definition: queue.h:714
Email::offset
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:84
Content::linemax
long linemax
Length of the longest line in the file.
Definition: content.h:40
MUTT_WRITE_HEADER_POSTPONE
@ MUTT_WRITE_HEADER_POSTPONE
A postponed Email, just the envelope info.
Definition: header.h:42
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_file_fopen
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
mutt_file_unlink
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
LL_DEBUG1
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
mutt_check_mime_type
enum ContentType mutt_check_mime_type(const char *s)
Check a MIME type string.
Definition: parse.c:325
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
Content::hibin
long hibin
8-bit characters
Definition: content.h:35
Body::disposition
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:67
mutt_perror
#define mutt_perror(...)
Definition: logging.h:85
ContentType
ContentType
Content-Type.
Definition: mime.h:29
Body::encoding
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
Content::lobin
long lobin
Unprintable 7-bit chars (eg., control chars)
Definition: content.h:36
ContentState::whitespace
int whitespace
Definition: sendlib.c:68
SecurityFlags
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:83
PATH_MAX
#define PATH_MAX
Definition: mutt.h:44
Content::nulbin
long nulbin
Null characters (0x0)
Definition: content.h:37
mutt_buffer_pool_release
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
Content::space
bool space
Whitespace at the end of lines?
Definition: content.h:41
STAILQ_EMPTY
#define STAILQ_EMPTY(head)
Definition: queue.h:345
mailbox_free
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:71
MUTT_CM_DECODE_PGP
#define MUTT_CM_DECODE_PGP
Used for decoding PGP messages.
Definition: copy.h:44
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
mx_path_resolve
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1681
rfc2047_decode_envelope
void rfc2047_decode_envelope(struct Envelope *env)
Decode the fields of an Envelope.
Definition: rfc2047.c:779
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
State::fp_out
FILE * fp_out
File to write to.
Definition: state.h:47
mutt_strn_copy
char * mutt_strn_copy(char *dest, const char *src, size_t len, size_t dsize)
Copy a sub-string into a buffer.
Definition: string.c:528
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_ch_iconv_open
iconv_t mutt_ch_iconv_open(const char *tocode, const char *fromcode, uint8_t flags)
Set up iconv for conversions.
Definition: charset.c:565
mutt_istr_equal
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
rfc2047_encode_addrlist
void rfc2047_encode_addrlist(struct AddressList *al, const char *tag)
Encode any RFC2047 headers, where required, in an Address list.
Definition: rfc2047.c:738
gen_msgid
static char * gen_msgid(struct ConfigSubset *sub)
Generate a unique Message ID.
Definition: sendlib.c:1211
TAILQ_HEAD_INITIALIZER
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:630
AddressSpecials
const char AddressSpecials[]
Characters with special meaning for email addresses.
Definition: address.c:42
MUTT_RL_NO_FLAGS
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:39
Message::committed_path
char * committed_path
the final path generated by mx_msg_commit()
Definition: mx.h:98
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
mutt_parse_content_type
void mutt_parse_content_type(const char *s, struct Body *ct)
Parse a content type.
Definition: parse.c:426
mutt_buffer_file_expand_fmt_quote
void mutt_buffer_file_expand_fmt_quote(struct Buffer *dest, const char *fmt, const char *src)
Replace s in a string with a filename.
Definition: file.c:1432
filter_create
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
Envelope::cc
struct AddressList cc
Email's 'Cc' list.
Definition: envelope.h:59
CH_WEED_DELIVERED
#define CH_WEED_DELIVERED
Weed eventual Delivered-To headers.
Definition: copy.h:64
mutt_body_new
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
mutt_expand_path
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:128
mutt_buffer_pool_get
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
bounce_message
static int bounce_message(FILE *fp, struct Mailbox *m, struct Email *e, struct AddressList *to, const char *resent_from, struct AddressList *env_from, struct ConfigSubset *sub)
Bounce an email message.
Definition: sendlib.c:1303
mutt_is_application_pgp
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:554
Body::xtype
char * xtype
content-type if x-unknown
Definition: body.h:36
Mailbox::type
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
mx_msg_commit
int mx_msg_commit(struct Mailbox *m, struct Message *msg)
Commit a message to a folder - Wrapper for MxOps::msg_commit()
Definition: mx.c:1183
Content::binary
bool binary
Long lines, or CR not in CRLF pair.
Definition: content.h:42
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
Body::force_charset
bool force_charset
Send mode: don't adjust the character set when in send-mode.
Definition: body.h:74
mutt_is_multipart_encrypted
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:449
MUTT_RANDTAG_LEN
#define MUTT_RANDTAG_LEN
Definition: sendlib.h:35
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
mx_mbox_close
enum MxStatus mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:632
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
Body::length
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
ContentState
Info about the body of an email.
Definition: sendlib.c:65
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_str_skip_email_wsp
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:743
mutt_body_get_charset
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body's character set.
Definition: body.c:131
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_addrlist_clear
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1468
mutt_copy_hdr
int mutt_copy_hdr(FILE *fp_in, FILE *fp_out, LOFF_T off_start, LOFF_T off_end, CopyHeaderFlags chflags, const char *prefix, int wraplen)
Copy header from one file to another.
Definition: copy.c:103
mutt_ch_is_us_ascii
#define mutt_ch_is_us_ascii(str)
Definition: charset.h:98
mutt_param_set
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
mutt_is_message_type
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1368
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
TYPE_MESSAGE
@ TYPE_MESSAGE
Type: 'message/*'.
Definition: mime.h:35
Context::mailbox
struct Mailbox * mailbox
Definition: context.h:50
mutt_mem_realloc
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
Email::env
struct Envelope * env
Envelope information.
Definition: email.h:90
Content::ascii
long ascii
Number of ascii chars.
Definition: content.h:39
Body::charset
char * charset
Send mode: charset of attached file as stored on disk.
Definition: body.h:49
mutt_debug
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
mutt_copy_header
int mutt_copy_header(FILE *fp_in, struct Email *e, FILE *fp_out, CopyHeaderFlags chflags, const char *prefix, int wraplen)
Copy Email header.
Definition: copy.c:405
chs
static char * chs
Definition: gnupgparse.c:73
MUTT_ADD_FROM
#define MUTT_ADD_FROM
add a From_ line
Definition: mx.h:65
Message::fp
FILE * fp
pointer to the message data
Definition: mx.h:96
MUTT_QUIET
#define MUTT_QUIET
Do not print any messages.
Definition: mx.h:55
mutt_str_len
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
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
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
MUTT_DATE_NOW
#define MUTT_DATE_NOW
Constant representing the 'current time', see: mutt_date_gmtime(), mutt_date_localtime()
Definition: date.h:39
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
WithCrypto
#define WithCrypto
Definition: lib.h:123
mutt_param_delete
void mutt_param_delete(struct ParameterList *pl, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:142
Address::mailbox
char * mailbox
Mailbox and host address.
Definition: address.h:37
mutt_param_get
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
CH_NOQFROM
#define CH_NOQFROM
Ignore ">From " line.
Definition: copy.h:66
PGP_ENCRYPT
#define PGP_ENCRYPT
Definition: lib.h:103
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
ContentState::dot
bool dot
Definition: sendlib.c:69
Envelope::userhdrs
struct ListHead userhdrs
user defined headers
Definition: envelope.h:83
TYPE_APPLICATION
@ TYPE_APPLICATION
Type: 'application/*'.
Definition: mime.h:33
State
Keep track when processing files.
Definition: state.h:44
transform_to_7bit
static void transform_to_7bit(struct Body *a, FILE *fp_in, struct ConfigSubset *sub)
Convert MIME parts to 7-bit.
Definition: sendlib.c:685
Body::d_filename
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
HomeDir
char * HomeDir
User's home directory.
Definition: mutt_globals.h:49
Content::crlf
long crlf
\r and \n characters
Definition: content.h:38
Body::stamp
time_t stamp
Time stamp of last encoding update.
Definition: body.h:61
ENC_BASE64
@ ENC_BASE64
Base-64 encoded text.
Definition: mime.h:52
mutt_mem_malloc
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
MsgOpenFlags
uint8_t MsgOpenFlags
Flags for mx_msg_open_new(), e.g. MUTT_ADD_FROM.
Definition: mx.h:63
ShortHostname
WHERE char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:50
TYPE_TEXT
@ TYPE_TEXT
Type: 'text/*'.
Definition: mime.h:38
mutt_strn_dup
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:548
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
set_noconv_flags
static void set_noconv_flags(struct Body *b, bool flag)
Set/reset the "x-mutt-noconv" flag.
Definition: sendlib.c:1434
Content::cr
bool cr
Has CR, even when in a CRLF pair.
Definition: content.h:45
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
Content
Info about an attachment.
Definition: content.h:33
Body::type
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
mutt_date_gmtime
struct tm mutt_date_gmtime(time_t t)
Converts calendar time to a broken-down time structure expressed in UTC timezone.
Definition: date.c:661
mx_mbox_open
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:309
TYPE_OTHER
@ TYPE_OTHER
Unknown Content-Type.
Definition: mime.h:31
mutt_addr_cat
void mutt_addr_cat(char *buf, size_t buflen, const char *value, const char *specials)
Copy a string and wrap it in quotes if it contains special characters.
Definition: address.c:681
mutt_addrlist_write_file
void mutt_addrlist_write_file(const struct AddressList *al, FILE *fp, int start_col, bool display)
Wrapper for mutt_write_address()
Definition: address.c:1231
mutt_write_mime_header
int mutt_write_mime_header(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Create a MIME header.
Definition: header.c:764
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
ContentState::was_cr
bool was_cr
Definition: sendlib.c:71
mutt_rfc822_read_header
struct Envelope * mutt_rfc822_read_header(FILE *fp, struct Email *e, bool user_hdrs, bool weed)
parses an RFC822 header
Definition: parse.c:1112
MUTT_CM_DECODE
#define MUTT_CM_DECODE
Decode the message body into text/plain.
Definition: copy.h:37
Body::use_disp
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
set_encoding
static void set_encoding(struct Body *b, struct Content *info, struct ConfigSubset *sub)
determine which Content-Transfer-Encoding to use
Definition: sendlib.c:835
OptNewsSend
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:46
CH_MIME
#define CH_MIME
Ignore MIME fields.
Definition: copy.h:60
CH_TXTPLAIN
#define CH_TXTPLAIN
Generate text/plain MIME headers.
Definition: copy.h:62
Body::email
struct Email * email
header information for message/rfc822
Definition: body.h:55
mutt_buffer_strdup
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:432
mutt_rand_base32
void mutt_rand_base32(char *buf, size_t buflen)
Fill a buffer with a base32-encoded random string.
Definition: random.c:102
mutt_set_followup_to
void mutt_set_followup_to(struct Envelope *env, struct ConfigSubset *sub)
Set followup-to field.
Definition: send.c:1213
Body::unlink
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
MUTT_APPEND
#define MUTT_APPEND
Open mailbox for appending messages.
Definition: mx.h:53
Body::parameter
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
mutt_decode_attachment
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email's attachment.
Definition: handler.c:1845
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
IS_SPACE
#define IS_SPACE(ch)
Definition: string2.h:38
TYPE_MULTIPART
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition: mime.h:37
convert_file_to
static size_t convert_file_to(FILE *fp, const char *fromcode, int ncodes, char const *const *tocodes, int *tocode, struct Content *info)
Change the encoding of a file.
Definition: sendlib.c:228
MUTT_SET_DRAFT
#define MUTT_SET_DRAFT
set the message draft flag
Definition: mx.h:66
mx_msg_open_new
struct Message * mx_msg_open_new(struct Mailbox *m, const struct Email *e, MsgOpenFlags flags)
Open a new message.
Definition: mx.c:1072
convert_file_from_to
static size_t convert_file_from_to(FILE *fp, const char *fromcodes, const char *tocodes, char **fromcode, char **tocode, struct Content *info)
Convert a file between encodings.
Definition: sendlib.c:381
mutt_lookup_mime_type
enum ContentType mutt_lookup_mime_type(struct Body *att, const char *path)
Find the MIME type for an attachment.
Definition: sendlib.c:565
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_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
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
SEC_NO_FLAGS
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:84
MUTT_MBOX
@ MUTT_MBOX
'mbox' Mailbox type
Definition: mailbox.h:48
run_mime_type_query
static void run_mime_type_query(struct Body *att, struct ConfigSubset *sub)
Run an external command to determine the MIME type.
Definition: sendlib.c:1041
mutt_is_application_smime
SecurityFlags mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
Definition: crypt.c:612
ENC_7BIT
@ ENC_7BIT
7-bit text
Definition: mime.h:49
mutt_message_to_7bit
void mutt_message_to_7bit(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Convert an email's MIME parts to 7-bit.
Definition: sendlib.c:748
mutt_get_content_info
struct Content * mutt_get_content_info(const char *fname, struct Body *b, struct ConfigSubset *sub)
Analyze file to determine MIME encoding to use.
Definition: sendlib.c:467
SEC_AUTOCRYPT
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:94
Address
An email address.
Definition: address.h:34
Message
A local copy of an email.
Definition: mx.h:94
mutt_rfc822_parse_message
struct Body * mutt_rfc822_parse_message(FILE *fp, struct Body *parent)
parse a Message/RFC822 body
Definition: parse.c:1674
ContentState::from
bool from
Definition: sendlib.c:67
Body::filename
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
CH_XMIT
#define CH_XMIT
Transmitting this message? (Ignore Lines: and Content-Length:)
Definition: copy.h:54
Email::body
struct Body * body
List of MIME parts.
Definition: email.h:91
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_file_read_line
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition: file.c:667
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