NeoMutt  2020-06-26-89-g172cd3
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 "context.h"
#include "copy.h"
#include "handler.h"
#include "mutt_globals.h"
#include "mutt_mailbox.h"
#include "mutt_parse.h"
#include "muttlib.h"
#include "mx.h"
#include "options.h"
#include "state.h"
#include "ncrypt/lib.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 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 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

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 80 of file sendlib.c.

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

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

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

468 {
469  struct Content *info = NULL;
470  struct ContentState state = { 0 };
471  FILE *fp = NULL;
472  char *fromcode = NULL;
473  char *tocode = NULL;
474  char buf[100];
475  size_t r;
476 
477  struct stat sb;
478 
479  if (b && !fname)
480  fname = b->filename;
481 
482  if (stat(fname, &sb) == -1)
483  {
484  mutt_error(_("Can't stat %s: %s"), fname, strerror(errno));
485  return NULL;
486  }
487 
488  if (!S_ISREG(sb.st_mode))
489  {
490  mutt_error(_("%s isn't a regular file"), fname);
491  return NULL;
492  }
493 
494  fp = fopen(fname, "r");
495  if (!fp)
496  {
497  mutt_debug(LL_DEBUG1, "%s: %s (errno %d)\n", fname, strerror(errno), errno);
498  return NULL;
499  }
500 
501  info = mutt_mem_calloc(1, sizeof(struct Content));
502 
503  const char *c_charset = cs_subset_string(sub, "charset");
504 
505  if (b && (b->type == TYPE_TEXT) && (!b->noconv && !b->force_charset))
506  {
507  const char *c_attach_charset = cs_subset_string(sub, "attach_charset");
508  const char *c_send_charset = cs_subset_string(sub, "send_charset");
509 
510  char *chs = mutt_param_get(&b->parameter, "charset");
511  const char *fchs =
512  b->use_disp ? (c_attach_charset ? c_attach_charset : c_charset) : c_charset;
513  if (c_charset && (chs || c_send_charset) &&
514  (convert_file_from_to(fp, fchs, chs ? chs : c_send_charset, &fromcode,
515  &tocode, info) != (size_t)(-1)))
516  {
517  if (!chs)
518  {
519  char chsbuf[256];
520  mutt_ch_canonical_charset(chsbuf, sizeof(chsbuf), tocode);
521  mutt_param_set(&b->parameter, "charset", chsbuf);
522  }
523  FREE(&b->charset);
524  b->charset = fromcode;
525  FREE(&tocode);
526  mutt_file_fclose(&fp);
527  return info;
528  }
529  }
530 
531  rewind(fp);
532  while ((r = fread(buf, 1, sizeof(buf), fp)))
533  update_content_info(info, &state, buf, r);
534  update_content_info(info, &state, 0, 0);
535 
536  mutt_file_fclose(&fp);
537 
538  if (b && (b->type == TYPE_TEXT) && (!b->noconv && !b->force_charset))
539  {
540  mutt_param_set(&b->parameter, "charset",
541  (!info->hibin ?
542  "us-ascii" :
543  c_charset && !mutt_ch_is_us_ascii(c_charset) ? c_charset : "unknown-8bit"));
544  }
545 
546  return info;
547 }
Info about the body of an email.
Definition: sendlib.c:64
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:80
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
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:74
void mutt_ch_canonical_charset(char *buf, size_t buflen, const char *name)
Canonicalise the charset of a string.
Definition: charset.c:352
#define mutt_ch_is_us_ascii(str)
Definition: charset.h:96
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:219
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
Log at debug level 1.
Definition: logging.h:40
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
#define mutt_error(...)
Definition: logging.h:84
#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
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
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
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:380
+ 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 561 of file sendlib.c.

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

