NeoMutt  2020-03-20-65-g141838
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 <fcntl.h>
#include <iconv.h>
#include <inttypes.h>
#include <limits.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include "mutt/lib.h"
#include "address/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "sendlib.h"
#include "context.h"
#include "copy.h"
#include "format_flags.h"
#include "globals.h"
#include "handler.h"
#include "mutt_mailbox.h"
#include "mutt_parse.h"
#include "muttlib.h"
#include "mx.h"
#include "options.h"
#include "pager.h"
#include "send.h"
#include "smtp.h"
#include "state.h"
#include "ncrypt/lib.h"
#include "nntp/lib.h"
#include "autocrypt/lib.h"
+ Include dependency graph for sendlib.c:

Go to the source code of this file.

Data Structures

struct  B64Context
 Cursor for the Base64 conversion. More...
 
struct  ContentState
 Info about the body of an email. More...
 
struct  UserHdrsOverride
 

Macros

#define EX_OK   0
 
#define MUTT_RANDTAG_LEN   16
 

Enumerations

enum  UserHdrsOverrideIdx { USERHDRS_OVERRIDE_CONTENT_TYPE, USERHDRS_OVERRIDE_USER_AGENT }
 

Functions

static void encode_quoted (struct FgetConv *fc, FILE *fp_out, bool istext)
 Encode text as quoted printable. More...
 
static int b64_init (struct B64Context *bctx)
 Set up the base64 conversion. More...
 
static void b64_flush (struct B64Context *bctx, FILE *fp_out)
 Save the bytes to the file. More...
 
static void b64_putc (struct B64Context *bctx, char c, FILE *fp_out)
 Base64-encode one character. More...
 
static void encode_base64 (struct FgetConv *fc, FILE *fp_out, int istext)
 Base64-encode some data. More...
 
static void encode_8bit (struct FgetConv *fc, FILE *fp_out)
 Write the data as raw 8-bit data. More...
 
int mutt_write_mime_header (struct Body *a, FILE *fp)
 Create a MIME header. More...
 
static bool write_as_text_part (struct Body *b)
 Should the Body be written as a text MIME part. More...
 
int mutt_write_mime_body (struct Body *a, FILE *fp)
 Write a MIME part. More...
 
void mutt_generate_boundary (struct ParameterList *pl)
 Create a unique boundary id for a MIME part. More...
 
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)
 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)
 Convert MIME parts to 7-bit. More...
 
void mutt_message_to_7bit (struct Body *a, FILE *fp)
 Convert an email's MIME parts to 7-bit. More...
 
static void set_encoding (struct Body *b, struct Content *info)
 determine which Content-Transfer-Encoding to use More...
 
void mutt_stamp_attachment (struct Body *a)
 Timestamp an Attachment. More...
 
char * mutt_body_get_charset (struct Body *b, char *buf, size_t buflen)
 Get a body's character set. More...
 
void mutt_update_encoding (struct Body *a)
 Update the encoding type. More...
 
struct Bodymutt_make_message_attach (struct Mailbox *m, struct Email *e, bool attach_msg)
 Create a message attachment. More...
 
static void run_mime_type_query (struct Body *att)
 Run an external command to determine the MIME type. More...
 
struct Bodymutt_make_file_attach (const char *path)
 Create a file attachment. More...
 
static int get_toplevel_encoding (struct Body *a)
 Find the most restrictive encoding type. More...
 
static bool check_boundary (const char *boundary, struct Body *b)
 check for duplicate boundary More...
 
struct Bodymutt_make_multipart (struct Body *b)
 Create a multipart email. More...
 
struct Bodymutt_remove_multipart (struct Body *b)
 Extract the multipart body if it exists. More...
 
void mutt_write_addrlist (struct AddressList *al, FILE *fp, int linelen, bool display)
 Wrapper for mutt_write_address() More...
 
void mutt_write_references (const struct ListHead *r, FILE *fp, size_t trim)
 Add the message references to a list. More...
 
static int print_val (FILE *fp, const char *pfx, const char *value, CopyHeaderFlags chflags, size_t col)
 Add pieces to an email header, wrapping where necessary. More...
 
static int fold_one_header (FILE *fp, const char *tag, const char *value, size_t vlen, const char *pfx, int wraplen, CopyHeaderFlags chflags)
 Fold one header line. More...
 
static char * unfold_header (char *s)
 Unfold a wrapped email header. More...
 
static int write_one_header (FILE *fp, int pfxw, int max, int wraplen, const char *pfx, const char *start, const char *end, CopyHeaderFlags chflags)
 Write out one header line. More...
 
int mutt_write_one_header (FILE *fp, const char *tag, const char *value, const char *pfx, int wraplen, CopyHeaderFlags chflags)
 Write one header line to a file. More...
 
static int userhdrs_override_cmp (const void *a, const void *b)
 Compare a user-defined header with an element of the userhdrs_override_headers list. More...
 
static struct UserHdrsOverride write_userhdrs (FILE *fp, const struct ListHead *userhdrs, bool privacy)
 Write user-defined headers and keep track of the interesting ones. More...
 
int mutt_rfc822_write_header (FILE *fp, struct Envelope *env, struct Body *attach, enum MuttWriteHeaderMode mode, bool privacy, bool hide_protected_subject)
 Write out one RFC822 header line. More...
 
static void encode_headers (struct ListHead *h)
 RFC2047-encode a list of headers. More...
 
const char * mutt_fqdn (bool may_hide_host)
 Get the Fully-Qualified Domain Name. More...
 
static char * gen_msgid (void)
 Generate a unique Message ID. More...
 
static void alarm_handler (int sig)
 Async notification of an alarm signal. More...
 
static int send_msg (const char *path, char **args, const char *msg, char **tempfile)
 invoke sendmail in a subshell More...
 
static char ** add_args_one (char **args, size_t *argslen, size_t *argsmax, struct Address *addr)
 Add an Address to a dynamic array. More...
 
static char ** add_args (char **args, size_t *argslen, size_t *argsmax, struct AddressList *al)
 Add a list of Addresses to a dynamic array. More...
 
static char ** add_option (char **args, size_t *argslen, size_t *argsmax, char *s)
 Add a string to a dynamic array. More...
 
int mutt_invoke_sendmail (struct AddressList *from, struct AddressList *to, struct AddressList *cc, struct AddressList *bcc, const char *msg, int eightbit)
 Run sendmail. More...
 
void mutt_prepare_envelope (struct Envelope *env, bool final)
 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)
 Bounce an email message. More...
 
int mutt_bounce_message (FILE *fp, struct Email *e, struct AddressList *to)
 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)
 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)
 Write email to FCC mailbox. More...
 

Variables

bool C_Allow8bit
 Config: Allow 8-bit messages, don't use quoted-printable or base64. More...
 
char * C_AttachCharset
 Config: When attaching files, use one of these character sets. More...
 
bool C_BounceDelivered
 Config: Add 'Delivered-To' to bounced messages. More...
 
bool C_EncodeFrom
 Config: Encode 'From ' as 'quote-printable' at the beginning of lines. More...
 
bool C_ForwardDecrypt
 Config: Decrypt the message when forwarding it. More...
 
bool C_HiddenHost
 Config: Don't use the hostname, just the domain, when generating the message id. More...
 
char * C_Inews
 Config: (nntp) External command to post news articles. More...
 
bool C_MimeForwardDecode
 Config: Decode the forwarded message before attaching it. More...
 
bool C_MimeSubject
 Config: (nntp) Encode the article subject in base64. More...
 
char * C_MimeTypeQueryCommand
 Config: External command to determine the MIME type of an attachment. More...
 
bool C_MimeTypeQueryFirst
 Config: Run the C_MimeTypeQueryCommand before the mime.types lookup. More...
 
char * C_Sendmail
 Config: External command to send email. More...
 
short C_SendmailWait
 Config: Time to wait for sendmail to finish. More...
 
bool C_Use8bitmime
 Config: Use 8-bit messages and ESMTP to send messages. More...
 
bool C_UseEnvelopeFrom
 Config: Set the envelope sender of the message. More...
 
bool C_UserAgent
 Config: Add a 'User-Agent' head to outgoing mail. More...
 
short C_WrapHeaders
 Config: Width to wrap headers in outgoing messages. More...
 
static const char *const userhdrs_override_headers []
 The next array/enum pair is used to to keep track of user headers that override pre-defined headers NeoMutt would emit. 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.

Macro Definition Documentation

◆ EX_OK

#define EX_OK   0

Definition at line 73 of file sendlib.c.

◆ MUTT_RANDTAG_LEN

#define MUTT_RANDTAG_LEN   16

Definition at line 98 of file sendlib.c.

Enumeration Type Documentation

◆ UserHdrsOverrideIdx

Enumerator
USERHDRS_OVERRIDE_CONTENT_TYPE 
USERHDRS_OVERRIDE_USER_AGENT 

Definition at line 132 of file sendlib.c.

Function Documentation

◆ encode_quoted()

static void encode_quoted ( struct FgetConv fc,
FILE *  fp_out,
bool  istext 
)
static

Encode text as quoted printable.

Parameters
fcCursor for converting a file's encoding
fp_outFile to store the result
istextIs the input text?

Definition at line 149 of file sendlib.c.

150 {
151  int c, linelen = 0;
152  char line[77], savechar;
153 
154  while ((c = mutt_ch_fgetconv(fc)) != EOF)
155  {
156  /* Wrap the line if needed. */
157  if ((linelen == 76) && ((istext && (c != '\n')) || !istext))
158  {
159  /* If the last character is "quoted", then be sure to move all three
160  * characters to the next line. Otherwise, just move the last
161  * character... */
162  if (line[linelen - 3] == '=')
163  {
164  line[linelen - 3] = 0;
165  fputs(line, fp_out);
166  fputs("=\n", fp_out);
167  line[linelen] = 0;
168  line[0] = '=';
169  line[1] = line[linelen - 2];
170  line[2] = line[linelen - 1];
171  linelen = 3;
172  }
173  else
174  {
175  savechar = line[linelen - 1];
176  line[linelen - 1] = '=';
177  line[linelen] = 0;
178  fputs(line, fp_out);
179  fputc('\n', fp_out);
180  line[0] = savechar;
181  linelen = 1;
182  }
183  }
184 
185  /* Escape lines that begin with/only contain "the message separator". */
186  if ((linelen == 4) && mutt_str_startswith(line, "From", CASE_MATCH))
187  {
188  mutt_str_strfcpy(line, "=46rom", sizeof(line));
189  linelen = 6;
190  }
191  else if ((linelen == 4) && mutt_str_startswith(line, "from", CASE_MATCH))
192  {
193  mutt_str_strfcpy(line, "=66rom", sizeof(line));
194  linelen = 6;
195  }
196  else if ((linelen == 1) && (line[0] == '.'))
197  {
198  mutt_str_strfcpy(line, "=2E", sizeof(line));
199  linelen = 3;
200  }
201 
202  if ((c == '\n') && istext)
203  {
204  /* Check to make sure there is no trailing space on this line. */
205  if ((linelen > 0) && ((line[linelen - 1] == ' ') || (line[linelen - 1] == '\t')))
206  {
207  if (linelen < 74)
208  {
209  sprintf(line + linelen - 1, "=%2.2X", (unsigned char) line[linelen - 1]);
210  fputs(line, fp_out);
211  }
212  else
213  {
214  int savechar2 = line[linelen - 1];
215 
216  line[linelen - 1] = '=';
217  line[linelen] = 0;
218  fputs(line, fp_out);
219  fprintf(fp_out, "\n=%2.2X", (unsigned char) savechar2);
220  }
221  }
222  else
223  {
224  line[linelen] = 0;
225  fputs(line, fp_out);
226  }
227  fputc('\n', fp_out);
228  linelen = 0;
229  }
230  else if ((c != 9) && ((c < 32) || (c > 126) || (c == '=')))
231  {
232  /* Check to make sure there is enough room for the quoted character.
233  * If not, wrap to the next line. */
234  if (linelen > 73)
235  {
236  line[linelen++] = '=';
237  line[linelen] = 0;
238  fputs(line, fp_out);
239  fputc('\n', fp_out);
240  linelen = 0;
241  }
242  sprintf(line + linelen, "=%2.2X", (unsigned char) c);
243  linelen += 3;
244  }
245  else
246  {
247  /* Don't worry about wrapping the line here. That will happen during
248  * the next iteration when I'll also know what the next character is. */
249  line[linelen++] = c;
250  }
251  }
252 
253  /* Take care of anything left in the buffer */
254  if (linelen > 0)
255  {
256  if ((line[linelen - 1] == ' ') || (line[linelen - 1] == '\t'))
257  {
258  /* take care of trailing whitespace */
259  if (linelen < 74)
260  sprintf(line + linelen - 1, "=%2.2X", (unsigned char) line[linelen - 1]);
261  else
262  {
263  savechar = line[linelen - 1];
264  line[linelen - 1] = '=';
265  line[linelen] = 0;
266  fputs(line, fp_out);
267  fputc('\n', fp_out);
268  sprintf(line, "=%2.2X", (unsigned char) savechar);
269  }
270  }
271  else
272  line[linelen] = 0;
273  fputs(line, fp_out);
274  }
275 }
int mutt_ch_fgetconv(struct FgetConv *fc)
Convert a file&#39;s character set.
Definition: charset.c:902
Match case when comparing strings.
Definition: string2.h:67
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:773
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
int const char int line
Definition: acutest.h:602
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ b64_init()

static int b64_init ( struct B64Context bctx)
static

Set up the base64 conversion.

Parameters
bctxCursor for the base64 conversion
Return values
0Always

Definition at line 282 of file sendlib.c.

283 {
284  memset(bctx->buffer, '\0', sizeof(bctx->buffer));
285  bctx->size = 0;
286  bctx->linelen = 0;
287 
288  return 0;
289 }
char buffer[3]
Definition: sendlib.c:105
short size
Definition: sendlib.c:106
short linelen
Definition: sendlib.c:107
+ Here is the caller graph for this function:

◆ b64_flush()

static void b64_flush ( struct B64Context bctx,
FILE *  fp_out 
)
static

Save the bytes to the file.

Parameters
bctxCursor for the base64 conversion
fp_outFile to save the output

Definition at line 296 of file sendlib.c.

297 {
298  /* for some reasons, mutt_b64_encode expects the
299  * output buffer to be larger than 10B */
300  char encoded[11];
301  size_t ret;
302 
303  if (bctx->size == 0)
304  return;
305 
306  if (bctx->linelen >= 72)
307  {
308  fputc('\n', fp_out);
309  bctx->linelen = 0;
310  }
311 
312  /* ret should always be equal to 4 here, because bctx->size
313  * is a value between 1 and 3 (included), but let's not hardcode it
314  * and prefer the return value of the function */
315  ret = mutt_b64_encode(bctx->buffer, bctx->size, encoded, sizeof(encoded));
316  for (size_t i = 0; i < ret; i++)
317  {
318  fputc(encoded[i], fp_out);
319  bctx->linelen++;
320  }
321 
322  bctx->size = 0;
323 }
size_t mutt_b64_encode(const char *in, size_t inlen, char *out, size_t outlen)
Convert raw bytes to null-terminated base64 string.
Definition: base64.c:88
char buffer[3]
Definition: sendlib.c:105
static const char encoded[]
short size
Definition: sendlib.c:106
short linelen
Definition: sendlib.c:107
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ b64_putc()

static void b64_putc ( struct B64Context bctx,
char  c,
FILE *  fp_out 
)
static

Base64-encode one character.

Parameters
bctxCursor for the base64 conversion
cCharacter to encode
fp_outFile to save the output

Definition at line 331 of file sendlib.c.

332 {
333  if (bctx->size == 3)
334  b64_flush(bctx, fp_out);
335 
336  bctx->buffer[bctx->size++] = c;
337 }
char buffer[3]
Definition: sendlib.c:105
short size
Definition: sendlib.c:106
static void b64_flush(struct B64Context *bctx, FILE *fp_out)
Save the bytes to the file.
Definition: sendlib.c:296
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ encode_base64()

static void encode_base64 ( struct FgetConv fc,
FILE *  fp_out,
int  istext 
)
static

Base64-encode some data.

Parameters
fcCursor for converting a file's encoding
fp_outFile to store the result
istextIs the input text?

Definition at line 345 of file sendlib.c.

346 {
347  struct B64Context bctx;
348  int ch, ch1 = EOF;
349 
350  b64_init(&bctx);
351 
352  while ((ch = mutt_ch_fgetconv(fc)) != EOF)
353  {
354  if (SigInt == 1)
355  {
356  SigInt = 0;
357  return;
358  }
359  if (istext && (ch == '\n') && (ch1 != '\r'))
360  b64_putc(&bctx, '\r', fp_out);
361  b64_putc(&bctx, ch, fp_out);
362  ch1 = ch;
363  }
364  b64_flush(&bctx, fp_out);
365  fputc('\n', fp_out);
366 }
static void b64_putc(struct B64Context *bctx, char c, FILE *fp_out)
Base64-encode one character.
Definition: sendlib.c:331
int mutt_ch_fgetconv(struct FgetConv *fc)
Convert a file&#39;s character set.
Definition: charset.c:902
WHERE SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: globals.h:79
static int b64_init(struct B64Context *bctx)
Set up the base64 conversion.
Definition: sendlib.c:282
static void b64_flush(struct B64Context *bctx, FILE *fp_out)
Save the bytes to the file.
Definition: sendlib.c:296
Cursor for the Base64 conversion.
Definition: sendlib.c:103
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ encode_8bit()

static void encode_8bit ( struct FgetConv fc,
FILE *  fp_out 
)
static

Write the data as raw 8-bit data.

Parameters
fcCursor for converting a file's encoding
fp_outFile to store the result

Definition at line 373 of file sendlib.c.

374 {
375  int ch;
376 
377  while ((ch = mutt_ch_fgetconv(fc)) != EOF)
378  {
379  if (SigInt == 1)
380  {
381  SigInt = 0;
382  return;
383  }
384  fputc(ch, fp_out);
385  }
386 }
int mutt_ch_fgetconv(struct FgetConv *fc)
Convert a file&#39;s character set.
Definition: charset.c:902
WHERE SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: globals.h:79
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_write_mime_header()

int mutt_write_mime_header ( struct Body a,
FILE *  fp 
)

Create a MIME header.

Parameters
aBody part
fpFile to write to
Return values
0Success
-1Failure

Definition at line 395 of file sendlib.c.

