NeoMutt  2020-11-20
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 "context.h"
#include "copy.h"
#include "handler.h"
#include "mutt_globals.h"
#include "mutt_mailbox.h"
#include "mutt_parse.h"
#include "muttlib.h"
#include "mx.h"
#include "options.h"
#include "state.h"
+ Include dependency graph for sendlib.c:

Go to the source code of this file.

Data Structures

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

Functions

static void update_content_info (struct Content *info, struct ContentState *s, char *buf, size_t buflen)
 Cache some info about an email. More...
 
static size_t convert_file_to (FILE *fp, const char *fromcode, int ncodes, char const *const *tocodes, int *tocode, struct Content *info)
 Change the encoding of a file. More...
 
static size_t convert_file_from_to (FILE *fp, const char *fromcodes, const char *tocodes, char **fromcode, char **tocode, struct Content *info)
 Convert a file between encodings. More...
 
struct Contentmutt_get_content_info (const char *fname, struct Body *b, struct ConfigSubset *sub)
 Analyze file to determine MIME encoding to use. More...
 
enum ContentType mutt_lookup_mime_type (struct Body *att, const char *path)
 Find the MIME type for an attachment. More...
 
static void transform_to_7bit (struct Body *a, FILE *fp_in, struct ConfigSubset *sub)
 Convert MIME parts to 7-bit. More...
 
void mutt_message_to_7bit (struct Body *a, FILE *fp, struct ConfigSubset *sub)
 Convert an email's MIME parts to 7-bit. More...
 
static void set_encoding (struct Body *b, struct Content *info, struct ConfigSubset *sub)
 determine which Content-Transfer-Encoding to use More...
 
void mutt_stamp_attachment (struct Body *a)
 Timestamp an Attachment. More...
 
void mutt_update_encoding (struct Body *a, struct ConfigSubset *sub)
 Update the encoding type. More...
 
struct Bodymutt_make_message_attach (struct Mailbox *m, struct Email *e, bool attach_msg, struct ConfigSubset *sub)
 Create a message attachment. More...
 
static void run_mime_type_query (struct Body *att, struct ConfigSubset *sub)
 Run an external command to determine the MIME type. More...
 
struct Bodymutt_make_file_attach (const char *path, struct ConfigSubset *sub)
 Create a file attachment. More...
 
static void encode_headers (struct ListHead *h, struct ConfigSubset *sub)
 RFC2047-encode a list of headers. More...
 
const char * mutt_fqdn (bool may_hide_host, const struct ConfigSubset *sub)
 Get the Fully-Qualified Domain Name. More...
 
static char * gen_msgid (struct ConfigSubset *sub)
 Generate a unique Message ID. More...
 
void mutt_prepare_envelope (struct Envelope *env, bool final, struct ConfigSubset *sub)
 Prepare an email header. More...
 
void mutt_unprepare_envelope (struct Envelope *env)
 Undo the encodings of mutt_prepare_envelope() More...
 
static int bounce_message (FILE *fp, struct 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:883
Info about an attachment.
Definition: content.h:33
#define FREE(x)
Definition: memory.h:40
iconv_t mutt_ch_iconv_open(const char *tocode, const char *fromcode, int flags)
Set up iconv for conversions.
Definition: charset.c:565
+ 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: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: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  if (!fname)
482  return NULL;
483 
484  if (stat(fname, &sb) == -1)
485  {
486  mutt_error(_("Can't stat %s: %s"), fname, strerror(errno));
487  return NULL;
488  }
489 
490  if (!S_ISREG(sb.st_mode))
491  {
492  mutt_error(_("%s isn't a regular file"), fname);
493  return NULL;
494  }
495 
496  fp = fopen(fname, "r");
497  if (!fp)
498  {
499  mutt_debug(LL_DEBUG1, "%s: %s (errno %d)\n", fname, strerror(errno), errno);
500  return NULL;
501  }
502 
503  info = mutt_mem_calloc(1, sizeof(struct Content));
504 
505  const char *c_charset = cs_subset_string(sub, "charset");
506 
507  if (b && (b->type == TYPE_TEXT) && (!b->noconv && !b->force_charset))
508  {
509  const char *c_attach_charset = cs_subset_string(sub, "attach_charset");
510  const char *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 ?
544  "us-ascii" :
545  c_charset && !mutt_ch_is_us_ascii(c_charset) ? c_charset : "unknown-8bit"));
546  }
547 
548  return info;
549 }
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
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:241
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 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_ch_canonical_charset(char *buf, size_t buflen, const char *name)
Canonicalise the charset of a string.
Definition: charset.c:352
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 563 of file sendlib.c.

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

