NeoMutt  2019-12-07-60-g0cfa53
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/mutt.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 "filter.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 "ncrypt/ncrypt.h"
#include "options.h"
#include "pager.h"
#include "send.h"
#include "smtp.h"
#include "state.h"
#include "nntp/nntp.h"
#include "autocrypt/autocrypt.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 74 of file sendlib.c.

◆ MUTT_RANDTAG_LEN

#define MUTT_RANDTAG_LEN   16

Definition at line 99 of file sendlib.c.

Enumeration Type Documentation

◆ UserHdrsOverrideIdx

Enumerator
USERHDRS_OVERRIDE_CONTENT_TYPE 
USERHDRS_OVERRIDE_USER_AGENT 

Definition at line 133 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 150 of file sendlib.c.

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

284 {
285  memset(bctx->buffer, '\0', sizeof(bctx->buffer));
286  bctx->size = 0;
287  bctx->linelen = 0;
288 
289  return 0;
290 }
char buffer[3]
Definition: sendlib.c:106
short size
Definition: sendlib.c:107
short linelen
Definition: sendlib.c:108
+ 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 297 of file sendlib.c.

298 {
299  /* for some reasons, mutt_b64_encode expects the
300  * output buffer to be larger than 10B */
301  char encoded[11];
302  size_t ret;
303 
304  if (bctx->size == 0)
305  return;
306 
307  if (bctx->linelen >= 72)
308  {
309  fputc('\n', fp_out);
310  bctx->linelen = 0;
311  }
312 
313  /* ret should always be equal to 4 here, because bctx->size
314  * is a value between 1 and 3 (included), but let's not hardcode it
315  * and prefer the return value of the function */
316  ret = mutt_b64_encode(bctx->buffer, bctx->size, encoded, sizeof(encoded));
317  for (size_t i = 0; i < ret; i++)
318  {
319  fputc(encoded[i], fp_out);
320  bctx->linelen++;
321  }
322 
323  bctx->size = 0;
324 }
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:106
static const char encoded[]
short size
Definition: sendlib.c:107
short linelen
Definition: sendlib.c:108
+ 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 332 of file sendlib.c.

333 {
334  if (bctx->size == 3)
335  b64_flush(bctx, fp_out);
336 
337  bctx->buffer[bctx->size++] = c;
338 }
char buffer[3]
Definition: sendlib.c:106
short size
Definition: sendlib.c:107
static void b64_flush(struct B64Context *bctx, FILE *fp_out)
Save the bytes to the file.
Definition: sendlib.c:297
+ 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 346 of file sendlib.c.

347 {
348  struct B64Context bctx;
349  int ch, ch1 = EOF;
350 
351  b64_init(&bctx);
352 
353  while ((ch = mutt_ch_fgetconv(fc)) != EOF)
354  {
355  if (SigInt == 1)
356  {
357  SigInt = 0;
358  return;
359  }
360  if (istext && (ch == '\n') && (ch1 != '\r'))
361  b64_putc(&bctx, '\r', fp_out);
362  b64_putc(&bctx, ch, fp_out);
363  ch1 = ch;
364  }
365  b64_flush(&bctx, fp_out);
366  fputc('\n', fp_out);
367 }
static void b64_putc(struct B64Context *bctx, char c, FILE *fp_out)
Base64-encode one character.
Definition: sendlib.c:332
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:283
static void b64_flush(struct B64Context *bctx, FILE *fp_out)
Save the bytes to the file.
Definition: sendlib.c:297
Cursor for the Base64 conversion.
Definition: sendlib.c:104
+ 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 374 of file sendlib.c.

375 {
376  int ch;
377 
378  while ((ch = mutt_ch_fgetconv(fc)) != EOF)
379  {
380  if (SigInt == 1)
381  {
382  SigInt = 0;
383  return;
384  }
385  fputc(ch, fp_out);
386  }
387 }
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 396 of file sendlib.c.

397 {
398  if (!a || !fp)
399  return -1;
400 
401  int len;
402  int tmplen;
403  char buf[256] = { 0 };
404 
405  fprintf(fp, "Content-Type: %s/%s", TYPE(a), a->subtype);
406 
407  if (!TAILQ_EMPTY(&a->parameter))
408  {
409  len = 25 + mutt_str_strlen(a->subtype); /* approximate len. of content-type */
410 
411  struct Parameter *np = NULL;
412  TAILQ_FOREACH(np, &a->parameter, entries)
413  {
414  if (!np->attribute || !np->value)
415  continue;
416 
417  struct ParameterList pl_conts = rfc2231_encode_string(np->attribute, np->value);
418  struct Parameter *cont = NULL;
419  TAILQ_FOREACH(cont, &pl_conts, entries)
420  {
421  fputc(';', fp);
422 
423  buf[0] = 0;
424  mutt_addr_cat(buf, sizeof(buf), cont->value, MimeSpecials);
425 
426  /* Dirty hack to make messages readable by Outlook Express
427  * for the Mac: force quotes around the boundary parameter
428  * even when they aren't needed.
429  */
430  if (!mutt_str_strcasecmp(cont->attribute, "boundary") &&
431  !mutt_str_strcmp(buf, cont->value))
432  snprintf(buf, sizeof(buf), "\"%s\"", cont->value);
433 
434  tmplen = mutt_str_strlen(buf) + mutt_str_strlen(cont->attribute) + 1;
435  if (len + tmplen + 2 > 76)
436  {
437  fputs("\n\t", fp);
438  len = tmplen + 1;
439  }
440  else
441  {
442  fputc(' ', fp);
443  len += tmplen + 1;
444  }
445 
446  fprintf(fp, "%s=%s", cont->attribute, buf);
447  }
448 
449  mutt_param_free(&pl_conts);
450  }
451  }
452 
453  fputc('\n', fp);
454 
455  if (a->language)
456  fprintf(fp, "Content-Language: %s\n", a->language);
457 
458  if (a->description)
459  fprintf(fp, "Content-Description: %s\n", a->description);
460 
461  if (a->disposition != DISP_NONE)
462  {
463  const char *dispstr[] = { "inline", "attachment", "form-data" };
464 
465  if (a->disposition < sizeof(dispstr) / sizeof(char *))
466  {
467  fprintf(fp, "Content-Disposition: %s", dispstr[a->disposition]);
468  len = 21 + mutt_str_strlen(dispstr[a->disposition]);
469 
470  if (a->use_disp && (a->disposition != DISP_INLINE))
471  {
472  char *fn = a->d_filename;
473  if (!fn)
474  fn = a->filename;
475 
476  if (fn)
477  {
478  /* Strip off the leading path... */
479  char *t = strrchr(fn, '/');
480  if (t)
481  t++;
482  else
483  t = fn;
484 
485  struct ParameterList pl_conts = rfc2231_encode_string("filename", t);
486  struct Parameter *cont = NULL;
487  TAILQ_FOREACH(cont, &pl_conts, entries)
488  {
489  fputc(';', fp);
490  buf[0] = 0;
491  mutt_addr_cat(buf, sizeof(buf), cont->value, MimeSpecials);
492 
493  tmplen = mutt_str_strlen(buf) + mutt_str_strlen(cont->attribute) + 1;
494  if (len + tmplen + 2 > 76)
495  {
496  fputs("\n\t", fp);
497  len = tmplen + 1;
498  }
499  else
500  {
501  fputc(' ', fp);
502  len += tmplen + 1;
503  }
504 
505  fprintf(fp, "%s=%s", cont->attribute, buf);
506  }
507 
508  mutt_param_free(&pl_conts);
509  }
510  }
511 
512  fputc('\n', fp);
513  }
514  else
515  {
516  mutt_debug(LL_DEBUG1, "ERROR: invalid content-disposition %d\n", a->disposition);
517  }
518  }
519 
520  if (a->encoding != ENC_7BIT)
521  fprintf(fp, "Content-Transfer-Encoding: %s\n", ENCODING(a->encoding));
522 
524 #ifdef USE_AUTOCRYPT
525  || C_Autocrypt
526 #endif
527  ) &&
528  a->mime_headers)
529  {
530  mutt_rfc822_write_header(fp, a->mime_headers, NULL, MUTT_WRITE_HEADER_MIME, false, false);
531  }
532 
533  /* Do NOT add the terminator here!!! */
534  return ferror(fp) ? -1 : 0;
535 }
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:198
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:666
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:2325
#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:628
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:615
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 542 of file sendlib.c.

543 {
544  return mutt_is_text_part(b) ||
546 }
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:557
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
Definition: muttlib.c:452
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:134
#define WithCrypto
Definition: ncrypt.h:160
+ 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 555 of file sendlib.c.

556 {
557  FILE *fp_in = NULL;
558  struct FgetConv *fc = NULL;
559 
560  if (a->type == TYPE_MULTIPART)
561  {
562  /* First, find the boundary to use */
563  const char *p = mutt_param_get(&a->parameter, "boundary");
564  if (!p)
565  {
566  mutt_debug(LL_DEBUG1, "no boundary parameter found\n");
567  mutt_error(_("No boundary parameter found [report this error]"));
568  return -1;
569  }
570  char boundary[128];
571  mutt_str_strfcpy(boundary, p, sizeof(boundary));
572 
573  for (struct Body *t = a->parts; t; t = t->next)
574  {
575  fprintf(fp, "\n--%s\n", boundary);
576  if (mutt_write_mime_header(t, fp) == -1)
577  return -1;
578  fputc('\n', fp);
579  if (mutt_write_mime_body(t, fp) == -1)
580  return -1;
581  }
582  fprintf(fp, "\n--%s--\n", boundary);
583  return ferror(fp) ? -1 : 0;
584  }
585 
586  /* This is pretty gross, but it's the best solution for now... */
587  if (((WithCrypto & APPLICATION_PGP) != 0) && (a->type == TYPE_APPLICATION) &&
588  (mutt_str_strcmp(a->subtype, "pgp-encrypted") == 0) && !a->filename)
589  {
590  fputs("Version: 1\n", fp);
591  return 0;
592  }
593 
594  fp_in = fopen(a->filename, "r");
595  if (!fp_in)
596  {
597  mutt_debug(LL_DEBUG1, "%s no longer exists\n", a->filename);
598  mutt_error(_("%s no longer exists"), a->filename);
599  return -1;
600  }
601 
602  if ((a->type == TYPE_TEXT) && (!a->noconv))
603  {
604  char send_charset[128];
606  fp_in, a->charset,
607  mutt_body_get_charset(a, send_charset, sizeof(send_charset)), 0);
608  }
609  else
610  fc = mutt_ch_fgetconv_open(fp_in, 0, 0, 0);
611 
613  if (a->encoding == ENC_QUOTED_PRINTABLE)
615  else if (a->encoding == ENC_BASE64)
617  else if ((a->type == TYPE_TEXT) && (!a->noconv))
618  encode_8bit(fc, fp);
619  else
620  mutt_file_copy_stream(fp_in, fp);
622 
624  mutt_file_fclose(&fp_in);
625 
626  if (SigInt == 1)
627  {
628  SigInt = 0;
629  return -1;
630  }
631  return ferror(fp) ? -1 : 0;
632 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
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:346
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:542
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:152
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:150
char * subtype
content-type subtype
Definition: body.h:37
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:555
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:750
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:1461
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:374
unsigned int type
content-type primary type
Definition: body.h:65
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:134
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:270
#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:396
#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
#define WithCrypto
Definition: ncrypt.h:160
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:615
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 638 of file sendlib.c.

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

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

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

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

1034 {
1035  struct Content *info = NULL;
1036  struct ContentState state = { 0 };
1037  FILE *fp = NULL;
1038  char *fromcode = NULL;
1039  char *tocode = NULL;
1040  char buf[100];
1041  size_t r;
1042 
1043  struct stat sb;
1044 
1045  if (b && !fname)
1046  fname = b->filename;
1047 
1048  if (stat(fname, &sb) == -1)
1049  {
1050  mutt_error(_("Can't stat %s: %s"), fname, strerror(errno));
1051  return NULL;
1052  }
1053 
1054  if (!S_ISREG(sb.st_mode))
1055  {
1056  mutt_error(_("%s isn't a regular file"), fname);
1057  return NULL;
1058  }
1059 
1060  fp = fopen(fname, "r");
1061  if (!fp)
1062  {
1063  mutt_debug(LL_DEBUG1, "%s: %s (errno %d)\n", fname, strerror(errno), errno);
1064  return NULL;
1065  }
1066 
1067  info = mutt_mem_calloc(1, sizeof(struct Content));
1068 
1069  if (b && (b->type == TYPE_TEXT) && (!b->noconv && !b->force_charset))
1070  {
1071  char *chs = mutt_param_get(&b->parameter, "charset");
1072  char *fchs = b->use_disp ? (C_AttachCharset ? C_AttachCharset : C_Charset) : C_Charset;
1073  if (C_Charset && (chs || C_SendCharset) &&
1074  (convert_file_from_to(fp, fchs, chs ? chs : C_SendCharset, &fromcode,
1075  &tocode, info) != (size_t)(-1)))
1076  {
1077  if (!chs)
1078  {
1079  char chsbuf[256];
1080  mutt_ch_canonical_charset(chsbuf, sizeof(chsbuf), tocode);
1081  mutt_param_set(&b->parameter, "charset", chsbuf);
1082  }
1083  FREE(&b->charset);
1084  b->charset = fromcode;
1085  FREE(&tocode);
1086  mutt_file_fclose(&fp);
1087  return info;
1088  }
1089  }
1090 
1091  rewind(fp);
1092  while ((r = fread(buf, 1, sizeof(buf), fp)))
1093  update_content_info(info, &state, buf, r);
1094  update_content_info(info, &state, 0, 0);
1095 
1096  mutt_file_fclose(&fp);
1097 
1098  if (b && (b->type == TYPE_TEXT) && (!b->noconv && !b->force_charset))
1099  {
1100  mutt_param_set(&b->parameter, "charset",
1101  (!info->hibin ?
1102  "us-ascii" :
1103  C_Charset && !mutt_ch_is_us_ascii(C_Charset) ? C_Charset : "unknown-8bit"));
1104  }
1105 
1106  return info;
1107 }
Info about the body of an email.
Definition: sendlib.c:114
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:654
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:152
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:73
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:82
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:954
+ 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 1121 of file sendlib.c.

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