396 {
397  if (!a || !fp)
398  return -1;
399 
400  int len;
401  int tmplen;
402  char buf[256] = { 0 };
403 
404  fprintf(fp, "Content-Type: %s/%s", TYPE(a), a->subtype);
405 
406  if (!TAILQ_EMPTY(&a->parameter))
407  {
408  len = 25 + mutt_str_strlen(a->subtype); /* approximate len. of content-type */
409 
410  struct Parameter *np = NULL;
411  TAILQ_FOREACH(np, &a->parameter, entries)
412  {
413  if (!np->attribute || !np->value)
414  continue;
415 
416  struct ParameterList pl_conts = rfc2231_encode_string(np->attribute, np->value);
417  struct Parameter *cont = NULL;
418  TAILQ_FOREACH(cont, &pl_conts, entries)
419  {
420  fputc(';', fp);
421 
422  buf[0] = 0;
423  mutt_addr_cat(buf, sizeof(buf), cont->value, MimeSpecials);
424 
425  /* Dirty hack to make messages readable by Outlook Express
426  * for the Mac: force quotes around the boundary parameter
427  * even when they aren't needed. */
428  if (!mutt_str_strcasecmp(cont->attribute, "boundary") &&
429  !mutt_str_strcmp(buf, cont->value))
430  snprintf(buf, sizeof(buf), "\"%s\"", cont->value);
431 
432  tmplen = mutt_str_strlen(buf) + mutt_str_strlen(cont->attribute) + 1;
433  if (len + tmplen + 2 > 76)
434  {
435  fputs("\n\t", fp);
436  len = tmplen + 1;
437  }
438  else
439  {
440  fputc(' ', fp);
441  len += tmplen + 1;
442  }
443 
444  fprintf(fp, "%s=%s", cont->attribute, buf);
445  }
446 
447  mutt_param_free(&pl_conts);
448  }
449  }
450 
451  fputc('\n', fp);
452 
453  if (a->language)
454  fprintf(fp, "Content-Language: %s\n", a->language);
455 
456  if (a->description)
457  fprintf(fp, "Content-Description: %s\n", a->description);
458 
459  if (a->disposition != DISP_NONE)
460  {
461  const char *dispstr[] = { "inline", "attachment", "form-data" };
462 
463  if (a->disposition < sizeof(dispstr) / sizeof(char *))
464  {
465  fprintf(fp, "Content-Disposition: %s", dispstr[a->disposition]);
466  len = 21 + mutt_str_strlen(dispstr[a->disposition]);
467 
468  if (a->use_disp && (a->disposition != DISP_INLINE))
469  {
470  char *fn = a->d_filename;
471  if (!fn)
472  fn = a->filename;
473 
474  if (fn)
475  {
476  /* Strip off the leading path... */
477  char *t = strrchr(fn, '/');
478  if (t)
479  t++;
480  else
481  t = fn;
482 
483  struct ParameterList pl_conts = rfc2231_encode_string("filename", t);
484  struct Parameter *cont = NULL;
485  TAILQ_FOREACH(cont, &pl_conts, entries)
486  {
487  fputc(';', fp);
488  buf[0] = 0;
489  mutt_addr_cat(buf, sizeof(buf), cont->value, MimeSpecials);
490 
491  tmplen = mutt_str_strlen(buf) + mutt_str_strlen(cont->attribute) + 1;
492  if (len + tmplen + 2 > 76)
493  {
494  fputs("\n\t", fp);
495  len = tmplen + 1;
496  }
497  else
498  {
499  fputc(' ', fp);
500  len += tmplen + 1;
501  }
502 
503  fprintf(fp, "%s=%s", cont->attribute, buf);
504  }
505 
506  mutt_param_free(&pl_conts);
507  }
508  }
509 
510  fputc('\n', fp);
511  }
512  else
513  {
514  mutt_debug(LL_DEBUG1, "ERROR: invalid content-disposition %d\n", a->disposition);
515  }
516  }
517 
518  if (a->encoding != ENC_7BIT)
519  fprintf(fp, "Content-Transfer-Encoding: %s\n", ENCODING(a->encoding));
520 
522 #ifdef USE_AUTOCRYPT
523  || C_Autocrypt
524 #endif
525  ) &&
526  a->mime_headers)
527  {
528  mutt_rfc822_write_header(fp, a->mime_headers, NULL, MUTT_WRITE_HEADER_MIME, false, false);
529  }
530 
531  /* Do NOT add the terminator here!!! */
532  return ferror(fp) ? -1 : 0;
533 }
char * attribute
Parameter name.
Definition: parameter.h:34
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
WHERE bool C_Autocrypt
Config: Enables the Autocrypt feature.
Definition: globals.h:200
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
7-bit text
Definition: mime.h:49
WHERE bool C_CryptProtectedHeadersWrite
Config: Generate protected header (Memory Hole) for signed and encrypted emails.
Definition: globals.h:272
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:689
unsigned int disposition
content-disposition
Definition: body.h:67
int mutt_rfc822_write_header(FILE *fp, struct Envelope *env, struct Body *attach, enum MuttWriteHeaderMode mode, bool privacy, bool hide_protected_subject)
Write out one RFC822 header line.
Definition: sendlib.c:2320
#define ENCODING(x)
Definition: mime.h:85
void mutt_param_free(struct ParameterList *pl)
Free a ParameterList.
Definition: parameter.c:61
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
char * subtype
content-type subtype
Definition: body.h:37
const char MimeSpecials[]
Characters that need special treatment in MIME.
Definition: mime.c:67
char * description
content-description
Definition: body.h:40
#define TYPE(body)
Definition: mime.h:83
char * value
Parameter value.
Definition: parameter.h:35
Log at debug level 1.
Definition: logging.h:40
No preferred disposition.
Definition: mime.h:65
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
struct ParameterList rfc2231_encode_string(const char *attribute, char *value)
Encode a string to be suitable for an RFC2231 header.
Definition: rfc2231.c:328
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:651
Attribute associated with a MIME part.
Definition: parameter.h:32
char * language
content-language (RFC8255)
Definition: body.h:38
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Write protected headers.
Definition: sendlib.h:64
#define TAILQ_EMPTY(head)
Definition: queue.h:714
Content is inline.
Definition: mime.h:62
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:638
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:672
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ write_as_text_part()

static bool write_as_text_part ( struct Body b)
static

Should the Body be written as a text MIME part.

Parameters
bEmail to examine
Return values
trueIf the Body should be written as text

Definition at line 540 of file sendlib.c.

541 {
542  return mutt_is_text_part(b) ||
544 }
#define WithCrypto
Definition: lib.h:163
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:565
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:137
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
Definition: muttlib.c:438
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_write_mime_body()

int mutt_write_mime_body ( struct Body a,
FILE *  fp 
)

Write a MIME part.

Parameters
aBody to use
fpFile to write to
Return values
0Success
-1Failure

Definition at line 553 of file sendlib.c.

554 {
555  FILE *fp_in = NULL;
556  struct FgetConv *fc = NULL;
557 
558  if (a->type == TYPE_MULTIPART)
559  {
560  /* First, find the boundary to use */
561  const char *p = mutt_param_get(&a->parameter, "boundary");
562  if (!p)
563  {
564  mutt_debug(LL_DEBUG1, "no boundary parameter found\n");
565  mutt_error(_("No boundary parameter found [report this error]"));
566  return -1;
567  }
568  char boundary[128];
569  mutt_str_strfcpy(boundary, p, sizeof(boundary));
570 
571  for (struct Body *t = a->parts; t; t = t->next)
572  {
573  fprintf(fp, "\n--%s\n", boundary);
574  if (mutt_write_mime_header(t, fp) == -1)
575  return -1;
576  fputc('\n', fp);
577  if (mutt_write_mime_body(t, fp) == -1)
578  return -1;
579  }
580  fprintf(fp, "\n--%s--\n", boundary);
581  return ferror(fp) ? -1 : 0;
582  }
583 
584  /* This is pretty gross, but it's the best solution for now... */
585  if (((WithCrypto & APPLICATION_PGP) != 0) && (a->type == TYPE_APPLICATION) &&
586  (mutt_str_strcmp(a->subtype, "pgp-encrypted") == 0) && !a->filename)
587  {
588  fputs("Version: 1\n", fp);
589  return 0;
590  }
591 
592  fp_in = fopen(a->filename, "r");
593  if (!fp_in)
594  {
595  mutt_debug(LL_DEBUG1, "%s no longer exists\n", a->filename);
596  mutt_error(_("%s no longer exists"), a->filename);
597  return -1;
598  }
599 
600  if ((a->type == TYPE_TEXT) && (!a->noconv))
601  {
602  char send_charset[128];
604  fp_in, a->charset,
605  mutt_body_get_charset(a, send_charset, sizeof(send_charset)), 0);
606  }
607  else
608  fc = mutt_ch_fgetconv_open(fp_in, 0, 0, 0);
609 
611  if (a->encoding == ENC_QUOTED_PRINTABLE)
613  else if (a->encoding == ENC_BASE64)
615  else if ((a->type == TYPE_TEXT) && (!a->noconv))
616  encode_8bit(fc, fp);
617  else
618  mutt_file_copy_stream(fp_in, fp);
620 
622  mutt_file_fclose(&fp_in);
623 
624  if (SigInt == 1)
625  {
626  SigInt = 0;
627  return -1;
628  }
629  return ferror(fp) ? -1 : 0;
630 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
#define WithCrypto
Definition: lib.h:163
WHERE SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: globals.h:79
static void encode_base64(struct FgetConv *fc, FILE *fp_out, int istext)
Base64-encode some data.
Definition: sendlib.c:345
bool noconv
Don&#39;t do character set conversion.
Definition: body.h:73
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:53
static bool write_as_text_part(struct Body *b)
Should the Body be written as a text MIME part.
Definition: sendlib.c:540
void mutt_sig_allow_interrupt(bool allow)
Allow/disallow Ctrl-C (SIGINT)
Definition: signal.c:238
The body of an email.
Definition: body.h:34
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
static void encode_quoted(struct FgetConv *fc, FILE *fp_out, bool istext)
Encode text as quoted printable.
Definition: sendlib.c:149
char * subtype
content-type subtype
Definition: body.h:37
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:137
FILE * fp
Definition: charset.h:43
Type: &#39;text/*&#39;.
Definition: mime.h:38
int mutt_write_mime_body(struct Body *a, FILE *fp)
Write a MIME part.
Definition: sendlib.c:553
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:773
char * charset
Send mode: charset of attached file as stored on disk.
Definition: body.h:49
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body&#39;s character set.
Definition: sendlib.c:1456
char * p
Definition: charset.h:47
static void encode_8bit(struct FgetConv *fc, FILE *fp_out)
Write the data as raw 8-bit data.
Definition: sendlib.c:373
unsigned int type
content-type primary type
Definition: body.h:65
void mutt_ch_fgetconv_close(struct FgetConv **fc)
Close an fgetconv handle.
Definition: charset.c:882
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
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
#define mutt_error(...)
Definition: logging.h:84
Quoted-printable text.
Definition: mime.h:51
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
int mutt_write_mime_header(struct Body *a, FILE *fp)
Create a MIME header.
Definition: sendlib.c:395
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct FgetConv * mutt_ch_fgetconv_open(FILE *fp, const char *from, const char *to, int flags)
Prepare a file for charset conversion.
Definition: charset.c:852
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
Cursor for converting a file&#39;s encoding.
Definition: charset.h:41
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:638
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_generate_boundary()

void mutt_generate_boundary ( struct ParameterList *  pl)

Create a unique boundary id for a MIME part.

Parameters
plMIME part

Definition at line 636 of file sendlib.c.

637 {
638  char rs[MUTT_RANDTAG_LEN + 1];
639 
640  mutt_rand_base32(rs, sizeof(rs) - 1);
641  rs[MUTT_RANDTAG_LEN] = 0;
642  mutt_param_set(pl, "boundary", rs);
643 }
#define MUTT_RANDTAG_LEN
Definition: sendlib.c:98
void mutt_rand_base32(void *buf, size_t buflen)
Fill a buffer with a base32-encoded random string.
Definition: muttlib.c:514
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:

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

654 {
655  bool from = s->from;
656  int whitespace = s->whitespace;
657  bool dot = s->dot;
658  int linelen = s->linelen;
659  bool was_cr = s->was_cr;
660 
661  if (!buf) /* This signals EOF */
662  {
663  if (was_cr)
664  info->binary = true;
665  if (linelen > info->linemax)
666  info->linemax = linelen;
667 
668  return;
669  }
670 
671  for (; buflen; buf++, buflen--)
672  {
673  char ch = *buf;
674 
675  if (was_cr)
676  {
677  was_cr = false;
678  if (ch == '\n')
679  {
680  if (whitespace)
681  info->space = true;
682  if (dot)
683  info->dot = true;
684  if (linelen > info->linemax)
685  info->linemax = linelen;
686  whitespace = 0;
687  dot = false;
688  linelen = 0;
689  continue;
690  }
691 
692  info->binary = true;
693  }
694 
695  linelen++;
696  if (ch == '\n')
697  {
698  info->crlf++;
699  if (whitespace)
700  info->space = true;
701  if (dot)
702  info->dot = true;
703  if (linelen > info->linemax)
704  info->linemax = linelen;
705  whitespace = 0;
706  linelen = 0;
707  dot = false;
708  }
709  else if (ch == '\r')
710  {
711  info->crlf++;
712  info->cr = true;
713  was_cr = true;
714  continue;
715  }
716  else if (ch & 0x80)
717  info->hibin++;
718  else if ((ch == '\t') || (ch == '\f'))
719  {
720  info->ascii++;
721  whitespace++;
722  }
723  else if (ch == 0)
724  {
725  info->nulbin++;
726  info->lobin++;
727  }
728  else if ((ch < 32) || (ch == 127))
729  info->lobin++;
730  else
731  {
732  if (linelen == 1)
733  {
734  if ((ch == 'F') || (ch == 'f'))
735  from = true;
736  else
737  from = false;
738  if (ch == '.')
739  dot = true;
740  else
741  dot = false;
742  }
743  else if (from)
744  {
745  if ((linelen == 2) && (ch != 'r'))
746  from = false;
747  else if ((linelen == 3) && (ch != 'o'))
748  from = false;
749  else if (linelen == 4)
750  {
751  if (ch == 'm')
752  info->from = true;
753  from = false;
754  }
755  }
756  if (ch == ' ')
757  whitespace++;
758  info->ascii++;
759  }
760 
761  if (linelen > 1)
762  dot = false;
763  if ((ch != ' ') && (ch != '\t'))
764  whitespace = 0;
765  }
766 
767  s->from = from;
768  s->whitespace = whitespace;
769  s->dot = dot;
770  s->linelen = linelen;
771  s->was_cr = was_cr;
772 }
int whitespace
Definition: sendlib.c:116
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:117
long hibin
8-bit characters
Definition: content.h:35
bool was_cr
Definition: sendlib.c:119
bool from
Definition: sendlib.c:115
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:118
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 799 of file sendlib.c.

801 {
802  char bufi[256], bufu[512], bufo[4 * sizeof(bufi)];
803  size_t ret;
804 
805  const iconv_t cd1 = mutt_ch_iconv_open("utf-8", fromcode, 0);
806  if (cd1 == (iconv_t)(-1))
807  return -1;
808 
809  iconv_t *cd = mutt_mem_calloc(ncodes, sizeof(iconv_t));
810  size_t *score = mutt_mem_calloc(ncodes, sizeof(size_t));
811  struct ContentState *states = mutt_mem_calloc(ncodes, sizeof(struct ContentState));
812  struct Content *infos = mutt_mem_calloc(ncodes, sizeof(struct Content));
813 
814  for (int i = 0; i < ncodes; i++)
815  {
816  if (mutt_str_strcasecmp(tocodes[i], "utf-8") != 0)
817  cd[i] = mutt_ch_iconv_open(tocodes[i], "utf-8", 0);
818  else
819  {
820  /* Special case for conversion to UTF-8 */
821  cd[i] = (iconv_t)(-1);
822  score[i] = (size_t)(-1);
823  }
824  }
825 
826  rewind(fp);
827  size_t ibl = 0;
828  while (true)
829  {
830  /* Try to fill input buffer */
831  size_t n = fread(bufi + ibl, 1, sizeof(bufi) - ibl, fp);
832  ibl += n;
833 
834  /* Convert to UTF-8 */
835  const char *ib = bufi;
836  char *ob = bufu;
837  size_t obl = sizeof(bufu);
838  n = iconv(cd1, (ICONV_CONST char **) ((ibl != 0) ? &ib : 0), &ibl, &ob, &obl);
839  /* assert(n == (size_t)(-1) || !n); */
840  if ((n == (size_t)(-1)) && (((errno != EINVAL) && (errno != E2BIG)) || (ib == bufi)))
841  {
842  /* assert(errno == EILSEQ || (errno == EINVAL && ib == bufi && ibl < sizeof(bufi))); */
843  ret = (size_t)(-1);
844  break;
845  }
846  const size_t ubl1 = ob - bufu;
847 
848  /* Convert from UTF-8 */
849  for (int i = 0; i < ncodes; i++)
850  {
851  if ((cd[i] != (iconv_t)(-1)) && (score[i] != (size_t)(-1)))
852  {
853  const char *ub = bufu;
854  size_t ubl = ubl1;
855  ob = bufo;
856  obl = sizeof(bufo);
857  n = iconv(cd[i], (ICONV_CONST char **) ((ibl || ubl) ? &ub : 0), &ubl, &ob, &obl);
858  if (n == (size_t)(-1))
859  {
860  /* assert(errno == E2BIG || (BUGGY_ICONV && (errno == EILSEQ || errno == ENOENT))); */
861  score[i] = (size_t)(-1);
862  }
863  else
864  {
865  score[i] += n;
866  update_content_info(&infos[i], &states[i], bufo, ob - bufo);
867  }
868  }
869  else if ((cd[i] == (iconv_t)(-1)) && (score[i] == (size_t)(-1)))
870  {
871  /* Special case for conversion to UTF-8 */
872  update_content_info(&infos[i], &states[i], bufu, ubl1);
873  }
874  }
875 
876  if (ibl)
877  {
878  /* Save unused input */
879  memmove(bufi, ib, ibl);
880  }
881  else if (!ubl1 && (ib < bufi + sizeof(bufi)))
882  {
883  ret = 0;
884  break;
885  }
886  }
887 
888  if (ret == 0)
889  {
890  /* Find best score */
891  ret = (size_t)(-1);
892  for (int i = 0; i < ncodes; i++)
893  {
894  if ((cd[i] == (iconv_t)(-1)) && (score[i] == (size_t)(-1)))
895  {
896  /* Special case for conversion to UTF-8 */
897  *tocode = i;
898  ret = 0;
899  break;
900  }
901  else if ((cd[i] == (iconv_t)(-1)) || (score[i] == (size_t)(-1)))
902  continue;
903  else if ((ret == (size_t)(-1)) || (score[i] < ret))
904  {
905  *tocode = i;
906  ret = score[i];
907  if (ret == 0)
908  break;
909  }
910  }
911  if (ret != (size_t)(-1))
912  {
913  memcpy(info, &infos[*tocode], sizeof(struct Content));
914  update_content_info(info, &states[*tocode], 0, 0); /* EOF */
915  }
916  }
917 
918  for (int i = 0; i < ncodes; i++)
919  if (cd[i] != (iconv_t)(-1))
920  iconv_close(cd[i]);
921 
922  iconv_close(cd1);
923  FREE(&cd);
924  FREE(&infos);
925  FREE(&score);
926  FREE(&states);
927 
928  return ret;
929 }
Info about the body of an email.
Definition: sendlib.c:113
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:652
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
char bufi[512]
Definition: charset.h:45
Info about an attachment.
Definition: content.h:33
iconv_t cd
Definition: charset.h:44
iconv_t mutt_ch_iconv_open(const char *tocode, const char *fromcode, int flags)
Set up iconv for conversions.
Definition: charset.c:559
char bufo[512]
Definition: charset.h:46
int n
Definition: acutest.h:477
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:651
#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 952 of file sendlib.c.