682 {
683  struct Buffer *buf = NULL;
684  struct State s = { 0 };
685  struct stat sb;
686 
687  for (; a; a = a->next)
688  {
689  if (a->type == TYPE_MULTIPART)
690  {
691  a->encoding = ENC_7BIT;
692  transform_to_7bit(a->parts, fp_in, sub);
693  }
694  else if (mutt_is_message_type(a->type, a->subtype))
695  {
696  mutt_message_to_7bit(a, fp_in, sub);
697  }
698  else
699  {
700  a->noconv = true;
701  a->force_charset = true;
702 
703  /* Because of the potential recursion in message types, we
704  * restrict the lifetime of the buffer tightly */
705  buf = mutt_buffer_pool_get();
706  mutt_buffer_mktemp(buf);
707  s.fp_out = mutt_file_fopen(mutt_b2s(buf), "w");
708  if (!s.fp_out)
709  {
710  mutt_perror("fopen");
712  return;
713  }
714  s.fp_in = fp_in;
715  mutt_decode_attachment(a, &s);
717  FREE(&a->d_filename);
718  a->d_filename = a->filename;
719  a->filename = mutt_buffer_strdup(buf);
721  a->unlink = true;
722  if (stat(a->filename, &sb) == -1)
723  {
724  mutt_perror("stat");
725  return;
726  }
727  a->length = sb.st_size;
728 
729  mutt_update_encoding(a, sub);
730  if (a->encoding == ENC_8BIT)
732  else if (a->encoding == ENC_BINARY)
733  a->encoding = ENC_BASE64;
734  }
735  }
736 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1835
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
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:1361
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
void mutt_update_encoding(struct Body *a, struct ConfigSubset *sub)
Update the encoding type.
Definition: sendlib.c:901
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:744
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
char * mutt_buffer_strdup(struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
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
FILE * fp_in
File to read from.
Definition: state.h:46
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:74
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
#define mutt_b2s(buf)
Definition: buffer.h:41
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:681
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:588
+ 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 744 of file sendlib.c.

745 {
746  struct Buffer temp = mutt_buffer_make(0);
747  FILE *fp_in = NULL;
748  FILE *fp_out = NULL;
749  struct stat sb;
750 
751  if (!a->filename && fp)
752  fp_in = fp;
753  else if (!a->filename || !(fp_in = fopen(a->filename, "r")))
754  {
755  mutt_error(_("Could not open %s"), a->filename ? a->filename : "(null)");
756  return;
757  }
758  else
759  {
760  a->offset = 0;
761  if (stat(a->filename, &sb) == -1)
762  {
763  mutt_perror("stat");
764  mutt_file_fclose(&fp_in);
765  goto cleanup;
766  }
767  a->length = sb.st_size;
768  }
769 
770  /* Avoid buffer pool due to recursion */
771  mutt_buffer_mktemp(&temp);
772  fp_out = mutt_file_fopen(mutt_b2s(&temp), "w+");
773  if (!fp_out)
774  {
775  mutt_perror("fopen");
776  goto cleanup;
777  }
778 
779  fseeko(fp_in, a->offset, SEEK_SET);
780  a->parts = mutt_rfc822_parse_message(fp_in, a);
781 
782  transform_to_7bit(a->parts, fp_in, sub);
783 
784  mutt_copy_hdr(fp_in, fp_out, a->offset, a->offset + a->length,
785  CH_MIME | CH_NONEWLINE | CH_XMIT, NULL, 0);
786 
787  fputs("MIME-Version: 1.0\n", fp_out);
788  mutt_write_mime_header(a->parts, fp_out, sub);
789  fputc('\n', fp_out);
790  mutt_write_mime_body(a->parts, fp_out, sub);
791 
792  if (fp_in != fp)
793  mutt_file_fclose(&fp_in);
794  mutt_file_fclose(&fp_out);
795 
796  a->encoding = ENC_7BIT;
797  FREE(&a->d_filename);
798  a->d_filename = a->filename;
799  if (a->filename && a->unlink)
800  unlink(a->filename);
801  a->filename = mutt_buffer_strdup(&temp);
802  a->unlink = true;
803  if (stat(a->filename, &sb) == -1)
804  {
805  mutt_perror("stat");
806  goto cleanup;
807  }
808  a->length = sb.st_size;
809  mutt_body_free(&a->parts);
810  a->email->content = NULL;
811 
812 cleanup:
813  if (fp_in && (fp_in != fp))
814  mutt_file_fclose(&fp_in);
815 
816  if (fp_out)
817  {
818  mutt_file_fclose(&fp_out);
819  mutt_file_unlink(mutt_b2s(&temp));
820  }
821 
822  mutt_buffer_dealloc(&temp);
823 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
#define CH_MIME
Ignore MIME fields.
Definition: copy.h:60
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
#define mutt_perror(...)
Definition: logging.h:85
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
struct Body * content
List of MIME parts.
Definition: email.h:90
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
char * mutt_buffer_strdup(struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
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
struct Body * mutt_rfc822_parse_message(FILE *fp, struct Body *parent)
parse a Message/RFC822 body
Definition: parse.c:1543
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:755
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
#define mutt_b2s(buf)
Definition: buffer.h:41
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:54
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:681
#define mutt_error(...)
Definition: logging.h:84
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:77
#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:588
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:59
+ 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 831 of file sendlib.c.

832 {
833  const bool c_allow_8bit = cs_subset_bool(sub, "allow_8bit");
834  if (b->type == TYPE_TEXT)
835  {
836  const bool c_encode_from = cs_subset_bool(sub, "encode_from");
837  char send_charset[128];
838  char *chsname = mutt_body_get_charset(b, send_charset, sizeof(send_charset));
839  if ((info->lobin && !mutt_istr_startswith(chsname, "iso-2022")) ||
840  (info->linemax > 990) || (info->from && c_encode_from))
841  {
843  }
844  else if (info->hibin)
845  {
846  b->encoding = c_allow_8bit ? ENC_8BIT : ENC_QUOTED_PRINTABLE;
847  }
848  else
849  {
850  b->encoding = ENC_7BIT;
851  }
852  }
853  else if ((b->type == TYPE_MESSAGE) || (b->type == TYPE_MULTIPART))
854  {
855  if (info->lobin || info->hibin)
856  {
857  if (c_allow_8bit && !info->lobin)
858  b->encoding = ENC_8BIT;
859  else
860  mutt_message_to_7bit(b, NULL, sub);
861  }
862  else
863  b->encoding = ENC_7BIT;
864  }
865  else if ((b->type == TYPE_APPLICATION) &&
866  mutt_istr_equal(b->subtype, "pgp-keys"))
867  {
868  b->encoding = ENC_7BIT;
869  }
870  else
871  {
872  /* Determine which encoding is smaller */
873  if (1.33 * (float) (info->lobin + info->hibin + info->ascii) <
874  3.0 * (float) (info->lobin + info->hibin) + (float) info->ascii)
875  {
876  b->encoding = ENC_BASE64;
877  }
878  else
879  {
881  }
882  }
883 }
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:68
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:744
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:888
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:177
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 889 of file sendlib.c.

890 {
891  a->stamp = mutt_date_epoch();
892 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:414
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 901 of file sendlib.c.

902 {
903  struct Content *info = NULL;
904  char chsbuf[256];
905 
906  /* override noconv when it's us-ascii */
907  if (mutt_ch_is_us_ascii(mutt_body_get_charset(a, chsbuf, sizeof(chsbuf))))
908  a->noconv = false;
909 
910  if (!a->force_charset && !a->noconv)
911  mutt_param_delete(&a->parameter, "charset");
912 
913  info = mutt_get_content_info(a->filename, a, sub);
914  if (!info)
915  return;
916 
917  set_encoding(a, info, sub);
919 
920  FREE(&a->content);
921  a->content = info;
922 }
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:466
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:889
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:74
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body&#39;s character set.
Definition: body.c:131
#define mutt_ch_is_us_ascii(str)
Definition: charset.h:96
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 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:831
+ 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 933 of file sendlib.c.

935 {
936  struct Body *body = NULL;
937  FILE *fp = NULL;
938  CopyMessageFlags cmflags;
940 
941  const bool c_mime_forward_decode = cs_subset_bool(sub, "mime_forward_decode");
942  const bool c_forward_decrypt = cs_subset_bool(sub, "forward_decrypt");
943  if (WithCrypto)
944  {
945  if ((c_mime_forward_decode || c_forward_decrypt) && (e->security & SEC_ENCRYPT))
946  {
948  return NULL;
949  }
950  }
951 
952  struct Buffer *buf = mutt_buffer_pool_get();
953  mutt_buffer_mktemp(buf);
954  fp = mutt_file_fopen(mutt_b2s(buf), "w+");
955  if (!fp)
956  {
958  return NULL;
959  }
960 
961  body = mutt_body_new();
962  body->type = TYPE_MESSAGE;
963  body->subtype = mutt_str_dup("rfc822");
964  body->filename = mutt_str_dup(mutt_b2s(buf));
965  body->unlink = true;
966  body->use_disp = false;
967  body->disposition = DISP_INLINE;
968  body->noconv = true;
969 
971 
973 
974  CopyHeaderFlags chflags = CH_XMIT;
975  cmflags = MUTT_CM_NO_FLAGS;
976 
977  const bool c_forward_decode = cs_subset_bool(sub, "forward_decode");
978  /* If we are attaching a message, ignore `$mime_forward_decode` */
979  if (!attach_msg && c_forward_decode)
980  {
981  chflags |= CH_MIME | CH_TXTPLAIN;
982  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
984  pgp &= ~PGP_ENCRYPT;
986  pgp &= ~SMIME_ENCRYPT;
987  }
988  else if ((WithCrypto != 0) && c_forward_decrypt && (e->security & SEC_ENCRYPT))
989  {
990  if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_multipart_encrypted(e->content))
991  {
992  chflags |= CH_MIME | CH_NONEWLINE;
993  cmflags = MUTT_CM_DECODE_PGP;
994  pgp &= ~PGP_ENCRYPT;
995  }
996  else if (((WithCrypto & APPLICATION_PGP) != 0) &&
998  {
999  chflags |= CH_MIME | CH_TXTPLAIN;
1000  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1001  pgp &= ~PGP_ENCRYPT;
1002  }
1003  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
1005  {
1006  chflags |= CH_MIME | CH_TXTPLAIN;
1007  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1008  pgp &= ~SMIME_ENCRYPT;
1009  }
1010  }
1011 
1012  mutt_copy_message(fp, m, e, cmflags, chflags, 0);
1013 
1014  fflush(fp);
1015  rewind(fp);
1016 
1017  body->email = email_new();
1018  body->email->offset = 0;
1019  /* we don't need the user headers here */
1020  body->email->env = mutt_rfc822_read_header(fp, body->email, false, false);
1021  if (WithCrypto)
1022  body->email->security = pgp;
1023  mutt_update_encoding(body, sub);
1024  body->parts = body->email->content;
1025 
1026  mutt_file_fclose(&fp);
1027 
1028  return body;
1029 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
#define CH_MIME
Ignore MIME fields.
Definition: copy.h:60
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:68
#define WithCrypto
Definition: lib.h:118
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:901
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:79
#define SMIME_ENCRYPT
Definition: lib.h:104
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:80
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Body * content
List of MIME parts.
Definition: email.h:90
bool noconv
Don&#39;t do character set conversion.
Definition: body.h:73
#define PGP_ENCRYPT
Definition: lib.h:98
String manipulation buffer.
Definition: buffer.h:33
void mutt_parse_mime_message(struct Mailbox *m, struct Email *e)
Parse a MIME email.
Definition: mutt_parse.c:48
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
int mutt_copy_message(FILE *fp_out, struct Mailbox *m, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags, int wraplen)
Copy a message from a Mailbox.
Definition: copy.c:821
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:78
uint16_t CopyMessageFlags
Flags for mutt_copy_message(), e.g. MUTT_CM_NOHEADER.
Definition: copy.h:31
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:34
The body of an email.
Definition: body.h:34
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:67
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:134
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:445
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:89
char * subtype
content-type subtype
Definition: body.h:37
#define CH_TXTPLAIN
Generate text/plain MIME headers.
Definition: copy.h:62
#define mutt_b2s(buf)
Definition: buffer.h:41
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:93
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:550
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:92
#define MUTT_CM_DECODE
Decode the message body into text/plain.
Definition: copy.h:37
#define MUTT_CM_CHARCONV
Perform character set conversions.
Definition: copy.h:41
#define CH_XMIT
Transmitting this message? (Ignore Lines: and Content-Length:)
Definition: copy.h:54
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
SecurityFlags mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
Definition: crypt.c:608
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:83
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:49
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
#define MUTT_CM_DECODE_PGP
Used for decoding PGP messages.
Definition: copy.h:44
struct Email * email_new(void)
Create a new Email.
Definition: email.c:68
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
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:1106
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:59
+ 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 1038 of file sendlib.c.

1039 {
1040  FILE *fp = NULL, *fp_err = NULL;
1041  char *buf = NULL;
1042  size_t buflen;
1043  pid_t pid;
1044  struct Buffer *cmd = mutt_buffer_pool_get();
1045 
1046  const char *c_mime_type_query_command =
1047  cs_subset_string(sub, "mime_type_query_command");
1048 
1049  mutt_buffer_file_expand_fmt_quote(cmd, c_mime_type_query_command, att->filename);
1050 
1051  pid = filter_create(mutt_b2s(cmd), NULL, &fp, &fp_err);
1052  if (pid < 0)
1053  {
1054  mutt_error(_("Error running \"%s\""), mutt_b2s(cmd));
1056  return;
1057  }
1059 
1060  buf = mutt_file_read_line(buf, &buflen, fp, NULL, 0);
1061  if (buf)
1062  {
1063  if (strchr(buf, '/'))
1064  mutt_parse_content_type(buf, att);
1065  FREE(&buf);
1066  }
1067 
1068  mutt_file_fclose(&fp);
1069  mutt_file_fclose(&fp_err);
1070  filter_wait(pid);
1071 }
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
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, int flags)
Read a line from a file.
Definition: file.c:667
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
#define mutt_b2s(buf)
Definition: buffer.h:41
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:219
void mutt_parse_content_type(const char *s, struct Body *ct)
Parse a content type.
Definition: parse.c:420
#define mutt_error(...)
Definition: logging.h:84
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:1425
#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 1080 of file sendlib.c.

1081 {
1082  struct Body *att = mutt_body_new();
1083  att->filename = mutt_str_dup(path);
1084 
1085  const char *c_mime_type_query_command =
1086  cs_subset_string(sub, "mime_type_query_command");
1087  const bool c_mime_type_query_first =
1088  cs_subset_bool(sub, "mime_type_query_first");
1089 
1090  if (c_mime_type_query_command && c_mime_type_query_first)
1091  run_mime_type_query(att, sub);
1092 
1093  /* Attempt to determine the appropriate content-type based on the filename
1094  * suffix. */
1095  if (!att->subtype)
1096  mutt_lookup_mime_type(att, path);
1097 
1098  if (!att->subtype && c_mime_type_query_command && !c_mime_type_query_first)
1099  {
1100  run_mime_type_query(att, sub);
1101  }
1102 
1103  struct Content *info = mutt_get_content_info(path, att, sub);
1104  if (!info)
1105  {
1106  mutt_body_free(&att);
1107  return NULL;
1108  }
1109 
1110  if (!att->subtype)
1111  {
1112  if ((info->nulbin == 0) &&
1113  ((info->lobin == 0) || ((info->lobin + info->hibin + info->ascii) / info->lobin >= 10)))
1114  {
1115  /* Statistically speaking, there should be more than 10% "lobin"
1116  * chars if this is really a binary file... */
1117  att->type = TYPE_TEXT;
1118  att->subtype = mutt_str_dup("plain");
1119  }
1120  else
1121  {
1122  att->type = TYPE_APPLICATION;
1123  att->subtype = mutt_str_dup("octet-stream");
1124  }
1125  }
1126 
1127  FREE(&info);
1128  mutt_update_encoding(att, sub);
1129  return att;
1130 }
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:466
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:68
void mutt_update_encoding(struct Body *a, struct ConfigSubset *sub)
Update the encoding type.
Definition: sendlib.c:901
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
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:219
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:561
#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:1038
+ 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 1139 of file sendlib.c.

1140 {
1141  char *tmp = NULL;
1142  char *p = NULL;
1143  int i;
1144 
1145  const char *c_send_charset = cs_subset_string(sub, "send_charset");
1146 
1147  struct ListNode *np = NULL;
1148  STAILQ_FOREACH(np, h, entries)
1149  {
1150  p = strchr(np->data, ':');
1151  if (!p)
1152  continue;
1153 
1154  i = p - np->data;
1155  p = mutt_str_skip_email_wsp(p + 1);
1156  tmp = mutt_str_dup(p);
1157 
1158  if (!tmp)
1159  continue;
1160 
1161  rfc2047_encode(&tmp, NULL, i + 2, c_send_charset);
1162  mutt_mem_realloc(&np->data, i + 2 + mutt_str_len(tmp) + 1);
1163 
1164  sprintf(np->data + i + 2, "%s", tmp);
1165 
1166  FREE(&tmp);
1167  }
1168 }
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
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:219
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:748
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
void rfc2047_encode(char **pd, const char *specials, int col, const char *charsets)
RFC-2047-encode a string.
Definition: rfc2047.c:615
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:636
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 1179 of file sendlib.c.

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

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

1236 {
1237  if (final)
1238  {
1239  if (!TAILQ_EMPTY(&env->bcc) && TAILQ_EMPTY(&env->to) && TAILQ_EMPTY(&env->cc))
1240  {
1241  /* some MTA's will put an Apparently-To: header field showing the Bcc:
1242  * recipients if there is no To: or Cc: field, so attempt to suppress
1243  * it by using an empty To: field. */
1244  struct Address *to = mutt_addr_new();
1245  to->group = true;
1246  mutt_addrlist_append(&env->to, to);
1248 
1249  char buf[1024];
1250  buf[0] = '\0';
1251  mutt_addr_cat(buf, sizeof(buf), "undisclosed-recipients", AddressSpecials);
1252 
1253  to->mailbox = mutt_str_dup(buf);
1254  }
1255 
1256  mutt_set_followup_to(env, sub);
1257 
1258  if (!env->message_id)
1259  env->message_id = gen_msgid(sub);
1260  }
1261 
1262  /* Take care of 8-bit => 7-bit conversion. */
1264  encode_headers(&env->userhdrs, sub);
1265 }
void rfc2047_encode_envelope(struct Envelope *env)
Encode the fields of an Envelope.
Definition: rfc2047.c:799
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:1139
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
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:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
char * message_id
Message ID.
Definition: envelope.h:69
static char * gen_msgid(struct ConfigSubset *sub)
Generate a unique Message ID.
Definition: sendlib.c:1208
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:1198
bool group
Group mailbox?
Definition: address.h:38
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
#define TAILQ_EMPTY(head)
Definition: queue.h:714
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:1481
+ 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 1274 of file sendlib.c.

1275 {
1276  struct ListNode *item = NULL;
1277  STAILQ_FOREACH(item, &env->userhdrs, entries)
1278  {
1279  rfc2047_decode(&item->data);
1280  }
1281 
1283 
1284  /* back conversions */
1286 }
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:1461
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:779
void rfc2047_decode(char **pd)
Decode any RFC2047-encoded header fields.
Definition: rfc2047.c:639
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
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 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
eEmail
toAddress to bounce to
resent_fromAddress of new sender
env_fromEnvelope of original sender
subConfig Subset
Return values
0Success
-1Failure

Definition at line 1299 of file sendlib.c.

1302 {
1303  if (!e)
1304  return -1;
1305 
1306  int rc = 0;
1307 
1308  struct Buffer *tempfile = mutt_buffer_pool_get();
1309  mutt_buffer_mktemp(tempfile);
1310  FILE *fp_tmp = mutt_file_fopen(mutt_b2s(tempfile), "w");
1311  if (fp_tmp)
1312  {
1313  char date[128];
1315 
1316  const bool c_bounce_delivered = cs_subset_bool(sub, "bounce_delivered");
1317  if (!c_bounce_delivered)
1318  chflags |= CH_WEED_DELIVERED;
1319 
1320  fseeko(fp, e->offset, SEEK_SET);
1321  fprintf(fp_tmp, "Resent-From: %s", resent_from);
1322  fprintf(fp_tmp, "\nResent-%s", mutt_date_make_date(date, sizeof(date)));
1323  char *msgid_str = gen_msgid(sub);
1324  fprintf(fp_tmp, "Resent-Message-ID: %s\n", msgid_str);
1325  FREE(&msgid_str);
1326  fputs("Resent-To: ", fp_tmp);
1327  mutt_addrlist_write_file(to, fp_tmp, 11, false);
1328  mutt_copy_header(fp, e, fp_tmp, chflags, NULL, 0);
1329  fputc('\n', fp_tmp);
1330  mutt_file_copy_bytes(fp, fp_tmp, e->content->length);
1331  if (mutt_file_fclose(&fp_tmp) != 0)
1332  {
1333  mutt_perror(mutt_b2s(tempfile));
1334  unlink(mutt_b2s(tempfile));
1335  return -1;
1336  }
1337 #ifdef USE_SMTP
1338  const char *c_smtp_url = cs_subset_string(sub, "smtp_url");
1339  if (c_smtp_url)
1340  {
1341  rc = mutt_smtp_send(env_from, to, NULL, NULL, mutt_b2s(tempfile),
1342  (e->content->encoding == ENC_8BIT), sub);
1343  }
1344  else
1345 #endif
1346  {
1347  rc = mutt_invoke_sendmail(env_from, to, NULL, NULL, mutt_b2s(tempfile),
1348  (e->content->encoding == ENC_8BIT), sub);
1349  }
1350  }
1351 
1352  mutt_buffer_pool_release(&tempfile);
1353  return rc;
1354 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:68
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Body * content
List of MIME parts.
Definition: email.h:90
String manipulation buffer.
Definition: buffer.h:33
8-bit text
Definition: mime.h:50
char * mutt_date_make_date(char *buf, size_t buflen)
Write a date in RFC822 format to a buffer.
Definition: date.c:375
#define CH_WEED_DELIVERED
Weed eventual Delivered-To headers.
Definition: copy.h:64
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:1208
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
#define mutt_b2s(buf)
Definition: buffer.h:41
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:54
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:219
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:753
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:83
#define CH_NOQFROM
Ignore ">From " line.
Definition: copy.h:66
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:49
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:399
int mutt_invoke_sendmail(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:315
#define FREE(x)
Definition: memory.h:40
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
#define CH_NONEWLINE
Don&#39;t output terminating newline after the header.
Definition: copy.h:59
void mutt_addrlist_write_file(const struct AddressList *al, FILE *fp, int linelen, bool display)
Wrapper for mutt_write_address()
Definition: address.c:1226
+ 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 Email e,
struct AddressList *  to,
struct ConfigSubset sub 
)

Bounce an email message.

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

Definition at line 1365 of file sendlib.c.

1367 {
1368  if (!fp || !e || !to || TAILQ_EMPTY(to))
1369  return -1;
1370 
1371  const char *fqdn = mutt_fqdn(true, sub);
1372  char resent_from[256];
1373  char *err = NULL;
1374 
1375  resent_from[0] = '\0';
1376  struct Address *from = mutt_default_from(sub);
1377  struct AddressList from_list = TAILQ_HEAD_INITIALIZER(from_list);
1378  mutt_addrlist_append(&from_list, from);
1379 
1380  /* mutt_default_from() does not use $realname if the real name is not set
1381  * in $from, so we add it here. The reason it is not added in
1382  * mutt_default_from() is that during normal sending, we execute
1383  * send-hooks and set the realname last so that it can be changed based
1384  * upon message criteria. */
1385  if (!from->personal)
1386  {
1387  const char *c_realname = cs_subset_string(sub, "realname");
1388  from->personal = mutt_str_dup(c_realname);
1389  }
1390 
1391  mutt_addrlist_qualify(&from_list, fqdn);
1392 
1393  rfc2047_encode_addrlist(&from_list, "Resent-From");
1394  if (mutt_addrlist_to_intl(&from_list, &err))
1395  {
1396  mutt_error(_("Bad IDN %s while preparing resent-from"), err);
1397  FREE(&err);
1398  mutt_addrlist_clear(&from_list);
1399  return -1;
1400  }
1401  mutt_addrlist_write(&from_list, resent_from, sizeof(resent_from), false);
1402 
1403 #ifdef USE_NNTP
1404  OptNewsSend = false;
1405 #endif
1406 
1407  /* prepare recipient list. idna conversion appears to happen before this
1408  * function is called, since the user receives confirmation of the address
1409  * list being bounced to. */
1410  struct AddressList resent_to = TAILQ_HEAD_INITIALIZER(resent_to);
1411  mutt_addrlist_copy(&resent_to, to, false);
1412  rfc2047_encode_addrlist(&resent_to, "Resent-To");
1413  int rc = bounce_message(fp, e, &resent_to, resent_from, &from_list, sub);
1414  mutt_addrlist_clear(&resent_to);
1415  mutt_addrlist_clear(&from_list);
1416 
1417  return rc;
1418 }
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1461
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:375
#define _(a)
Definition: message.h:28
An email address.
Definition: address.h:34
void rfc2047_encode_addrlist(struct AddressList *al, const char *tag)
Encode any RFC2047 headers, where required, in an Address list.
Definition: rfc2047.c:738
struct Address * mutt_default_from(struct ConfigSubset *sub)
Get a default &#39;from&#39; Address.
Definition: send.c:1323
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:219
char * personal
Real name of address.
Definition: address.h:36
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:1179
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1297
#define mutt_error(...)
Definition: logging.h:84
static int bounce_message(FILE *fp, struct Email *e, struct AddressList *to, const char *resent_from, struct AddressList *env_from, struct ConfigSubset *sub)
Bounce an email message.
Definition: sendlib.c:1299
#define FREE(x)
Definition: memory.h:40
#define TAILQ_EMPTY(head)
Definition: queue.h:714
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:46
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:630
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:1147
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1481
+ 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 1425 of file sendlib.c.

1426 {
1427  for (; b; b = b->next)
1428  {
1429  if ((b->type == TYPE_MESSAGE) || (b->type == TYPE_MULTIPART))
1430  set_noconv_flags(b->parts, flag);
1431  else if ((b->type == TYPE_TEXT) && b->noconv)
1432  {
1433  if (flag)
1434  mutt_param_set(&b->parameter, "x-mutt-noconv", "yes");
1435  else
1436  mutt_param_delete(&b->parameter, "x-mutt-noconv");
1437  }
1438  }
1439 }
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:1425
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 1453 of file sendlib.c.

1455 {
1456  char fcc_tok[PATH_MAX];
1457  char fcc_expanded[PATH_MAX];
1458 
1459  mutt_str_copy(fcc_tok, path, sizeof(fcc_tok));
1460 
1461  char *tok = strtok(fcc_tok, ",");
1462  if (!tok)
1463  return -1;
1464 
1465  mutt_debug(LL_DEBUG1, "Fcc: initial mailbox = '%s'\n", tok);
1466  /* mutt_expand_path already called above for the first token */
1467  int status = mutt_write_fcc(tok, e, msgid, post, fcc, finalpath, sub);
1468  if (status != 0)
1469  return status;
1470 
1471  while ((tok = strtok(NULL, ",")))
1472  {
1473  if (*tok == '\0')
1474  continue;
1475 
1476  /* Only call mutt_expand_path if tok has some data */
1477  mutt_debug(LL_DEBUG1, "Fcc: additional mailbox token = '%s'\n", tok);
1478  mutt_str_copy(fcc_expanded, tok, sizeof(fcc_expanded));
1479  mutt_expand_path(fcc_expanded, sizeof(fcc_expanded));
1480  mutt_debug(LL_DEBUG1, " Additional mailbox expanded = '%s'\n", fcc_expanded);
1481  status = mutt_write_fcc(fcc_expanded, e, msgid, post, fcc, finalpath, sub);
1482  if (status != 0)
1483  return status;
1484  }
1485 
1486  return 0;
1487 }
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:1501
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:128
#define PATH_MAX
Definition: mutt.h:44
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:721
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
+ 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 1501 of file sendlib.c.

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