684 {
685  struct Buffer *buf = NULL;
686  struct State s = { 0 };
687  struct stat sb;
688 
689  for (; a; a = a->next)
690  {
691  if (a->type == TYPE_MULTIPART)
692  {
693  a->encoding = ENC_7BIT;
694  transform_to_7bit(a->parts, fp_in, sub);
695  }
696  else if (mutt_is_message_type(a->type, a->subtype))
697  {
698  mutt_message_to_7bit(a, fp_in, sub);
699  }
700  else
701  {
702  a->noconv = true;
703  a->force_charset = true;
704 
705  /* Because of the potential recursion in message types, we
706  * restrict the lifetime of the buffer tightly */
707  buf = mutt_buffer_pool_get();
708  mutt_buffer_mktemp(buf);
709  s.fp_out = mutt_file_fopen(mutt_b2s(buf), "w");
710  if (!s.fp_out)
711  {
712  mutt_perror("fopen");
714  return;
715  }
716  s.fp_in = fp_in;
717  mutt_decode_attachment(a, &s);
719  FREE(&a->d_filename);
720  a->d_filename = a->filename;
721  a->filename = mutt_buffer_strdup(buf);
723  a->unlink = true;
724  if (stat(a->filename, &sb) == -1)
725  {
726  mutt_perror("stat");
727  return;
728  }
729  a->length = sb.st_size;
730 
731  mutt_update_encoding(a, sub);
732  if (a->encoding == ENC_8BIT)
734  else if (a->encoding == ENC_BINARY)
735  a->encoding = ENC_BASE64;
736  }
737  }
738 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1843
#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:1366
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:903
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:746
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
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:683
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 746 of file sendlib.c.

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

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

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

904 {
905  struct Content *info = NULL;
906  char chsbuf[256];
907 
908  /* override noconv when it's us-ascii */
909  if (mutt_ch_is_us_ascii(mutt_body_get_charset(a, chsbuf, sizeof(chsbuf))))
910  a->noconv = false;
911 
912  if (!a->force_charset && !a->noconv)
913  mutt_param_delete(&a->parameter, "charset");
914 
915  info = mutt_get_content_info(a->filename, a, sub);
916  if (!info)
917  return;
918 
919  set_encoding(a, info, sub);
921 
922  FREE(&a->content);
923  a->content = info;
924 }
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:891
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
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:833
+ 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 935 of file sendlib.c.

937 {
938  struct Body *body = NULL;
939  FILE *fp = NULL;
940  CopyMessageFlags cmflags;
942 
943  const bool c_mime_forward_decode = cs_subset_bool(sub, "mime_forward_decode");
944  const bool c_forward_decrypt = cs_subset_bool(sub, "forward_decrypt");
945  if (WithCrypto)
946  {
947  if ((c_mime_forward_decode || c_forward_decrypt) && (e->security & SEC_ENCRYPT))
948  {
950  return NULL;
951  }
952  }
953 
954  struct Buffer *buf = mutt_buffer_pool_get();
955  mutt_buffer_mktemp(buf);
956  fp = mutt_file_fopen(mutt_b2s(buf), "w+");
957  if (!fp)
958  {
960  return NULL;
961  }
962 
963  body = mutt_body_new();
964  body->type = TYPE_MESSAGE;
965  body->subtype = mutt_str_dup("rfc822");
966  body->filename = mutt_str_dup(mutt_b2s(buf));
967  body->unlink = true;
968  body->use_disp = false;
969  body->disposition = DISP_INLINE;
970  body->noconv = true;
971 
973 
975 
976  CopyHeaderFlags chflags = CH_XMIT;
977  cmflags = MUTT_CM_NO_FLAGS;
978 
979  const bool c_forward_decode = cs_subset_bool(sub, "forward_decode");
980  /* If we are attaching a message, ignore `$mime_forward_decode` */
981  if (!attach_msg && c_forward_decode)
982  {
983  chflags |= CH_MIME | CH_TXTPLAIN;
984  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
986  pgp &= ~PGP_ENCRYPT;
988  pgp &= ~SMIME_ENCRYPT;
989  }
990  else if ((WithCrypto != 0) && c_forward_decrypt && (e->security & SEC_ENCRYPT))
991  {
992  if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_multipart_encrypted(e->body))
993  {
994  chflags |= CH_MIME | CH_NONEWLINE;
995  cmflags = MUTT_CM_DECODE_PGP;
996  pgp &= ~PGP_ENCRYPT;
997  }
998  else if (((WithCrypto & APPLICATION_PGP) != 0) &&
1000  {
1001  chflags |= CH_MIME | CH_TXTPLAIN;
1002  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1003  pgp &= ~PGP_ENCRYPT;
1004  }
1005  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
1007  {
1008  chflags |= CH_MIME | CH_TXTPLAIN;
1009  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1010  pgp &= ~SMIME_ENCRYPT;
1011  }
1012  }
1013 
1014  mutt_copy_message(fp, m, e, cmflags, chflags, 0);
1015 
1016  fflush(fp);
1017  rewind(fp);
1018 
1019  body->email = email_new();
1020  body->email->offset = 0;
1021  /* we don't need the user headers here */
1022  body->email->env = mutt_rfc822_read_header(fp, body->email, false, false);
1023  if (WithCrypto)
1024  body->email->security = pgp;
1025  mutt_update_encoding(body, sub);
1026  body->parts = body->email->body;
1027 
1028  mutt_file_fclose(&fp);
1029 
1030  return body;
1031 }
#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:69
#define WithCrypto
Definition: lib.h:123
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:903
struct Body * body
List of MIME parts.
Definition: email.h:91
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:84
#define SMIME_ENCRYPT
Definition: lib.h:109
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:85
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
#define PGP_ENCRYPT
Definition: lib.h:103
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:49
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
int mutt_copy_message(FILE *fp_out, struct Mailbox *m, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags, int wraplen)
Copy a message from a Mailbox.
Definition: copy.c:835
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:83
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:447
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:62
#define mutt_b2s(buf)
Definition: buffer.h:41
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:98
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:552
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:97
#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:610
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: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:72
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:1111
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 1040 of file sendlib.c.

1041 {
1042  FILE *fp = NULL, *fp_err = NULL;
1043  char *buf = NULL;
1044  size_t buflen;
1045  pid_t pid;
1046  struct Buffer *cmd = mutt_buffer_pool_get();
1047 
1048  const char *c_mime_type_query_command =
1049  cs_subset_string(sub, "mime_type_query_command");
1050 
1051  mutt_buffer_file_expand_fmt_quote(cmd, c_mime_type_query_command, att->filename);
1052 
1053  pid = filter_create(mutt_b2s(cmd), NULL, &fp, &fp_err);
1054  if (pid < 0)
1055  {
1056  mutt_error(_("Error running \"%s\""), mutt_b2s(cmd));
1058  return;
1059  }
1061 
1062  buf = mutt_file_read_line(buf, &buflen, fp, NULL, 0);
1063  if (buf)
1064  {
1065  if (strchr(buf, '/'))
1066  mutt_parse_content_type(buf, att);
1067  FREE(&buf);
1068  }
1069 
1070  mutt_file_fclose(&fp);
1071  mutt_file_fclose(&fp_err);
1072  filter_wait(pid);
1073 }
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:241
void mutt_parse_content_type(const char *s, struct Body *ct)
Parse a content type.
Definition: parse.c:425
#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:1432
#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 1082 of file sendlib.c.

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

1142 {
1143  char *tmp = NULL;
1144  char *p = NULL;
1145  int i;
1146 
1147  const char *c_send_charset = cs_subset_string(sub, "send_charset");
1148 
1149  struct ListNode *np = NULL;
1150  STAILQ_FOREACH(np, h, entries)
1151  {
1152  p = strchr(np->data, ':');
1153  if (!p)
1154  continue;
1155 
1156  i = p - np->data;
1157  p = mutt_str_skip_email_wsp(p + 1);
1158  tmp = mutt_str_dup(p);
1159 
1160  if (!tmp)
1161  continue;
1162 
1163  rfc2047_encode(&tmp, NULL, i + 2, c_send_charset);
1164  mutt_mem_realloc(&np->data, i + 2 + mutt_str_len(tmp) + 1);
1165 
1166  sprintf(np->data + i + 2, "%s", tmp);
1167 
1168  FREE(&tmp);
1169  }
1170 }
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:241
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:743
#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:631
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 1181 of file sendlib.c.

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

1211 {
1212  char buf[128];
1213  char rndid[MUTT_RANDTAG_LEN + 1];
1214 
1215  mutt_rand_base32(rndid, sizeof(rndid) - 1);
1216  rndid[MUTT_RANDTAG_LEN] = 0;
1217  const char *fqdn = mutt_fqdn(false, sub);
1218  if (!fqdn)
1219  fqdn = NONULL(ShortHostname);
1220 
1221  struct tm tm = mutt_date_gmtime(MUTT_DATE_NOW);
1222  snprintf(buf, sizeof(buf), "<%d%02d%02d%02d%02d%02d.%s@%s>", tm.tm_year + 1900,
1223  tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, rndid, fqdn);
1224  return mutt_str_dup(buf);
1225 }
#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:661
#define MUTT_RANDTAG_LEN
Definition: sendlib.h:35
WHERE char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:50
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:1181
void mutt_rand_base32(char *buf, size_t buflen)
Fill a buffer with a base32-encoded random string.
Definition: random.c:102
+ 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 1237 of file sendlib.c.

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

1277 {
1278  struct ListNode *item = NULL;
1279  STAILQ_FOREACH(item, &env->userhdrs, entries)
1280  {
1281  rfc2047_decode(&item->data);
1282  }
1283 
1285 
1286  /* back conversions */
1288 }
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:1468
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 1301 of file sendlib.c.

1304 {
1305  if (!e)
1306  return -1;
1307 
1308  int rc = 0;
1309 
1310  struct Buffer *tempfile = mutt_buffer_pool_get();
1311  mutt_buffer_mktemp(tempfile);
1312  FILE *fp_tmp = mutt_file_fopen(mutt_b2s(tempfile), "w");
1313  if (fp_tmp)
1314  {
1316 
1317  const bool c_bounce_delivered = cs_subset_bool(sub, "bounce_delivered");
1318  if (!c_bounce_delivered)
1319  chflags |= CH_WEED_DELIVERED;
1320 
1321  fseeko(fp, e->offset, SEEK_SET);
1322  fprintf(fp_tmp, "Resent-From: %s\n", resent_from);
1323 
1324  struct Buffer *date = mutt_buffer_pool_get();
1325  mutt_date_make_date(date);
1326  fprintf(fp_tmp, "Resent-Date: %s\n", mutt_b2s(date));
1327  mutt_buffer_pool_release(&date);
1328 
1329  char *msgid_str = gen_msgid(sub);
1330  fprintf(fp_tmp, "Resent-Message-ID: %s\n", msgid_str);
1331  FREE(&msgid_str);
1332  fputs("Resent-To: ", fp_tmp);
1333  mutt_addrlist_write_file(to, fp_tmp, 11, false);
1334  mutt_copy_header(fp, e, fp_tmp, chflags, NULL, 0);
1335  fputc('\n', fp_tmp);
1336  mutt_file_copy_bytes(fp, fp_tmp, e->body->length);
1337  if (mutt_file_fclose(&fp_tmp) != 0)
1338  {
1339  mutt_perror(mutt_b2s(tempfile));
1340  unlink(mutt_b2s(tempfile));
1341  return -1;
1342  }
1343 #ifdef USE_SMTP
1344  const char *c_smtp_url = cs_subset_string(sub, "smtp_url");
1345  if (c_smtp_url)
1346  {
1347  rc = mutt_smtp_send(env_from, to, NULL, NULL, mutt_b2s(tempfile),
1348  (e->body->encoding == ENC_8BIT), sub);
1349  }
1350  else
1351 #endif
1352  {
1353  rc = mutt_invoke_sendmail(env_from, to, NULL, NULL, mutt_b2s(tempfile),
1354  (e->body->encoding == ENC_8BIT), sub);
1355  }
1356  }
1357 
1358  mutt_buffer_pool_release(&tempfile);
1359  return rc;
1360 }
#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:69
void mutt_date_make_date(struct Buffer *buf)
Write a date in RFC822 format to a buffer.
Definition: date.c:377
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
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
8-bit text
Definition: mime.h:50
#define CH_WEED_DELIVERED
Weed eventual Delivered-To headers.
Definition: copy.h:64
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:1210
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:241
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:880
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:84
#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:405
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:286
#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
+ 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 1371 of file sendlib.c.

1373 {
1374  if (!fp || !e || !to || TAILQ_EMPTY(to))
1375  return -1;
1376 
1377  const char *fqdn = mutt_fqdn(true, sub);
1378  char resent_from[256];
1379  char *err = NULL;
1380 
1381  resent_from[0] = '\0';
1382  struct Address *from = mutt_default_from(sub);
1383  struct AddressList from_list = TAILQ_HEAD_INITIALIZER(from_list);
1384  mutt_addrlist_append(&from_list, from);
1385 
1386  /* mutt_default_from() does not use $realname if the real name is not set
1387  * in $from, so we add it here. The reason it is not added in
1388  * mutt_default_from() is that during normal sending, we execute
1389  * send-hooks and set the realname last so that it can be changed based
1390  * upon message criteria. */
1391  if (!from->personal)
1392  {
1393  const char *c_realname = cs_subset_string(sub, "realname");
1394  from->personal = mutt_str_dup(c_realname);
1395  }
1396 
1397  mutt_addrlist_qualify(&from_list, fqdn);
1398 
1399  rfc2047_encode_addrlist(&from_list, "Resent-From");
1400  if (mutt_addrlist_to_intl(&from_list, &err))
1401  {
1402  mutt_error(_("Bad IDN %s while preparing resent-from"), err);
1403  FREE(&err);
1404  mutt_addrlist_clear(&from_list);
1405  return -1;
1406  }
1407  mutt_addrlist_write(&from_list, resent_from, sizeof(resent_from), false);
1408 
1409 #ifdef USE_NNTP
1410  OptNewsSend = false;
1411 #endif
1412 
1413  /* prepare recipient list. idna conversion appears to happen before this
1414  * function is called, since the user receives confirmation of the address
1415  * list being bounced to. */
1416  struct AddressList resent_to = TAILQ_HEAD_INITIALIZER(resent_to);
1417  mutt_addrlist_copy(&resent_to, to, false);
1418  rfc2047_encode_addrlist(&resent_to, "Resent-To");
1419  int rc = bounce_message(fp, e, &resent_to, resent_from, &from_list, sub);
1420  mutt_addrlist_clear(&resent_to);
1421  mutt_addrlist_clear(&from_list);
1422 
1423  return rc;
1424 }
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1468
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: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:1328
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:241
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:1181
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1304
#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:1301
#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:1150
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1488
+ 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 1431 of file sendlib.c.

1432 {
1433  for (; b; b = b->next)
1434  {
1435  if ((b->type == TYPE_MESSAGE) || (b->type == TYPE_MULTIPART))
1436  set_noconv_flags(b->parts, flag);
1437  else if ((b->type == TYPE_TEXT) && b->noconv)
1438  {
1439  if (flag)
1440  mutt_param_set(&b->parameter, "x-mutt-noconv", "yes");
1441  else
1442  mutt_param_delete(&b->parameter, "x-mutt-noconv");
1443  }
1444  }
1445 }
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:1431
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 1459 of file sendlib.c.

1461 {
1462  char fcc_tok[PATH_MAX];
1463  char fcc_expanded[PATH_MAX];
1464 
1465  mutt_str_copy(fcc_tok, path, sizeof(fcc_tok));
1466 
1467  char *tok = strtok(fcc_tok, ",");
1468  if (!tok)
1469  return -1;
1470 
1471  mutt_debug(LL_DEBUG1, "Fcc: initial mailbox = '%s'\n", tok);
1472  /* mutt_expand_path already called above for the first token */
1473  int status = mutt_write_fcc(tok, e, msgid, post, fcc, finalpath, sub);
1474  if (status != 0)
1475  return status;
1476 
1477  while ((tok = strtok(NULL, ",")))
1478  {
1479  if (*tok == '\0')
1480  continue;
1481 
1482  /* Only call mutt_expand_path if tok has some data */
1483  mutt_debug(LL_DEBUG1, "Fcc: additional mailbox token = '%s'\n", tok);
1484  mutt_str_copy(fcc_expanded, tok, sizeof(fcc_expanded));
1485  mutt_expand_path(fcc_expanded, sizeof(fcc_expanded));
1486  mutt_debug(LL_DEBUG1, " Additional mailbox expanded = '%s'\n", fcc_expanded);
1487  status = mutt_write_fcc(fcc_expanded, e, msgid, post, fcc, finalpath, sub);
1488  if (status != 0)
1489  return status;
1490  }
1491 
1492  return 0;
1493 }
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:1507
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:716
#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 1507 of file sendlib.c.

1509 {
1510  struct Message *msg = NULL;
1511  struct Buffer *tempfile = NULL;
1512  FILE *fp_tmp = NULL;
1513  int rc = -1;
1514  bool need_mailbox_cleanup = false;
1515  struct stat st;
1516  MsgOpenFlags onm_flags;
1517 
1518  if (post)
1519  set_noconv_flags(e->body, true);
1520 
1521 #ifdef RECORD_FOLDER_HOOK
1522  mutt_folder_hook(path, NULL);
1523 #endif
1524  struct Mailbox *m_fcc = mx_path_resolve(path);
1525  bool old_append = m_fcc->append;
1526  struct Context *ctx_fcc = mx_mbox_open(m_fcc, MUTT_APPEND | MUTT_QUIET);
1527  if (!ctx_fcc)
1528  {
1529  mutt_debug(LL_DEBUG1, "unable to open mailbox %s in append-mode, aborting\n", path);
1530  mailbox_free(&m_fcc);
1531  goto done;
1532  }
1533 
1534  /* We need to add a Content-Length field to avoid problems where a line in
1535  * the message body begins with "From " */
1536  if ((ctx_fcc->mailbox->type == MUTT_MMDF) || (ctx_fcc->mailbox->type == MUTT_MBOX))
1537  {
1538  tempfile = mutt_buffer_pool_get();
1539  mutt_buffer_mktemp(tempfile);
1540  fp_tmp = mutt_file_fopen(mutt_b2s(tempfile), "w+");
1541  if (!fp_tmp)
1542  {
1543  mutt_perror(mutt_b2s(tempfile));
1544  mx_mbox_close(&ctx_fcc);
1545  goto done;
1546  }
1547  /* remember new mail status before appending message */
1548  need_mailbox_cleanup = true;
1549  stat(path, &st);
1550  }
1551 
1552  e->read = !post; /* make sure to put it in the 'cur' directory (maildir) */
1553  onm_flags = MUTT_ADD_FROM;
1554  if (post)
1555  onm_flags |= MUTT_SET_DRAFT;
1556  msg = mx_msg_open_new(ctx_fcc->mailbox, e, onm_flags);
1557  if (!msg)
1558  {
1559  mutt_file_fclose(&fp_tmp);
1560  mx_mbox_close(&ctx_fcc);
1561  goto done;
1562  }
1563 
1564  const bool c_crypt_protected_headers_read =
1565  cs_subset_bool(sub, "crypt_protected_headers_read");
1566 
1567  /* post == 1 => postpone message.
1568  * post == 0 => Normal mode. */
1570  msg->fp, e->env, e->body,
1572  c_crypt_protected_headers_read && mutt_should_hide_protected_subject(e), sub);
1573 
1574  /* (postponement) if this was a reply of some sort, <msgid> contains the
1575  * Message-ID: of message replied to. Save it using a special X-Mutt-
1576  * header so it can be picked up if the message is recalled at a later
1577  * point in time. This will allow the message to be marked as replied if
1578  * the same mailbox is still open. */
1579  if (post && msgid)
1580  fprintf(msg->fp, "X-Mutt-References: %s\n", msgid);
1581 
1582  /* (postponement) save the Fcc: using a special X-Mutt- header so that
1583  * it can be picked up when the message is recalled */
1584  if (post && fcc)
1585  fprintf(msg->fp, "X-Mutt-Fcc: %s\n", fcc);
1586 
1587  if ((ctx_fcc->mailbox->type == MUTT_MMDF) || (ctx_fcc->mailbox->type == MUTT_MBOX))
1588  fprintf(msg->fp, "Status: RO\n");
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->body, 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->body, 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->body, 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:53
The "current" mailbox.
Definition: context.h:38
#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:69
#define WithCrypto
Definition: lib.h:123
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
struct Body * body
List of MIME parts.
Definition: email.h:91
int mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:630
void mutt_mailbox_cleanup(const char *path, struct stat *st)
Restore the timestamp of a mailbox.
Definition: mutt_mailbox.c:354
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:85
bool mutt_should_hide_protected_subject(struct Email *e)
Should NeoMutt hide the protected subject?
Definition: crypt.c:1073
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
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:303
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:94
#define MUTT_SET_DRAFT
set the message draft flag
Definition: mx.h:66
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:92
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1204
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 Message * mx_msg_open_new(struct Mailbox *m, const struct Email *e, MsgOpenFlags flags)
Open a new message.
Definition: mx.c:1072
struct Mailbox * mailbox
Definition: context.h:50
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:63
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 mutt_b2s(buf)
Definition: buffer.h:41
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:98
struct ListHead chain
Mixmaster chain.
Definition: email.h:102
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:97
A local copy of an email.
Definition: mx.h:82
A mailbox.
Definition: mailbox.h:81
#define SEC_AUTOCRYPT_OVERRIDE
(Autocrypt) Indicates manual set/unset of encryption
Definition: lib.h:95
&#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:241
bool append
Mailbox is opened in append mode.
Definition: mailbox.h:113
#define MUTT_QUIET
Do not print any messages.
Definition: mx.h:55
#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:63
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:93
&#39;mbox&#39; Mailbox type
Definition: mailbox.h:48
#define SEC_SIGN
Email is signed.
Definition: lib.h:86
char * committed_path
the final path generated by mx_msg_commit()
Definition: mx.h:86
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:1183
FILE * fp
pointer to the message data
Definition: mx.h:84
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1681
static void set_noconv_flags(struct Body *b, bool flag)
Set/reset the "x-mutt-noconv" flag.
Definition: sendlib.c:1431
#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:65
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: