NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
sendlib.c File Reference

Miscellaneous functions for sending an email. More...

#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 "attachments.h"
#include "copy.h"
#include "handler.h"
#include "mutt_globals.h"
#include "mutt_mailbox.h"
#include "muttlib.h"
#include "mx.h"
#include "options.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 79 of file sendlib.c.

81 {
82  bool from = s->from;
83  int whitespace = s->whitespace;
84  bool dot = s->dot;
85  int linelen = s->linelen;
86  bool was_cr = s->was_cr;
87 
88  if (!buf) /* This signals EOF */
89  {
90  if (was_cr)
91  info->binary = true;
92  if (linelen > info->linemax)
93  info->linemax = linelen;
94 
95  return;
96  }
97 
98  for (; buflen; buf++, buflen--)
99  {
100  char ch = *buf;
101 
102  if (was_cr)
103  {
104  was_cr = false;
105  if (ch == '\n')
106  {
107  if (whitespace)
108  info->space = true;
109  if (dot)
110  info->dot = true;
111  if (linelen > info->linemax)
112  info->linemax = linelen;
113  whitespace = 0;
114  dot = false;
115  linelen = 0;
116  continue;
117  }
118 
119  info->binary = true;
120  }
121 
122  linelen++;
123  if (ch == '\n')
124  {
125  info->crlf++;
126  if (whitespace)
127  info->space = true;
128  if (dot)
129  info->dot = true;
130  if (linelen > info->linemax)
131  info->linemax = linelen;
132  whitespace = 0;
133  linelen = 0;
134  dot = false;
135  }
136  else if (ch == '\r')
137  {
138  info->crlf++;
139  info->cr = true;
140  was_cr = true;
141  continue;
142  }
143  else if (ch & 0x80)
144  info->hibin++;
145  else if ((ch == '\t') || (ch == '\f'))
146  {
147  info->ascii++;
148  whitespace++;
149  }
150  else if (ch == 0)
151  {
152  info->nulbin++;
153  info->lobin++;
154  }
155  else if ((ch < 32) || (ch == 127))
156  info->lobin++;
157  else
158  {
159  if (linelen == 1)
160  {
161  if ((ch == 'F') || (ch == 'f'))
162  from = true;
163  else
164  from = false;
165  if (ch == '.')
166  dot = true;
167  else
168  dot = false;
169  }
170  else if (from)
171  {
172  if ((linelen == 2) && (ch != 'r'))
173  from = false;
174  else if ((linelen == 3) && (ch != 'o'))
175  from = false;
176  else if (linelen == 4)
177  {
178  if (ch == 'm')
179  info->from = true;
180  from = false;
181  }
182  }
183  if (ch == ' ')
184  whitespace++;
185  info->ascii++;
186  }
187 
188  if (linelen > 1)
189  dot = false;
190  if ((ch != ' ') && (ch != '\t'))
191  whitespace = 0;
192  }
193 
194  s->from = from;
195  s->whitespace = whitespace;
196  s->dot = dot;
197  s->linelen = linelen;
198  s->was_cr = was_cr;
199 }
int whitespace
Definition: sendlib.c:66
bool dot
Has a line consisting of a single dot?
Definition: content.h:44
long linemax
Length of the longest line in the file.
Definition: content.h:40
bool dot
Definition: sendlib.c:67
long hibin
8-bit characters
Definition: content.h:35
bool was_cr
Definition: sendlib.c:69
bool from
Definition: sendlib.c:65
bool binary
Long lines, or CR not in CRLF pair.
Definition: content.h:42
long ascii
Number of ascii chars.
Definition: content.h:39
int linelen
Definition: sendlib.c:68
bool from
Has a line beginning with "From "?
Definition: content.h:43
long lobin
Unprintable 7-bit chars (eg., control chars)
Definition: content.h:36
long crlf
\r and \n characters
Definition: content.h:38
bool space
Whitespace at the end of lines?
Definition: content.h:41
long nulbin
Null characters (0x0)
Definition: content.h:37
bool cr
Has CR, even when in a CRLF pair.
Definition: content.h:45
+ 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 226 of file sendlib.c.

228 {
229  char bufi[256], bufu[512], bufo[4 * sizeof(bufi)];
230  size_t ret;
231 
232  const iconv_t cd1 = mutt_ch_iconv_open("utf-8", fromcode, MUTT_ICONV_NO_FLAGS);
233  if (cd1 == (iconv_t) (-1))
234  return -1;
235 
236  iconv_t *cd = mutt_mem_calloc(ncodes, sizeof(iconv_t));
237  size_t *score = mutt_mem_calloc(ncodes, sizeof(size_t));
238  struct ContentState *states = mutt_mem_calloc(ncodes, sizeof(struct ContentState));
239  struct Content *infos = mutt_mem_calloc(ncodes, sizeof(struct Content));
240 
241  for (int i = 0; i < ncodes; i++)
242  {
243  if (!mutt_istr_equal(tocodes[i], "utf-8"))
244  cd[i] = mutt_ch_iconv_open(tocodes[i], "utf-8", MUTT_ICONV_NO_FLAGS);
245  else
246  {
247  /* Special case for conversion to UTF-8 */
248  cd[i] = (iconv_t) (-1);
249  score[i] = (size_t) (-1);
250  }
251  }
252 
253  rewind(fp);
254  size_t ibl = 0;
255  while (true)
256  {
257  /* Try to fill input buffer */
258  size_t n = fread(bufi + ibl, 1, sizeof(bufi) - ibl, fp);
259  ibl += n;
260 
261  /* Convert to UTF-8 */
262  const char *ib = bufi;
263  char *ob = bufu;
264  size_t obl = sizeof(bufu);
265  n = iconv(cd1, (ICONV_CONST char **) ((ibl != 0) ? &ib : 0), &ibl, &ob, &obl);
266  /* assert(n == (size_t)(-1) || !n); */
267  if ((n == (size_t) (-1)) && (((errno != EINVAL) && (errno != E2BIG)) || (ib == bufi)))
268  {
269  /* assert(errno == EILSEQ || (errno == EINVAL && ib == bufi && ibl < sizeof(bufi))); */
270  ret = (size_t) (-1);
271  break;
272  }
273  const size_t ubl1 = ob - bufu;
274 
275  /* Convert from UTF-8 */
276  for (int i = 0; i < ncodes; i++)
277  {
278  if ((cd[i] != (iconv_t) (-1)) && (score[i] != (size_t) (-1)))
279  {
280  const char *ub = bufu;
281  size_t ubl = ubl1;
282  ob = bufo;
283  obl = sizeof(bufo);
284  n = iconv(cd[i], (ICONV_CONST char **) ((ibl || ubl) ? &ub : 0), &ubl, &ob, &obl);
285  if (n == (size_t) (-1))
286  {
287  /* assert(errno == E2BIG || (BUGGY_ICONV && (errno == EILSEQ || errno == ENOENT))); */
288  score[i] = (size_t) (-1);
289  }
290  else
291  {
292  score[i] += n;
293  update_content_info(&infos[i], &states[i], bufo, ob - bufo);
294  }
295  }
296  else if ((cd[i] == (iconv_t) (-1)) && (score[i] == (size_t) (-1)))
297  {
298  /* Special case for conversion to UTF-8 */
299  update_content_info(&infos[i], &states[i], bufu, ubl1);
300  }
301  }
302 
303  if (ibl)
304  {
305  /* Save unused input */
306  memmove(bufi, ib, ibl);
307  }
308  else if (!ubl1 && (ib < bufi + sizeof(bufi)))
309  {
310  ret = 0;
311  break;
312  }
313  }
314 
315  if (ret == 0)
316  {
317  /* Find best score */
318  ret = (size_t) (-1);
319  for (int i = 0; i < ncodes; i++)
320  {
321  if ((cd[i] == (iconv_t) (-1)) && (score[i] == (size_t) (-1)))
322  {
323  /* Special case for conversion to UTF-8 */
324  *tocode = i;
325  ret = 0;
326  break;
327  }
328  else if ((cd[i] == (iconv_t) (-1)) || (score[i] == (size_t) (-1)))
329  continue;
330  else if ((ret == (size_t) (-1)) || (score[i] < ret))
331  {
332  *tocode = i;
333  ret = score[i];
334  if (ret == 0)
335  break;
336  }
337  }
338  if (ret != (size_t) (-1))
339  {
340  memcpy(info, &infos[*tocode], sizeof(struct Content));
341  update_content_info(info, &states[*tocode], 0, 0); /* EOF */
342  }
343  }
344 
345  for (int i = 0; i < ncodes; i++)
346  if (cd[i] != (iconv_t) (-1))
347  iconv_close(cd[i]);
348 
349  iconv_close(cd1);
350  FREE(&cd);
351  FREE(&infos);
352  FREE(&score);
353  FREE(&states);
354 
355  return ret;
356 }
Info about the body of an email.
Definition: sendlib.c:63
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:79
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:71
iconv_t mutt_ch_iconv_open(const char *tocode, const char *fromcode, uint8_t flags)
Set up iconv for conversions.
Definition: charset.c:569
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
Info about an attachment.
Definition: content.h:33
#define FREE(x)
Definition: memory.h:40
+ 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 379 of file sendlib.c.

381 {
382  char *fcode = NULL;
383  char **tcode = NULL;
384  const char *c = NULL, *c1 = NULL;
385  size_t ret;
386  int ncodes, i, cn;
387 
388  /* Count the tocodes */
389  ncodes = 0;
390  for (c = tocodes; c; c = c1 ? c1 + 1 : 0)
391  {
392  c1 = strchr(c, ':');
393  if (c1 == c)
394  continue;
395  ncodes++;
396  }
397 
398  /* Copy them */
399  tcode = mutt_mem_malloc(ncodes * sizeof(char *));
400  for (c = tocodes, i = 0; c; c = c1 ? c1 + 1 : 0, i++)
401  {
402  c1 = strchr(c, ':');
403  if (c1 == c)
404  continue;
405  if (c1)
406  tcode[i] = mutt_strn_dup(c, c1 - c);
407  else
408  tcode[i] = mutt_str_dup(c);
409  }
410 
411  ret = (size_t) (-1);
412  if (fromcode)
413  {
414  /* Try each fromcode in turn */
415  for (c = fromcodes; c; c = c1 ? c1 + 1 : 0)
416  {
417  c1 = strchr(c, ':');
418  if (c1 == c)
419  continue;
420  if (c1)
421  fcode = mutt_strn_dup(c, c1 - c);
422  else
423  fcode = mutt_str_dup(c);
424 
425  ret = convert_file_to(fp, fcode, ncodes, (char const *const *) tcode, &cn, info);
426  if (ret != (size_t) (-1))
427  {
428  *fromcode = fcode;
429  *tocode = tcode[cn];
430  tcode[cn] = 0;
431  break;
432  }
433  FREE(&fcode);
434  }
435  }
436  else
437  {
438  /* There is only one fromcode */
439  ret = convert_file_to(fp, fromcodes, ncodes, (char const *const *) tcode, &cn, info);
440  if (ret != (size_t) (-1))
441  {
442  *tocode = tcode[cn];
443  tcode[cn] = 0;
444  }
445  }
446 
447  /* Free memory */
448  for (i = 0; i < ncodes; i++)
449  FREE(&tcode[i]);
450 
451  FREE(&tcode);
452 
453  return ret;
454 }
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:548
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define FREE(x)
Definition: memory.h:40
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:226
+ 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 465 of file sendlib.c.

467 {
468  struct Content *info = NULL;
469  struct ContentState state = { 0 };
470  FILE *fp = NULL;
471  char *fromcode = NULL;
472  char *tocode = NULL;
473  char buf[100];
474  size_t r;
475 
476  struct stat sb;
477 
478  if (b && !fname)
479  fname = b->filename;
480  if (!fname)
481  return NULL;
482 
483  if (stat(fname, &sb) == -1)
484  {
485  mutt_error(_("Can't stat %s: %s"), fname, strerror(errno));
486  return NULL;
487  }
488 
489  if (!S_ISREG(sb.st_mode))
490  {
491  mutt_error(_("%s isn't a regular file"), fname);
492  return NULL;
493  }
494 
495  fp = fopen(fname, "r");
496  if (!fp)
497  {
498  mutt_debug(LL_DEBUG1, "%s: %s (errno %d)\n", fname, strerror(errno), errno);
499  return NULL;
500  }
501 
502  info = mutt_mem_calloc(1, sizeof(struct Content));
503 
504  const char *const c_charset = cs_subset_string(sub, "charset");
505 
506  if (b && (b->type == TYPE_TEXT) && (!b->noconv && !b->force_charset))
507  {
508  const char *const c_attach_charset =
509  cs_subset_string(sub, "attach_charset");
510  const char *const c_send_charset = cs_subset_string(sub, "send_charset");
511 
512  char *chs = mutt_param_get(&b->parameter, "charset");
513  const char *fchs =
514  b->use_disp ? (c_attach_charset ? c_attach_charset : c_charset) : c_charset;
515  if (c_charset && (chs || c_send_charset) &&
516  (convert_file_from_to(fp, fchs, chs ? chs : c_send_charset, &fromcode,
517  &tocode, info) != (size_t) (-1)))
518  {
519  if (!chs)
520  {
521  char chsbuf[256];
522  mutt_ch_canonical_charset(chsbuf, sizeof(chsbuf), tocode);
523  mutt_param_set(&b->parameter, "charset", chsbuf);
524  }
525  FREE(&b->charset);
526  b->charset = fromcode;
527  FREE(&tocode);
528  mutt_file_fclose(&fp);
529  return info;
530  }
531  }
532 
533  rewind(fp);
534  while ((r = fread(buf, 1, sizeof(buf), fp)))
535  update_content_info(info, &state, buf, r);
536  update_content_info(info, &state, 0, 0);
537 
538  mutt_file_fclose(&fp);
539 
540  if (b && (b->type == TYPE_TEXT) && (!b->noconv && !b->force_charset))
541  {
542  mutt_param_set(&b->parameter, "charset",
543  (!info->hibin ? "us-ascii" :
544  c_charset && !mutt_ch_is_us_ascii(c_charset) ?
545  c_charset :
546  "unknown-8bit"));
547  }
548 
549  return info;
550 }
Info about the body of an email.
Definition: sendlib.c:63
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:79
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define mutt_error(...)
Definition: logging.h:88
bool noconv
Don&#39;t do character set conversion.
Definition: body.h:73
#define _(a)
Definition: message.h:28
long hibin
8-bit characters
Definition: content.h:35
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
bool force_charset
Send mode: don&#39;t adjust the character set when in send-mode.
Definition: body.h:75
static char * chs
Definition: gnupgparse.c:73
Info about an attachment.
Definition: content.h:33
Type: &#39;text/*&#39;.
Definition: mime.h:38
char * charset
Send mode: charset of attached file as stored on disk.
Definition: body.h:49
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
#define mutt_ch_is_us_ascii(str)
Definition: charset.h:96
Log at debug level 1.
Definition: logging.h:40
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
#define FREE(x)
Definition: memory.h:40
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
void mutt_ch_canonical_charset(char *buf, size_t buflen, const char *name)
Canonicalise the charset of a string.
Definition: charset.c:354
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
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:379
+ 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 564 of file sendlib.c.