954 {
955  char *fcode = NULL;
956  char **tcode = NULL;
957  const char *c = NULL, *c1 = NULL;
958  size_t ret;
959  int ncodes, i, cn;
960 
961  /* Count the tocodes */
962  ncodes = 0;
963  for (c = tocodes; c; c = c1 ? c1 + 1 : 0)
964  {
965  c1 = strchr(c, ':');
966  if (c1 == c)
967  continue;
968  ncodes++;
969  }
970 
971  /* Copy them */
972  tcode = mutt_mem_malloc(ncodes * sizeof(char *));
973  for (c = tocodes, i = 0; c; c = c1 ? c1 + 1 : 0, i++)
974  {
975  c1 = strchr(c, ':');
976  if (c1 == c)
977  continue;
978  tcode[i] = mutt_str_substr_dup(c, c1);
979  }
980 
981  ret = (size_t)(-1);
982  if (fromcode)
983  {
984  /* Try each fromcode in turn */
985  for (c = fromcodes; c; c = c1 ? c1 + 1 : 0)
986  {
987  c1 = strchr(c, ':');
988  if (c1 == c)
989  continue;
990  fcode = mutt_str_substr_dup(c, c1);
991 
992  ret = convert_file_to(fp, fcode, ncodes, (char const *const *) tcode, &cn, info);
993  if (ret != (size_t)(-1))
994  {
995  *fromcode = fcode;
996  *tocode = tcode[cn];
997  tcode[cn] = 0;
998  break;
999  }
1000  FREE(&fcode);
1001  }
1002  }
1003  else
1004  {
1005  /* There is only one fromcode */
1006  ret = convert_file_to(fp, fromcodes, ncodes, (char const *const *) tcode, &cn, info);
1007  if (ret != (size_t)(-1))
1008  {
1009  *tocode = tcode[cn];
1010  tcode[cn] = 0;
1011  }
1012  }
1013 
1014  /* Free memory */
1015  for (i = 0; i < ncodes; i++)
1016  FREE(&tcode[i]);
1017 
1018  FREE(&tcode);
1019 
1020  return ret;
1021 }
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:799
char * mutt_str_substr_dup(const char *begin, const char *end)
Duplicate a sub-string.
Definition: string.c:602
+ 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 
)

Analyze file to determine MIME encoding to use.

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

Also set the body charset, sometimes, or not.

Definition at line 1031 of file sendlib.c.

1032 {
1033  struct Content *info = NULL;
1034  struct ContentState state = { 0 };
1035  FILE *fp = NULL;
1036  char *fromcode = NULL;
1037  char *tocode = NULL;
1038  char buf[100];
1039  size_t r;
1040 
1041  struct stat sb;
1042 
1043  if (b && !fname)
1044  fname = b->filename;
1045 
1046  if (stat(fname, &sb) == -1)
1047  {
1048  mutt_error(_("Can't stat %s: %s"), fname, strerror(errno));
1049  return NULL;
1050  }
1051 
1052  if (!S_ISREG(sb.st_mode))
1053  {
1054  mutt_error(_("%s isn't a regular file"), fname);
1055  return NULL;
1056  }
1057 
1058  fp = fopen(fname, "r");
1059  if (!fp)
1060  {
1061  mutt_debug(LL_DEBUG1, "%s: %s (errno %d)\n", fname, strerror(errno), errno);
1062  return NULL;
1063  }
1064 
1065  info = mutt_mem_calloc(1, sizeof(struct Content));
1066 
1067  if (b && (b->type == TYPE_TEXT) && (!b->noconv && !b->force_charset))
1068  {
1069  char *chs = mutt_param_get(&b->parameter, "charset");
1070  char *fchs = b->use_disp ? (C_AttachCharset ? C_AttachCharset : C_Charset) : C_Charset;
1071  if (C_Charset && (chs || C_SendCharset) &&
1072  (convert_file_from_to(fp, fchs, chs ? chs : C_SendCharset, &fromcode,
1073  &tocode, info) != (size_t)(-1)))
1074  {
1075  if (!chs)
1076  {
1077  char chsbuf[256];
1078  mutt_ch_canonical_charset(chsbuf, sizeof(chsbuf), tocode);
1079  mutt_param_set(&b->parameter, "charset", chsbuf);
1080  }
1081  FREE(&b->charset);
1082  b->charset = fromcode;
1083  FREE(&tocode);
1084  mutt_file_fclose(&fp);
1085  return info;
1086  }
1087  }
1088 
1089  rewind(fp);
1090  while ((r = fread(buf, 1, sizeof(buf), fp)))
1091  update_content_info(info, &state, buf, r);
1092  update_content_info(info, &state, 0, 0);
1093 
1094  mutt_file_fclose(&fp);
1095 
1096  if (b && (b->type == TYPE_TEXT) && (!b->noconv && !b->force_charset))
1097  {
1098  mutt_param_set(&b->parameter, "charset",
1099  (!info->hibin ?
1100  "us-ascii" :
1101  C_Charset && !mutt_ch_is_us_ascii(C_Charset) ? C_Charset : "unknown-8bit"));
1102  }
1103 
1104  return info;
1105 }
Info about the body of an email.
Definition: sendlib.c:113
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:652
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
char * C_SendCharset
Config: Character sets for outgoing mail.
Definition: email_globals.c:38
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:345
#define mutt_ch_is_us_ascii(str)
Definition: charset.h:107
static char * chs
Definition: gnupgparse.c:72
Info about an attachment.
Definition: content.h:33
Type: &#39;text/*&#39;.
Definition: mime.h:38
char * C_AttachCharset
Config: When attaching files, use one of these character sets.
Definition: sendlib.c:81
char * charset
Send mode: charset of attached file as stored on disk.
Definition: body.h:49
unsigned int type
content-type primary type
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
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:54
#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:952
+ 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 1119 of file sendlib.c.

1120 {
1121  FILE *fp = NULL;
1122  char *p = NULL, *q = NULL, *ct = NULL;
1123  char buf[PATH_MAX];
1124  char subtype[256] = { 0 };
1125  char xtype[256] = { 0 };
1126  int sze, cur_sze = 0;
1127  bool found_mimetypes = false;
1128  enum ContentType type = TYPE_OTHER;
1129 
1130  int szf = mutt_str_strlen(path);
1131 
1132  for (int count = 0; count < 4; count++)
1133  {
1134  /* can't use strtok() because we use it in an inner loop below, so use
1135  * a switch statement here instead. */
1136  switch (count)
1137  {
1138  /* last file with last entry to match wins type/xtype */
1139  case 0:
1140  /* check default unix mimetypes location first */
1141  mutt_str_strfcpy(buf, "/etc/mime.types", sizeof(buf));
1142  break;
1143  case 1:
1144  mutt_str_strfcpy(buf, SYSCONFDIR "/mime.types", sizeof(buf));
1145  break;
1146  case 2:
1147  mutt_str_strfcpy(buf, PKGDATADIR "/mime.types", sizeof(buf));
1148  break;
1149  case 3:
1150  snprintf(buf, sizeof(buf), "%s/.mime.types", NONULL(HomeDir));
1151  break;
1152  default:
1153  mutt_debug(LL_DEBUG1, "Internal error, count = %d\n", count);
1154  goto bye; /* shouldn't happen */
1155  }
1156 
1157  fp = fopen(buf, "r");
1158  if (fp)
1159  {
1160  found_mimetypes = true;
1161 
1162  while (fgets(buf, sizeof(buf) - 1, fp))
1163  {
1164  /* weed out any comments */
1165  p = strchr(buf, '#');
1166  if (p)
1167  *p = '\0';
1168 
1169  /* remove any leading space. */
1170  ct = buf;
1171  SKIPWS(ct);
1172 
1173  /* position on the next field in this line */
1174  p = strpbrk(ct, " \t");
1175  if (!p)
1176  continue;
1177  *p++ = 0;
1178  SKIPWS(p);
1179 
1180  /* cycle through the file extensions */
1181  while ((p = strtok(p, " \t\n")))
1182  {
1183  sze = mutt_str_strlen(p);
1184  if ((sze > cur_sze) && (szf >= sze) &&
1185  (mutt_str_strcasecmp(path + szf - sze, p) == 0) &&
1186  ((szf == sze) || (path[szf - sze - 1] == '.')))
1187  {
1188  /* get the content-type */
1189 
1190  p = strchr(ct, '/');
1191  if (!p)
1192  {
1193  /* malformed line, just skip it. */
1194  break;
1195  }
1196  *p++ = 0;
1197 
1198  for (q = p; *q && !IS_SPACE(*q); q++)
1199  ;
1200 
1201  mutt_str_substr_copy(p, q, subtype, sizeof(subtype));
1202 
1203  type = mutt_check_mime_type(ct);
1204  if (type == TYPE_OTHER)
1205  mutt_str_strfcpy(xtype, ct, sizeof(xtype));
1206 
1207  cur_sze = sze;
1208  }
1209  p = NULL;
1210  }
1211  }
1212  mutt_file_fclose(&fp);
1213  }
1214  }
1215 
1216 bye:
1217 
1218  /* no mime.types file found */
1219  if (!found_mimetypes)
1220  {
1221  mutt_error(_("Could not find any mime.types file."));
1222  }
1223 
1224  if ((type != TYPE_OTHER) || (*xtype != '\0'))
1225  {
1226  att->type = type;
1227  mutt_str_replace(&att->subtype, subtype);
1228  mutt_str_replace(&att->xtype, xtype);
1229  }
1230 
1231  return type;
1232 }
Unknown Content-Type.
Definition: mime.h:31
#define NONULL(x)
Definition: string2.h:37
#define _(a)
Definition: message.h:28
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:689
char * HomeDir
User&#39;s home directory.
Definition: globals.h:49
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:47
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
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:773
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:453
unsigned int type
content-type primary type
Definition: body.h:65
#define IS_SPACE(ch)
Definition: string2.h:38
Log at debug level 1.
Definition: logging.h:40
#define mutt_error(...)
Definition: logging.h:84
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:651
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
ContentType
Content-Type.
Definition: mime.h:29
char * mutt_str_substr_copy(const char *begin, const char *end, char *buf, size_t buflen)
Copy a sub-string into a buffer.
Definition: string.c:579
+ 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 
)
static

Convert MIME parts to 7-bit.

Parameters
aBody of the email
fp_inFile to read

Definition at line 1239 of file sendlib.c.

1240 {
1241  struct Buffer *buf = NULL;
1242  struct State s = { 0 };
1243  struct stat sb;
1244 
1245  for (; a; a = a->next)
1246  {
1247  if (a->type == TYPE_MULTIPART)
1248  {
1249  a->encoding = ENC_7BIT;
1250  transform_to_7bit(a->parts, fp_in);
1251  }
1252  else if (mutt_is_message_type(a->type, a->subtype))
1253  {
1254  mutt_message_to_7bit(a, fp_in);
1255  }
1256  else
1257  {
1258  a->noconv = true;
1259  a->force_charset = true;
1260 
1261  /* Because of the potential recursion in message types, we
1262  * restrict the lifetime of the buffer tightly */
1263  buf = mutt_buffer_pool_get();
1264  mutt_buffer_mktemp(buf);
1265  s.fp_out = mutt_file_fopen(mutt_b2s(buf), "w");
1266  if (!s.fp_out)
1267  {
1268  mutt_perror("fopen");
1270  return;
1271  }
1272  s.fp_in = fp_in;
1273  mutt_decode_attachment(a, &s);
1275  FREE(&a->d_filename);
1276  a->d_filename = a->filename;
1277  a->filename = mutt_buffer_strdup(buf);
1279  a->unlink = true;
1280  if (stat(a->filename, &sb) == -1)
1281  {
1282  mutt_perror("stat");
1283  return;
1284  }
1285  a->length = sb.st_size;
1286 
1288  if (a->encoding == ENC_8BIT)
1290  else if (a->encoding == ENC_BINARY)
1291  a->encoding = ENC_BASE64;
1292  }
1293  }
1294 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1794
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:81
void mutt_message_to_7bit(struct Body *a, FILE *fp)
Convert an email&#39;s MIME parts to 7-bit.
Definition: sendlib.c:1301
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:1391
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
7-bit text
Definition: mime.h:49
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
static void transform_to_7bit(struct Body *a, FILE *fp_in)
Convert MIME parts to 7-bit.
Definition: sendlib.c:1239
FILE * fp_in
File to read from.
Definition: state.h:46
void mutt_update_encoding(struct Body *a)
Update the encoding type.
Definition: sendlib.c:1480
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
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
unsigned int type
content-type primary type
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 
)

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

Parameters
aBody of the email
fpFile to read (OPTIONAL)

Definition at line 1301 of file sendlib.c.

1302 {
1303  struct Buffer temp = mutt_buffer_make(0);
1304  FILE *fp_in = NULL;
1305  FILE *fp_out = NULL;
1306  struct stat sb;
1307 
1308  if (!a->filename && fp)
1309  fp_in = fp;
1310  else if (!a->filename || !(fp_in = fopen(a->filename, "r")))
1311  {
1312  mutt_error(_("Could not open %s"), a->filename ? a->filename : "(null)");
1313  return;
1314  }
1315  else
1316  {
1317  a->offset = 0;
1318  if (stat(a->filename, &sb) == -1)
1319  {
1320  mutt_perror("stat");
1321  mutt_file_fclose(&fp_in);
1322  goto cleanup;
1323  }
1324  a->length = sb.st_size;
1325  }
1326 
1327  /* Avoid buffer pool due to recursion */
1328  mutt_buffer_mktemp(&temp);
1329  fp_out = mutt_file_fopen(mutt_b2s(&temp), "w+");
1330  if (!fp_out)
1331  {
1332  mutt_perror("fopen");
1333  goto cleanup;
1334  }
1335 
1336  fseeko(fp_in, a->offset, SEEK_SET);
1337  a->parts = mutt_rfc822_parse_message(fp_in, a);
1338 
1339  transform_to_7bit(a->parts, fp_in);
1340 
1341  mutt_copy_hdr(fp_in, fp_out, a->offset, a->offset + a->length,
1342  CH_MIME | CH_NONEWLINE | CH_XMIT, NULL, 0);
1343 
1344  fputs("MIME-Version: 1.0\n", fp_out);
1345  mutt_write_mime_header(a->parts, fp_out);
1346  fputc('\n', fp_out);
1347  mutt_write_mime_body(a->parts, fp_out);
1348 
1349  if (fp_in != fp)
1350  mutt_file_fclose(&fp_in);
1351  mutt_file_fclose(&fp_out);
1352 
1353  a->encoding = ENC_7BIT;
1354  FREE(&a->d_filename);
1355  a->d_filename = a->filename;
1356  if (a->filename && a->unlink)
1357  unlink(a->filename);
1358  a->filename = mutt_buffer_strdup(&temp);
1359  a->unlink = true;
1360  if (stat(a->filename, &sb) == -1)
1361  {
1362  mutt_perror("stat");
1363  goto cleanup;
1364  }
1365  a->length = sb.st_size;
1366  mutt_body_free(&a->parts);
1367  a->email->content = NULL;
1368 
1369 cleanup:
1370  if (fp_in && (fp_in != fp))
1371  mutt_file_fclose(&fp_in);
1372 
1373  if (fp_out)
1374  {
1375  mutt_file_fclose(&fp_out);
1376  mutt_file_unlink(mutt_b2s(&temp));
1377  }
1378 
1379  mutt_buffer_dealloc(&temp);
1380 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:81
#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
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
static void transform_to_7bit(struct Body *a, FILE *fp_in)
Convert MIME parts to 7-bit.
Definition: sendlib.c:1239
struct Body * mutt_rfc822_parse_message(FILE *fp, struct Body *parent)
parse a Message/RFC822 body
Definition: parse.c:1564
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
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
#define mutt_b2s(buf)
Definition: buffer.h:41
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
int mutt_write_mime_body(struct Body *a, FILE *fp)
Write a MIME part.
Definition: sendlib.c:553
#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
#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
int mutt_write_mime_header(struct Body *a, FILE *fp)
Create a MIME header.
Definition: sendlib.c:395
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
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 
)
static

determine which Content-Transfer-Encoding to use

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

Definition at line 1387 of file sendlib.c.

1388 {
1389  if (b->type == TYPE_TEXT)
1390  {
1391  char send_charset[128];
1392  char *chsname = mutt_body_get_charset(b, send_charset, sizeof(send_charset));
1393  if ((info->lobin && !mutt_str_startswith(chsname, "iso-2022", CASE_IGNORE)) ||
1394  (info->linemax > 990) || (info->from && C_EncodeFrom))
1395  {
1397  }
1398  else if (info->hibin)
1399  {
1401  }
1402  else
1403  {
1404  b->encoding = ENC_7BIT;
1405  }
1406  }
1407  else if ((b->type == TYPE_MESSAGE) || (b->type == TYPE_MULTIPART))
1408  {
1409  if (info->lobin || info->hibin)
1410  {
1411  if (C_Allow8bit && !info->lobin)
1412  b->encoding = ENC_8BIT;
1413  else
1414  mutt_message_to_7bit(b, NULL);
1415  }
1416  else
1417  b->encoding = ENC_7BIT;
1418  }
1419  else if ((b->type == TYPE_APPLICATION) &&
1420  (mutt_str_strcasecmp(b->subtype, "pgp-keys") == 0))
1421  {
1422  b->encoding = ENC_7BIT;
1423  }
1424  else
1425  {
1426  /* Determine which encoding is smaller */
1427  if (1.33 * (float) (info->lobin + info->hibin + info->ascii) <
1428  3.0 * (float) (info->lobin + info->hibin) + (float) info->ascii)
1429  {
1430  b->encoding = ENC_BASE64;
1431  }
1432  else
1433  {
1435  }
1436  }
1437 }
void mutt_message_to_7bit(struct Body *a, FILE *fp)
Convert an email&#39;s MIME parts to 7-bit.
Definition: sendlib.c:1301
long linemax
Length of the longest line in the file.
Definition: content.h:40
bool C_EncodeFrom
Config: Encode &#39;From &#39; as &#39;quote-printable&#39; at the beginning of lines.
Definition: sendlib.c:83
7-bit text
Definition: mime.h:49
8-bit text
Definition: mime.h:50
long hibin
8-bit characters
Definition: content.h:35
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
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
Ignore case when comparing strings.
Definition: string2.h:68
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body&#39;s character set.
Definition: sendlib.c:1456
unsigned int type
content-type primary type
Definition: body.h:65
bool from
Has a line beginning with "From "?
Definition: content.h:43
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
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
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:651
Quoted-printable text.
Definition: mime.h:51
bool C_Allow8bit
Config: Allow 8-bit messages, don&#39;t use quoted-printable or base64.
Definition: sendlib.c:80
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 1443 of file sendlib.c.

1444 {
1445  a->stamp = mutt_date_epoch();
1446 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:411
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_body_get_charset()

char* mutt_body_get_charset ( struct Body b,
char *  buf,
size_t  buflen 
)

Get a body's character set.

Parameters
bBody to examine
bufBuffer for the result
buflenLength of the buffer
Return values
ptrBuffer containing character set
NULLOn error, or if not a text type

Definition at line 1456 of file sendlib.c.

1457 {
1458  char *p = NULL;
1459 
1460  if (b && (b->type != TYPE_TEXT))
1461  return NULL;
1462 
1463  if (b)
1464  p = mutt_param_get(&b->parameter, "charset");
1465 
1466  if (p)
1467  mutt_ch_canonical_charset(buf, buflen, p);
1468  else
1469  mutt_str_strfcpy(buf, "us-ascii", buflen);
1470 
1471  return buf;
1472 }
void mutt_ch_canonical_charset(char *buf, size_t buflen, const char *name)
Canonicalise the charset of a string.
Definition: charset.c:345
Type: &#39;text/*&#39;.
Definition: mime.h:38
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:773
unsigned int type
content-type primary type
Definition: body.h:65
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
+ 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)

Update the encoding type.

Parameters
aBody to update

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

Definition at line 1480 of file sendlib.c.

1481 {
1482  struct Content *info = NULL;
1483  char chsbuf[256];
1484 
1485  /* override noconv when it's us-ascii */
1486  if (mutt_ch_is_us_ascii(mutt_body_get_charset(a, chsbuf, sizeof(chsbuf))))
1487  a->noconv = false;
1488 
1489  if (!a->force_charset && !a->noconv)
1490  mutt_param_delete(&a->parameter, "charset");
1491 
1492  info = mutt_get_content_info(a->filename, a);
1493  if (!info)
1494  return;
1495 
1496  set_encoding(a, info);
1498 
1499  FREE(&a->content);
1500  a->content = info;
1501 }
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:1443
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
struct Content * mutt_get_content_info(const char *fname, struct Body *b)
Analyze file to determine MIME encoding to use.
Definition: sendlib.c:1031
bool force_charset
Send mode: don&#39;t adjust the character set when in send-mode.
Definition: body.h:74
#define mutt_ch_is_us_ascii(str)
Definition: charset.h:107
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
static void set_encoding(struct Body *b, struct Content *info)
determine which Content-Transfer-Encoding to use
Definition: sendlib.c:1387
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body&#39;s character set.
Definition: sendlib.c:1456
#define FREE(x)
Definition: memory.h:40
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
+ 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 
)

Create a message attachment.

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

Definition at line 1511 of file sendlib.c.

1512 {
1513  char buf[1024];
1514  struct Body *body = NULL;
1515  FILE *fp = NULL;
1516  CopyMessageFlags cmflags;
1518 
1519  if (WithCrypto)
1520  {
1522  {
1524  return NULL;
1525  }
1526  }
1527 
1528  mutt_mktemp(buf, sizeof(buf));
1529  fp = mutt_file_fopen(buf, "w+");
1530  if (!fp)
1531  return NULL;
1532 
1533  body = mutt_body_new();
1534  body->type = TYPE_MESSAGE;
1535  body->subtype = mutt_str_strdup("rfc822");
1536  body->filename = mutt_str_strdup(buf);
1537  body->unlink = true;
1538  body->use_disp = false;
1539  body->disposition = DISP_INLINE;
1540  body->noconv = true;
1541 
1543 
1544  CopyHeaderFlags chflags = CH_XMIT;
1545  cmflags = MUTT_CM_NO_FLAGS;
1546 
1547  /* If we are attaching a message, ignore C_MimeForwardDecode */
1548  if (!attach_msg && C_MimeForwardDecode)
1549  {
1550  chflags |= CH_MIME | CH_TXTPLAIN;
1551  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1553  pgp &= ~PGP_ENCRYPT;
1555  pgp &= ~SMIME_ENCRYPT;
1556  }
1557  else if ((WithCrypto != 0) && C_ForwardDecrypt && (e->security & SEC_ENCRYPT))
1558  {
1559  if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_multipart_encrypted(e->content))
1560  {
1561  chflags |= CH_MIME | CH_NONEWLINE;
1562  cmflags = MUTT_CM_DECODE_PGP;
1563  pgp &= ~PGP_ENCRYPT;
1564  }
1565  else if (((WithCrypto & APPLICATION_PGP) != 0) &&
1567  {
1568  chflags |= CH_MIME | CH_TXTPLAIN;
1569  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1570  pgp &= ~PGP_ENCRYPT;
1571  }
1572  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
1574  {
1575  chflags |= CH_MIME | CH_TXTPLAIN;
1576  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1577  pgp &= ~SMIME_ENCRYPT;
1578  }
1579  }
1580 
1581  mutt_copy_message(fp, m, e, cmflags, chflags, 0);
1582 
1583  fflush(fp);
1584  rewind(fp);
1585 
1586  body->email = email_new();
1587  body->email->offset = 0;
1588  /* we don't need the user headers here */
1589  body->email->env = mutt_rfc822_read_header(fp, body->email, false, false);
1590  if (WithCrypto)
1591  body->email->security = pgp;
1592  mutt_update_encoding(body);
1593  body->parts = body->email->content;
1594 
1595  mutt_file_fclose(&fp);
1596 
1597  return body;
1598 }
#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 WithCrypto
Definition: lib.h:163
bool C_MimeForwardDecode
Config: Decode the forwarded message before attaching it.
Definition: sendlib.c:87
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:124
#define SMIME_ENCRYPT
Definition: lib.h:149
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:125
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:143
void mutt_parse_mime_message(struct Mailbox *m, struct Email *e)
Parse a MIME email.
Definition: mutt_parse.c:49
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:812
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:123
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
Definition: body.h:67
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:146
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:459
void mutt_update_encoding(struct Body *a)
Update the encoding type.
Definition: sendlib.c:1480
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 APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:138
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:565
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:78
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:137
#define MUTT_CM_DECODE
Decode the message body into text/plain.
Definition: copy.h:37
bool C_ForwardDecrypt
Config: Decrypt the message when forwarding it.
Definition: sendlib.c:84
#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:624
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
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
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
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:1136
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)
static

Run an external command to determine the MIME type.

Parameters
attAttachment

The command in $mime_type_query_command is run.

Definition at line 1606 of file sendlib.c.

1607 {
1608  FILE *fp = NULL, *fp_err = NULL;
1609  char *buf = NULL;
1610  size_t buflen;
1611  int dummy = 0;
1612  pid_t pid;
1613  struct Buffer *cmd = mutt_buffer_pool_get();
1614 
1616 
1617  pid = filter_create(mutt_b2s(cmd), NULL, &fp, &fp_err);
1618  if (pid < 0)
1619  {
1620  mutt_error(_("Error running \"%s\""), mutt_b2s(cmd));
1622  return;
1623  }
1625 
1626  buf = mutt_file_read_line(buf, &buflen, fp, &dummy, 0);
1627  if (buf)
1628  {
1629  if (strchr(buf, '/'))
1630  mutt_parse_content_type(buf, att);
1631  FREE(&buf);
1632  }
1633 
1634  mutt_file_fclose(&fp);
1635  mutt_file_fclose(&fp_err);
1636  filter_wait(pid);
1637 }
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
void mutt_parse_content_type(const char *s, struct Body *ct)
Parse a content type.
Definition: parse.c:456
char * C_MimeTypeQueryCommand
Config: External command to determine the MIME type of an attachment.
Definition: sendlib.c:89
#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:1426
#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)

Create a file attachment.

Parameters
pathFile to attach
Return values
ptrNewly allocated Body
NULLError

Definition at line 1645 of file sendlib.c.

1646 {
1647  struct Body *att = mutt_body_new();
1648  att->filename = mutt_str_strdup(path);
1649 
1651  run_mime_type_query(att);
1652 
1653  /* Attempt to determine the appropriate content-type based on the filename
1654  * suffix. */
1655  if (!att->subtype)
1656  mutt_lookup_mime_type(att, path);
1657 
1659  {
1660  run_mime_type_query(att);
1661  }
1662 
1663  struct Content *info = mutt_get_content_info(path, att);
1664  if (!info)
1665  {
1666  mutt_body_free(&att);
1667  return NULL;
1668  }
1669 
1670  if (!att->subtype)
1671  {
1672  if ((info->nulbin == 0) &&
1673  ((info->lobin == 0) || ((info->lobin + info->hibin + info->ascii) / info->lobin >= 10)))
1674  {
1675  /* Statistically speaking, there should be more than 10% "lobin"
1676  * chars if this is really a binary file... */
1677  att->type = TYPE_TEXT;
1678  att->subtype = mutt_str_strdup("plain");
1679  }
1680  else
1681  {
1682  att->type = TYPE_APPLICATION;
1683  att->subtype = mutt_str_strdup("octet-stream");
1684  }
1685  }
1686 
1687  FREE(&info);
1688  mutt_update_encoding(att);
1689  return att;
1690 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
static void run_mime_type_query(struct Body *att)
Run an external command to determine the MIME type.
Definition: sendlib.c:1606
long hibin
8-bit characters
Definition: content.h:35
The body of an email.
Definition: body.h:34
struct Content * mutt_get_content_info(const char *fname, struct Body *b)
Analyze file to determine MIME encoding to use.
Definition: sendlib.c:1031
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
void mutt_update_encoding(struct Body *a)
Update the encoding type.
Definition: sendlib.c:1480
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
unsigned int type
content-type primary type
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:1119
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
char * C_MimeTypeQueryCommand
Config: External command to determine the MIME type of an attachment.
Definition: sendlib.c:89
#define FREE(x)
Definition: memory.h:40
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
long nulbin
Null characters (0x0)
Definition: content.h:37
Type: &#39;application/*&#39;.
Definition: mime.h:33
bool C_MimeTypeQueryFirst
Config: Run the C_MimeTypeQueryCommand before the mime.types lookup.
Definition: sendlib.c:90
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_toplevel_encoding()

static int get_toplevel_encoding ( struct Body a)
static

Find the most restrictive encoding type.

Parameters
aBody to examine
Return values
numEncoding type, e.g. ENC_7BIT

Definition at line 1697 of file sendlib.c.

1698 {
1699  int e = ENC_7BIT;
1700 
1701  for (; a; a = a->next)
1702  {
1703  if (a->encoding == ENC_BINARY)
1704  return ENC_BINARY;
1705  if (a->encoding == ENC_8BIT)
1706  e = ENC_8BIT;
1707  }
1708 
1709  return e;
1710 }
7-bit text
Definition: mime.h:49
struct Body * next
next attachment in the list
Definition: body.h:53
8-bit text
Definition: mime.h:50
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
Binary.
Definition: mime.h:53
+ Here is the caller graph for this function:

◆ check_boundary()

static bool check_boundary ( const char *  boundary,
struct Body b 
)
static

check for duplicate boundary

Parameters
boundaryBoundary to look for
bBody parts to check
Return values
trueif duplicate found

Definition at line 1718 of file sendlib.c.

1719 {
1720  char *p = NULL;
1721 
1722  if (b->parts && check_boundary(boundary, b->parts))
1723  return true;
1724 
1725  if (b->next && check_boundary(boundary, b->next))
1726  return true;
1727 
1728  p = mutt_param_get(&b->parameter, "boundary");
1729  if (p && (mutt_str_strcmp(p, boundary) == 0))
1730  {
1731  return true;
1732  }
1733  return false;
1734 }
struct Body * next
next attachment in the list
Definition: body.h:53
static bool check_boundary(const char *boundary, struct Body *b)
check for duplicate boundary
Definition: sendlib.c:1718
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:638
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_make_multipart()

struct Body* mutt_make_multipart ( struct Body b)

Create a multipart email.

Parameters
bBody of email to start
Return values
ptrNewly allocated Body

Definition at line 1741 of file sendlib.c.

1742 {
1743  struct Body *new_body = mutt_body_new();
1744  new_body->type = TYPE_MULTIPART;
1745  new_body->subtype = mutt_str_strdup("mixed");
1746  new_body->encoding = get_toplevel_encoding(b);
1747  do
1748  {
1749  mutt_generate_boundary(&new_body->parameter);
1750  if (check_boundary(mutt_param_get(&new_body->parameter, "boundary"), b))
1751  mutt_param_delete(&new_body->parameter, "boundary");
1752  } while (!mutt_param_get(&new_body->parameter, "boundary"));
1753  new_body->use_disp = false;
1754  new_body->disposition = DISP_INLINE;
1755  new_body->parts = b;
1756 
1757  return new_body;
1758 }
static int get_toplevel_encoding(struct Body *a)
Find the most restrictive encoding type.
Definition: sendlib.c:1697
The body of an email.
Definition: body.h:34
unsigned int disposition
content-disposition
Definition: body.h:67
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
void mutt_generate_boundary(struct ParameterList *pl)
Create a unique boundary id for a MIME part.
Definition: sendlib.c:636
static bool check_boundary(const char *boundary, struct Body *b)
check for duplicate boundary
Definition: sendlib.c:1718
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
char * subtype
content-type subtype
Definition: body.h:37
void mutt_param_delete(struct ParameterList *pl, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:142
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
unsigned int type
content-type primary type
Definition: body.h:65
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
Content is inline.
Definition: mime.h:62
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_remove_multipart()

struct Body* mutt_remove_multipart ( struct Body b)

Extract the multipart body if it exists.

Parameters
bBody to alter
Return values
ptrThe parts of the Body
Note
The original Body is freed

Definition at line 1767 of file sendlib.c.

1768 {
1769  struct Body *t = NULL;
1770 
1771  if (b->parts)
1772  {
1773  t = b;
1774  b = b->parts;
1775  t->parts = NULL;
1776  mutt_body_free(&t);
1777  }
1778  return b;
1779 }
The body of an email.
Definition: body.h:34
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
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_write_addrlist()

void mutt_write_addrlist ( struct AddressList *  al,
FILE *  fp,
int  linelen,
bool  display 
)

Wrapper for mutt_write_address()

Parameters
alAddress list
fpFile to write to
linelenLine length to use
displayTrue if these addresses will be displayed to the user

So we can handle very large recipient lists without needing a huge temporary buffer in memory

Definition at line 1791 of file sendlib.c.

1792 {
1793  char buf[1024];
1794  int count = 0;
1795 
1796  struct Address *a = NULL;
1797  TAILQ_FOREACH(a, al, entries)
1798  {
1799  buf[0] = '\0';
1800  mutt_addr_write(buf, sizeof(buf), a, display);
1801  size_t len = mutt_str_strlen(buf);
1802  if (count && (linelen + len > 74))
1803  {
1804  fputs("\n\t", fp);
1805  linelen = len + 8; /* tab is usually about 8 spaces... */
1806  }
1807  else
1808  {
1809  if (count && a->mailbox)
1810  {
1811  fputc(' ', fp);
1812  linelen++;
1813  }
1814  linelen += len;
1815  }
1816  fputs(buf, fp);
1817  struct Address *next = TAILQ_NEXT(a, entries);
1818  if (!a->group && next && next->mailbox)
1819  {
1820  linelen++;
1821  fputc(',', fp);
1822  }
1823  count++;
1824  }
1825  fputc('\n', fp);
1826 }
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:689
size_t mutt_addr_write(char *buf, size_t buflen, struct Address *addr, bool display)
Write a single Address to a buffer.
Definition: address.c:1016
bool group
Group mailbox?
Definition: address.h:38
#define TAILQ_NEXT(elm, field)
Definition: queue.h:825
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_write_references()

void mutt_write_references ( const struct ListHead *  r,
FILE *  fp,
size_t  trim 
)

Add the message references to a list.

Parameters
rString List of references
fpFile to write to
trimTrim the list to at most this many items

Write the list in reverse because they are stored in reverse order when parsed to speed up threading.

Definition at line 1837 of file sendlib.c.

1838 {
1839  struct ListNode *np = NULL;
1840  size_t length = 0;
1841 
1842  STAILQ_FOREACH(np, r, entries)
1843  {
1844  if (++length == trim)
1845  break;
1846  }
1847 
1848  struct ListNode **ref = mutt_mem_calloc(length, sizeof(struct ListNode *));
1849 
1850  // store in reverse order
1851  size_t tmp = length;
1852  STAILQ_FOREACH(np, r, entries)
1853  {
1854  ref[--tmp] = np;
1855  if (tmp == 0)
1856  break;
1857  }
1858 
1859  for (size_t i = 0; i < length; i++)
1860  {
1861  fputc(' ', fp);
1862  fputs(ref[i]->data, fp);
1863  if (i != length - 1)
1864  fputc('\n', fp);
1865  }
1866 
1867  FREE(&ref);
1868 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
char * data
String.
Definition: list.h:35
#define FREE(x)
Definition: memory.h:40
A List node for strings.
Definition: list.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ print_val()

static int print_val ( FILE *  fp,
const char *  pfx,
const char *  value,
CopyHeaderFlags  chflags,
size_t  col 
)
static

Add pieces to an email header, wrapping where necessary.

Parameters
fpFile to write to
pfxPrefix for headers
valueText to be added
chflagsFlags, see CopyHeaderFlags
colColumn that this text starts at
Return values
0Success
-1Failure

Definition at line 1880 of file sendlib.c.

1882 {
1883  while (value && (value[0] != '\0'))
1884  {
1885  if (fputc(*value, fp) == EOF)
1886  return -1;
1887  /* corner-case: break words longer than 998 chars by force,
1888  * mandated by RFC5322 */
1889  if (!(chflags & CH_DISPLAY) && (++col >= 998))
1890  {
1891  if (fputs("\n ", fp) < 0)
1892  return -1;
1893  col = 1;
1894  }
1895  if (*value == '\n')
1896  {
1897  if ((value[1] != '\0') && pfx && (pfx[0] != '\0') && (fputs(pfx, fp) == EOF))
1898  return -1;
1899  /* for display, turn folding spaces into folding tabs */
1900  if ((chflags & CH_DISPLAY) && ((value[1] == ' ') || (value[1] == '\t')))
1901  {
1902  value++;
1903  while ((value[0] != '\0') && ((value[0] == ' ') || (value[0] == '\t')))
1904  value++;
1905  if (fputc('\t', fp) == EOF)
1906  return -1;
1907  continue;
1908  }
1909  }
1910  value++;
1911  }
1912  return 0;
1913 }
#define CH_DISPLAY
Display result to user.
Definition: copy.h:69
+ Here is the caller graph for this function:

◆ fold_one_header()

static int fold_one_header ( FILE *  fp,
const char *  tag,
const char *  value,
size_t  vlen,
const char *  pfx,
int  wraplen,
CopyHeaderFlags  chflags 
)
static

Fold one header line.

Parameters
fpFile to write to
tagHeader key, e.g. "From"
valueHeader value
vlenLength of the header value string
pfxPrefix for header
wraplenColumn to wrap at
chflagsFlags, see CopyHeaderFlags
Return values
0Success
-1Failure

Definition at line 1927 of file sendlib.c.

1929 {
1930  if (!value || !*value || !vlen)
1931  return 0;
1932 
1933  const char *p = value;
1934  char buf[8192] = { 0 };
1935  int first = 1, col = 0, l = 0;
1936  const bool display = (chflags & CH_DISPLAY);
1937 
1938  mutt_debug(LL_DEBUG5, "pfx=[%s], tag=[%s], flags=%d value=[%.*s]\n", pfx, tag,
1939  chflags, ((value[vlen - 1] == '\n') ? vlen - 1 : vlen), value);
1940 
1941  if (tag && *tag && (fprintf(fp, "%s%s: ", NONULL(pfx), tag) < 0))
1942  return -1;
1943  col = mutt_str_strlen(tag) + ((tag && (tag[0] != '\0')) ? 2 : 0) + mutt_str_strlen(pfx);
1944 
1945  while (p && (p[0] != '\0'))
1946  {
1947  int fold = 0;
1948 
1949  /* find the next word and place it in 'buf'. it may start with
1950  * whitespace we can fold before */
1951  const char *next = mutt_str_find_word(p);
1952  l = MIN(sizeof(buf) - 1, next - p);
1953  memcpy(buf, p, l);
1954  buf[l] = '\0';
1955 
1956  /* determine width: character cells for display, bytes for sending
1957  * (we get pure ascii only) */
1958  const int w = mutt_mb_width(buf, col, display);
1959  const int enc = mutt_str_startswith(buf, "=?", CASE_MATCH);
1960 
1961  mutt_debug(LL_DEBUG5, "word=[%s], col=%d, w=%d, next=[0x0%x]\n",
1962  (buf[0] == '\n' ? "\\n" : buf), col, w, *next);
1963 
1964  /* insert a folding \n before the current word's lwsp except for
1965  * header name, first word on a line (word longer than wrap width)
1966  * and encoded words */
1967  if (!first && !enc && col && ((col + w) >= wraplen))
1968  {
1969  col = mutt_str_strlen(pfx);
1970  fold = 1;
1971  if (fprintf(fp, "\n%s", NONULL(pfx)) <= 0)
1972  return -1;
1973  }
1974 
1975  /* print the actual word; for display, ignore leading ws for word
1976  * and fold with tab for readability */
1977  if (display && fold)
1978  {
1979  char *pc = buf;
1980  while ((pc[0] != '\0') && ((pc[0] == ' ') || (pc[0] == '\t')))
1981  {
1982  pc++;
1983  col--;
1984  }
1985  if (fputc('\t', fp) == EOF)
1986  return -1;
1987  if (print_val(fp, pfx, pc, chflags, col) < 0)
1988  return -1;
1989  col += 8;
1990  }
1991  else if (print_val(fp, pfx, buf, chflags, col) < 0)
1992  return -1;
1993  col += w;
1994 
1995  /* if the current word ends in \n, ignore all its trailing spaces
1996  * and reset column; this prevents us from putting only spaces (or
1997  * even none) on a line if the trailing spaces are located at our
1998  * current line width
1999  * XXX this covers ASCII space only, for display we probably
2000  * want something like iswspace() here */
2001  const char *sp = next;
2002  while ((sp[0] != '\0') && ((sp[0] == ' ') || (sp[0] == '\t')))
2003  sp++;
2004  if (sp[0] == '\n')
2005  {
2006  if (sp[1] == '\0')
2007  break;
2008  next = sp;
2009  col = 0;
2010  }
2011 
2012  p = next;
2013  first = 0;
2014  }
2015 
2016  /* if we have printed something but didn't \n-terminate it, do it
2017  * except the last word we printed ended in \n already */
2018  if (col && ((l == 0) || (buf[l - 1] != '\n')))
2019  if (putc('\n', fp) == EOF)
2020  return -1;
2021 
2022  return 0;
2023 }
#define NONULL(x)
Definition: string2.h:37
#define MIN(a, b)
Definition: memory.h:31
Match case when comparing strings.
Definition: string2.h:67
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:689
int mutt_mb_width(const char *str, int col, bool display)
Measure a string&#39;s display width (in screen columns)
Definition: mbyte.c:139
#define CH_DISPLAY
Display result to user.
Definition: copy.h:69
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Log at debug level 5.
Definition: logging.h:44
static int print_val(FILE *fp, const char *pfx, const char *value, CopyHeaderFlags chflags, size_t col)
Add pieces to an email header, wrapping where necessary.
Definition: sendlib.c:1880
const char * mutt_str_find_word(const char *src)
Find the end of a word (non-space)
Definition: string.c:1051
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unfold_header()

static char* unfold_header ( char *  s)
static

Unfold a wrapped email header.

Parameters
sString to process
Return values
ptrUnfolded string
Note
The string is altered in-place

Definition at line 2032 of file sendlib.c.

2033 {
2034  char *p = s;
2035  char *q = s;
2036 
2037  while (p && (p[0] != '\0'))
2038  {
2039  /* remove CRLF prior to FWSP, turn \t into ' ' */
2040  if ((p[0] == '\r') && (p[1] == '\n') && ((p[2] == ' ') || (p[2] == '\t')))
2041  {
2042  *q++ = ' ';
2043  p += 3;
2044  continue;
2045  }
2046  /* remove LF prior to FWSP, turn \t into ' ' */
2047  else if ((p[0] == '\n') && ((p[1] == ' ') || (p[1] == '\t')))
2048  {
2049  *q++ = ' ';
2050  p += 2;
2051  continue;
2052  }
2053  *q++ = *p++;
2054  }
2055  if (q)
2056  q[0] = '\0';
2057 
2058  return s;
2059 }
+ Here is the caller graph for this function:

◆ write_one_header()

static int write_one_header ( FILE *  fp,
int  pfxw,
int  max,
int  wraplen,
const char *  pfx,
const char *  start,
const char *  end,
CopyHeaderFlags  chflags 
)
static

Write out one header line.

Parameters
fpFile to write to
pfxwWidth of prefix string
maxMax width
wraplenColumn to wrap at
pfxPrefix for header
startStart of header line
endEnd of header line
chflagsFlags, see CopyHeaderFlags
Return values
0Success
-1Failure

Definition at line 2074 of file sendlib.c.

2076 {
2077  const char *t = strchr(start, ':');
2078  if (!t || (t > end))
2079  {
2080  mutt_debug(LL_DEBUG1, "#2 warning: header not in 'key: value' format!\n");
2081  return 0;
2082  }
2083 
2084  const size_t vallen = end - start;
2085  const bool short_enough = (pfxw + max <= wraplen);
2086 
2087  mutt_debug((short_enough ? LL_DEBUG2 : LL_DEBUG5), "buf[%s%.*s] %s, max width = %d %s %d\n",
2088  NONULL(pfx), vallen - 1 /* skip newline */, start,
2089  (short_enough ? "short enough" : "too long"), max,
2090  (short_enough ? "<=" : ">"), wraplen);
2091 
2092  int rc = 0;
2093  const char *valbuf = NULL, *tagbuf = NULL;
2094  const bool is_from = (vallen > 5) && mutt_str_startswith(start, "from ", CASE_IGNORE);
2095 
2096  /* only pass through folding machinery if necessary for sending,
2097  * never wrap From_ headers on sending */
2098  if (!(chflags & CH_DISPLAY) && (short_enough || is_from))
2099  {
2100  if (pfx && *pfx)
2101  {
2102  if (fputs(pfx, fp) == EOF)
2103  {
2104  return -1;
2105  }
2106  }
2107 
2108  valbuf = mutt_str_substr_dup(start, end);
2109  rc = print_val(fp, pfx, valbuf, chflags, mutt_str_strlen(pfx));
2110  }
2111  else
2112  {
2113  if (!is_from)
2114  {
2115  tagbuf = mutt_str_substr_dup(start, t);
2116  /* skip over the colon separating the header field name and value */
2117  t++;
2118 
2119  /* skip over any leading whitespace (WSP, as defined in RFC5322)
2120  * NOTE: mutt_str_skip_email_wsp() does the wrong thing here.
2121  * See tickets 3609 and 3716. */
2122  while ((*t == ' ') || (*t == '\t'))
2123  t++;
2124  }
2125  valbuf = mutt_str_substr_dup(is_from ? start : t, end);
2126  rc = fold_one_header(fp, tagbuf, valbuf, end - (is_from ? start : t), pfx,
2127  wraplen, chflags);
2128  }
2129 
2130  FREE(&tagbuf);
2131  FREE(&valbuf);
2132  return rc;
2133 }
#define NONULL(x)
Definition: string2.h:37
static int fold_one_header(FILE *fp, const char *tag, const char *value, size_t vlen, const char *pfx, int wraplen, CopyHeaderFlags chflags)
Fold one header line.
Definition: sendlib.c:1927
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:689
Log at debug level 2.
Definition: logging.h:41
#define CH_DISPLAY
Display result to user.
Definition: copy.h:69
Ignore case when comparing strings.
Definition: string2.h:68
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
Log at debug level 1.
Definition: logging.h:40
#define FREE(x)
Definition: memory.h:40
bool is_from(const char *s, char *path, size_t pathlen, time_t *tp)
Is a string a &#39;From&#39; header line?
Definition: from.c:50
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Log at debug level 5.
Definition: logging.h:44
static int print_val(FILE *fp, const char *pfx, const char *value, CopyHeaderFlags chflags, size_t col)
Add pieces to an email header, wrapping where necessary.
Definition: sendlib.c:1880
char * mutt_str_substr_dup(const char *begin, const char *end)
Duplicate a sub-string.
Definition: string.c:602
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_write_one_header()

int mutt_write_one_header ( FILE *  fp,
const char *  tag,
const char *  value,
const char *  pfx,
int  wraplen,
CopyHeaderFlags  chflags 
)

Write one header line to a file.

Parameters
fpFile to write to
tagHeader key, e.g. "From"
valueHeader value
pfxPrefix for header
wraplenColumn to wrap at
chflagsFlags, see CopyHeaderFlags
Return values
0Success
-1Failure

split several headers into individual ones and call write_one_header for each one

Definition at line 2149 of file sendlib.c.

2151 {
2152  char *last = NULL, *line = NULL;
2153  int max = 0, w, rc = -1;
2154  int pfxw = mutt_strwidth(pfx);
2155  char *v = mutt_str_strdup(value);
2156  bool display = (chflags & CH_DISPLAY);
2157 
2158  if (!display || C_Weed)
2159  v = unfold_header(v);
2160 
2161  /* when not displaying, use sane wrap value */
2162  if (!display)
2163  {
2164  if ((C_WrapHeaders < 78) || (C_WrapHeaders > 998))
2165  wraplen = 78;
2166  else
2167  wraplen = C_WrapHeaders;
2168  }
2169  else if (wraplen <= 0)
2170  wraplen = 78;
2171 
2172  const size_t vlen = mutt_str_strlen(v);
2173  if (tag)
2174  {
2175  /* if header is short enough, simply print it */
2176  if (!display && (mutt_strwidth(tag) + 2 + pfxw + mutt_strnwidth(v, vlen) <= wraplen))
2177  {
2178  mutt_debug(LL_DEBUG5, "buf[%s%s: %s] is short enough\n", NONULL(pfx), tag, v);
2179  if (fprintf(fp, "%s%s: %s\n", NONULL(pfx), tag, v) <= 0)
2180  goto out;
2181  rc = 0;
2182  goto out;
2183  }
2184  else
2185  {
2186  rc = fold_one_header(fp, tag, v, vlen, pfx, wraplen, chflags);
2187  goto out;
2188  }
2189  }
2190 
2191  char *p = v;
2192  last = v;
2193  line = v;
2194  while (p && *p)
2195  {
2196  p = strchr(p, '\n');
2197 
2198  /* find maximum line width in current header */
2199  if (p)
2200  *p = '\0';
2201  w = mutt_mb_width(line, 0, display);
2202  if (w > max)
2203  max = w;
2204  if (p)
2205  *p = '\n';
2206 
2207  if (!p)
2208  break;
2209 
2210  line = ++p;
2211  if ((*p != ' ') && (*p != '\t'))
2212  {
2213  if (write_one_header(fp, pfxw, max, wraplen, pfx, last, p, chflags) < 0)
2214  goto out;
2215  last = p;
2216  max = 0;
2217  }
2218  }
2219 
2220  if (last && *last)
2221  if (write_one_header(fp, pfxw, max, wraplen, pfx, last, p, chflags) < 0)
2222  goto out;
2223 
2224  rc = 0;
2225 
2226 out:
2227  FREE(&v);
2228  return rc;
2229 }
short C_WrapHeaders
Config: Width to wrap headers in outgoing messages.
Definition: sendlib.c:96
#define NONULL(x)
Definition: string2.h:37
static int fold_one_header(FILE *fp, const char *tag, const char *value, size_t vlen, const char *pfx, int wraplen, CopyHeaderFlags chflags)
Fold one header line.
Definition: sendlib.c:1927
static char * unfold_header(char *s)
Unfold a wrapped email header.
Definition: sendlib.c:2032
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:689
int mutt_mb_width(const char *str, int col, bool display)
Measure a string&#39;s display width (in screen columns)
Definition: mbyte.c:139
int mutt_strwidth(const char *s)
Measure a string&#39;s width in screen cells.
Definition: curs_lib.c:1337
#define CH_DISPLAY
Display result to user.
Definition: copy.h:69
static int write_one_header(FILE *fp, int pfxw, int max, int wraplen, const char *pfx, const char *start, const char *end, CopyHeaderFlags chflags)
Write out one header line.
Definition: sendlib.c:2074
int mutt_strnwidth(const char *s, size_t n)
Measure a string&#39;s width in screen cells.
Definition: curs_lib.c:1350
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define FREE(x)
Definition: memory.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
int const char int line
Definition: acutest.h:602
Log at debug level 5.
Definition: logging.h:44
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: email_globals.c:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ userhdrs_override_cmp()

static int userhdrs_override_cmp ( const void *  a,
const void *  b 
)
static

Compare a user-defined header with an element of the userhdrs_override_headers list.

Parameters
aPointer to the string containing the user-defined header
bPointer to an element of the userhdrs_override_headers list
Return values
-1a precedes b
0a and b are identical
1b precedes a

Definition at line 2239 of file sendlib.c.

2240 {
2241  const char *ca = a;
2242  const char *cb = *(const char **) b;
2243  return mutt_str_strncasecmp(ca, cb, strlen(cb));
2244 }
int mutt_str_strncasecmp(const char *a, const char *b, size_t l)
Compare two strings ignoring case (to a maximum), safely.
Definition: string.c:679
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ write_userhdrs()

static struct UserHdrsOverride write_userhdrs ( FILE *  fp,
const struct ListHead *  userhdrs,
bool  privacy 
)
static

Write user-defined headers and keep track of the interesting ones.

Parameters
fpFILE pointer where to write the headers
userhdrsList of headers to write
privacyOmit headers that could identify the user
Return values
objUserHdrsOverride struct containing a bitmask of which unique headers were written

Definition at line 2253 of file sendlib.c.

2254 {
2255  struct UserHdrsOverride overrides = { { 0 } };
2256 
2257  struct ListNode *tmp = NULL;
2258  STAILQ_FOREACH(tmp, userhdrs, entries)
2259  {
2260  char *const colon = strchr(tmp->data, ':');
2261  if (!colon)
2262  {
2263  continue;
2264  }
2265 
2266  const char *const value = mutt_str_skip_email_wsp(colon + 1);
2267  if (*value == '\0')
2268  {
2269  continue; /* don't emit empty fields. */
2270  }
2271 
2272  /* check whether the current user-header is an override */
2273  size_t curr_override = (size_t) -1;
2274  const char *const *idx = bsearch(tmp->data, userhdrs_override_headers,
2276  sizeof(char *), userhdrs_override_cmp);
2277  if (idx != NULL)
2278  {
2279  curr_override = idx - userhdrs_override_headers;
2280  overrides.is_overridden[curr_override] = true;
2281  }
2282 
2283  if (privacy && (curr_override == USERHDRS_OVERRIDE_USER_AGENT))
2284  {
2285  continue;
2286  }
2287 
2288  *colon = '\0';
2289  mutt_write_one_header(fp, tmp->data, value, NULL, 0, CH_NO_FLAGS);
2290  *colon = ':';
2291  }
2292 
2293  return overrides;
2294 }
static const char *const userhdrs_override_headers[]
The next array/enum pair is used to to keep track of user headers that override pre-defined headers N...
Definition: sendlib.c:127
static int userhdrs_override_cmp(const void *a, const void *b)
Compare a user-defined header with an element of the userhdrs_override_headers list.
Definition: sendlib.c:2239
#define mutt_array_size(x)
Definition: memory.h:33
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:50
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:799
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
bool is_overridden[mutt_array_size(userhdrs_override_headers)]
Definition: sendlib.c:140
char * data
String.
Definition: list.h:35
A List node for strings.
Definition: list.h:33
int mutt_write_one_header(FILE *fp, const char *tag, const char *value, const char *pfx, int wraplen, CopyHeaderFlags chflags)
Write one header line to a file.
Definition: sendlib.c:2149
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_rfc822_write_header()

int mutt_rfc822_write_header ( FILE *  fp,
struct Envelope env,
struct Body attach,
enum MuttWriteHeaderMode  mode,
bool  privacy,
bool  hide_protected_subject 
)

Write out one RFC822 header line.

Parameters
fpFile to write to
envEnvelope of email
attachAttachment
modeMode, see MuttWriteHeaderMode
privacyIf true, remove headers that might identify the user
hide_protected_subjectIf true, replace subject header
Return values
0Success
-1Failure

Note: all RFC2047 encoding should be done outside of this routine, except for the "real name." This will allow this routine to be used more than once, if necessary.

Likewise, all IDN processing should happen outside of this routine.

privacy true => will omit any headers which may identify the user. Output generated is suitable for being sent through anonymous remailer chains.

hide_protected_subject: replaces the Subject header with $crypt_protected_headers_subject in NORMAL or POSTPONE mode.

Definition at line 2320 of file sendlib.c.

2323 {
2324  char buf[1024];
2325 
2326  if (((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_FCC)) && !privacy)
2327  fputs(mutt_date_make_date(buf, sizeof(buf)), fp);
2328 
2329  /* UseFrom is not consulted here so that we can still write a From:
2330  * field if the user sets it with the 'my_hdr' command */
2331  if (!TAILQ_EMPTY(&env->from) && !privacy)
2332  {
2333  buf[0] = '\0';
2334  mutt_addrlist_write(&env->from, buf, sizeof(buf), false);
2335  fprintf(fp, "From: %s\n", buf);
2336  }
2337 
2338  if (!TAILQ_EMPTY(&env->sender) && !privacy)
2339  {
2340  buf[0] = '\0';
2341  mutt_addrlist_write(&env->sender, buf, sizeof(buf), false);
2342  fprintf(fp, "Sender: %s\n", buf);
2343  }
2344 
2345  if (!TAILQ_EMPTY(&env->to))
2346  {
2347  fputs("To: ", fp);
2348  mutt_write_addrlist(&env->to, fp, 4, 0);
2349  }
2350  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2351 #ifdef USE_NNTP
2352  if (!OptNewsSend)
2353 #endif
2354  fputs("To:\n", fp);
2355 
2356  if (!TAILQ_EMPTY(&env->cc))
2357  {
2358  fputs("Cc: ", fp);
2359  mutt_write_addrlist(&env->cc, fp, 4, 0);
2360  }
2361  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2362 #ifdef USE_NNTP
2363  if (!OptNewsSend)
2364 #endif
2365  fputs("Cc:\n", fp);
2366 
2367  if (!TAILQ_EMPTY(&env->bcc))
2368  {
2369  if ((mode == MUTT_WRITE_HEADER_POSTPONE) ||
2370  (mode == MUTT_WRITE_HEADER_EDITHDRS) || (mode == MUTT_WRITE_HEADER_FCC) ||
2371  ((mode == MUTT_WRITE_HEADER_NORMAL) && C_WriteBcc))
2372  {
2373  fputs("Bcc: ", fp);
2374  mutt_write_addrlist(&env->bcc, fp, 5, 0);
2375  }
2376  }
2377  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2378 #ifdef USE_NNTP
2379  if (!OptNewsSend)
2380 #endif
2381  fputs("Bcc:\n", fp);
2382 
2383 #ifdef USE_NNTP
2384  if (env->newsgroups)
2385  fprintf(fp, "Newsgroups: %s\n", env->newsgroups);
2386  else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend)
2387  fputs("Newsgroups:\n", fp);
2388 
2389  if (env->followup_to)
2390  fprintf(fp, "Followup-To: %s\n", env->followup_to);
2391  else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend)
2392  fputs("Followup-To:\n", fp);
2393 
2394  if (env->x_comment_to)
2395  fprintf(fp, "X-Comment-To: %s\n", env->x_comment_to);
2396  else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend && C_XCommentTo)
2397  fputs("X-Comment-To:\n", fp);
2398 #endif
2399 
2400  if (env->subject)
2401  {
2402  if (hide_protected_subject &&
2403  ((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_FCC) ||
2404  (mode == MUTT_WRITE_HEADER_POSTPONE)))
2406  else
2407  mutt_write_one_header(fp, "Subject", env->subject, NULL, 0, CH_NO_FLAGS);
2408  }
2409  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2410  fputs("Subject:\n", fp);
2411 
2412  /* save message id if the user has set it */
2413  if (env->message_id && !privacy)
2414  fprintf(fp, "Message-ID: %s\n", env->message_id);
2415 
2416  if (!TAILQ_EMPTY(&env->reply_to))
2417  {
2418  fputs("Reply-To: ", fp);
2419  mutt_write_addrlist(&env->reply_to, fp, 10, 0);
2420  }
2421  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2422  fputs("Reply-To:\n", fp);
2423 
2424  if (!TAILQ_EMPTY(&env->mail_followup_to))
2425  {
2426 #ifdef USE_NNTP
2427  if (!OptNewsSend)
2428 #endif
2429  {
2430  fputs("Mail-Followup-To: ", fp);
2431  mutt_write_addrlist(&env->mail_followup_to, fp, 18, 0);
2432  }
2433  }
2434 
2435  /* Add any user defined headers */
2436  struct UserHdrsOverride userhdrs_overrides = write_userhdrs(fp, &env->userhdrs, privacy);
2437 
2438  if ((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_FCC) ||
2439  (mode == MUTT_WRITE_HEADER_POSTPONE))
2440  {
2441  if (!STAILQ_EMPTY(&env->references))
2442  {
2443  fputs("References:", fp);
2444  mutt_write_references(&env->references, fp, 10);
2445  fputc('\n', fp);
2446  }
2447 
2448  /* Add the MIME headers */
2449  if (!userhdrs_overrides.is_overridden[USERHDRS_OVERRIDE_CONTENT_TYPE])
2450  {
2451  fputs("MIME-Version: 1.0\n", fp);
2452  mutt_write_mime_header(attach, fp);
2453  }
2454  }
2455 
2456  if (!STAILQ_EMPTY(&env->in_reply_to))
2457  {
2458  fputs("In-Reply-To:", fp);
2459  mutt_write_references(&env->in_reply_to, fp, 0);
2460  fputc('\n', fp);
2461  }
2462 
2463 #ifdef USE_AUTOCRYPT
2464  if (C_Autocrypt)
2465  {
2466  if (mode == MUTT_WRITE_HEADER_NORMAL || mode == MUTT_WRITE_HEADER_FCC)
2468  if (mode == MUTT_WRITE_HEADER_MIME)
2470  }
2471 #endif
2472 
2473  if (((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_FCC)) && !privacy &&
2474  C_UserAgent && !userhdrs_overrides.is_overridden[USERHDRS_OVERRIDE_USER_AGENT])
2475  {
2476  /* Add a vanity header */
2477  fprintf(fp, "User-Agent: NeoMutt/%s%s\n", PACKAGE_VERSION, GitVer);
2478  }
2479 
2480  return (ferror(fp) == 0) ? 0 : -1;
2481 }
WHERE bool C_Autocrypt
Config: Enables the Autocrypt feature.
Definition: globals.h:200
WHERE bool C_WriteBcc
Config: Write out the &#39;Bcc&#39; field when preparing to send a mail.
Definition: globals.h:259
struct AddressList mail_followup_to
Email&#39;s &#39;mail-followup-to&#39;.
Definition: envelope.h:63
struct AddressList reply_to
Email&#39;s &#39;reply-to&#39;.
Definition: envelope.h:62
struct AddressList bcc
Email&#39;s &#39;Bcc&#39; list.
Definition: envelope.h:60
WHERE char * C_CryptProtectedHeadersSubject
Config: Use this as the subject for encrypted emails.
Definition: globals.h:107
bool C_UserAgent
Config: Add a &#39;User-Agent&#39; head to outgoing mail.
Definition: sendlib.c:95
A normal Email, write full header + MIME headers.
Definition: sendlib.h:60
A postponed Email, just the envelope info.
Definition: sendlib.h:62
struct ListHead userhdrs
user defined headers
Definition: envelope.h:83
char * mutt_date_make_date(char *buf, size_t buflen)
Write a date in RFC822 format to a buffer.
Definition: date.c:372
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:82
char * message_id
Message ID.
Definition: envelope.h:69
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
static struct UserHdrsOverride write_userhdrs(FILE *fp, const struct ListHead *userhdrs, bool privacy)
Write user-defined headers and keep track of the interesting ones.
Definition: sendlib.c:2253
char * x_comment_to
List of &#39;X-comment-to&#39; fields.
Definition: envelope.h:78
void mutt_write_references(const struct ListHead *r, FILE *fp, size_t trim)
Add the message references to a list.
Definition: sendlib.c:1837
const char * GitVer
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:50
"light" mode (used for edit_hdrs)
Definition: sendlib.h:63
fcc mode, like normal mode but for Bcc header
Definition: sendlib.h:61
void mutt_write_addrlist(struct AddressList *al, FILE *fp, int linelen, bool display)
Wrapper for mutt_write_address()
Definition: sendlib.c:1791
bool is_overridden[mutt_array_size(userhdrs_override_headers)]
Definition: sendlib.c:140
char * subject
Email&#39;s subject.
Definition: envelope.h:66
char * newsgroups
List of newsgroups.
Definition: envelope.h:75
WHERE bool C_XCommentTo
Config: (nntp) Add &#39;X-Comment-To&#39; header that contains article author.
Definition: globals.h:283
char * followup_to
List of &#39;followup-to&#39; fields.
Definition: envelope.h:77
int mutt_write_mime_header(struct Body *a, FILE *fp)
Create a MIME header.
Definition: sendlib.c:395
#define STAILQ_EMPTY(head)
Definition: queue.h:345
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
struct AddressList sender
Email&#39;s sender.
Definition: envelope.h:61
Write protected headers.
Definition: sendlib.h:64
#define TAILQ_EMPTY(head)
Definition: queue.h:714
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:47
struct ListHead references
message references (in reverse order)
Definition: envelope.h:81
int mutt_autocrypt_write_gossip_headers(struct Envelope *env, FILE *fp)
Write the Autocrypt gossip headers to a file.
Definition: autocrypt.c:765
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:1138
int mutt_write_one_header(FILE *fp, const char *tag, const char *value, const char *pfx, int wraplen, CopyHeaderFlags chflags)
Write one header line to a file.
Definition: sendlib.c:2149
int mutt_autocrypt_write_autocrypt_header(struct Envelope *env, FILE *fp)
Write the Autocrypt header to a file.
Definition: autocrypt.c:728
+ 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)
static

RFC2047-encode a list of headers.

Parameters
hString List of headers

The strings are encoded in-place.

Definition at line 2489 of file sendlib.c.

2490 {
2491  char *tmp = NULL;
2492  char *p = NULL;
2493  int i;
2494 
2495  struct ListNode *np = NULL;
2496  STAILQ_FOREACH(np, h, entries)
2497  {
2498  p = strchr(np->data, ':');
2499  if (!p)
2500  continue;
2501 
2502  i = p - np->data;
2503  p = mutt_str_skip_email_wsp(p + 1);
2504  tmp = mutt_str_strdup(p);
2505 
2506  if (!tmp)
2507  continue;
2508 
2509  rfc2047_encode(&tmp, NULL, i + 2, C_SendCharset);
2510  mutt_mem_realloc(&np->data, i + 2 + mutt_str_strlen(tmp) + 1);
2511 
2512  sprintf(np->data + i + 2, "%s", tmp);
2513 
2514  FREE(&tmp);
2515  }
2516 }
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:689
char * C_SendCharset
Config: Character sets for outgoing mail.
Definition: email_globals.c:38
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:799
#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:612
char * data
String.
Definition: list.h:35
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define FREE(x)
Definition: memory.h:40
A List node for strings.
Definition: list.h:33
+ 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)

Get the Fully-Qualified Domain Name.

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

Definition at line 2526 of file sendlib.c.

2527 {
2528  if (!C_Hostname || (C_Hostname[0] == '@'))
2529  return NULL;
2530 
2531  char *p = C_Hostname;
2532 
2533  if (may_hide_host && C_HiddenHost)
2534  {
2535  p = strchr(C_Hostname, '.');
2536  if (p)
2537  p++;
2538 
2539  // sanity check: don't hide the host if the fqdn is something like example.com
2540  if (!p || !strchr(p, '.'))
2541  p = C_Hostname;
2542  }
2543 
2544  return p;
2545 }
bool C_HiddenHost
Config: Don&#39;t use the hostname, just the domain, when generating the message id.
Definition: sendlib.c:85
WHERE char * C_Hostname
Config: Fully-qualified domain name of this machine.
Definition: globals.h:113
+ Here is the caller graph for this function:

◆ gen_msgid()

static char* gen_msgid ( void  )
static

Generate a unique Message ID.

Return values
ptrMessage ID
Note
The caller should free the string

Definition at line 2553 of file sendlib.c.

2554 {
2555  char buf[128];
2556  unsigned char rndid[MUTT_RANDTAG_LEN + 1];
2557 
2558  mutt_rand_base32(rndid, sizeof(rndid) - 1);
2559  rndid[MUTT_RANDTAG_LEN] = 0;
2560  const char *fqdn = mutt_fqdn(false);
2561  if (!fqdn)
2562  fqdn = NONULL(ShortHostname);
2563 
2564  struct tm tm = mutt_date_gmtime(MUTT_DATE_NOW);
2565  snprintf(buf, sizeof(buf), "<%d%02d%02d%02d%02d%02d.%s@%s>", tm.tm_year + 1900,
2566  tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, rndid, fqdn);
2567  return mutt_str_strdup(buf);
2568 }
#define NONULL(x)
Definition: string2.h:37
#define MUTT_RANDTAG_LEN
Definition: sendlib.c:98
#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:755
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2526
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
WHERE char * ShortHostname
Short version of the hostname.
Definition: globals.h:50
void mutt_rand_base32(void *buf, size_t buflen)
Fill a buffer with a base32-encoded random string.
Definition: muttlib.c:514
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ alarm_handler()

static void alarm_handler ( int  sig)
static

Async notification of an alarm signal.

Parameters
sigSignal, (SIGALRM)

Definition at line 2574 of file sendlib.c.

2575 {
2576  SigAlrm = 1;
2577 }
WHERE SIG_ATOMIC_VOLATILE_T SigAlrm
true after SIGALRM is received
Definition: globals.h:78
+ Here is the caller graph for this function:

◆ send_msg()

static int send_msg ( const char *  path,
char **  args,
const char *  msg,
char **  tempfile 
)
static

invoke sendmail in a subshell

Parameters
[in]pathPath to program to execute
[in]argsArguments to pass to program
[in]msgTemp file containing message to send
[out]tempfileIf sendmail is put in the background, this points to the temporary file containing the stdout of the child process. If it is NULL, stderr and stdout are not redirected.
Return values
0Success
>0Failure, return code from sendmail

Definition at line 2591 of file sendlib.c.

2592 {
2593  sigset_t set;
2594  int st;
2595 
2597 
2598  sigemptyset(&set);
2599  /* we also don't want to be stopped right now */
2600  sigaddset(&set, SIGTSTP);
2601  sigprocmask(SIG_BLOCK, &set, NULL);
2602 
2603  if ((C_SendmailWait >= 0) && tempfile)
2604  {
2605  struct Buffer *tmp = mutt_buffer_pool_get();
2606  mutt_buffer_mktemp(tmp);
2607  *tempfile = mutt_buffer_strdup(tmp);
2609  }
2610 
2611  pid_t pid = fork();
2612  if (pid == 0)
2613  {
2614  struct sigaction act, oldalrm;
2615 
2616  /* save parent's ID before setsid() */
2617  pid_t ppid = getppid();
2618 
2619  /* we want the delivery to continue even after the main process dies,
2620  * so we put ourselves into another session right away */
2621  setsid();
2622 
2623  /* next we close all open files */
2624  close(0);
2625 #ifdef OPEN_MAX
2626  for (int fd = tempfile ? 1 : 3; fd < OPEN_MAX; fd++)
2627  close(fd);
2628 #elif defined(_POSIX_OPEN_MAX)
2629  for (int fd = tempfile ? 1 : 3; fd < _POSIX_OPEN_MAX; fd++)
2630  close(fd);
2631 #else
2632  if (tempfile)
2633  {
2634  close(1);
2635  close(2);
2636  }
2637 #endif
2638 
2639  /* now the second fork() */
2640  pid = fork();
2641  if (pid == 0)
2642  {
2643  /* "msg" will be opened as stdin */
2644  if (open(msg, O_RDONLY, 0) < 0)
2645  {
2646  unlink(msg);
2647  _exit(S_ERR);
2648  }
2649  unlink(msg);
2650 
2651  if ((C_SendmailWait >= 0) && tempfile && *tempfile)
2652  {
2653  /* *tempfile will be opened as stdout */
2654  if (open(*tempfile, O_WRONLY | O_APPEND | O_CREAT | O_EXCL, 0600) < 0)
2655  _exit(S_ERR);
2656  /* redirect stderr to *tempfile too */
2657  if (dup(1) < 0)
2658  _exit(S_ERR);
2659  }
2660  else if (tempfile)
2661  {
2662  if (open("/dev/null", O_WRONLY | O_APPEND) < 0) /* stdout */
2663  _exit(S_ERR);
2664  if (open("/dev/null", O_RDWR | O_APPEND) < 0) /* stderr */
2665  _exit(S_ERR);
2666  }
2667 
2668  /* execvpe is a glibc extension */
2669  /* execvpe (path, args, mutt_envlist_getlist()); */
2670  execvp(path, args);
2671  _exit(S_ERR);
2672  }
2673  else if (pid == -1)
2674  {
2675  unlink(msg);
2676  FREE(tempfile);
2677  _exit(S_ERR);
2678  }
2679 
2680  /* C_SendmailWait > 0: interrupt waitpid() after C_SendmailWait seconds
2681  * C_SendmailWait = 0: wait forever
2682  * C_SendmailWait < 0: don't wait */
2683  if (C_SendmailWait > 0)
2684  {
2685  SigAlrm = 0;
2686  act.sa_handler = alarm_handler;
2687 #ifdef SA_INTERRUPT
2688  /* need to make sure waitpid() is interrupted on SIGALRM */
2689  act.sa_flags = SA_INTERRUPT;
2690 #else
2691  act.sa_flags = 0;
2692 #endif
2693  sigemptyset(&act.sa_mask);
2694  sigaction(SIGALRM, &act, &oldalrm);
2695  alarm(C_SendmailWait);
2696  }
2697  else if (C_SendmailWait < 0)
2698  _exit(0xff & EX_OK);
2699 
2700  if (waitpid(pid, &st, 0) > 0)
2701  {
2702  st = WIFEXITED(st) ? WEXITSTATUS(st) : S_ERR;
2703  if (C_SendmailWait && (st == (0xff & EX_OK)) && tempfile && *tempfile)
2704  {
2705  unlink(*tempfile); /* no longer needed */
2706  FREE(tempfile);
2707  }
2708  }
2709  else
2710  {
2711  st = ((C_SendmailWait > 0) && (errno == EINTR) && SigAlrm) ? S_BKG : S_ERR;
2712  if ((C_SendmailWait > 0) && tempfile && *tempfile)
2713  {
2714  unlink(*tempfile);
2715  FREE(tempfile);
2716  }
2717  }
2718 
2719  if (C_SendmailWait > 0)
2720  {
2721  /* reset alarm; not really needed, but... */
2722  alarm(0);
2723  sigaction(SIGALRM, &oldalrm, NULL);
2724  }
2725 
2726  if ((kill(ppid, 0) == -1) && (errno == ESRCH) && tempfile && *tempfile)
2727  {
2728  /* the parent is already dead */
2729  unlink(*tempfile);
2730  FREE(tempfile);
2731  }
2732 
2733  _exit(st);
2734  }
2735 
2736  sigprocmask(SIG_UNBLOCK, &set, NULL);
2737 
2738  if ((pid != -1) && (waitpid(pid, &st, 0) > 0))
2739  st = WIFEXITED(st) ? WEXITSTATUS(st) : S_ERR; /* return child status */
2740  else
2741  st = S_ERR; /* error */
2742 
2744 
2745  return st;
2746 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:81
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define S_ERR
Definition: string2.h:42
void mutt_sig_block_system(void)
Block signals before calling exec()
Definition: signal.c:183
WHERE SIG_ATOMIC_VOLATILE_T SigAlrm
true after SIGALRM is received
Definition: globals.h:78
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
char * mutt_buffer_strdup(struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
String manipulation buffer.
Definition: buffer.h:33
#define S_BKG
Definition: string2.h:43
void mutt_sig_unblock_system(bool restore)
Restore previously blocked signals.
Definition: signal.c:207
static void alarm_handler(int sig)
Async notification of an alarm signal.
Definition: sendlib.c:2574
short C_SendmailWait
Config: Time to wait for sendmail to finish.
Definition: sendlib.c:92
#define FREE(x)
Definition: memory.h:40
va_list args
Definition: acutest.h:700
#define EX_OK
Definition: sendlib.c:73
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ add_args_one()

static char** add_args_one ( char **  args,
size_t *  argslen,
size_t *  argsmax,
struct Address addr 
)
static

Add an Address to a dynamic array.

Parameters
[out]argsArray to add to
[out]argslenNumber of entries in array
[out]argsmaxAllocated size of the array
[in]addrAddress to add
Return values
ptrUpdated array

Definition at line 2756 of file sendlib.c.

2757 {
2758  /* weed out group mailboxes, since those are for display only */
2759  if (addr->mailbox && !addr->group)
2760  {
2761  if (*argslen == *argsmax)
2762  mutt_mem_realloc(&args, (*argsmax += 5) * sizeof(char *));
2763  args[(*argslen)++] = addr->mailbox;
2764  }
2765  return args;
2766 }
char * mailbox
Mailbox and host address.
Definition: address.h:37
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
bool group
Group mailbox?
Definition: address.h:38
va_list args
Definition: acutest.h:700
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ add_args()

static char** add_args ( char **  args,
size_t *  argslen,
size_t *  argsmax,
struct AddressList *  al 
)
static

Add a list of Addresses to a dynamic array.

Parameters
[out]argsArray to add to
[out]argslenNumber of entries in array
[out]argsmaxAllocated size of the array
[in]alAddresses to add
Return values
ptrUpdated array

Definition at line 2776 of file sendlib.c.

2777 {
2778  if (!al)
2779  return args;
2780 
2781  struct Address *a = NULL;
2782  TAILQ_FOREACH(a, al, entries)
2783  {
2784  args = add_args_one(args, argslen, argsmax, a);
2785  }
2786  return args;
2787 }
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
An email address.
Definition: address.h:34
va_list args
Definition: acutest.h:700
static char ** add_args_one(char **args, size_t *argslen, size_t *argsmax, struct Address *addr)
Add an Address to a dynamic array.
Definition: sendlib.c:2756
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ add_option()

static char** add_option ( char **  args,
size_t *  argslen,
size_t *  argsmax,
char *  s 
)
static

Add a string to a dynamic array.

Parameters
[out]argsArray to add to
[out]argslenNumber of entries in array
[out]argsmaxAllocated size of the array
[in]sstring to add
Return values
ptrUpdated array
Note
The array may be realloc()'d

Definition at line 2799 of file sendlib.c.

2800 {
2801  if (*argslen == *argsmax)
2802  mutt_mem_realloc(&args, (*argsmax += 5) * sizeof(char *));
2803  args[(*argslen)++] = s;
2804  return args;
2805 }
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
va_list args
Definition: acutest.h:700
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_invoke_sendmail()

int mutt_invoke_sendmail ( struct AddressList *  from,
struct AddressList *  to,
struct AddressList *  cc,
struct AddressList *  bcc,
const char *  msg,
int  eightbit 
)

Run sendmail.

Parameters
fromThe sender
toRecipients
ccRecipients
bccRecipients
msgFile containing message
eightbitMessage contains 8bit chars
Return values
0Success
-1Failure

Definition at line 2818 of file sendlib.c.

2821 {
2822  char *ps = NULL, *path = NULL, *s = NULL, *childout = NULL;
2823  char **args = NULL;
2824  size_t argslen = 0, argsmax = 0;
2825  char **extra_args = NULL;
2826  int i;
2827 
2828 #ifdef USE_NNTP
2829  if (OptNewsSend)
2830  {
2831  char cmd[1024];
2832 
2833  mutt_expando_format(cmd, sizeof(cmd), 0, sizeof(cmd), NONULL(C_Inews),
2835  if (!*cmd)
2836  {
2837  i = nntp_post(Context->mailbox, msg);
2838  unlink(msg);
2839  return i;
2840  }
2841 
2842  s = mutt_str_strdup(cmd);
2843  }
2844  else
2845 #endif
2847 
2848  /* ensure that $sendmail is set to avoid a crash. http://dev.mutt.org/trac/ticket/3548 */
2849  if (!s)
2850  {
2851  mutt_error(_("$sendmail must be set in order to send mail"));
2852  return -1;
2853  }
2854 
2855  ps = s;
2856  i = 0;
2857  while ((ps = strtok(ps, " ")))
2858  {
2859  if (argslen == argsmax)
2860  mutt_mem_realloc(&args, sizeof(char *) * (argsmax += 5));
2861 
2862  if (i)
2863  {
2864  if (mutt_str_strcmp(ps, "--") == 0)
2865  break;
2866  args[argslen++] = ps;
2867  }
2868  else
2869  {
2870  path = mutt_str_strdup(ps);
2871  ps = strrchr(ps, '/');
2872  if (ps)
2873  ps++;
2874  else
2875  ps = path;
2876  args[argslen++] = ps;
2877  }
2878  ps = NULL;
2879  i++;
2880  }
2881 
2882 #ifdef USE_NNTP
2883  if (!OptNewsSend)
2884  {
2885 #endif
2886  size_t extra_argslen = 0;
2887  /* If C_Sendmail contained a "--", we save the recipients to append to
2888  * args after other possible options added below. */
2889  if (ps)
2890  {
2891  ps = NULL;
2892  size_t extra_argsmax = 0;
2893  while ((ps = strtok(ps, " ")))
2894  {
2895  if (extra_argslen == extra_argsmax)
2896  mutt_mem_realloc(&extra_args, sizeof(char *) * (extra_argsmax += 5));
2897 
2898  extra_args[extra_argslen++] = ps;
2899  ps = NULL;
2900  }
2901  }
2902 
2903  if (eightbit && C_Use8bitmime)
2904  args = add_option(args, &argslen, &argsmax, "-B8BITMIME");
2905 
2906  if (C_UseEnvelopeFrom)
2907  {
2909  {
2910  args = add_option(args, &argslen, &argsmax, "-f");
2911  args = add_args_one(args, &argslen, &argsmax, C_EnvelopeFromAddress);
2912  }
2913  else if (!TAILQ_EMPTY(from) && !TAILQ_NEXT(TAILQ_FIRST(from), entries))
2914  {
2915  args = add_option(args, &argslen, &argsmax, "-f");
2916  args = add_args(args, &argslen, &argsmax, from);
2917  }
2918  }
2919 
2920  if (C_DsnNotify)
2921  {
2922  args = add_option(args, &argslen, &argsmax, "-N");
2923  args = add_option(args, &argslen, &argsmax, C_DsnNotify);
2924  }
2925  if (C_DsnReturn)
2926  {
2927  args = add_option(args, &argslen, &argsmax, "-R");
2928  args = add_option(args, &argslen, &argsmax, C_DsnReturn);
2929  }
2930  args = add_option(args, &argslen, &argsmax, "--");
2931  for (i = 0; i < extra_argslen; i++)
2932  args = add_option(args, &argslen, &argsmax, extra_args[i]);
2933  args = add_args(args, &argslen, &argsmax, to);
2934  args = add_args(args, &argslen, &argsmax, cc);
2935  args = add_args(args, &argslen, &argsmax, bcc);
2936 #ifdef USE_NNTP
2937  }
2938 #endif
2939 
2940  if (argslen == argsmax)
2941  mutt_mem_realloc(&args, sizeof(char *) * (++argsmax));
2942 
2943  args[argslen++] = NULL;
2944 
2945  /* Some user's $sendmail command uses gpg for password decryption,
2946  * and is set up to prompt using ncurses pinentry. If we
2947  * mutt_endwin() it leaves other users staring at a blank screen.
2948  * So instead, just force a hard redraw on the next refresh. */
2949  if (!OptNoCurses)
2951 
2952  i = send_msg(path, args, msg, OptNoCurses ? NULL : &childout);
2953  if (i != (EX_OK & 0xff))
2954  {
2955  if (i != S_BKG)
2956  {
2957  const char *e = mutt_str_sysexit(i);
2958  mutt_error(_("Error sending message, child exited %d (%s)"), i, NONULL(e));
2959  if (childout)
2960  {
2961  struct stat st;
2962 
2963  if ((stat(childout, &st) == 0) && (st.st_size > 0))
2964  {
2965  mutt_do_pager(_("Output of the delivery process"), childout,
2966  MUTT_PAGER_NO_FLAGS, NULL);
2967  }
2968  }
2969  }
2970  }
2971  else if (childout)
2972  unlink(childout);
2973 
2974  FREE(&childout);
2975  FREE(&path);
2976  FREE(&s);
2977  FREE(&args);
2978  FREE(&extra_args);
2979 
2980  if (i == (EX_OK & 0xff))
2981  i = 0;
2982  else if (i == S_BKG)
2983  i = 1;
2984  else
2985  i = -1;
2986  return i;
2987 }
The "current" mailbox.
Definition: context.h:37
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t *callback, unsigned long data, MuttFormatFlags flags)
Expand expandos (x) in a string.
Definition: muttlib.c:863
char * C_Sendmail
Config: External command to send email.
Definition: sendlib.c:91
#define NONULL(x)
Definition: string2.h:37
static int send_msg(const char *path, char **args, const char *msg, char **tempfile)
invoke sendmail in a subshell
Definition: sendlib.c:2591
#define TAILQ_FIRST(head)
Definition: queue.h:716
static char ** add_args(char **args, size_t *argslen, size_t *argsmax, struct AddressList *al)
Add a list of Addresses to a dynamic array.
Definition: sendlib.c:2776
#define _(a)
Definition: message.h:28
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:49
#define S_BKG
Definition: string2.h:43
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
bool C_Use8bitmime
Config: Use 8-bit messages and ESMTP to send messages.
Definition: sendlib.c:93
struct Mailbox * mailbox
Definition: context.h:51
char * C_Inews
Config: (nntp) External command to post news articles.
Definition: sendlib.c:86
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
const char * mutt_str_sysexit(int err_num)
Return a string matching an error code.
Definition: string.c:117
static char ** add_option(char **args, size_t *argslen, size_t *argsmax, char *s)
Add a string to a dynamic array.
Definition: sendlib.c:2799
bool C_UseEnvelopeFrom
Config: Set the envelope sender of the message.
Definition: sendlib.c:94
int nntp_post(struct Mailbox *m, const char *msg)
Post article.
Definition: nntp.c:1976
const char * nntp_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, unsigned long data, MuttFormatFlags flags)
Expand the newsrc filename - Implements format_t.
Definition: newsrc.c:922
WHERE char * C_DsnReturn
Config: What to send as a notification of message delivery or delay.
Definition: globals.h:110
int mutt_do_pager(const char *banner, const char *tempfile, PagerFlags do_color, struct Pager *info)
Display some page-able text to the user.
Definition: curs_lib.c:666
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define mutt_error(...)
Definition: logging.h:84
WHERE struct Address * C_EnvelopeFromAddress
Config: Manually set the sender for outgoing messages.
Definition: globals.h:93
#define FREE(x)
Definition: memory.h:40
#define TAILQ_NEXT(elm, field)
Definition: queue.h:825
#define TAILQ_EMPTY(head)
Definition: queue.h:714
va_list args
Definition: acutest.h:700
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:47
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition: curs_lib.c:129
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:638
WHERE char * C_DsnNotify
Config: Request notification for message delivery or delay.
Definition: globals.h:109
static char ** add_args_one(char **args, size_t *argslen, size_t *argsmax, struct Address *addr)
Add an Address to a dynamic array.
Definition: sendlib.c:2756
#define EX_OK
Definition: sendlib.c:73
#define MUTT_PAGER_NO_FLAGS
No flags are set.
Definition: pager.h:43
+ 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 
)

Prepare an email header.

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

Encode all the headers prior to sending the email.

For postponing (!final) do the necessary encodings only

Definition at line 2998 of file sendlib.c.

2999 {
3000  if (final)
3001  {
3002  if (!TAILQ_EMPTY(&env->bcc) && TAILQ_EMPTY(&env->to) && TAILQ_EMPTY(&env->cc))
3003  {
3004  /* some MTA's will put an Apparently-To: header field showing the Bcc:
3005  * recipients if there is no To: or Cc: field, so attempt to suppress
3006  * it by using an empty To: field. */
3007  struct Address *to = mutt_addr_new();
3008  to->group = true;
3009  mutt_addrlist_append(&env->to, to);
3011 
3012  char buf[1024];
3013  buf[0] = '\0';
3014  mutt_addr_cat(buf, sizeof(buf), "undisclosed-recipients", AddressSpecials);
3015 
3016  to->mailbox = mutt_str_strdup(buf);
3017  }
3018 
3019  mutt_set_followup_to(env);
3020 
3021  if (!env->message_id)
3022  env->message_id = gen_msgid();
3023  }
3024 
3025  /* Take care of 8-bit => 7-bit conversion. */
3027  encode_headers(&env->userhdrs);
3028 }
void rfc2047_encode_envelope(struct Envelope *env)
Encode the fields of an Envelope.
Definition: rfc2047.c:796
static char * gen_msgid(void)
Generate a unique Message ID.
Definition: sendlib.c:2553
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
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
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
void mutt_set_followup_to(struct Envelope *env)
Set followup-to field.
Definition: send.c:1213
bool group
Group mailbox?
Definition: address.h:38
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
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:672
static void encode_headers(struct ListHead *h)
RFC2047-encode a list of headers.
Definition: sendlib.c:2489
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1402
+ 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 3037 of file sendlib.c.

3038 {
3039  struct ListNode *item = NULL;
3040  STAILQ_FOREACH(item, &env->userhdrs, entries)
3041  {
3042  rfc2047_decode(&item->data);
3043  }
3044 
3046 
3047  /* back conversions */
3049 }
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:1382
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:776
void rfc2047_decode(char **pd)
Decode any RFC2047-encoded header fields.
Definition: rfc2047.c:636
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
char * data
String.
Definition: list.h:35
A List node for strings.
Definition: list.h:33
+ 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 
)
static

Bounce an email message.

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

Definition at line 3061 of file sendlib.c.

3063 {
3064  if (!e)
3065  return -1;
3066 
3067  int rc = 0;
3068 
3069  struct Buffer *tempfile = mutt_buffer_pool_get();
3070  mutt_buffer_mktemp(tempfile);
3071  FILE *fp_tmp = mutt_file_fopen(mutt_b2s(tempfile), "w");
3072  if (fp_tmp)
3073  {
3074  char date[128];
3076 
3077  if (!C_BounceDelivered)
3078  chflags |= CH_WEED_DELIVERED;
3079 
3080  fseeko(fp, e->offset, SEEK_SET);
3081  fprintf(fp_tmp, "Resent-From: %s", resent_from);
3082  fprintf(fp_tmp, "\nResent-%s", mutt_date_make_date(date, sizeof(date)));
3083  char *msgid_str = gen_msgid();
3084  fprintf(fp_tmp, "Resent-Message-ID: %s\n", msgid_str);
3085  FREE(&msgid_str);
3086  fputs("Resent-To: ", fp_tmp);
3087  mutt_write_addrlist(to, fp_tmp, 11, 0);
3088  mutt_copy_header(fp, e, fp_tmp, chflags, NULL, 0);
3089  fputc('\n', fp_tmp);
3090  mutt_file_copy_bytes(fp, fp_tmp, e->content->length);
3091  if (mutt_file_fclose(&fp_tmp) != 0)
3092  {
3093  mutt_perror(mutt_b2s(tempfile));
3094  unlink(mutt_b2s(tempfile));
3095  return -1;
3096  }
3097 #ifdef USE_SMTP
3098  if (C_SmtpUrl)
3099  {
3100  rc = mutt_smtp_send(env_from, to, NULL, NULL, mutt_b2s(tempfile),
3101  e->content->encoding == ENC_8BIT);
3102  }
3103  else
3104 #endif
3105  {
3106  rc = mutt_invoke_sendmail(env_from, to, NULL, NULL, mutt_b2s(tempfile),
3107  e->content->encoding == ENC_8BIT);
3108  }
3109  }
3110 
3111  mutt_buffer_pool_release(&tempfile);
3112  return rc;
3113 }
WHERE char * C_SmtpUrl
Config: (smtp) Url of the SMTP server.
Definition: globals.h:143
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:81
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
static char * gen_msgid(void)
Generate a unique Message ID.
Definition: sendlib.c:2553
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:372
#define CH_WEED_DELIVERED
Weed eventual Delivered-To headers.
Definition: copy.h:64
int mutt_invoke_sendmail(struct AddressList *from, struct AddressList *to, struct AddressList *cc, struct AddressList *bcc, const char *msg, int eightbit)
Run sendmail.
Definition: sendlib.c:2818
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
unsigned int encoding
content-transfer-encoding
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
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
void mutt_write_addrlist(struct AddressList *al, FILE *fp, int linelen, bool display)
Wrapper for mutt_write_address()
Definition: sendlib.c:1791
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:83
bool C_BounceDelivered
Config: Add &#39;Delivered-To&#39; to bounced messages.
Definition: sendlib.c:82
#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:392
#define FREE(x)
Definition: memory.h:40
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)
Send a message using SMTP.
Definition: smtp.c:763
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 
)

Bounce an email message.

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

Definition at line 3123 of file sendlib.c.

3124 {
3125  if (!fp || !e || !to || TAILQ_EMPTY(to))
3126  return -1;
3127 
3128  const char *fqdn = mutt_fqdn(true);
3129  char resent_from[256];
3130  char *err = NULL;
3131 
3132  resent_from[0] = '\0';
3133  struct Address *from = mutt_default_from();
3134  struct AddressList from_list = TAILQ_HEAD_INITIALIZER(from_list);
3135  mutt_addrlist_append(&from_list, from);
3136 
3137  /* mutt_default_from() does not use $realname if the real name is not set
3138  * in $from, so we add it here. The reason it is not added in
3139  * mutt_default_from() is that during normal sending, we execute
3140  * send-hooks and set the realname last so that it can be changed based
3141  * upon message criteria. */
3142  if (!from->personal)
3144 
3145  mutt_addrlist_qualify(&from_list, fqdn);
3146 
3147  rfc2047_encode_addrlist(&from_list, "Resent-From");
3148  if (mutt_addrlist_to_intl(&from_list, &err))
3149  {
3150  mutt_error(_("Bad IDN %s while preparing resent-from"), err);
3151  FREE(&err);
3152  mutt_addrlist_clear(&from_list);
3153  return -1;
3154  }
3155  mutt_addrlist_write(&from_list, resent_from, sizeof(resent_from), false);
3156 
3157 #ifdef USE_NNTP
3158  OptNewsSend = false;
3159 #endif
3160 
3161  /* prepare recipient list. idna conversion appears to happen before this
3162  * function is called, since the user receives confirmation of the address
3163  * list being bounced to. */
3164  struct AddressList resent_to = TAILQ_HEAD_INITIALIZER(resent_to);
3165  mutt_addrlist_copy(&resent_to, to, false);
3166  rfc2047_encode_addrlist(&resent_to, "Resent-To");
3167  int rc = bounce_message(fp, e, &resent_to, resent_from, &from_list);
3168  mutt_addrlist_clear(&resent_to);
3169  mutt_addrlist_clear(&from_list);
3170 
3171  return rc;
3172 }
static int bounce_message(FILE *fp, struct Email *e, struct AddressList *to, const char *resent_from, struct AddressList *env_from)
Bounce an email message.
Definition: sendlib.c:3061
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1382
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:728
#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:735
struct Address * mutt_default_from(void)
Get a default &#39;from&#39; Address.
Definition: send.c:1333
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2526
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:641
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1217
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define mutt_error(...)
Definition: logging.h:84
#define FREE(x)
Definition: memory.h:40
WHERE char * C_Realname
Config: Real name of the user.
Definition: globals.h:139
#define TAILQ_EMPTY(head)
Definition: queue.h:714
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:47
#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:1138
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1402
+ 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 3179 of file sendlib.c.

3180 {
3181  for (; b; b = b->next)
3182  {
3183  if ((b->type == TYPE_MESSAGE) || (b->type == TYPE_MULTIPART))
3184  set_noconv_flags(b->parts, flag);
3185  else if ((b->type == TYPE_TEXT) && b->noconv)
3186  {
3187  if (flag)
3188  mutt_param_set(&b->parameter, "x-mutt-noconv", "yes");
3189  else
3190  mutt_param_delete(&b->parameter, "x-mutt-noconv");
3191  }
3192  }
3193 }
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
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:3179
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 
)

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
Return values
0Success
-1Failure

Definition at line 3206 of file sendlib.c.

3208 {
3209  char fcc_tok[PATH_MAX];
3210  char fcc_expanded[PATH_MAX];
3211 
3212  mutt_str_strfcpy(fcc_tok, path, sizeof(fcc_tok));
3213 
3214  char *tok = strtok(fcc_tok, ",");
3215  if (!tok)
3216  return -1;
3217 
3218  mutt_debug(LL_DEBUG1, "Fcc: initial mailbox = '%s'\n", tok);
3219  /* mutt_expand_path already called above for the first token */
3220  int status = mutt_write_fcc(tok, e, msgid, post, fcc, finalpath);
3221  if (status != 0)
3222  return status;
3223 
3224  while ((tok = strtok(NULL, ",")))
3225  {
3226  if (!*tok)
3227  continue;
3228 
3229  /* Only call mutt_expand_path if tok has some data */
3230  mutt_debug(LL_DEBUG1, "Fcc: additional mailbox token = '%s'\n", tok);
3231  mutt_str_strfcpy(fcc_expanded, tok, sizeof(fcc_expanded));
3232  mutt_expand_path(fcc_expanded, sizeof(fcc_expanded));
3233  mutt_debug(LL_DEBUG1, " Additional mailbox expanded = '%s'\n", fcc_expanded);
3234  status = mutt_write_fcc(fcc_expanded, e, msgid, post, fcc, finalpath);
3235  if (status != 0)
3236  return status;
3237  }
3238 
3239  return 0;
3240 }
int mutt_write_fcc(const char *path, struct Email *e, const char *msgid, bool post, const char *fcc, char **finalpath)
Write email to FCC mailbox.
Definition: sendlib.c:3253
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:133
#define PATH_MAX
Definition: mutt.h:44
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:773
Log at debug level 1.
Definition: logging.h:40
#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 
)

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
Return values
0Success
-1Failure

Definition at line 3253 of file sendlib.c.

3255 {
3256  struct Message *msg = NULL;
3257  struct Buffer *tempfile = NULL;
3258  FILE *fp_tmp = NULL;
3259  int rc = -1;
3260  bool need_mailbox_cleanup = false;
3261  struct stat st;
3262  char buf[128];
3263  MsgOpenFlags onm_flags;
3264 
3265  if (post)
3266  set_noconv_flags(e->content, true);
3267 
3268 #ifdef RECORD_FOLDER_HOOK
3269  mutt_folder_hook(path, NULL);
3270 #endif
3271  struct Mailbox *m_fcc = mx_path_resolve(path);
3272  bool old_append = m_fcc->append;
3273  struct Context *ctx_fcc = mx_mbox_open(m_fcc, MUTT_APPEND | MUTT_QUIET);
3274  if (!ctx_fcc)
3275  {
3276  mutt_debug(LL_DEBUG1, "unable to open mailbox %s in append-mode, aborting\n", path);
3277  mailbox_free(&m_fcc);
3278  goto done;
3279  }
3280 
3281  /* We need to add a Content-Length field to avoid problems where a line in
3282  * the message body begins with "From " */
3283  if ((ctx_fcc->mailbox->type == MUTT_MMDF) || (ctx_fcc->mailbox->type == MUTT_MBOX))
3284  {
3285  tempfile = mutt_buffer_pool_get();
3286  mutt_buffer_mktemp(tempfile);
3287  fp_tmp = mutt_file_fopen(mutt_b2s(tempfile), "w+");
3288  if (!fp_tmp)
3289  {
3290  mutt_perror(mutt_b2s(tempfile));
3291  mx_mbox_close(&ctx_fcc);
3292  goto done;
3293  }
3294  /* remember new mail status before appending message */
3295  need_mailbox_cleanup = true;
3296  stat(path, &st);
3297  }
3298 
3299  e->read = !post; /* make sure to put it in the 'cur' directory (maildir) */
3300  onm_flags = MUTT_ADD_FROM;
3301  if (post)
3302  onm_flags |= MUTT_SET_DRAFT;
3303  msg = mx_msg_open_new(ctx_fcc->mailbox, e, onm_flags);
3304  if (!msg)
3305  {
3306  mutt_file_fclose(&fp_tmp);
3307  mx_mbox_close(&ctx_fcc);
3308  goto done;
3309  }
3310 
3311  /* post == 1 => postpone message.
3312  * post == 0 => Normal mode. */
3316 
3317  /* (postponement) if this was a reply of some sort, <msgid> contains the
3318  * Message-ID: of message replied to. Save it using a special X-Mutt-
3319  * header so it can be picked up if the message is recalled at a later
3320  * point in time. This will allow the message to be marked as replied if
3321  * the same mailbox is still open. */
3322  if (post && msgid)
3323  fprintf(msg->fp, "X-Mutt-References: %s\n", msgid);
3324 
3325  /* (postponement) save the Fcc: using a special X-Mutt- header so that
3326  * it can be picked up when the message is recalled */
3327  if (post && fcc)
3328  fprintf(msg->fp, "X-Mutt-Fcc: %s\n", fcc);
3329 
3330  if ((ctx_fcc->mailbox->type == MUTT_MMDF) || (ctx_fcc->mailbox->type == MUTT_MBOX))
3331  fprintf(msg->fp, "Status: RO\n");
3332 
3333  /* mutt_rfc822_write_header() only writes out a Date: header with
3334  * mode == 0, i.e. _not_ postponement; so write out one ourself */
3335  if (post)
3336  fprintf(msg->fp, "%s", mutt_date_make_date(buf, sizeof(buf)));
3337 
3338  /* (postponement) if the mail is to be signed or encrypted, save this info */
3339  if (((WithCrypto & APPLICATION_PGP) != 0) && post && (e->security & APPLICATION_PGP))
3340  {
3341  fputs("X-Mutt-PGP: ", msg->fp);
3342  if (e->security & SEC_ENCRYPT)
3343  fputc('E', msg->fp);
3344  if (e->security & SEC_OPPENCRYPT)
3345  fputc('O', msg->fp);
3346  if (e->security & SEC_SIGN)
3347  {
3348  fputc('S', msg->fp);
3349  if (C_PgpSignAs)
3350  fprintf(msg->fp, "<%s>", C_PgpSignAs);
3351  }
3352  if (e->security & SEC_INLINE)
3353  fputc('I', msg->fp);
3354 #ifdef USE_AUTOCRYPT
3355  if (e->security & SEC_AUTOCRYPT)
3356  fputc('A', msg->fp);
3358  fputc('Z', msg->fp);
3359 #endif
3360  fputc('\n', msg->fp);
3361  }
3362 
3363  /* (postponement) if the mail is to be signed or encrypted, save this info */
3364  if (((WithCrypto & APPLICATION_SMIME) != 0) && post && (e->security & APPLICATION_SMIME))
3365  {
3366  fputs("X-Mutt-SMIME: ", msg->fp);
3367  if (e->security & SEC_ENCRYPT)
3368  {
3369  fputc('E', msg->fp);
3370  if (C_SmimeEncryptWith)
3371  fprintf(msg->fp, "C<%s>", C_SmimeEncryptWith);
3372  }
3373  if (e->security & SEC_OPPENCRYPT)
3374  fputc('O', msg->fp);
3375  if (e->security & SEC_SIGN)
3376  {
3377  fputc('S', msg->fp);
3378  if (C_SmimeSignAs)
3379  fprintf(msg->fp, "<%s>", C_SmimeSignAs);
3380  }
3381  if (e->security & SEC_INLINE)
3382  fputc('I', msg->fp);
3383  fputc('\n', msg->fp);
3384  }
3385 
3386 #ifdef MIXMASTER
3387  /* (postponement) if the mail is to be sent through a mixmaster
3388  * chain, save that information */
3389 
3390  if (post && !STAILQ_EMPTY(&e->chain))
3391  {
3392  fputs("X-Mutt-Mix:", msg->fp);
3393  struct ListNode *p = NULL;
3394  STAILQ_FOREACH(p, &e->chain, entries)
3395  {
3396  fprintf(msg->fp, " %s", (char *) p->data);
3397  }
3398 
3399  fputc('\n', msg->fp);
3400  }
3401 #endif
3402 
3403  if (fp_tmp)
3404  {
3405  mutt_write_mime_body(e->content, fp_tmp);
3406 
3407  /* make sure the last line ends with a newline. Emacs doesn't ensure this
3408  * will happen, and it can cause problems parsing the mailbox later. */
3409  fseek(fp_tmp, -1, SEEK_END);
3410  if (fgetc(fp_tmp) != '\n')
3411  {
3412  fseek(fp_tmp, 0, SEEK_END);
3413  fputc('\n', fp_tmp);
3414  }
3415 
3416  fflush(fp_tmp);
3417  if (ferror(fp_tmp))
3418  {
3419  mutt_debug(LL_DEBUG1, "%s: write failed\n", mutt_b2s(tempfile));
3420  mutt_file_fclose(&fp_tmp);
3421  unlink(mutt_b2s(tempfile));
3422  mx_msg_commit(ctx_fcc->mailbox, msg); /* XXX really? */
3423  mx_msg_close(ctx_fcc->mailbox, &msg);
3424  mx_mbox_close(&ctx_fcc);
3425  goto done;
3426  }
3427 
3428  /* count the number of lines */
3429  int lines = 0;
3430  char line_buf[1024];
3431  rewind(fp_tmp);
3432  while (fgets(line_buf, sizeof(line_buf), fp_tmp))
3433  lines++;
3434  fprintf(msg->fp, "Content-Length: " OFF_T_FMT "\n", (LOFF_T) ftello(fp_tmp));
3435  fprintf(msg->fp, "Lines: %d\n\n", lines);
3436 
3437  /* copy the body and clean up */
3438  rewind(fp_tmp);
3439  rc = mutt_file_copy_stream(fp_tmp, msg->fp);
3440  if (mutt_file_fclose(&fp_tmp) != 0)
3441  rc = -1;
3442  /* if there was an error, leave the temp version */
3443  if (rc >= 0)
3444  {
3445  unlink(mutt_b2s(tempfile));
3446  rc = 0;
3447  }
3448  }
3449  else
3450  {
3451  fputc('\n', msg->fp); /* finish off the header */
3452  rc = mutt_write_mime_body(e->content, msg->fp);
3453  }
3454 
3455  if (mx_msg_commit(ctx_fcc->mailbox, msg) != 0)
3456  rc = -1;
3457  else if (finalpath)
3458  *finalpath = mutt_str_strdup(msg->committed_path);
3459  mx_msg_close(ctx_fcc->mailbox, &msg);
3460  mx_mbox_close(&ctx_fcc);
3461 
3462  if (!post && need_mailbox_cleanup)
3463  mutt_mailbox_cleanup(path, &st);
3464 
3465  if (post)
3466  set_noconv_flags(e->content, false);
3467 
3468 done:
3469  if (m_fcc)
3470  m_fcc->append = old_append;
3471 #ifdef RECORD_FOLDER_HOOK
3472  /* We ran a folder hook for the destination mailbox,
3473  * now we run it for the user's current mailbox */
3474  if (Context && Context->mailbox->path)
3476 #endif
3477 
3478  if (fp_tmp)
3479  {
3480  mutt_file_fclose(&fp_tmp);
3481  unlink(mutt_b2s(tempfile));
3482  }
3483  mutt_buffer_pool_release(&tempfile);
3484 
3485  return rc;
3486 }
#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:81
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
#define WithCrypto
Definition: lib.h:163
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
int mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:593
void mutt_mailbox_cleanup(const char *path, struct stat *st)
Restore the timestamp of a mailbox.
Definition: mutt_mailbox.c:381
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:125
bool mutt_should_hide_protected_subject(struct Email *e)
Should NeoMutt hide the protected subject?
Definition: crypt.c:1088
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
A postponed Email, just the envelope info.
Definition: sendlib.h:62
String manipulation buffer.
Definition: buffer.h:33
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:255
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:134
char * mutt_date_make_date(char *buf, size_t buflen)
Write a date in RFC822 format to a buffer.
Definition: date.c:372
#define MUTT_SET_DRAFT
set the message draft flag
Definition: mx.h:67
int mutt_rfc822_write_header(FILE *fp, struct Envelope *env, struct Body *attach, enum MuttWriteHeaderMode mode, bool privacy, bool hide_protected_subject)
Write out one RFC822 header line.
Definition: sendlib.c:2320
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:132
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1171
void mutt_folder_hook(const char *path, const char *desc)
Perform a folder hook.
Definition: hook.c:508
bool read
Email is read.
Definition: email.h:51
struct Mailbox * mailbox
Definition: context.h:51
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:1036
#define mutt_b2s(buf)
Definition: buffer.h:41
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:138
struct ListHead chain
Mixmaster chain.
Definition: email.h:99
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:137
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:135
int mutt_write_mime_body(struct Body *a, FILE *fp)
Write a MIME part.
Definition: sendlib.c:553
WHERE char * C_SmimeEncryptWith
Config: Algorithm for encryption.
Definition: globals.h:166
&#39;mmdf&#39; Mailbox type
Definition: mailbox.h:49
bool append
Mailbox is opened in append mode.
Definition: mailbox.h:113
fcc mode, like normal mode but for Bcc header
Definition: sendlib.h:61
#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
WHERE bool C_CryptProtectedHeadersRead
Config: Display protected headers (Memory Hole) in the pager.
Definition: globals.h:270
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:133
&#39;mbox&#39; Mailbox type
Definition: mailbox.h:48
#define SEC_SIGN
Email is signed.
Definition: lib.h:126
char * committed_path
the final path generated by mx_msg_commit()
Definition: mx.h:87
char * data
String.
Definition: list.h:35
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
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
int mx_msg_commit(struct Mailbox *m, struct Message *msg)
Commit a message to a folder - Wrapper for MxOps::msg_commit()
Definition: mx.c:1150
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:1655
static void set_noconv_flags(struct Body *b, bool flag)
Set/reset the "x-mutt-noconv" flag.
Definition: sendlib.c:3179
#define STAILQ_EMPTY(head)
Definition: queue.h:345
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
WHERE char * C_PgpSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:161
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
WHERE char * C_SmimeSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:165
A List node for strings.
Definition: list.h:33
#define MUTT_ADD_FROM
add a From_ line
Definition: mx.h:66
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ C_Allow8bit

bool C_Allow8bit

Config: Allow 8-bit messages, don't use quoted-printable or base64.

Definition at line 80 of file sendlib.c.

◆ C_AttachCharset

char* C_AttachCharset

Config: When attaching files, use one of these character sets.

Definition at line 81 of file sendlib.c.

◆ C_BounceDelivered

bool C_BounceDelivered

Config: Add 'Delivered-To' to bounced messages.

Definition at line 82 of file sendlib.c.

◆ C_EncodeFrom

bool C_EncodeFrom

Config: Encode 'From ' as 'quote-printable' at the beginning of lines.

Definition at line 83 of file sendlib.c.

◆ C_ForwardDecrypt

bool C_ForwardDecrypt

Config: Decrypt the message when forwarding it.

Definition at line 84 of file sendlib.c.

◆ C_HiddenHost

bool C_HiddenHost

Config: Don't use the hostname, just the domain, when generating the message id.

Definition at line 85 of file sendlib.c.

◆ C_Inews

char* C_Inews

Config: (nntp) External command to post news articles.

Definition at line 86 of file sendlib.c.

◆ C_MimeForwardDecode

bool C_MimeForwardDecode

Config: Decode the forwarded message before attaching it.

Definition at line 87 of file sendlib.c.

◆ C_MimeSubject

bool C_MimeSubject

Config: (nntp) Encode the article subject in base64.

encode subject line with RFC2047

Definition at line 88 of file sendlib.c.

◆ C_MimeTypeQueryCommand

char* C_MimeTypeQueryCommand

Config: External command to determine the MIME type of an attachment.

Definition at line 89 of file sendlib.c.

◆ C_MimeTypeQueryFirst

bool C_MimeTypeQueryFirst

Config: Run the C_MimeTypeQueryCommand before the mime.types lookup.

Definition at line 90 of file sendlib.c.

◆ C_Sendmail

char* C_Sendmail

Config: External command to send email.

Definition at line 91 of file sendlib.c.

◆ C_SendmailWait

short C_SendmailWait

Config: Time to wait for sendmail to finish.

Definition at line 92 of file sendlib.c.

◆ C_Use8bitmime

bool C_Use8bitmime

Config: Use 8-bit messages and ESMTP to send messages.

Definition at line 93 of file sendlib.c.

◆ C_UseEnvelopeFrom

bool C_UseEnvelopeFrom

Config: Set the envelope sender of the message.

Definition at line 94 of file sendlib.c.

◆ C_UserAgent

bool C_UserAgent

Config: Add a 'User-Agent' head to outgoing mail.

Definition at line 95 of file sendlib.c.

◆ C_WrapHeaders

short C_WrapHeaders

Config: Width to wrap headers in outgoing messages.

Definition at line 96 of file sendlib.c.

◆ userhdrs_override_headers

const char* const userhdrs_override_headers[]
static
Initial value:
= {
"content-type:",
"user-agent:",
}

The next array/enum pair is used to to keep track of user headers that override pre-defined headers NeoMutt would emit.

Keep the array sorted and in sync with the enum.

Definition at line 127 of file sendlib.c.