1242 {
1243  struct Buffer *buf = NULL;
1244  struct State s = { 0 };
1245  struct stat sb;
1246 
1247  for (; a; a = a->next)
1248  {
1249  if (a->type == TYPE_MULTIPART)
1250  {
1251  a->encoding = ENC_7BIT;
1252  transform_to_7bit(a->parts, fp_in);
1253  }
1254  else if (mutt_is_message_type(a->type, a->subtype))
1255  {
1256  mutt_message_to_7bit(a, fp_in);
1257  }
1258  else
1259  {
1260  a->noconv = true;
1261  a->force_charset = true;
1262 
1263  /* Because of the potential recursion in message types, we
1264  * restrict the lifetime of the buffer tightly */
1265  buf = mutt_buffer_pool_get();
1266  mutt_buffer_mktemp(buf);
1267  s.fp_out = mutt_file_fopen(mutt_b2s(buf), "w");
1268  if (!s.fp_out)
1269  {
1270  mutt_perror("fopen");
1272  return;
1273  }
1274  s.fp_in = fp_in;
1275  mutt_decode_attachment(a, &s);
1277  FREE(&a->d_filename);
1278  a->d_filename = a->filename;
1279  a->filename = mutt_buffer_strdup(buf);
1281  a->unlink = true;
1282  if (stat(a->filename, &sb) == -1)
1283  {
1284  mutt_perror("stat");
1285  return;
1286  }
1287  a->length = sb.st_size;
1288 
1290  if (a->encoding == ENC_8BIT)
1292  else if (a->encoding == ENC_BINARY)
1293  a->encoding = ENC_BASE64;
1294  }
1295  }
1296 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1795
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:78
void mutt_message_to_7bit(struct Body *a, FILE *fp)
Convert an email&#39;s MIME parts to 7-bit.
Definition: sendlib.c:1303
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:1241
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:1485
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
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:585
+ 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 1303 of file sendlib.c.

1304 {
1305  struct Buffer temp = mutt_buffer_make(0);
1306  FILE *fp_in = NULL;
1307  FILE *fp_out = NULL;
1308  struct stat sb;
1309 
1310  if (!a->filename && fp)
1311  fp_in = fp;
1312  else if (!a->filename || !(fp_in = fopen(a->filename, "r")))
1313  {
1314  mutt_error(_("Could not open %s"), a->filename ? a->filename : "(null)");
1315  return;
1316  }
1317  else
1318  {
1319  a->offset = 0;
1320  if (stat(a->filename, &sb) == -1)
1321  {
1322  mutt_perror("stat");
1323  mutt_file_fclose(&fp_in);
1324  goto cleanup;
1325  }
1326  a->length = sb.st_size;
1327  }
1328 
1329  /* Avoid buffer pool due to recursion */
1330  mutt_buffer_mktemp(&temp);
1331  fp_out = mutt_file_fopen(mutt_b2s(&temp), "w+");
1332  if (!fp_out)
1333  {
1334  mutt_perror("fopen");
1335  goto cleanup;
1336  }
1337 
1338  if (!fp_in)
1339  goto cleanup;
1340 
1341  fseeko(fp_in, a->offset, SEEK_SET);
1342  a->parts = mutt_rfc822_parse_message(fp_in, a);
1343 
1344  transform_to_7bit(a->parts, fp_in);
1345 
1346  mutt_copy_hdr(fp_in, fp_out, a->offset, a->offset + a->length,
1347  CH_MIME | CH_NONEWLINE | CH_XMIT, NULL, 0);
1348 
1349  fputs("MIME-Version: 1.0\n", fp_out);
1350  mutt_write_mime_header(a->parts, fp_out);
1351  fputc('\n', fp_out);
1352  mutt_write_mime_body(a->parts, fp_out);
1353 
1354  if (fp_in != fp)
1355  mutt_file_fclose(&fp_in);
1356  mutt_file_fclose(&fp_out);
1357 
1358  a->encoding = ENC_7BIT;
1359  FREE(&a->d_filename);
1360  a->d_filename = a->filename;
1361  if (a->filename && a->unlink)
1362  unlink(a->filename);
1363  a->filename = mutt_buffer_strdup(&temp);
1364  a->unlink = true;
1365  if (stat(a->filename, &sb) == -1)
1366  {
1367  mutt_perror("stat");
1368  goto cleanup;
1369  }
1370  a->length = sb.st_size;
1371  mutt_body_free(&a->parts);
1372  a->email->content = NULL;
1373 
1374 cleanup:
1375  if (fp_in && (fp_in != fp))
1376  mutt_file_fclose(&fp_in);
1377 
1378  if (fp_out)
1379  {
1380  mutt_file_fclose(&fp_out);
1381  mutt_file_unlink(mutt_b2s(&temp));
1382  }
1383 
1384  mutt_buffer_dealloc(&temp);
1385 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:78
#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:194
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:1241
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:152
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:555
#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:396
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:585
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 1392 of file sendlib.c.

1393 {
1394  if (b->type == TYPE_TEXT)
1395  {
1396  char send_charset[128];
1397  char *chsname = mutt_body_get_charset(b, send_charset, sizeof(send_charset));
1398  if ((info->lobin && !mutt_str_startswith(chsname, "iso-2022", CASE_IGNORE)) ||
1399  (info->linemax > 990) || (info->from && C_EncodeFrom))
1400  {
1402  }
1403  else if (info->hibin)
1404  {
1406  }
1407  else
1408  {
1409  b->encoding = ENC_7BIT;
1410  }
1411  }
1412  else if ((b->type == TYPE_MESSAGE) || (b->type == TYPE_MULTIPART))
1413  {
1414  if (info->lobin || info->hibin)
1415  {
1416  if (C_Allow8bit && !info->lobin)
1417  b->encoding = ENC_8BIT;
1418  else
1419  mutt_message_to_7bit(b, NULL);
1420  }
1421  else
1422  b->encoding = ENC_7BIT;
1423  }
1424  else if ((b->type == TYPE_APPLICATION) &&
1425  (mutt_str_strcasecmp(b->subtype, "pgp-keys") == 0))
1426  {
1427  b->encoding = ENC_7BIT;
1428  }
1429  else
1430  {
1431  /* Determine which encoding is smaller */
1432  if (1.33 * (float) (info->lobin + info->hibin + info->ascii) <
1433  3.0 * (float) (info->lobin + info->hibin) + (float) info->ascii)
1434  {
1435  b->encoding = ENC_BASE64;
1436  }
1437  else
1438  {
1440  }
1441  }
1442 }
void mutt_message_to_7bit(struct Body *a, FILE *fp)
Convert an email&#39;s MIME parts to 7-bit.
Definition: sendlib.c:1303
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:84
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:1461
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:628
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:81
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 1448 of file sendlib.c.

1449 {
1450  a->stamp = mutt_date_epoch();
1451 }
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 1461 of file sendlib.c.

1462 {
1463  char *p = NULL;
1464 
1465  if (b && (b->type != TYPE_TEXT))
1466  return NULL;
1467 
1468  if (b)
1469  p = mutt_param_get(&b->parameter, "charset");
1470 
1471  if (p)
1472  mutt_ch_canonical_charset(buf, buflen, p);
1473  else
1474  mutt_str_strfcpy(buf, "us-ascii", buflen);
1475 
1476  return buf;
1477 }
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:750
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 1485 of file sendlib.c.

1486 {
1487  struct Content *info = NULL;
1488  char chsbuf[256];
1489 
1490  /* override noconv when it's us-ascii */
1491  if (mutt_ch_is_us_ascii(mutt_body_get_charset(a, chsbuf, sizeof(chsbuf))))
1492  a->noconv = false;
1493 
1494  if (!a->force_charset && !a->noconv)
1495  mutt_param_delete(&a->parameter, "charset");
1496 
1497  info = mutt_get_content_info(a->filename, a);
1498  if (!info)
1499  return;
1500 
1501  set_encoding(a, info);
1503 
1504  FREE(&a->content);
1505  a->content = info;
1506 }
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:1448
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:1033
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:1392
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body&#39;s character set.
Definition: sendlib.c:1461
#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 1516 of file sendlib.c.

1517 {
1518  char buf[1024];
1519  struct Body *body = NULL;
1520  FILE *fp = NULL;
1521  CopyMessageFlags cmflags;
1523 
1524  if (WithCrypto)
1525  {
1527  {
1529  return NULL;
1530  }
1531  }
1532 
1533  mutt_mktemp(buf, sizeof(buf));
1534  fp = mutt_file_fopen(buf, "w+");
1535  if (!fp)
1536  return NULL;
1537 
1538  body = mutt_body_new();
1539  body->type = TYPE_MESSAGE;
1540  body->subtype = mutt_str_strdup("rfc822");
1541  body->filename = mutt_str_strdup(buf);
1542  body->unlink = true;
1543  body->use_disp = false;
1544  body->disposition = DISP_INLINE;
1545  body->noconv = true;
1546 
1548 
1549  CopyHeaderFlags chflags = CH_XMIT;
1550  cmflags = MUTT_CM_NO_FLAGS;
1551 
1552  /* If we are attaching a message, ignore C_MimeForwardDecode */
1553  if (!attach_msg && C_MimeForwardDecode)
1554  {
1555  chflags |= CH_MIME | CH_TXTPLAIN;
1556  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1558  pgp &= ~PGP_ENCRYPT;
1560  pgp &= ~SMIME_ENCRYPT;
1561  }
1562  else if ((WithCrypto != 0) && C_ForwardDecrypt && (e->security & SEC_ENCRYPT))
1563  {
1564  if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_multipart_encrypted(e->content))
1565  {
1566  chflags |= CH_MIME | CH_NONEWLINE;
1567  cmflags = MUTT_CM_DECODE_PGP;
1568  pgp &= ~PGP_ENCRYPT;
1569  }
1570  else if (((WithCrypto & APPLICATION_PGP) != 0) &&
1572  {
1573  chflags |= CH_MIME | CH_TXTPLAIN;
1574  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1575  pgp &= ~PGP_ENCRYPT;
1576  }
1577  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
1579  {
1580  chflags |= CH_MIME | CH_TXTPLAIN;
1581  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1582  pgp &= ~SMIME_ENCRYPT;
1583  }
1584  }
1585 
1586  mutt_copy_message(fp, m, e, cmflags, chflags, 0);
1587 
1588  fflush(fp);
1589  rewind(fp);
1590 
1591  body->email = email_new();
1592  body->email->offset = 0;
1593  /* we don't need the user headers here */
1594  body->email->env = mutt_rfc822_read_header(fp, body->email, false, false);
1595  if (WithCrypto)
1596  body->email->security = pgp;
1597  mutt_update_encoding(body);
1598  body->parts = body->email->content;
1599 
1600  mutt_file_fclose(&fp);
1601 
1602  return body;
1603 }
#define CH_MIME
Ignore MIME fields.
Definition: copy.h:60
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
bool C_MimeForwardDecode
Config: Decode the forwarded message before attaching it.
Definition: sendlib.c:88
#define SEC_NO_FLAGS
No flags are set.
Definition: ncrypt.h:121
struct Body * content
List of MIME parts.
Definition: email.h:90
bool noconv
Don&#39;t do character set conversion.
Definition: body.h:73
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:810
uint16_t CopyMessageFlags
Flags for mutt_copy_message(), e.g. MUTT_CM_NOHEADER.
Definition: copy.h:31
#define SEC_ENCRYPT
Email is encrypted.
Definition: ncrypt.h:122
#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:145
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:451
void mutt_update_encoding(struct Body *a)
Update the encoding type.
Definition: sendlib.c:1485
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
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
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:557
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:75
#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:85
#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:616
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/ncrypt.h pgplib.h, smime.h
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
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:134
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
#define SMIME_ENCRYPT
Definition: ncrypt.h:146
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
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: ncrypt.h:120
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:585
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 WithCrypto
Definition: ncrypt.h:160
#define PGP_ENCRYPT
Definition: ncrypt.h:140
#define CH_NONEWLINE
Don&#39;t output terminating newline after the header.
Definition: copy.h:59
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: ncrypt.h:135
+ 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 1611 of file sendlib.c.

1612 {
1613  FILE *fp = NULL, *fp_err = NULL;
1614  char *buf = NULL;
1615  size_t buflen;
1616  int dummy = 0;
1617  pid_t pid;
1618  struct Buffer *cmd = mutt_buffer_pool_get();
1619 
1621 
1622  pid = mutt_create_filter(mutt_b2s(cmd), NULL, &fp, &fp_err);
1623  if (pid < 0)
1624  {
1625  mutt_error(_("Error running \"%s\""), mutt_b2s(cmd));
1627  return;
1628  }
1630 
1631  buf = mutt_file_read_line(buf, &buflen, fp, &dummy, 0);
1632  if (buf)
1633  {
1634  if (strchr(buf, '/'))
1635  mutt_parse_content_type(buf, att);
1636  FREE(&buf);
1637  }
1638 
1639  mutt_file_fclose(&fp);
1640  mutt_file_fclose(&fp_err);
1641  mutt_wait_filter(pid);
1642 }
pid_t mutt_create_filter(const char *s, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:209
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
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:664
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
#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:90
#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:1423
#define FREE(x)
Definition: memory.h:40
int mutt_wait_filter(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:220
+ 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 1650 of file sendlib.c.

1651 {
1652  struct Body *att = mutt_body_new();
1653  att->filename = mutt_str_strdup(path);
1654 
1656  run_mime_type_query(att);
1657 
1658  /* Attempt to determine the appropriate content-type based on the filename
1659  * suffix. */
1660  if (!att->subtype)
1661  mutt_lookup_mime_type(att, path);
1662 
1664  {
1665  run_mime_type_query(att);
1666  }
1667 
1668  struct Content *info = mutt_get_content_info(path, att);
1669  if (!info)
1670  {
1671  mutt_body_free(&att);
1672  return NULL;
1673  }
1674 
1675  if (!att->subtype)
1676  {
1677  if ((info->nulbin == 0) &&
1678  ((info->lobin == 0) || ((info->lobin + info->hibin + info->ascii) / info->lobin >= 10)))
1679  {
1680  /* Statistically speaking, there should be more than 10% "lobin"
1681  * chars if this is really a binary file... */
1682  att->type = TYPE_TEXT;
1683  att->subtype = mutt_str_strdup("plain");
1684  }
1685  else
1686  {
1687  att->type = TYPE_APPLICATION;
1688  att->subtype = mutt_str_strdup("octet-stream");
1689  }
1690  }
1691 
1692  FREE(&info);
1693  mutt_update_encoding(att);
1694  return att;
1695 }
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:1611
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:1033
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:1485
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:1121
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:90
#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:91
+ 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 1702 of file sendlib.c.

1703 {
1704  int e = ENC_7BIT;
1705 
1706  for (; a; a = a->next)
1707  {
1708  if (a->encoding == ENC_BINARY)
1709  return ENC_BINARY;
1710  if (a->encoding == ENC_8BIT)
1711  e = ENC_8BIT;
1712  }
1713 
1714  return e;
1715 }
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 1723 of file sendlib.c.

1724 {
1725  char *p = NULL;
1726 
1727  if (b->parts && check_boundary(boundary, b->parts))
1728  return true;
1729 
1730  if (b->next && check_boundary(boundary, b->next))
1731  return true;
1732 
1733  p = mutt_param_get(&b->parameter, "boundary");
1734  if (p && (mutt_str_strcmp(p, boundary) == 0))
1735  {
1736  return true;
1737  }
1738  return false;
1739 }
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:1723
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:615
+ 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 1746 of file sendlib.c.

1747 {
1748  struct Body *new_body = mutt_body_new();
1749  new_body->type = TYPE_MULTIPART;
1750  new_body->subtype = mutt_str_strdup("mixed");
1751  new_body->encoding = get_toplevel_encoding(b);
1752  do
1753  {
1754  mutt_generate_boundary(&new_body->parameter);
1755  if (check_boundary(mutt_param_get(&new_body->parameter, "boundary"), b))
1756  mutt_param_delete(&new_body->parameter, "boundary");
1757  } while (!mutt_param_get(&new_body->parameter, "boundary"));
1758  new_body->use_disp = false;
1759  new_body->disposition = DISP_INLINE;
1760  new_body->parts = b;
1761 
1762  return new_body;
1763 }
static int get_toplevel_encoding(struct Body *a)
Find the most restrictive encoding type.
Definition: sendlib.c:1702
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:638
static bool check_boundary(const char *boundary, struct Body *b)
check for duplicate boundary
Definition: sendlib.c:1723
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 1772 of file sendlib.c.

1773 {
1774  struct Body *t = NULL;
1775 
1776  if (b->parts)
1777  {
1778  t = b;
1779  b = b->parts;
1780  t->parts = NULL;
1781  mutt_body_free(&t);
1782  }
1783  return b;
1784 }
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 1796 of file sendlib.c.

1797 {
1798  char buf[1024];
1799  int count = 0;
1800 
1801  struct Address *a = NULL;
1802  TAILQ_FOREACH(a, al, entries)
1803  {
1804  buf[0] = '\0';
1805  mutt_addr_write(buf, sizeof(buf), a, display);
1806  size_t len = mutt_str_strlen(buf);
1807  if (count && (linelen + len > 74))
1808  {
1809  fputs("\n\t", fp);
1810  linelen = len + 8; /* tab is usually about 8 spaces... */
1811  }
1812  else
1813  {
1814  if (count && a->mailbox)
1815  {
1816  fputc(' ', fp);
1817  linelen++;
1818  }
1819  linelen += len;
1820  }
1821  fputs(buf, fp);
1822  struct Address *next = TAILQ_NEXT(a, entries);
1823  if (!a->group && next && next->mailbox)
1824  {
1825  linelen++;
1826  fputc(',', fp);
1827  }
1828  count++;
1829  }
1830  fputc('\n', fp);
1831 }
#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:666
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 1842 of file sendlib.c.

1843 {
1844  struct ListNode *np = NULL;
1845  size_t length = 0;
1846 
1847  STAILQ_FOREACH(np, r, entries)
1848  {
1849  if (++length == trim)
1850  break;
1851  }
1852 
1853  struct ListNode **ref = mutt_mem_calloc(length, sizeof(struct ListNode *));
1854 
1855  // store in reverse order
1856  size_t tmp = length;
1857  STAILQ_FOREACH(np, r, entries)
1858  {
1859  ref[--tmp] = np;
1860  if (tmp == 0)
1861  break;
1862  }
1863 
1864  for (size_t i = 0; i < length; i++)
1865  {
1866  fputc(' ', fp);
1867  fputs(ref[i]->data, fp);
1868  if (i != length - 1)
1869  fputc('\n', fp);
1870  }
1871 
1872  FREE(&ref);
1873 }
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 1885 of file sendlib.c.

1887 {
1888  while (value && (value[0] != '\0'))
1889  {
1890  if (fputc(*value, fp) == EOF)
1891  return -1;
1892  /* corner-case: break words longer than 998 chars by force,
1893  * mandated by RFC5322 */
1894  if (!(chflags & CH_DISPLAY) && (++col >= 998))
1895  {
1896  if (fputs("\n ", fp) < 0)
1897  return -1;
1898  col = 1;
1899  }
1900  if (*value == '\n')
1901  {
1902  if ((value[1] != '\0') && pfx && (pfx[0] != '\0') && (fputs(pfx, fp) == EOF))
1903  return -1;
1904  /* for display, turn folding spaces into folding tabs */
1905  if ((chflags & CH_DISPLAY) && ((value[1] == ' ') || (value[1] == '\t')))
1906  {
1907  value++;
1908  while ((value[0] != '\0') && ((value[0] == ' ') || (value[0] == '\t')))
1909  value++;
1910  if (fputc('\t', fp) == EOF)
1911  return -1;
1912  continue;
1913  }
1914  }
1915  value++;
1916  }
1917  return 0;
1918 }
#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 1932 of file sendlib.c.

1934 {
1935  if (!value || !*value || !vlen)
1936  return 0;
1937 
1938  const char *p = value;
1939  char buf[8192] = { 0 };
1940  int first = 1, col = 0, l = 0;
1941  const bool display = (chflags & CH_DISPLAY);
1942 
1943  mutt_debug(LL_DEBUG5, "pfx=[%s], tag=[%s], flags=%d value=[%.*s]\n", pfx, tag,
1944  chflags, ((value[vlen - 1] == '\n') ? vlen - 1 : vlen), value);
1945 
1946  if (tag && *tag && (fprintf(fp, "%s%s: ", NONULL(pfx), tag) < 0))
1947  return -1;
1948  col = mutt_str_strlen(tag) + ((tag && (tag[0] != '\0')) ? 2 : 0) + mutt_str_strlen(pfx);
1949 
1950  while (p && (p[0] != '\0'))
1951  {
1952  int fold = 0;
1953 
1954  /* find the next word and place it in 'buf'. it may start with
1955  * whitespace we can fold before */
1956  const char *next = mutt_str_find_word(p);
1957  l = MIN(sizeof(buf) - 1, next - p);
1958  memcpy(buf, p, l);
1959  buf[l] = '\0';
1960 
1961  /* determine width: character cells for display, bytes for sending
1962  * (we get pure ascii only) */
1963  const int w = mutt_mb_width(buf, col, display);
1964  const int enc = mutt_str_startswith(buf, "=?", CASE_MATCH);
1965 
1966  mutt_debug(LL_DEBUG5, "word=[%s], col=%d, w=%d, next=[0x0%x]\n",
1967  (buf[0] == '\n' ? "\\n" : buf), col, w, *next);
1968 
1969  /* insert a folding \n before the current word's lwsp except for
1970  * header name, first word on a line (word longer than wrap width)
1971  * and encoded words */
1972  if (!first && !enc && col && ((col + w) >= wraplen))
1973  {
1974  col = mutt_str_strlen(pfx);
1975  fold = 1;
1976  if (fprintf(fp, "\n%s", NONULL(pfx)) <= 0)
1977  return -1;
1978  }
1979 
1980  /* print the actual word; for display, ignore leading ws for word
1981  * and fold with tab for readability */
1982  if (display && fold)
1983  {
1984  char *pc = buf;
1985  while ((pc[0] != '\0') && ((pc[0] == ' ') || (pc[0] == '\t')))
1986  {
1987  pc++;
1988  col--;
1989  }
1990  if (fputc('\t', fp) == EOF)
1991  return -1;
1992  if (print_val(fp, pfx, pc, chflags, col) < 0)
1993  return -1;
1994  col += 8;
1995  }
1996  else if (print_val(fp, pfx, buf, chflags, col) < 0)
1997  return -1;
1998  col += w;
1999 
2000  /* if the current word ends in \n, ignore all its trailing spaces
2001  * and reset column; this prevents us from putting only spaces (or
2002  * even none) on a line if the trailing spaces are located at our
2003  * current line width
2004  * XXX this covers ASCII space only, for display we probably
2005  * want something like iswspace() here */
2006  const char *sp = next;
2007  while ((sp[0] != '\0') && ((sp[0] == ' ') || (sp[0] == '\t')))
2008  sp++;
2009  if (sp[0] == '\n')
2010  {
2011  if (sp[1] == '\0')
2012  break;
2013  next = sp;
2014  col = 0;
2015  }
2016 
2017  p = next;
2018  first = 0;
2019  }
2020 
2021  /* if we have printed something but didn't \n-terminate it, do it
2022  * except the last word we printed ended in \n already */
2023  if (col && ((l == 0) || (buf[l - 1] != '\n')))
2024  if (putc('\n', fp) == EOF)
2025  return -1;
2026 
2027  return 0;
2028 }
#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:666
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:1885
const char * mutt_str_find_word(const char *src)
Find the end of a word (non-space)
Definition: string.c:1028
+ 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 2037 of file sendlib.c.

2038 {
2039  char *p = s;
2040  char *q = s;
2041 
2042  while (p && (p[0] != '\0'))
2043  {
2044  /* remove CRLF prior to FWSP, turn \t into ' ' */
2045  if ((p[0] == '\r') && (p[1] == '\n') && ((p[2] == ' ') || (p[2] == '\t')))
2046  {
2047  *q++ = ' ';
2048  p += 3;
2049  continue;
2050  }
2051  /* remove LF prior to FWSP, turn \t into ' ' */
2052  else if ((p[0] == '\n') && ((p[1] == ' ') || (p[1] == '\t')))
2053  {
2054  *q++ = ' ';
2055  p += 2;
2056  continue;
2057  }
2058  *q++ = *p++;
2059  }
2060  if (q)
2061  q[0] = '\0';
2062 
2063  return s;
2064 }
+ 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 2079 of file sendlib.c.

2081 {
2082  const char *t = strchr(start, ':');
2083  if (!t || (t > end))
2084  {
2085  mutt_debug(LL_DEBUG1, "#2 warning: header not in 'key: value' format!\n");
2086  return 0;
2087  }
2088 
2089  const size_t vallen = end - start;
2090  const bool short_enough = (pfxw + max <= wraplen);
2091 
2092  mutt_debug((short_enough ? LL_DEBUG2 : LL_DEBUG5), "buf[%s%.*s] %s, max width = %d %s %d\n",
2093  NONULL(pfx), vallen - 1 /* skip newline */, start,
2094  (short_enough ? "short enough" : "too long"), max,
2095  (short_enough ? "<=" : ">"), wraplen);
2096 
2097  int rc = 0;
2098  const char *valbuf = NULL, *tagbuf = NULL;
2099  const bool is_from = (vallen > 5) && mutt_str_startswith(start, "from ", CASE_IGNORE);
2100 
2101  /* only pass through folding machinery if necessary for sending,
2102  * never wrap From_ headers on sending */
2103  if (!(chflags & CH_DISPLAY) && (short_enough || is_from))
2104  {
2105  if (pfx && *pfx)
2106  {
2107  if (fputs(pfx, fp) == EOF)
2108  {
2109  return -1;
2110  }
2111  }
2112 
2113  valbuf = mutt_str_substr_dup(start, end);
2114  rc = print_val(fp, pfx, valbuf, chflags, mutt_str_strlen(pfx));
2115  }
2116  else
2117  {
2118  if (!is_from)
2119  {
2120  tagbuf = mutt_str_substr_dup(start, t);
2121  /* skip over the colon separating the header field name and value */
2122  t++;
2123 
2124  /* skip over any leading whitespace (WSP, as defined in RFC5322)
2125  * NOTE: mutt_str_skip_email_wsp() does the wrong thing here.
2126  * See tickets 3609 and 3716. */
2127  while ((*t == ' ') || (*t == '\t'))
2128  t++;
2129  }
2130  valbuf = mutt_str_substr_dup(is_from ? start : t, end);
2131  rc = fold_one_header(fp, tagbuf, valbuf, end - (is_from ? start : t), pfx,
2132  wraplen, chflags);
2133  }
2134 
2135  FREE(&tagbuf);
2136  FREE(&valbuf);
2137  return rc;
2138 }
#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:1932
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
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:1885
char * mutt_str_substr_dup(const char *begin, const char *end)
Duplicate a sub-string.
Definition: string.c:579
+ 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 2154 of file sendlib.c.

2156 {
2157  char *last = NULL, *line = NULL;
2158  int max = 0, w, rc = -1;
2159  int pfxw = mutt_strwidth(pfx);
2160  char *v = mutt_str_strdup(value);
2161  bool display = (chflags & CH_DISPLAY);
2162 
2163  if (!display || C_Weed)
2164  v = unfold_header(v);
2165 
2166  /* when not displaying, use sane wrap value */
2167  if (!display)
2168  {
2169  if ((C_WrapHeaders < 78) || (C_WrapHeaders > 998))
2170  wraplen = 78;
2171  else
2172  wraplen = C_WrapHeaders;
2173  }
2174  else if (wraplen <= 0)
2175  wraplen = 78;
2176 
2177  const size_t vlen = mutt_str_strlen(v);
2178  if (tag)
2179  {
2180  /* if header is short enough, simply print it */
2181  if (!display && (mutt_strwidth(tag) + 2 + pfxw + mutt_strnwidth(v, vlen) <= wraplen))
2182  {
2183  mutt_debug(LL_DEBUG5, "buf[%s%s: %s] is short enough\n", NONULL(pfx), tag, v);
2184  if (fprintf(fp, "%s%s: %s\n", NONULL(pfx), tag, v) <= 0)
2185  goto out;
2186  rc = 0;
2187  goto out;
2188  }
2189  else
2190  {
2191  rc = fold_one_header(fp, tag, v, vlen, pfx, wraplen, chflags);
2192  goto out;
2193  }
2194  }
2195 
2196  char *p = v;
2197  last = v;
2198  line = v;
2199  while (p && *p)
2200  {
2201  p = strchr(p, '\n');
2202 
2203  /* find maximum line width in current header */
2204  if (p)
2205  *p = '\0';
2206  w = mutt_mb_width(line, 0, display);
2207  if (w > max)
2208  max = w;
2209  if (p)
2210  *p = '\n';
2211 
2212  if (!p)
2213  break;
2214 
2215  line = ++p;
2216  if ((*p != ' ') && (*p != '\t'))
2217  {
2218  if (write_one_header(fp, pfxw, max, wraplen, pfx, last, p, chflags) < 0)
2219  goto out;
2220  last = p;
2221  max = 0;
2222  }
2223  }
2224 
2225  if (last && *last)
2226  if (write_one_header(fp, pfxw, max, wraplen, pfx, last, p, chflags) < 0)
2227  goto out;
2228 
2229  rc = 0;
2230 
2231 out:
2232  FREE(&v);
2233  return rc;
2234 }
short C_WrapHeaders
Config: Width to wrap headers in outgoing messages.
Definition: sendlib.c:97
#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:1932
static char * unfold_header(char *s)
Unfold a wrapped email header.
Definition: sendlib.c:2037
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
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
const char * line
Definition: common.c:36
int mutt_strwidth(const char *s)
Measure a string&#39;s width in screen cells.
Definition: curs_lib.c:1359
#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:2079
int mutt_strnwidth(const char *s, size_t n)
Measure a string&#39;s width in screen cells.
Definition: curs_lib.c:1372
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
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 2244 of file sendlib.c.

2245 {
2246  const char *ca = a;
2247  const char *cb = *(const char **) b;
2248  return mutt_str_strncasecmp(ca, cb, strlen(cb));
2249 }
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:656
+ 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 2258 of file sendlib.c.

2259 {
2260  struct UserHdrsOverride overrides = { { 0 } };
2261 
2262  struct ListNode *tmp = NULL;
2263  STAILQ_FOREACH(tmp, userhdrs, entries)
2264  {
2265  char *const colon = strchr(tmp->data, ':');
2266  if (!colon)
2267  {
2268  continue;
2269  }
2270 
2271  const char *const value = mutt_str_skip_email_wsp(colon + 1);
2272  if (*value == '\0')
2273  {
2274  continue; /* don't emit empty fields. */
2275  }
2276 
2277  /* check whether the current user-header is an override */
2278  size_t curr_override = (size_t) -1;
2279  const char *const *idx = bsearch(tmp->data, userhdrs_override_headers,
2281  sizeof(char *), userhdrs_override_cmp);
2282  if (idx != NULL)
2283  {
2284  curr_override = idx - userhdrs_override_headers;
2285  overrides.is_overridden[curr_override] = true;
2286  }
2287 
2288  if (privacy && (curr_override == USERHDRS_OVERRIDE_USER_AGENT))
2289  {
2290  continue;
2291  }
2292 
2293  *colon = '\0';
2294  mutt_write_one_header(fp, tmp->data, value, NULL, 0, CH_NO_FLAGS);
2295  *colon = ':';
2296  }
2297 
2298  return overrides;
2299 }
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:128
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:2244
#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:776
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
bool is_overridden[mutt_array_size(userhdrs_override_headers)]
Definition: sendlib.c:141
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:2154
+ 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 2325 of file sendlib.c.

2328 {
2329  char buf[1024];
2330 
2331  if (((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_FCC)) && !privacy)
2332  fputs(mutt_date_make_date(buf, sizeof(buf)), fp);
2333 
2334  /* UseFrom is not consulted here so that we can still write a From:
2335  * field if the user sets it with the 'my_hdr' command */
2336  if (!TAILQ_EMPTY(&env->from) && !privacy)
2337  {
2338  buf[0] = '\0';
2339  mutt_addrlist_write(&env->from, buf, sizeof(buf), false);
2340  fprintf(fp, "From: %s\n", buf);
2341  }
2342 
2343  if (!TAILQ_EMPTY(&env->sender) && !privacy)
2344  {
2345  buf[0] = '\0';
2346  mutt_addrlist_write(&env->sender, buf, sizeof(buf), false);
2347  fprintf(fp, "Sender: %s\n", buf);
2348  }
2349 
2350  if (!TAILQ_EMPTY(&env->to))
2351  {
2352  fputs("To: ", fp);
2353  mutt_write_addrlist(&env->to, fp, 4, 0);
2354  }
2355  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2356 #ifdef USE_NNTP
2357  if (!OptNewsSend)
2358 #endif
2359  fputs("To:\n", fp);
2360 
2361  if (!TAILQ_EMPTY(&env->cc))
2362  {
2363  fputs("Cc: ", fp);
2364  mutt_write_addrlist(&env->cc, fp, 4, 0);
2365  }
2366  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2367 #ifdef USE_NNTP
2368  if (!OptNewsSend)
2369 #endif
2370  fputs("Cc:\n", fp);
2371 
2372  if (!TAILQ_EMPTY(&env->bcc))
2373  {
2374  if ((mode == MUTT_WRITE_HEADER_POSTPONE) ||
2375  (mode == MUTT_WRITE_HEADER_EDITHDRS) || (mode == MUTT_WRITE_HEADER_FCC) ||
2376  ((mode == MUTT_WRITE_HEADER_NORMAL) && C_WriteBcc))
2377  {
2378  fputs("Bcc: ", fp);
2379  mutt_write_addrlist(&env->bcc, fp, 5, 0);
2380  }
2381  }
2382  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2383 #ifdef USE_NNTP
2384  if (!OptNewsSend)
2385 #endif
2386  fputs("Bcc:\n", fp);
2387 
2388 #ifdef USE_NNTP
2389  if (env->newsgroups)
2390  fprintf(fp, "Newsgroups: %s\n", env->newsgroups);
2391  else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend)
2392  fputs("Newsgroups:\n", fp);
2393 
2394  if (env->followup_to)
2395  fprintf(fp, "Followup-To: %s\n", env->followup_to);
2396  else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend)
2397  fputs("Followup-To:\n", fp);
2398 
2399  if (env->x_comment_to)
2400  fprintf(fp, "X-Comment-To: %s\n", env->x_comment_to);
2401  else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend && C_XCommentTo)
2402  fputs("X-Comment-To:\n", fp);
2403 #endif
2404 
2405  if (env->subject)
2406  {
2407  if (hide_protected_subject &&
2408  ((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_FCC) ||
2409  (mode == MUTT_WRITE_HEADER_POSTPONE)))
2411  else
2412  mutt_write_one_header(fp, "Subject", env->subject, NULL, 0, CH_NO_FLAGS);
2413  }
2414  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2415  fputs("Subject:\n", fp);
2416 
2417  /* save message id if the user has set it */
2418  if (env->message_id && !privacy)
2419  fprintf(fp, "Message-ID: %s\n", env->message_id);
2420 
2421  if (!TAILQ_EMPTY(&env->reply_to))
2422  {
2423  fputs("Reply-To: ", fp);
2424  mutt_write_addrlist(&env->reply_to, fp, 10, 0);
2425  }
2426  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2427  fputs("Reply-To:\n", fp);
2428 
2429  if (!TAILQ_EMPTY(&env->mail_followup_to))
2430  {
2431 #ifdef USE_NNTP
2432  if (!OptNewsSend)
2433 #endif
2434  {
2435  fputs("Mail-Followup-To: ", fp);
2436  mutt_write_addrlist(&env->mail_followup_to, fp, 18, 0);
2437  }
2438  }
2439 
2440  /* Add any user defined headers */
2441  struct UserHdrsOverride userhdrs_overrides = write_userhdrs(fp, &env->userhdrs, privacy);
2442 
2443  if ((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_FCC) ||
2444  (mode == MUTT_WRITE_HEADER_POSTPONE))
2445  {
2446  if (!STAILQ_EMPTY(&env->references))
2447  {
2448  fputs("References:", fp);
2449  mutt_write_references(&env->references, fp, 10);
2450  fputc('\n', fp);
2451  }
2452 
2453  /* Add the MIME headers */
2454  if (!userhdrs_overrides.is_overridden[USERHDRS_OVERRIDE_CONTENT_TYPE])
2455  {
2456  fputs("MIME-Version: 1.0\n", fp);
2457  mutt_write_mime_header(attach, fp);
2458  }
2459  }
2460 
2461  if (!STAILQ_EMPTY(&env->in_reply_to))
2462  {
2463  fputs("In-Reply-To:", fp);
2464  mutt_write_references(&env->in_reply_to, fp, 0);
2465  fputc('\n', fp);
2466  }
2467 
2468 #ifdef USE_AUTOCRYPT
2469  if (C_Autocrypt)
2470  {
2471  if (mode == MUTT_WRITE_HEADER_NORMAL || mode == MUTT_WRITE_HEADER_FCC)
2473  if (mode == MUTT_WRITE_HEADER_MIME)
2475  }
2476 #endif
2477 
2478  if (((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_FCC)) && !privacy &&
2479  C_UserAgent && !userhdrs_overrides.is_overridden[USERHDRS_OVERRIDE_USER_AGENT])
2480  {
2481  /* Add a vanity header */
2482  fprintf(fp, "User-Agent: NeoMutt/%s%s\n", PACKAGE_VERSION, GitVer);
2483  }
2484 
2485  return (ferror(fp) == 0) ? 0 : -1;
2486 }
WHERE bool C_Autocrypt
Config: Enables the Autocrypt feature.
Definition: globals.h:198
WHERE bool C_WriteBcc
Config: Write out the &#39;Bcc&#39; field when preparing to send a mail.
Definition: globals.h:262
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:105
bool C_UserAgent
Config: Add a &#39;User-Agent&#39; head to outgoing mail.
Definition: sendlib.c:96
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:2258
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:1842
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:1796
bool is_overridden[mutt_array_size(userhdrs_override_headers)]
Definition: sendlib.c:141
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:396
#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:44
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:776
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:2154
int mutt_autocrypt_write_autocrypt_header(struct Envelope *env, FILE *fp)
Write the Autocrypt header to a file.
Definition: autocrypt.c:739
+ 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 2494 of file sendlib.c.

2495 {
2496  char *tmp = NULL;
2497  char *p = NULL;
2498  int i;
2499 
2500  struct ListNode *np = NULL;
2501  STAILQ_FOREACH(np, h, entries)
2502  {
2503  p = strchr(np->data, ':');
2504  if (!p)
2505  continue;
2506 
2507  i = p - np->data;
2508  p = mutt_str_skip_email_wsp(p + 1);
2509  tmp = mutt_str_strdup(p);
2510 
2511  if (!tmp)
2512  continue;
2513 
2514  rfc2047_encode(&tmp, NULL, i + 2, C_SendCharset);
2515  mutt_mem_realloc(&np->data, i + 2 + mutt_str_strlen(tmp) + 1);
2516 
2517  sprintf(np->data + i + 2, "%s", tmp);
2518 
2519  FREE(&tmp);
2520  }
2521 }
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
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:776
#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:627
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 2531 of file sendlib.c.

2532 {
2533  if (!C_Hostname || (C_Hostname[0] == '@'))
2534  return NULL;
2535 
2536  char *p = C_Hostname;
2537 
2538  if (may_hide_host && C_HiddenHost)
2539  {
2540  p = strchr(C_Hostname, '.');
2541  if (p)
2542  p++;
2543 
2544  // sanity check: don't hide the host if the fqdn is something like example.com
2545  if (!p || !strchr(p, '.'))
2546  p = C_Hostname;
2547  }
2548 
2549  return p;
2550 }
bool C_HiddenHost
Config: Don&#39;t use the hostname, just the domain, when generating the message id.
Definition: sendlib.c:86
WHERE char * C_Hostname
Config: Fully-qualified domain name of this machine.
Definition: globals.h:111
+ 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 2558 of file sendlib.c.

2559 {
2560  char buf[128];
2561  unsigned char rndid[MUTT_RANDTAG_LEN + 1];
2562 
2563  mutt_rand_base32(rndid, sizeof(rndid) - 1);
2564  rndid[MUTT_RANDTAG_LEN] = 0;
2565  const char *fqdn = mutt_fqdn(false);
2566  if (!fqdn)
2567  fqdn = NONULL(ShortHostname);
2568 
2569  struct tm tm = mutt_date_gmtime(MUTT_DATE_NOW);
2570  snprintf(buf, sizeof(buf), "<%d%02d%02d%02d%02d%02d.%s@%s>", tm.tm_year + 1900,
2571  tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, rndid, fqdn);
2572  return mutt_str_strdup(buf);
2573 }
#define NONULL(x)
Definition: string2.h:37
#define MUTT_RANDTAG_LEN
Definition: sendlib.c:99
#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:2531
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:528
+ 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 2579 of file sendlib.c.

2580 {
2581  SigAlrm = 1;
2582 }
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 2596 of file sendlib.c.

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

2762 {
2763  /* weed out group mailboxes, since those are for display only */
2764  if (addr->mailbox && !addr->group)
2765  {
2766  if (*argslen == *argsmax)
2767  mutt_mem_realloc(&args, (*argsmax += 5) * sizeof(char *));
2768  args[(*argslen)++] = addr->mailbox;
2769  }
2770  return args;
2771 }
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
+ 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 2781 of file sendlib.c.

2782 {
2783  if (!al)
2784  return args;
2785 
2786  struct Address *a = NULL;
2787  TAILQ_FOREACH(a, al, entries)
2788  {
2789  args = add_args_one(args, argslen, argsmax, a);
2790  }
2791  return args;
2792 }
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
An email address.
Definition: address.h:34
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:2761
+ 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 2804 of file sendlib.c.

2805 {
2806  if (*argslen == *argsmax)
2807  mutt_mem_realloc(&args, (*argsmax += 5) * sizeof(char *));
2808  args[(*argslen)++] = s;
2809  return args;
2810 }
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
+ 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 2823 of file sendlib.c.

2826 {
2827  char *ps = NULL, *path = NULL, *s = NULL, *childout = NULL;
2828  char **args = NULL;
2829  size_t argslen = 0, argsmax = 0;
2830  char **extra_args = NULL;
2831  int i;
2832 
2833 #ifdef USE_NNTP
2834  if (OptNewsSend)
2835  {
2836  char cmd[1024];
2837 
2838  mutt_expando_format(cmd, sizeof(cmd), 0, sizeof(cmd), NONULL(C_Inews),
2840  if (!*cmd)
2841  {
2842  i = nntp_post(Context->mailbox, msg);
2843  unlink(msg);
2844  return i;
2845  }
2846 
2847  s = mutt_str_strdup(cmd);
2848  }
2849  else
2850 #endif
2852 
2853  /* ensure that $sendmail is set to avoid a crash. http://dev.mutt.org/trac/ticket/3548 */
2854  if (!s)
2855  {
2856  mutt_error(_("$sendmail must be set in order to send mail"));
2857  return -1;
2858  }
2859 
2860  ps = s;
2861  i = 0;
2862  while ((ps = strtok(ps, " ")))
2863  {
2864  if (argslen == argsmax)
2865  mutt_mem_realloc(&args, sizeof(char *) * (argsmax += 5));
2866 
2867  if (i)
2868  {
2869  if (mutt_str_strcmp(ps, "--") == 0)
2870  break;
2871  args[argslen++] = ps;
2872  }
2873  else
2874  {
2875  path = mutt_str_strdup(ps);
2876  ps = strrchr(ps, '/');
2877  if (ps)
2878  ps++;
2879  else
2880  ps = path;
2881  args[argslen++] = ps;
2882  }
2883  ps = NULL;
2884  i++;
2885  }
2886 
2887 #ifdef USE_NNTP
2888  if (!OptNewsSend)
2889  {
2890 #endif
2891  size_t extra_argslen = 0;
2892  /* If C_Sendmail contained a "--", we save the recipients to append to
2893  * args after other possible options added below. */
2894  if (ps)
2895  {
2896  ps = NULL;
2897  size_t extra_argsmax = 0;
2898  while ((ps = strtok(ps, " ")))
2899  {
2900  if (extra_argslen == extra_argsmax)
2901  mutt_mem_realloc(&extra_args, sizeof(char *) * (extra_argsmax += 5));
2902 
2903  extra_args[extra_argslen++] = ps;
2904  ps = NULL;
2905  }
2906  }
2907 
2908  if (eightbit && C_Use8bitmime)
2909  args = add_option(args, &argslen, &argsmax, "-B8BITMIME");
2910 
2911  if (C_UseEnvelopeFrom)
2912  {
2914  {
2915  args = add_option(args, &argslen, &argsmax, "-f");
2916  args = add_args_one(args, &argslen, &argsmax, C_EnvelopeFromAddress);
2917  }
2918  else if (!TAILQ_EMPTY(from) && !TAILQ_NEXT(TAILQ_FIRST(from), entries))
2919  {
2920  args = add_option(args, &argslen, &argsmax, "-f");
2921  args = add_args(args, &argslen, &argsmax, from);
2922  }
2923  }
2924 
2925  if (C_DsnNotify)
2926  {
2927  args = add_option(args, &argslen, &argsmax, "-N");
2928  args = add_option(args, &argslen, &argsmax, C_DsnNotify);
2929  }
2930  if (C_DsnReturn)
2931  {
2932  args = add_option(args, &argslen, &argsmax, "-R");
2933  args = add_option(args, &argslen, &argsmax, C_DsnReturn);
2934  }
2935  args = add_option(args, &argslen, &argsmax, "--");
2936  for (i = 0; i < extra_argslen; i++)
2937  args = add_option(args, &argslen, &argsmax, extra_args[i]);
2938  args = add_args(args, &argslen, &argsmax, to);
2939  args = add_args(args, &argslen, &argsmax, cc);
2940  args = add_args(args, &argslen, &argsmax, bcc);
2941 #ifdef USE_NNTP
2942  }
2943 #endif
2944 
2945  if (argslen == argsmax)
2946  mutt_mem_realloc(&args, sizeof(char *) * (++argsmax));
2947 
2948  args[argslen++] = NULL;
2949 
2950  /* Some user's $sendmail command uses gpg for password decryption,
2951  * and is set up to prompt using ncurses pinentry. If we
2952  * mutt_endwin() it leaves other users staring at a blank screen.
2953  * So instead, just force a hard redraw on the next refresh. */
2954  if (!OptNoCurses)
2956 
2957  i = send_msg(path, args, msg, OptNoCurses ? NULL : &childout);
2958  if (i != (EX_OK & 0xff))
2959  {
2960  if (i != S_BKG)
2961  {
2962  const char *e = mutt_str_sysexit(i);
2963  mutt_error(_("Error sending message, child exited %d (%s)"), i, NONULL(e));
2964  if (childout)
2965  {
2966  struct stat st;
2967 
2968  if ((stat(childout, &st) == 0) && (st.st_size > 0))
2969  mutt_do_pager(_("Output of the delivery process"), childout,
2970  MUTT_PAGER_NO_FLAGS, NULL);
2971  }
2972  }
2973  }
2974  else if (childout)
2975  unlink(childout);
2976 
2977  FREE(&childout);
2978  FREE(&path);
2979  FREE(&s);
2980  FREE(&args);
2981  FREE(&extra_args);
2982 
2983  if (i == (EX_OK & 0xff))
2984  i = 0;
2985  else if (i == S_BKG)
2986  i = 1;
2987  else
2988  i = -1;
2989  return i;
2990 }
The "current" mailbox.
Definition: context.h:36
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:877
char * C_Sendmail
Config: External command to send email.
Definition: sendlib.c:92
#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:2596
#define TAILQ_FIRST(head)
Definition: queue.h:716
int nntp_post(struct Mailbox *m, const char *msg)
Post article.
Definition: nntp.c:1976
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:2781
#define _(a)
Definition: message.h:28
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:46
#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:94
struct Mailbox * mailbox
Definition: context.h:50
char * C_Inews
Config: (nntp) External command to post news articles.
Definition: sendlib.c:87
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:2804
bool C_UseEnvelopeFrom
Config: Set the envelope sender of the message.
Definition: sendlib.c:95
WHERE char * C_DsnReturn
Config: What to send as a notification of message delivery or delay.
Definition: globals.h:108
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:664
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
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:44
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:914
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition: curs_lib.c:128
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
WHERE char * C_DsnNotify
Config: Request notification for message delivery or delay.
Definition: globals.h:107
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:2761
#define EX_OK
Definition: sendlib.c:74
#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 3001 of file sendlib.c.

3002 {
3003  if (final)
3004  {
3005  if (!TAILQ_EMPTY(&env->bcc) && TAILQ_EMPTY(&env->to) && TAILQ_EMPTY(&env->cc))
3006  {
3007  /* some MTA's will put an Apparently-To: header field showing the Bcc:
3008  * recipients if there is no To: or Cc: field, so attempt to suppress
3009  * it by using an empty To: field. */
3010  struct Address *to = mutt_addr_new();
3011  to->group = true;
3012  mutt_addrlist_append(&env->to, to);
3014 
3015  char buf[1024];
3016  buf[0] = '\0';
3017  mutt_addr_cat(buf, sizeof(buf), "undisclosed-recipients", AddressSpecials);
3018 
3019  to->mailbox = mutt_str_strdup(buf);
3020  }
3021 
3022  mutt_set_followup_to(env);
3023 
3024  if (!env->message_id)
3025  env->message_id = gen_msgid();
3026  }
3027 
3028  /* Take care of 8-bit => 7-bit conversion. */
3030  encode_headers(&env->userhdrs);
3031 }
void rfc2047_encode_envelope(struct Envelope *env)
Encode the fields of an Envelope.
Definition: rfc2047.c:811
static char * gen_msgid(void)
Generate a unique Message ID.
Definition: sendlib.c:2558
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:1214
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:2494
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 3040 of file sendlib.c.

3041 {
3042  struct ListNode *item = NULL;
3043  STAILQ_FOREACH(item, &env->userhdrs, entries)
3044  {
3045  rfc2047_decode(&item->data);
3046  }
3047 
3049 
3050  /* back conversions */
3052 }
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:791
void rfc2047_decode(char **pd)
Decode any RFC2047-encoded header fields.
Definition: rfc2047.c:651
#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 3064 of file sendlib.c.

3066 {
3067  if (!e)
3068  return -1;
3069 
3070  int rc = 0;
3071 
3072  struct Buffer *tempfile = mutt_buffer_pool_get();
3073  mutt_buffer_mktemp(tempfile);
3074  FILE *fp_tmp = mutt_file_fopen(mutt_b2s(tempfile), "w");
3075  if (fp_tmp)
3076  {
3077  char date[128];
3079 
3080  if (!C_BounceDelivered)
3081  chflags |= CH_WEED_DELIVERED;
3082 
3083  fseeko(fp, e->offset, SEEK_SET);
3084  fprintf(fp_tmp, "Resent-From: %s", resent_from);
3085  fprintf(fp_tmp, "\nResent-%s", mutt_date_make_date(date, sizeof(date)));
3086  char *msgid_str = gen_msgid();
3087  fprintf(fp_tmp, "Resent-Message-ID: %s\n", msgid_str);
3088  FREE(&msgid_str);
3089  fputs("Resent-To: ", fp_tmp);
3090  mutt_write_addrlist(to, fp_tmp, 11, 0);
3091  mutt_copy_header(fp, e, fp_tmp, chflags, NULL, 0);
3092  fputc('\n', fp_tmp);
3093  mutt_file_copy_bytes(fp, fp_tmp, e->content->length);
3094  if (mutt_file_fclose(&fp_tmp) != 0)
3095  {
3096  mutt_perror(mutt_b2s(tempfile));
3097  unlink(mutt_b2s(tempfile));
3098  return -1;
3099  }
3100 #ifdef USE_SMTP
3101  if (C_SmtpUrl)
3102  rc = mutt_smtp_send(env_from, to, NULL, NULL, mutt_b2s(tempfile),
3103  e->content->encoding == ENC_8BIT);
3104  else
3105 #endif
3106  rc = mutt_invoke_sendmail(env_from, to, NULL, NULL, mutt_b2s(tempfile),
3107  e->content->encoding == ENC_8BIT);
3108  }
3109 
3110  mutt_buffer_pool_release(&tempfile);
3111  return rc;
3112 }
WHERE char * C_SmtpUrl
Config: (smtp) Url of the SMTP server.
Definition: globals.h:142
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:78
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:2558
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:2823
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
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:240
void mutt_write_addrlist(struct AddressList *al, FILE *fp, int linelen, bool display)
Wrapper for mutt_write_address()
Definition: sendlib.c:1796
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:83
#define CH_NOQFROM
Ignore ">From " line.
Definition: copy.h:66
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:49
int mutt_copy_header(FILE *fp_in, struct Email *e, FILE *fp_out, CopyHeaderFlags chflags, const char *prefix, int wraplen)
Copy Email header.
Definition: copy.c: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:738
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:585
#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 3122 of file sendlib.c.

3123 {
3124  if (!fp || !e || !to || TAILQ_EMPTY(to))
3125  return -1;
3126 
3127  const char *fqdn = mutt_fqdn(true);
3128  char resent_from[256];
3129  char *err = NULL;
3130 
3131  resent_from[0] = '\0';
3132  struct Address *from = mutt_default_from();
3133  struct AddressList from_list = TAILQ_HEAD_INITIALIZER(from_list);
3134  mutt_addrlist_append(&from_list, from);
3135 
3136  /* mutt_default_from() does not use $realname if the real name is not set
3137  * in $from, so we add it here. The reason it is not added in
3138  * mutt_default_from() is that during normal sending, we execute
3139  * send-hooks and set the realname last so that it can be changed based
3140  * upon message criteria. */
3141  if (!from->personal)
3143 
3144  mutt_addrlist_qualify(&from_list, fqdn);
3145 
3146  rfc2047_encode_addrlist(&from_list, "Resent-From");
3147  if (mutt_addrlist_to_intl(&from_list, &err))
3148  {
3149  mutt_error(_("Bad IDN %s while preparing resent-from"), err);
3150  FREE(&err);
3151  mutt_addrlist_clear(&from_list);
3152  return -1;
3153  }
3154  mutt_addrlist_write(&from_list, resent_from, sizeof(resent_from), false);
3155 
3156 #ifdef USE_NNTP
3157  OptNewsSend = false;
3158 #endif
3159 
3160  /* prepare recipient list. idna conversion appears to happen before this
3161  * function is called, since the user receives confirmation of the address
3162  * list being bounced to. */
3163  struct AddressList resent_to = TAILQ_HEAD_INITIALIZER(resent_to);
3164  mutt_addrlist_copy(&resent_to, to, false);
3165  rfc2047_encode_addrlist(&resent_to, "Resent-To");
3166  int rc = bounce_message(fp, e, &resent_to, resent_from, &from_list);
3167  mutt_addrlist_clear(&resent_to);
3168  mutt_addrlist_clear(&from_list);
3169 
3170  return rc;
3171 }
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:3064
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:750
struct Address * mutt_default_from(void)
Get a default &#39;from&#39; Address.
Definition: send.c:1334
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2531
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:138
#define TAILQ_EMPTY(head)
Definition: queue.h:714
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:44
#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 3178 of file sendlib.c.

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

3207 {
3208  char fcc_tok[PATH_MAX];
3209  char fcc_expanded[PATH_MAX];
3210 
3211  mutt_str_strfcpy(fcc_tok, path, sizeof(fcc_tok));
3212 
3213  char *tok = strtok(fcc_tok, ",");
3214  if (!tok)
3215  return -1;
3216 
3217  mutt_debug(LL_DEBUG1, "Fcc: initial mailbox = '%s'\n", tok);
3218  /* mutt_expand_path already called above for the first token */
3219  int status = mutt_write_fcc(tok, e, msgid, post, fcc, finalpath);
3220  if (status != 0)
3221  return status;
3222 
3223  while ((tok = strtok(NULL, ",")))
3224  {
3225  if (!*tok)
3226  continue;
3227 
3228  /* Only call mutt_expand_path if tok has some data */
3229  mutt_debug(LL_DEBUG1, "Fcc: additional mailbox token = '%s'\n", tok);
3230  mutt_str_strfcpy(fcc_expanded, tok, sizeof(fcc_expanded));
3231  mutt_expand_path(fcc_expanded, sizeof(fcc_expanded));
3232  mutt_debug(LL_DEBUG1, " Additional mailbox expanded = '%s'\n", fcc_expanded);
3233  status = mutt_write_fcc(fcc_expanded, e, msgid, post, fcc, finalpath);
3234  if (status != 0)
3235  return status;
3236  }
3237 
3238  return 0;
3239 }
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:3252
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:133
#define PATH_MAX
Definition: mutt.h:50
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:750
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 3252 of file sendlib.c.

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

◆ C_AttachCharset

char* C_AttachCharset

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

Definition at line 82 of file sendlib.c.

◆ C_BounceDelivered

bool C_BounceDelivered

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

Definition at line 83 of file sendlib.c.

◆ C_EncodeFrom

bool C_EncodeFrom

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

Definition at line 84 of file sendlib.c.

◆ C_ForwardDecrypt

bool C_ForwardDecrypt

Config: Decrypt the message when forwarding it.

Definition at line 85 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 86 of file sendlib.c.

◆ C_Inews

char* C_Inews

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

Definition at line 87 of file sendlib.c.

◆ C_MimeForwardDecode

bool C_MimeForwardDecode

Config: Decode the forwarded message before attaching it.

Definition at line 88 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 89 of file sendlib.c.

◆ C_MimeTypeQueryCommand

char* C_MimeTypeQueryCommand

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

Definition at line 90 of file sendlib.c.

◆ C_MimeTypeQueryFirst

bool C_MimeTypeQueryFirst

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

Definition at line 91 of file sendlib.c.

◆ C_Sendmail

char* C_Sendmail

Config: External command to send email.

Definition at line 92 of file sendlib.c.

◆ C_SendmailWait

short C_SendmailWait

Config: Time to wait for sendmail to finish.

Definition at line 93 of file sendlib.c.

◆ C_Use8bitmime

bool C_Use8bitmime

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

Definition at line 94 of file sendlib.c.

◆ C_UseEnvelopeFrom

bool C_UseEnvelopeFrom

Config: Set the envelope sender of the message.

Definition at line 95 of file sendlib.c.

◆ C_UserAgent

bool C_UserAgent

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

Definition at line 96 of file sendlib.c.

◆ C_WrapHeaders

short C_WrapHeaders

Config: Width to wrap headers in outgoing messages.

Definition at line 97 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 128 of file sendlib.c.