565 {
566  FILE *fp = NULL;
567  char *p = NULL, *q = NULL, *ct = NULL;
568  char buf[PATH_MAX];
569  char subtype[256] = { 0 };
570  char xtype[256] = { 0 };
571  int sze, cur_sze = 0;
572  bool found_mimetypes = false;
573  enum ContentType type = TYPE_OTHER;
574 
575  int szf = mutt_str_len(path);
576 
577  for (int count = 0; count < 4; count++)
578  {
579  /* can't use strtok() because we use it in an inner loop below, so use
580  * a switch statement here instead. */
581  switch (count)
582  {
583  /* last file with last entry to match wins type/xtype */
584  case 0:
585  /* check default unix mimetypes location first */
586  mutt_str_copy(buf, "/etc/mime.types", sizeof(buf));
587  break;
588  case 1:
589  mutt_str_copy(buf, SYSCONFDIR "/mime.types", sizeof(buf));
590  break;
591  case 2:
592  mutt_str_copy(buf, PKGDATADIR "/mime.types", sizeof(buf));
593  break;
594  case 3:
595  snprintf(buf, sizeof(buf), "%s/.mime.types", NONULL(HomeDir));
596  break;
597  default:
598  mutt_debug(LL_DEBUG1, "Internal error, count = %d\n", count);
599  goto bye; /* shouldn't happen */
600  }
601 
602  fp = fopen(buf, "r");
603  if (fp)
604  {
605  found_mimetypes = true;
606 
607  while (fgets(buf, sizeof(buf) - 1, fp))
608  {
609  /* weed out any comments */
610  p = strchr(buf, '#');
611  if (p)
612  *p = '\0';
613 
614  /* remove any leading space. */
615  ct = buf;
616  SKIPWS(ct);
617 
618  /* position on the next field in this line */
619  p = strpbrk(ct, " \t");
620  if (!p)
621  continue;
622  *p++ = 0;
623  SKIPWS(p);
624 
625  /* cycle through the file extensions */
626  while ((p = strtok(p, " \t\n")))
627  {
628  sze = mutt_str_len(p);
629  if ((sze > cur_sze) && (szf >= sze) && mutt_istr_equal(path + szf - sze, p) &&
630  ((szf == sze) || (path[szf - sze - 1] == '.')))
631  {
632  /* get the content-type */
633 
634  p = strchr(ct, '/');
635  if (!p)
636  {
637  /* malformed line, just skip it. */
638  break;
639  }
640  *p++ = 0;
641 
642  for (q = p; *q && !IS_SPACE(*q); q++)
643  ; // do nothing
644 
645  mutt_strn_copy(subtype, p, q - p, sizeof(subtype));
646 
647  type = mutt_check_mime_type(ct);
648  if (type == TYPE_OTHER)
649  mutt_str_copy(xtype, ct, sizeof(xtype));
650 
651  cur_sze = sze;
652  }
653  p = NULL;
654  }
655  }
656  mutt_file_fclose(&fp);
657  }
658  }
659 
660 bye:
661 
662  /* no mime.types file found */
663  if (!found_mimetypes)
664  {
665  mutt_error(_("Could not find any mime.types file"));
666  }
667 
668  if ((type != TYPE_OTHER) || (*xtype != '\0'))
669  {
670  att->type = type;
671  mutt_str_replace(&att->subtype, subtype);
672  mutt_str_replace(&att->xtype, xtype);
673  }
674 
675  return type;
676 }
Unknown Content-Type.
Definition: mime.h:31
#define NONULL(x)
Definition: string2.h:37
#define mutt_error(...)
Definition: logging.h:88
#define _(a)
Definition: message.h:28
char * HomeDir
User&#39;s home directory.
Definition: mutt_globals.h:45
enum ContentType mutt_check_mime_type(const char *s)
Check a MIME type string.
Definition: parse.c:326
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
#define SKIPWS(ch)
Definition: string2.h:46
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
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
char * subtype
content-type subtype
Definition: body.h:37
#define PATH_MAX
Definition: mutt.h:40
char * xtype
content-type if x-unknown
Definition: body.h:36
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
#define IS_SPACE(ch)
Definition: string2.h:38
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
Log at debug level 1.
Definition: logging.h:40
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:749
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
ContentType
Content-Type.
Definition: mime.h:29
+ 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 684 of file sendlib.c.

685 {
686  struct Buffer *buf = NULL;
687  struct State s = { 0 };
688  struct stat sb;
689 
690  for (; a; a = a->next)
691  {
692  if (a->type == TYPE_MULTIPART)
693  {
694  a->encoding = ENC_7BIT;
695  transform_to_7bit(a->parts, fp_in, sub);
696  }
697  else if (mutt_is_message_type(a->type, a->subtype))
698  {
699  mutt_message_to_7bit(a, fp_in, sub);
700  }
701  else
702  {
703  a->noconv = true;
704  a->force_charset = true;
705 
706  /* Because of the potential recursion in message types, we
707  * restrict the lifetime of the buffer tightly */
708  buf = mutt_buffer_pool_get();
709  mutt_buffer_mktemp(buf);
711  if (!s.fp_out)
712  {
713  mutt_perror("fopen");
715  return;
716  }
717  s.fp_in = fp_in;
718  mutt_decode_attachment(a, &s);
720  FREE(&a->d_filename);
721  a->d_filename = a->filename;
722  a->filename = mutt_buffer_strdup(buf);
724  a->unlink = true;
725  if (stat(a->filename, &sb) == -1)
726  {
727  mutt_perror("stat");
728  return;
729  }
730  a->length = sb.st_size;
731 
732  mutt_update_encoding(a, sub);
733  if (a->encoding == ENC_8BIT)
735  else if (a->encoding == ENC_BINARY)
736  a->encoding = ENC_BASE64;
737  }
738  }
739 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1861
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1385
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
void mutt_update_encoding(struct Body *a, struct ConfigSubset *sub)
Update the encoding type.
Definition: sendlib.c:904
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
7-bit text
Definition: mime.h:49
void mutt_message_to_7bit(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Convert an email&#39;s MIME parts to 7-bit.
Definition: sendlib.c:747
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
bool noconv
Don&#39;t do character set conversion.
Definition: body.h:73
String manipulation buffer.
Definition: buffer.h:33
struct Body * next
next attachment in the list
Definition: body.h:53
8-bit text
Definition: mime.h:50
FILE * fp_out
File to write to.
Definition: state.h:47
#define mutt_perror(...)
Definition: logging.h:89
FILE * fp_in
File to read from.
Definition: state.h:46
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
bool force_charset
Send mode: don&#39;t adjust the character set when in send-mode.
Definition: body.h:75
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
char * subtype
content-type subtype
Definition: body.h:37
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
static void transform_to_7bit(struct Body *a, FILE *fp_in, struct ConfigSubset *sub)
Convert MIME parts to 7-bit.
Definition: sendlib.c:684
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
Binary.
Definition: mime.h:53
Quoted-printable text.
Definition: mime.h:51
#define FREE(x)
Definition: memory.h:40
Keep track when processing files.
Definition: state.h:44
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
+ 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 747 of file sendlib.c.

748 {
749  struct Buffer temp = mutt_buffer_make(0);
750  FILE *fp_in = NULL;
751  FILE *fp_out = NULL;
752  struct stat sb;
753 
754  if (!a->filename && fp)
755  fp_in = fp;
756  else if (!a->filename || !(fp_in = fopen(a->filename, "r")))
757  {
758  mutt_error(_("Could not open %s"), a->filename ? a->filename : "(null)");
759  return;
760  }
761  else
762  {
763  a->offset = 0;
764  if (stat(a->filename, &sb) == -1)
765  {
766  mutt_perror("stat");
767  mutt_file_fclose(&fp_in);
768  goto cleanup;
769  }
770  a->length = sb.st_size;
771  }
772 
773  /* Avoid buffer pool due to recursion */
774  mutt_buffer_mktemp(&temp);
775  fp_out = mutt_file_fopen(mutt_buffer_string(&temp), "w+");
776  if (!fp_out)
777  {
778  mutt_perror("fopen");
779  goto cleanup;
780  }
781 
782  fseeko(fp_in, a->offset, SEEK_SET);
783  a->parts = mutt_rfc822_parse_message(fp_in, a);
784 
785  transform_to_7bit(a->parts, fp_in, sub);
786 
787  mutt_copy_hdr(fp_in, fp_out, a->offset, a->offset + a->length,
788  CH_MIME | CH_NONEWLINE | CH_XMIT, NULL, 0);
789 
790  fputs("MIME-Version: 1.0\n", fp_out);
791  mutt_write_mime_header(a->parts, fp_out, sub);
792  fputc('\n', fp_out);
793  mutt_write_mime_body(a->parts, fp_out, sub);
794 
795  if (fp_in != fp)
796  mutt_file_fclose(&fp_in);
797  mutt_file_fclose(&fp_out);
798 
799  a->encoding = ENC_7BIT;
800  FREE(&a->d_filename);
801  a->d_filename = a->filename;
802  if (a->filename && a->unlink)
803  unlink(a->filename);
804  a->filename = mutt_buffer_strdup(&temp);
805  a->unlink = true;
806  if (stat(a->filename, &sb) == -1)
807  {
808  mutt_perror("stat");
809  goto cleanup;
810  }
811  a->length = sb.st_size;
812  mutt_body_free(&a->parts);
813  a->email->body = NULL;
814 
815 cleanup:
816  if (fp_in && (fp_in != fp))
817  mutt_file_fclose(&fp_in);
818 
819  if (fp_out)
820  {
821  mutt_file_fclose(&fp_out);
823  }
824 
825  mutt_buffer_dealloc(&temp);
826 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
#define CH_MIME
Ignore MIME fields.
Definition: copy.h:61
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
struct Body * body
List of MIME parts.
Definition: email.h:91
#define mutt_error(...)
Definition: logging.h:88
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
7-bit text
Definition: mime.h:49
int mutt_write_mime_body(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Write a MIME part.
Definition: body.c:314
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
#define mutt_perror(...)
Definition: logging.h:89
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
struct Body * mutt_rfc822_parse_message(FILE *fp, struct Body *parent)
parse a Message/RFC822 body
Definition: parse.c:1693
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
int mutt_write_mime_header(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Create a MIME header.
Definition: header.c:764
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
#define CH_XMIT
Transmitting this message? (Ignore Lines: and Content-Length:)
Definition: copy.h:55
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
static void transform_to_7bit(struct Body *a, FILE *fp_in, struct ConfigSubset *sub)
Convert MIME parts to 7-bit.
Definition: sendlib.c:684
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
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:104
#define FREE(x)
Definition: memory.h:40
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
struct Email * email
header information for message/rfc822
Definition: body.h:55
#define CH_NONEWLINE
Don&#39;t output terminating newline after the header.
Definition: copy.h:60
+ 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 834 of file sendlib.c.

835 {
836  const bool c_allow_8bit = cs_subset_bool(sub, "allow_8bit");
837  if (b->type == TYPE_TEXT)
838  {
839  const bool c_encode_from = cs_subset_bool(sub, "encode_from");
840  char send_charset[128];
841  char *chsname = mutt_body_get_charset(b, send_charset, sizeof(send_charset));
842  if ((info->lobin && !mutt_istr_startswith(chsname, "iso-2022")) ||
843  (info->linemax > 990) || (info->from && c_encode_from))
844  {
846  }
847  else if (info->hibin)
848  {
849  b->encoding = c_allow_8bit ? ENC_8BIT : ENC_QUOTED_PRINTABLE;
850  }
851  else
852  {
853  b->encoding = ENC_7BIT;
854  }
855  }
856  else if ((b->type == TYPE_MESSAGE) || (b->type == TYPE_MULTIPART))
857  {
858  if (info->lobin || info->hibin)
859  {
860  if (c_allow_8bit && !info->lobin)
861  b->encoding = ENC_8BIT;
862  else
863  mutt_message_to_7bit(b, NULL, sub);
864  }
865  else
866  b->encoding = ENC_7BIT;
867  }
868  else if ((b->type == TYPE_APPLICATION) &&
869  mutt_istr_equal(b->subtype, "pgp-keys"))
870  {
871  b->encoding = ENC_7BIT;
872  }
873  else
874  {
875  /* Determine which encoding is smaller */
876  if (1.33 * (float) (info->lobin + info->hibin + info->ascii) <
877  3.0 * (float) (info->lobin + info->hibin) + (float) info->ascii)
878  {
879  b->encoding = ENC_BASE64;
880  }
881  else
882  {
884  }
885  }
886 }
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
long linemax
Length of the longest line in the file.
Definition: content.h:40
7-bit text
Definition: mime.h:49
void mutt_message_to_7bit(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Convert an email&#39;s MIME parts to 7-bit.
Definition: sendlib.c:747
8-bit text
Definition: mime.h:50
long hibin
8-bit characters
Definition: content.h:35
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body&#39;s character set.
Definition: body.c:131
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
char * subtype
content-type subtype
Definition: body.h:37
long ascii
Number of ascii chars.
Definition: content.h:39
Type: &#39;text/*&#39;.
Definition: mime.h:38
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
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
bool from
Has a line beginning with "From "?
Definition: content.h:43
Type: &#39;message/*&#39;.
Definition: mime.h:35
long lobin
Unprintable 7-bit chars (eg., control chars)
Definition: content.h:36
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
Quoted-printable text.
Definition: mime.h:51
Type: &#39;application/*&#39;.
Definition: mime.h:33
+ 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 892 of file sendlib.c.

893 {
894  a->stamp = mutt_date_epoch();
895 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:427
time_t stamp
Time stamp of last encoding update.
Definition: body.h:61
+ 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 904 of file sendlib.c.

905 {
906  struct Content *info = NULL;
907  char chsbuf[256];
908 
909  /* override noconv when it's us-ascii */
910  if (mutt_ch_is_us_ascii(mutt_body_get_charset(a, chsbuf, sizeof(chsbuf))))
911  a->noconv = false;
912 
913  if (!a->force_charset && !a->noconv)
914  mutt_param_delete(&a->parameter, "charset");
915 
916  info = mutt_get_content_info(a->filename, a, sub);
917  if (!info)
918  return;
919 
920  set_encoding(a, info, sub);
922 
923  FREE(&a->content);
924  a->content = info;
925 }
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:465
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:892
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
struct Content * content
Detailed info about the content of the attachment.
Definition: body.h:51
bool noconv
Don&#39;t do character set conversion.
Definition: body.h:73
bool force_charset
Send mode: don&#39;t adjust the character set when in send-mode.
Definition: body.h:75
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body&#39;s character set.
Definition: body.c:131
Info about an attachment.
Definition: content.h:33
void mutt_param_delete(struct ParameterList *pl, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:142
#define mutt_ch_is_us_ascii(str)
Definition: charset.h:96
#define FREE(x)
Definition: memory.h:40
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
static void set_encoding(struct Body *b, struct Content *info, struct ConfigSubset *sub)
determine which Content-Transfer-Encoding to use
Definition: sendlib.c:834
+ 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 936 of file sendlib.c.

938 {
939  struct Body *body = NULL;
940  FILE *fp = NULL;
941  CopyMessageFlags cmflags;
943 
944  const bool c_mime_forward_decode = cs_subset_bool(sub, "mime_forward_decode");
945  const bool c_forward_decrypt = cs_subset_bool(sub, "forward_decrypt");
946  if (WithCrypto)
947  {
948  if ((c_mime_forward_decode || c_forward_decrypt) && (e->security & SEC_ENCRYPT))
949  {
951  return NULL;
952  }
953  }
954 
955  struct Buffer *buf = mutt_buffer_pool_get();
956  mutt_buffer_mktemp(buf);
957  fp = mutt_file_fopen(mutt_buffer_string(buf), "w+");
958  if (!fp)
959  {
961  return NULL;
962  }
963 
964  body = mutt_body_new();
965  body->type = TYPE_MESSAGE;
966  body->subtype = mutt_str_dup("rfc822");
968  body->unlink = true;
969  body->use_disp = false;
970  body->disposition = DISP_INLINE;
971  body->noconv = true;
972 
974 
975  struct Message *msg = mx_msg_open(m, e->msgno);
976  if (!msg)
977  {
978  return NULL;
979  }
980  mutt_parse_mime_message(m, e, msg->fp);
981 
982  CopyHeaderFlags chflags = CH_XMIT;
983  cmflags = MUTT_CM_NO_FLAGS;
984 
985  /* If we are attaching a message, ignore `$mime_forward_decode` */
986  if (!attach_msg && c_mime_forward_decode)
987  {
988  chflags |= CH_MIME | CH_TXTPLAIN;
989  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
991  pgp &= ~PGP_ENCRYPT;
993  pgp &= ~SMIME_ENCRYPT;
994  }
995  else if ((WithCrypto != 0) && c_forward_decrypt && (e->security & SEC_ENCRYPT))
996  {
997  if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_multipart_encrypted(e->body))
998  {
999  chflags |= CH_MIME | CH_NONEWLINE;
1000  cmflags = MUTT_CM_DECODE_PGP;
1001  pgp &= ~PGP_ENCRYPT;
1002  }
1003  else if (((WithCrypto & APPLICATION_PGP) != 0) &&
1005  {
1006  chflags |= CH_MIME | CH_TXTPLAIN;
1007  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1008  pgp &= ~PGP_ENCRYPT;
1009  }
1010  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
1012  {
1013  chflags |= CH_MIME | CH_TXTPLAIN;
1014  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1015  pgp &= ~SMIME_ENCRYPT;
1016  }
1017  }
1018 
1019  mutt_copy_message(fp, m, e, msg, cmflags, chflags, 0);
1020  mx_msg_close(m, &msg);
1021 
1022  fflush(fp);
1023  rewind(fp);
1024 
1025  body->email = email_new();
1026  body->email->offset = 0;
1027  /* we don't need the user headers here */
1028  body->email->env = mutt_rfc822_read_header(fp, body->email, false, false);
1029  if (WithCrypto)
1030  body->email->security = pgp;
1031  mutt_update_encoding(body, sub);
1032  body->parts = body->email->body;
1033 
1034  mutt_file_fclose(&fp);
1035 
1036  return body;
1037 }
void mutt_parse_mime_message(struct Mailbox *m, struct Email *e, FILE *fp)
Parse a MIME email.
Definition: attachments.c:591
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
#define CH_MIME
Ignore MIME fields.
Definition: copy.h:61
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
#define WithCrypto
Definition: lib.h:113
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
void mutt_update_encoding(struct Body *a, struct ConfigSubset *sub)
Update the encoding type.
Definition: sendlib.c:904
struct Body * body
List of MIME parts.
Definition: email.h:91
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:74
#define SMIME_ENCRYPT
Definition: lib.h:99
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:75
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
bool noconv
Don&#39;t do character set conversion.
Definition: body.h:73
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:623
#define PGP_ENCRYPT
Definition: lib.h:93
String manipulation buffer.
Definition: buffer.h:33
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:71
uint16_t CopyMessageFlags
Flags for mutt_copy_message(), e.g. MUTT_CM_NOHEADER.
Definition: copy.h:32
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:35
The body of an email.
Definition: body.h:34
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:67
struct Email * email_new(void)
Create a new Email.
Definition: email.c:78
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1186
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:135
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:460
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
struct Envelope * env
Envelope information.
Definition: email.h:90
char * subtype
content-type subtype
Definition: body.h:37
#define CH_TXTPLAIN
Generate text/plain MIME headers.
Definition: copy.h:63
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:88
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:87
A local copy of an email.
Definition: mxapi.h:41
#define MUTT_CM_DECODE
Decode the message body into text/plain.
Definition: copy.h:38
#define MUTT_CM_CHARCONV
Perform character set conversions.
Definition: copy.h:42
#define CH_XMIT
Transmitting this message? (Ignore Lines: and Content-Length:)
Definition: copy.h:55
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:84
Type: &#39;message/*&#39;.
Definition: mime.h:35
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:50
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
Definition: crypt.c:565
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
FILE * fp
pointer to the message data
Definition: mxapi.h:43
int mutt_copy_message(FILE *fp_out, struct Mailbox *m, struct Email *e, struct Message *msg, CopyMessageFlags cmflags, CopyHeaderFlags chflags, int wraplen)
Copy a message from a Mailbox.
Definition: copy.c:853
#define MUTT_CM_DECODE_PGP
Used for decoding PGP messages.
Definition: copy.h:45
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
Content is inline.
Definition: mime.h:62
struct Envelope * mutt_rfc822_read_header(FILE *fp, struct Email *e, bool user_hdrs, bool weed)
parses an RFC822 header
Definition: parse.c:1124
struct Email * email
header information for message/rfc822
Definition: body.h:55
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
return a stream pointer for a message
Definition: mx.c:1140
#define CH_NONEWLINE
Don&#39;t output terminating newline after the header.
Definition: copy.h:60
int msgno
Number displayed to the user.
Definition: email.h:87
+ 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 1046 of file sendlib.c.

1047 {
1048  FILE *fp = NULL, *fp_err = NULL;
1049  char *buf = NULL;
1050  size_t buflen;
1051  pid_t pid;
1052  struct Buffer *cmd = mutt_buffer_pool_get();
1053 
1054  const char *const c_mime_type_query_command =
1055  cs_subset_string(sub, "mime_type_query_command");
1056 
1057  mutt_buffer_file_expand_fmt_quote(cmd, c_mime_type_query_command, att->filename);
1058 
1059  pid = filter_create(mutt_buffer_string(cmd), NULL, &fp, &fp_err);
1060  if (pid < 0)
1061  {
1062  mutt_error(_("Error running \"%s\""), mutt_buffer_string(cmd));
1064  return;
1065  }
1067 
1068  buf = mutt_file_read_line(buf, &buflen, fp, NULL, MUTT_RL_NO_FLAGS);
1069  if (buf)
1070  {
1071  if (strchr(buf, '/'))
1072  mutt_parse_content_type(buf, att);
1073  FREE(&buf);
1074  }
1075 
1076  mutt_file_fclose(&fp);
1077  mutt_file_fclose(&fp_err);
1078  filter_wait(pid);
1079 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_error(...)
Definition: logging.h:88
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
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
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
void mutt_parse_content_type(const char *s, struct Body *ct)
Parse a content type.
Definition: parse.c:427
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:38
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:1435
FILE * fp
pointer to the message data
Definition: mxapi.h:43
#define FREE(x)
Definition: memory.h:40
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
+ 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 1088 of file sendlib.c.

1089 {
1090  struct Body *att = mutt_body_new();
1091  att->filename = mutt_str_dup(path);
1092 
1093  const char *const c_mime_type_query_command =
1094  cs_subset_string(sub, "mime_type_query_command");
1095  const bool c_mime_type_query_first =
1096  cs_subset_bool(sub, "mime_type_query_first");
1097 
1098  if (c_mime_type_query_command && c_mime_type_query_first)
1099  run_mime_type_query(att, sub);
1100 
1101  /* Attempt to determine the appropriate content-type based on the filename
1102  * suffix. */
1103  if (!att->subtype)
1104  mutt_lookup_mime_type(att, path);
1105 
1106  if (!att->subtype && c_mime_type_query_command && !c_mime_type_query_first)
1107  {
1108  run_mime_type_query(att, sub);
1109  }
1110 
1111  struct Content *info = mutt_get_content_info(path, att, sub);
1112  if (!info)
1113  {
1114  mutt_body_free(&att);
1115  return NULL;
1116  }
1117 
1118  if (!att->subtype)
1119  {
1120  if ((info->nulbin == 0) &&
1121  ((info->lobin == 0) || ((info->lobin + info->hibin + info->ascii) / info->lobin >= 10)))
1122  {
1123  /* Statistically speaking, there should be more than 10% "lobin"
1124  * chars if this is really a binary file... */
1125  att->type = TYPE_TEXT;
1126  att->subtype = mutt_str_dup("plain");
1127  }
1128  else
1129  {
1130  att->type = TYPE_APPLICATION;
1131  att->subtype = mutt_str_dup("octet-stream");
1132  }
1133  }
1134 
1135  FREE(&info);
1136  mutt_update_encoding(att, sub);
1137  return att;
1138 }
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:465
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
void mutt_update_encoding(struct Body *a, struct ConfigSubset *sub)
Update the encoding type.
Definition: sendlib.c:904
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
long hibin
8-bit characters
Definition: content.h:35
The body of an email.
Definition: body.h:34
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
char * subtype
content-type subtype
Definition: body.h:37
Info about an attachment.
Definition: content.h:33
long ascii
Number of ascii chars.
Definition: content.h:39
Type: &#39;text/*&#39;.
Definition: mime.h:38
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
long lobin
Unprintable 7-bit chars (eg., control chars)
Definition: content.h:36
enum ContentType mutt_lookup_mime_type(struct Body *att, const char *path)
Find the MIME type for an attachment.
Definition: sendlib.c:564
#define FREE(x)
Definition: memory.h:40
long nulbin
Null characters (0x0)
Definition: content.h:37
Type: &#39;application/*&#39;.
Definition: mime.h:33
static void run_mime_type_query(struct Body *att, struct ConfigSubset *sub)
Run an external command to determine the MIME type.
Definition: sendlib.c:1046
+ 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 1147 of file sendlib.c.

1148 {
1149  char *tmp = NULL;
1150  char *p = NULL;
1151  int i;
1152 
1153  const char *const c_send_charset = cs_subset_string(sub, "send_charset");
1154 
1155  struct ListNode *np = NULL;
1156  STAILQ_FOREACH(np, h, entries)
1157  {
1158  p = strchr(np->data, ':');
1159  if (!p)
1160  continue;
1161 
1162  i = p - np->data;
1163  p = mutt_str_skip_email_wsp(p + 1);
1164  tmp = mutt_str_dup(p);
1165 
1166  if (!tmp)
1167  continue;
1168 
1169  rfc2047_encode(&tmp, NULL, i + 2, c_send_charset);
1170  mutt_mem_realloc(&np->data, i + 2 + mutt_str_len(tmp) + 1);
1171 
1172  sprintf(np->data + i + 2, "%s", tmp);
1173 
1174  FREE(&tmp);
1175  }
1176 }
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:776
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
void rfc2047_encode(char **pd, const char *specials, int col, const char *charsets)
RFC-2047-encode a string.
Definition: rfc2047.c:616
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
char * data
String.
Definition: list.h:36
#define FREE(x)
Definition: memory.h:40
A List node for strings.
Definition: list.h:34
+ 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 1187 of file sendlib.c.

1188 {
1189  const char *const c_hostname = cs_subset_string(sub, "hostname");
1190  if (!c_hostname || (c_hostname[0] == '@'))
1191  return NULL;
1192 
1193  const char *p = c_hostname;
1194 
1195  const bool c_hidden_host = cs_subset_bool(sub, "hidden_host");
1196  if (may_hide_host && c_hidden_host)
1197  {
1198  p = strchr(c_hostname, '.');
1199  if (p)
1200  p++;
1201 
1202  // sanity check: don't hide the host if the fqdn is something like example.com
1203  if (!p || !strchr(p, '.'))
1204  p = c_hostname;
1205  }
1206 
1207  return p;
1208 }
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
+ 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 1216 of file sendlib.c.

1217 {
1218  char buf[128];
1219  char rndid[MUTT_RANDTAG_LEN + 1];
1220 
1221  mutt_rand_base32(rndid, sizeof(rndid) - 1);
1222  rndid[MUTT_RANDTAG_LEN] = 0;
1223  const char *fqdn = mutt_fqdn(false, sub);
1224  if (!fqdn)
1225  fqdn = NONULL(ShortHostname);
1226 
1227  struct tm tm = mutt_date_gmtime(MUTT_DATE_NOW);
1228  snprintf(buf, sizeof(buf), "<%d%02d%02d%02d%02d%02d.%s@%s>", tm.tm_year + 1900,
1229  tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, rndid, fqdn);
1230  return mutt_str_dup(buf);
1231 }
#define NONULL(x)
Definition: string2.h:37
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define MUTT_DATE_NOW
Constant representing the &#39;current time&#39;, see: mutt_date_gmtime(), mutt_date_localtime() ...
Definition: date.h:39
struct tm mutt_date_gmtime(time_t t)
Converts calendar time to a broken-down time structure expressed in UTC timezone. ...
Definition: date.c:672
#define MUTT_RANDTAG_LEN
Definition: sendlib.h:35
WHERE char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:46
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:1187
void mutt_rand_base32(char *buf, size_t buflen)
Fill a buffer with a base32-encoded random string.
Definition: random.c:103
+ 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 1243 of file sendlib.c.

1244 {
1245  if (final)
1246  {
1247  if (!TAILQ_EMPTY(&env->bcc) && TAILQ_EMPTY(&env->to) && TAILQ_EMPTY(&env->cc))
1248  {
1249  /* some MTA's will put an Apparently-To: header field showing the Bcc:
1250  * recipients if there is no To: or Cc: field, so attempt to suppress
1251  * it by using an empty To: field. */
1252  struct Address *to = mutt_addr_new();
1253  to->group = true;
1254  mutt_addrlist_append(&env->to, to);
1256 
1257  char buf[1024];
1258  buf[0] = '\0';
1259  mutt_addr_cat(buf, sizeof(buf), "undisclosed-recipients", AddressSpecials);
1260 
1261  to->mailbox = mutt_str_dup(buf);
1262  }
1263 
1264  mutt_set_followup_to(env, sub);
1265 
1266  if (!env->message_id)
1267  env->message_id = gen_msgid(sub);
1268  }
1269 
1270  /* Take care of 8-bit => 7-bit conversion. */
1272  encode_headers(&env->userhdrs, sub);
1273 }
void rfc2047_encode_envelope(struct Envelope *env)
Encode the fields of an Envelope.
Definition: rfc2047.c:807
const char AddressSpecials[]
Characters with special meaning for email addresses.
Definition: address.c:42
struct AddressList bcc
Email&#39;s &#39;Bcc&#39; list.
Definition: envelope.h:60
static void encode_headers(struct ListHead *h, struct ConfigSubset *sub)
RFC2047-encode a list of headers.
Definition: sendlib.c:1147
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
struct ListHead userhdrs
user defined headers
Definition: envelope.h:83
struct Address * mutt_addr_new(void)
Create a new Address.
Definition: address.c:385
An email address.
Definition: address.h:35
char * mailbox
Mailbox and host address.
Definition: address.h:38
char * message_id
Message ID.
Definition: envelope.h:69
static char * gen_msgid(struct ConfigSubset *sub)
Generate a unique Message ID.
Definition: sendlib.c:1216
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
void mutt_set_followup_to(struct Envelope *env, struct ConfigSubset *sub)
Set followup-to field.
Definition: send.c:1329
bool group
Group mailbox?
Definition: address.h:39
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
#define TAILQ_EMPTY(head)
Definition: queue.h:721
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
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1490
+ 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 1282 of file sendlib.c.

1283 {
1284  struct ListNode *item = NULL;
1285  STAILQ_FOREACH(item, &env->userhdrs, entries)
1286  {
1287  rfc2047_decode(&item->data);
1288  }
1289 
1291 
1292  /* back conversions */
1294 }
struct AddressList mail_followup_to
Email&#39;s &#39;mail-followup-to&#39;.
Definition: envelope.h:63
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1470
struct ListHead userhdrs
user defined headers
Definition: envelope.h:83
void rfc2047_decode_envelope(struct Envelope *env)
Decode the fields of an Envelope.
Definition: rfc2047.c:787
void rfc2047_decode(char **pd)
Decode any RFC2047-encoded header fields.
Definition: rfc2047.c:641
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
char * data
String.
Definition: list.h:36
A List node for strings.
Definition: list.h:34
+ 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 1308 of file sendlib.c.

1311 {
1312  if (!e)
1313  return -1;
1314 
1315  int rc = 0;
1316 
1317  struct Buffer *tempfile = mutt_buffer_pool_get();
1318  mutt_buffer_mktemp(tempfile);
1319  FILE *fp_tmp = mutt_file_fopen(mutt_buffer_string(tempfile), "w");
1320  if (fp_tmp)
1321  {
1323 
1324  const bool c_bounce_delivered = cs_subset_bool(sub, "bounce_delivered");
1325  if (!c_bounce_delivered)
1326  chflags |= CH_WEED_DELIVERED;
1327 
1328  fseeko(fp, e->offset, SEEK_SET);
1329  fprintf(fp_tmp, "Resent-From: %s\n", resent_from);
1330 
1331  struct Buffer *date = mutt_buffer_pool_get();
1332  mutt_date_make_date(date, cs_subset_bool(sub, "local_date_header"));
1333  fprintf(fp_tmp, "Resent-Date: %s\n", mutt_buffer_string(date));
1334  mutt_buffer_pool_release(&date);
1335 
1336  char *msgid_str = gen_msgid(sub);
1337  fprintf(fp_tmp, "Resent-Message-ID: %s\n", msgid_str);
1338  FREE(&msgid_str);
1339  fputs("Resent-To: ", fp_tmp);
1340  mutt_addrlist_write_file(to, fp_tmp, 11, false);
1341  mutt_copy_header(fp, e, fp_tmp, chflags, NULL, 0);
1342  fputc('\n', fp_tmp);
1343  mutt_file_copy_bytes(fp, fp_tmp, e->body->length);
1344  if (mutt_file_fclose(&fp_tmp) != 0)
1345  {
1346  mutt_perror(mutt_buffer_string(tempfile));
1347  unlink(mutt_buffer_string(tempfile));
1348  return -1;
1349  }
1350 #ifdef USE_SMTP
1351  const char *const c_smtp_url = cs_subset_string(sub, "smtp_url");
1352  if (c_smtp_url)
1353  {
1354  rc = mutt_smtp_send(env_from, to, NULL, NULL, mutt_buffer_string(tempfile),
1355  (e->body->encoding == ENC_8BIT), sub);
1356  }
1357  else
1358 #endif
1359  {
1360  rc = mutt_invoke_sendmail(m, env_from, to, NULL, NULL, mutt_buffer_string(tempfile),
1361  (e->body->encoding == ENC_8BIT), sub);
1362  }
1363  }
1364 
1365  mutt_buffer_pool_release(&tempfile);
1366  return rc;
1367 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
struct Body * body
List of MIME parts.
Definition: email.h:91
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
void mutt_date_make_date(struct Buffer *buf, bool local)
Write a date in RFC822 format to a buffer.
Definition: date.c:378
8-bit text
Definition: mime.h:50
#define mutt_perror(...)
Definition: logging.h:89
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
#define CH_WEED_DELIVERED
Weed eventual Delivered-To headers.
Definition: copy.h:65
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
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
static char * gen_msgid(struct ConfigSubset *sub)
Generate a unique Message ID.
Definition: sendlib.c:1216
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
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
#define CH_XMIT
Transmitting this message? (Ignore Lines: and Content-Length:)
Definition: copy.h:55
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
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
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:882
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:84
#define CH_NOQFROM
Ignore ">From " line.
Definition: copy.h:67
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:50
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:413
#define FREE(x)
Definition: memory.h:40
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
#define CH_NONEWLINE
Don&#39;t output terminating newline after the header.
Definition: copy.h:60
+ 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 1379 of file sendlib.c.

1381 {
1382  if (!fp || !e || !to || TAILQ_EMPTY(to))
1383  return -1;
1384 
1385  const char *fqdn = mutt_fqdn(true, sub);
1386  char resent_from[256];
1387  char *err = NULL;
1388 
1389  resent_from[0] = '\0';
1390  struct Address *from = mutt_default_from(sub);
1391  struct AddressList from_list = TAILQ_HEAD_INITIALIZER(from_list);
1392  mutt_addrlist_append(&from_list, from);
1393 
1394  /* mutt_default_from() does not use $real_name if the real name is not set
1395  * in $from, so we add it here. The reason it is not added in
1396  * mutt_default_from() is that during normal sending, we execute
1397  * send-hooks and set the real_name last so that it can be changed based
1398  * upon message criteria. */
1399  if (!from->personal)
1400  {
1401  const char *const c_real_name = cs_subset_string(sub, "real_name");
1402  from->personal = mutt_str_dup(c_real_name);
1403  }
1404 
1405  mutt_addrlist_qualify(&from_list, fqdn);
1406 
1407  rfc2047_encode_addrlist(&from_list, "Resent-From");
1408  if (mutt_addrlist_to_intl(&from_list, &err))
1409  {
1410  mutt_error(_("Bad IDN %s while preparing resent-from"), err);
1411  FREE(&err);
1412  mutt_addrlist_clear(&from_list);
1413  return -1;
1414  }
1415  mutt_addrlist_write(&from_list, resent_from, sizeof(resent_from), false);
1416 
1417 #ifdef USE_NNTP
1418  OptNewsSend = false;
1419 #endif
1420 
1421  /* prepare recipient list. idna conversion appears to happen before this
1422  * function is called, since the user receives confirmation of the address
1423  * list being bounced to. */
1424  struct AddressList resent_to = TAILQ_HEAD_INITIALIZER(resent_to);
1425  mutt_addrlist_copy(&resent_to, to, false);
1426  rfc2047_encode_addrlist(&resent_to, "Resent-To");
1427  int rc = bounce_message(fp, m, e, &resent_to, resent_from, &from_list, sub);
1428  mutt_addrlist_clear(&resent_to);
1429  mutt_addrlist_clear(&from_list);
1430 
1431  return rc;
1432 }
#define mutt_error(...)
Definition: logging.h:88
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1470
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
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define _(a)
Definition: message.h:28
An email address.
Definition: address.h:35
void rfc2047_encode_addrlist(struct AddressList *al, const char *tag)
Encode any RFC2047 headers, where required, in an Address list.
Definition: rfc2047.c:742
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:1308
struct Address * mutt_default_from(struct ConfigSubset *sub)
Get a default &#39;from&#39; Address.
Definition: send.c:1454
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
char * personal
Real name of address.
Definition: address.h:37
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:650
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:1187
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1305
#define FREE(x)
Definition: memory.h:40
#define TAILQ_EMPTY(head)
Definition: queue.h:721
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:45
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
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
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1490
+ 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 1439 of file sendlib.c.

1440 {
1441  for (; b; b = b->next)
1442  {
1443  if ((b->type == TYPE_MESSAGE) || (b->type == TYPE_MULTIPART))
1444  set_noconv_flags(b->parts, flag);
1445  else if ((b->type == TYPE_TEXT) && b->noconv)
1446  {
1447  if (flag)
1448  mutt_param_set(&b->parameter, "x-mutt-noconv", "yes");
1449  else
1450  mutt_param_delete(&b->parameter, "x-mutt-noconv");
1451  }
1452  }
1453 }
bool noconv
Don&#39;t do character set conversion.
Definition: body.h:73
struct Body * next
next attachment in the list
Definition: body.h:53
void mutt_param_delete(struct ParameterList *pl, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:142
Type: &#39;text/*&#39;.
Definition: mime.h:38
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
Type: &#39;message/*&#39;.
Definition: mime.h:35
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
static void set_noconv_flags(struct Body *b, bool flag)
Set/reset the "x-mutt-noconv" flag.
Definition: sendlib.c:1439
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
+ 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 1467 of file sendlib.c.

1469 {
1470  char fcc_tok[PATH_MAX];
1471  char fcc_expanded[PATH_MAX];
1472 
1473  mutt_str_copy(fcc_tok, path, sizeof(fcc_tok));
1474 
1475  char *tok = strtok(fcc_tok, ",");
1476  if (!tok)
1477  return -1;
1478 
1479  mutt_debug(LL_DEBUG1, "Fcc: initial mailbox = '%s'\n", tok);
1480  /* mutt_expand_path already called above for the first token */
1481  int status = mutt_write_fcc(tok, e, msgid, post, fcc, finalpath, sub);
1482  if (status != 0)
1483  return status;
1484 
1485  while ((tok = strtok(NULL, ",")))
1486  {
1487  if (*tok == '\0')
1488  continue;
1489 
1490  /* Only call mutt_expand_path if tok has some data */
1491  mutt_debug(LL_DEBUG1, "Fcc: additional mailbox token = '%s'\n", tok);
1492  mutt_str_copy(fcc_expanded, tok, sizeof(fcc_expanded));
1493  mutt_expand_path(fcc_expanded, sizeof(fcc_expanded));
1494  mutt_debug(LL_DEBUG1, " Additional mailbox expanded = '%s'\n", fcc_expanded);
1495  status = mutt_write_fcc(fcc_expanded, e, msgid, post, fcc, finalpath, sub);
1496  if (status != 0)
1497  return status;
1498  }
1499 
1500  return 0;
1501 }
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:1515
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:122
#define PATH_MAX
Definition: mutt.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Log at debug level 1.
Definition: logging.h:40
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:749
+ 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 1515 of file sendlib.c.

1517 {
1518  struct Message *msg = NULL;
1519  struct Buffer *tempfile = NULL;
1520  FILE *fp_tmp = NULL;
1521  int rc = -1;
1522  bool need_mailbox_cleanup = false;
1523  struct stat st;
1524  MsgOpenFlags onm_flags;
1525 
1526  if (post)
1527  set_noconv_flags(e->body, true);
1528 
1529 #ifdef RECORD_FOLDER_HOOK
1530  mutt_folder_hook(path, NULL);
1531 #endif
1532  struct Mailbox *m_fcc = mx_path_resolve(path);
1533  bool old_append = m_fcc->append;
1534  if (!mx_mbox_open(m_fcc, MUTT_APPEND | MUTT_QUIET))
1535  {
1536  mutt_debug(LL_DEBUG1, "unable to open mailbox %s in append-mode, aborting\n", path);
1537  mailbox_free(&m_fcc);
1538  goto done;
1539  }
1540 
1541  /* We need to add a Content-Length field to avoid problems where a line in
1542  * the message body begins with "From " */
1543  if ((m_fcc->type == MUTT_MMDF) || (m_fcc->type == MUTT_MBOX))
1544  {
1545  tempfile = mutt_buffer_pool_get();
1546  mutt_buffer_mktemp(tempfile);
1547  fp_tmp = mutt_file_fopen(mutt_buffer_string(tempfile), "w+");
1548  if (!fp_tmp)
1549  {
1550  mutt_perror(mutt_buffer_string(tempfile));
1551  mx_mbox_close(m_fcc);
1552  goto done;
1553  }
1554  /* remember new mail status before appending message */
1555  need_mailbox_cleanup = true;
1556  stat(path, &st);
1557  }
1558 
1559  e->read = !post; /* make sure to put it in the 'cur' directory (maildir) */
1560  onm_flags = MUTT_ADD_FROM;
1561  if (post)
1562  onm_flags |= MUTT_SET_DRAFT;
1563  msg = mx_msg_open_new(m_fcc, e, onm_flags);
1564  if (!msg)
1565  {
1566  mutt_file_fclose(&fp_tmp);
1567  mx_mbox_close(m_fcc);
1568  goto done;
1569  }
1570 
1571  const bool c_crypt_protected_headers_read =
1572  cs_subset_bool(sub, "crypt_protected_headers_read");
1573 
1574  /* post == 1 => postpone message.
1575  * post == 0 => Normal mode. */
1577  msg->fp, e->env, e->body,
1579  c_crypt_protected_headers_read && mutt_should_hide_protected_subject(e), sub);
1580 
1581  /* (postponement) if this was a reply of some sort, <msgid> contains the
1582  * Message-ID: of message replied to. Save it using a special X-Mutt-
1583  * header so it can be picked up if the message is recalled at a later
1584  * point in time. This will allow the message to be marked as replied if
1585  * the same mailbox is still open. */
1586  if (post && msgid)
1587  fprintf(msg->fp, "X-Mutt-References: %s\n", msgid);
1588 
1589  /* (postponement) save the Fcc: using a special X-Mutt- header so that
1590  * it can be picked up when the message is recalled */
1591  if (post && fcc)
1592  fprintf(msg->fp, "X-Mutt-Fcc: %s\n", fcc);
1593 
1594  if ((m_fcc->type == MUTT_MMDF) || (m_fcc->type == MUTT_MBOX))
1595  fprintf(msg->fp, "Status: RO\n");
1596 
1597  /* (postponement) if the mail is to be signed or encrypted, save this info */
1598  if (((WithCrypto & APPLICATION_PGP) != 0) && post && (e->security & APPLICATION_PGP))
1599  {
1600  fputs("X-Mutt-PGP: ", msg->fp);
1601  if (e->security & SEC_ENCRYPT)
1602  fputc('E', msg->fp);
1603  if (e->security & SEC_OPPENCRYPT)
1604  fputc('O', msg->fp);
1605  if (e->security & SEC_SIGN)
1606  {
1607  fputc('S', msg->fp);
1608 
1609  const char *const c_pgp_sign_as = cs_subset_string(sub, "pgp_sign_as");
1610  if (c_pgp_sign_as)
1611  fprintf(msg->fp, "<%s>", c_pgp_sign_as);
1612  }
1613  if (e->security & SEC_INLINE)
1614  fputc('I', msg->fp);
1615 #ifdef USE_AUTOCRYPT
1616  if (e->security & SEC_AUTOCRYPT)
1617  fputc('A', msg->fp);
1619  fputc('Z', msg->fp);
1620 #endif
1621  fputc('\n', msg->fp);
1622  }
1623 
1624  /* (postponement) if the mail is to be signed or encrypted, save this info */
1625  if (((WithCrypto & APPLICATION_SMIME) != 0) && post && (e->security & APPLICATION_SMIME))
1626  {
1627  fputs("X-Mutt-SMIME: ", msg->fp);
1628  if (e->security & SEC_ENCRYPT)
1629  {
1630  fputc('E', msg->fp);
1631 
1632  const char *const c_smime_encrypt_with =
1633  cs_subset_string(sub, "smime_encrypt_with");
1634  if (c_smime_encrypt_with)
1635  fprintf(msg->fp, "C<%s>", c_smime_encrypt_with);
1636  }
1637  if (e->security & SEC_OPPENCRYPT)
1638  fputc('O', msg->fp);
1639  if (e->security & SEC_SIGN)
1640  {
1641  fputc('S', msg->fp);
1642 
1643  const char *const c_smime_sign_as =
1644  cs_subset_string(sub, "smime_sign_as");
1645  if (c_smime_sign_as)
1646  fprintf(msg->fp, "<%s>", c_smime_sign_as);
1647  }
1648  if (e->security & SEC_INLINE)
1649  fputc('I', msg->fp);
1650  fputc('\n', msg->fp);
1651  }
1652 
1653 #ifdef MIXMASTER
1654  /* (postponement) if the mail is to be sent through a mixmaster
1655  * chain, save that information */
1656 
1657  if (post && !STAILQ_EMPTY(&e->chain))
1658  {
1659  fputs("X-Mutt-Mix:", msg->fp);
1660  struct ListNode *p = NULL;
1661  STAILQ_FOREACH(p, &e->chain, entries)
1662  {
1663  fprintf(msg->fp, " %s", (char *) p->data);
1664  }
1665 
1666  fputc('\n', msg->fp);
1667  }
1668 #endif
1669 
1670  if (fp_tmp)
1671  {
1672  mutt_write_mime_body(e->body, fp_tmp, sub);
1673 
1674  /* make sure the last line ends with a newline. Emacs doesn't ensure this
1675  * will happen, and it can cause problems parsing the mailbox later. */
1676  fseek(fp_tmp, -1, SEEK_END);
1677  if (fgetc(fp_tmp) != '\n')
1678  {
1679  fseek(fp_tmp, 0, SEEK_END);
1680  fputc('\n', fp_tmp);
1681  }
1682 
1683  fflush(fp_tmp);
1684  if (ferror(fp_tmp))
1685  {
1686  mutt_debug(LL_DEBUG1, "%s: write failed\n", mutt_buffer_string(tempfile));
1687  mutt_file_fclose(&fp_tmp);
1688  unlink(mutt_buffer_string(tempfile));
1689  mx_msg_commit(m_fcc, msg); /* XXX really? */
1690  mx_msg_close(m_fcc, &msg);
1691  mx_mbox_close(m_fcc);
1692  goto done;
1693  }
1694 
1695  /* count the number of lines */
1696  int lines = 0;
1697  char line_buf[1024];
1698  rewind(fp_tmp);
1699  while (fgets(line_buf, sizeof(line_buf), fp_tmp))
1700  lines++;
1701  fprintf(msg->fp, "Content-Length: " OFF_T_FMT "\n", (LOFF_T) ftello(fp_tmp));
1702  fprintf(msg->fp, "Lines: %d\n\n", lines);
1703 
1704  /* copy the body and clean up */
1705  rewind(fp_tmp);
1706  rc = mutt_file_copy_stream(fp_tmp, msg->fp);
1707  if (mutt_file_fclose(&fp_tmp) != 0)
1708  rc = -1;
1709  /* if there was an error, leave the temp version */
1710  if (rc >= 0)
1711  {
1712  unlink(mutt_buffer_string(tempfile));
1713  rc = 0;
1714  }
1715  }
1716  else
1717  {
1718  fputc('\n', msg->fp); /* finish off the header */
1719  rc = mutt_write_mime_body(e->body, msg->fp, sub);
1720  }
1721 
1722  if (mx_msg_commit(m_fcc, msg) != 0)
1723  rc = -1;
1724  else if (finalpath)
1725  *finalpath = mutt_str_dup(msg->committed_path);
1726  mx_msg_close(m_fcc, &msg);
1727  mx_mbox_close(m_fcc);
1728 
1729  if (!post && need_mailbox_cleanup)
1730  mutt_mailbox_cleanup(path, &st);
1731 
1732  if (post)
1733  set_noconv_flags(e->body, false);
1734 
1735 done:
1736  if (m_fcc)
1737  m_fcc->append = old_append;
1738 #ifdef RECORD_FOLDER_HOOK
1739  /* We ran a folder hook for the destination mailbox,
1740  * now we run it for the user's current mailbox */
1741  const struct Mailbox *m = ctx_mailbox(Context);
1742  if (m)
1743  mutt_folder_hook(m->path, m->desc);
1744 #endif
1745 
1746  if (fp_tmp)
1747  {
1748  mutt_file_fclose(&fp_tmp);
1749  unlink(mutt_buffer_string(tempfile));
1750  }
1751  mutt_buffer_pool_release(&tempfile);
1752 
1753  return rc;
1754 }
The "current" mailbox.
Definition: context.h:37
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
#define WithCrypto
Definition: lib.h:113
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:304
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
A postponed Email, just the envelope info.
Definition: header.h:42
struct Body * body
List of MIME parts.
Definition: email.h:91
struct Mailbox * ctx_mailbox(struct Context *ctx)
wrapper to get the mailbox in a Context, or NULL
Definition: context.c:444
void mutt_mailbox_cleanup(const char *path, struct stat *st)
Restore the timestamp of a mailbox.
Definition: mutt_mailbox.c:360
int mutt_write_mime_body(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Write a MIME part.
Definition: body.c:314
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:75
bool mutt_should_hide_protected_subject(struct Email *e)
Should NeoMutt hide the protected subject?
Definition: crypt.c:1108
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define MUTT_APPEND
Open mailbox for appending messages.
Definition: mxapi.h:62
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:84
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
Definition: mx.c:610
#define mutt_perror(...)
Definition: logging.h:89
#define MUTT_SET_DRAFT
set the message draft flag
Definition: mx.h:43
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:82
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1186
void mutt_folder_hook(const char *path, const char *desc)
Perform a folder hook.
Definition: hook.c:529
fcc mode, like normal mode but for Bcc header
Definition: header.h:41
bool read
Email is read.
Definition: email.h:51
struct Message * mx_msg_open_new(struct Mailbox *m, const struct Email *e, MsgOpenFlags flags)
Open a new message.
Definition: mx.c:1054
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:87
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
struct Envelope * env
Envelope information.
Definition: email.h:90
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:88
struct ListHead chain
Mixmaster chain.
Definition: email.h:102
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:87
A local copy of an email.
Definition: mxapi.h:41
A mailbox.
Definition: mailbox.h:81
#define SEC_AUTOCRYPT_OVERRIDE
(Autocrypt) Indicates manual set/unset of encryption
Definition: lib.h:85
&#39;mmdf&#39; Mailbox type
Definition: mailbox.h:49
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
bool append
Mailbox is opened in append mode.
Definition: mailbox.h:113
#define MUTT_QUIET
Do not print any messages.
Definition: mxapi.h:64
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
uint8_t MsgOpenFlags
Flags for mx_msg_open_new(), e.g. MUTT_ADD_FROM.
Definition: mx.h:40
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:83
&#39;mbox&#39; Mailbox type
Definition: mailbox.h:48
#define SEC_SIGN
Email is signed.
Definition: lib.h:76
char * committed_path
the final path generated by mx_msg_commit()
Definition: mxapi.h:45
char * data
String.
Definition: list.h:36
Log at debug level 1.
Definition: logging.h:40
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
int mx_msg_commit(struct Mailbox *m, struct Message *msg)
Commit a message to a folder - Wrapper for MxOps::msg_commit()
Definition: mx.c:1165
FILE * fp
pointer to the message data
Definition: mxapi.h:43
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1668
static void set_noconv_flags(struct Body *b, bool flag)
Set/reset the "x-mutt-noconv" flag.
Definition: sendlib.c:1439
#define STAILQ_EMPTY(head)
Definition: queue.h:348
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
A List node for strings.
Definition: list.h:34
#define MUTT_ADD_FROM
add a From_ line
Definition: mx.h:42
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
+ Here is the call graph for this function:
+ Here is the caller graph for this function: