NeoMutt  2019-11-11
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 "mutt.h"
#include "sendlib.h"
#include "context.h"
#include "copy.h"
#include "curs_lib.h"
#include "filter.h"
#include "format_flags.h"
#include "globals.h"
#include "handler.h"
#include "mutt_mailbox.h"
#include "mutt_parse.h"
#include "mutt_window.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 around 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, 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 75 of file sendlib.c.

◆ MUTT_RANDTAG_LEN

#define MUTT_RANDTAG_LEN   16

Definition at line 100 of file sendlib.c.

Enumeration Type Documentation

◆ UserHdrsOverrideIdx

Enumerator
USERHDRS_OVERRIDE_CONTENT_TYPE 
USERHDRS_OVERRIDE_USER_AGENT 

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

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

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

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

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

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

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

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

544 {
545  return mutt_is_text_part(b) ||
547 }
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:559
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
Definition: muttlib.c:453
#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 556 of file sendlib.c.

557 {
558  FILE *fp_in = NULL;
559  struct FgetConv *fc = NULL;
560 
561  if (a->type == TYPE_MULTIPART)
562  {
563  /* First, find the boundary to use */
564  const char *p = mutt_param_get(&a->parameter, "boundary");
565  if (!p)
566  {
567  mutt_debug(LL_DEBUG1, "no boundary parameter found\n");
568  mutt_error(_("No boundary parameter found [report this error]"));
569  return -1;
570  }
571  char boundary[128];
572  mutt_str_strfcpy(boundary, p, sizeof(boundary));
573 
574  for (struct Body *t = a->parts; t; t = t->next)
575  {
576  fprintf(fp, "\n--%s\n", boundary);
577  if (mutt_write_mime_header(t, fp) == -1)
578  return -1;
579  fputc('\n', fp);
580  if (mutt_write_mime_body(t, fp) == -1)
581  return -1;
582  }
583  fprintf(fp, "\n--%s--\n", boundary);
584  return ferror(fp) ? -1 : 0;
585  }
586 
587  /* This is pretty gross, but it's the best solution for now... */
588  if (((WithCrypto & APPLICATION_PGP) != 0) && (a->type == TYPE_APPLICATION) &&
589  (mutt_str_strcmp(a->subtype, "pgp-encrypted") == 0) && !a->filename)
590  {
591  fputs("Version: 1\n", fp);
592  return 0;
593  }
594 
595  fp_in = fopen(a->filename, "r");
596  if (!fp_in)
597  {
598  mutt_debug(LL_DEBUG1, "%s no longer exists\n", a->filename);
599  mutt_error(_("%s no longer exists"), a->filename);
600  return -1;
601  }
602 
603  if ((a->type == TYPE_TEXT) && (!a->noconv))
604  {
605  char send_charset[128];
607  fp_in, a->charset,
608  mutt_body_get_charset(a, send_charset, sizeof(send_charset)), 0);
609  }
610  else
611  fc = mutt_ch_fgetconv_open(fp_in, 0, 0, 0);
612 
614  if (a->encoding == ENC_QUOTED_PRINTABLE)
616  else if (a->encoding == ENC_BASE64)
618  else if ((a->type == TYPE_TEXT) && (!a->noconv))
619  encode_8bit(fc, fp);
620  else
621  mutt_file_copy_stream(fp_in, fp);
623 
625  mutt_file_fclose(&fp_in);
626 
627  if (SigInt == 1)
628  {
629  SigInt = 0;
630  return -1;
631  }
632  return ferror(fp) ? -1 : 0;
633 }
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:81
static void encode_base64(struct FgetConv *fc, FILE *fp_out, int istext)
Base64-encode some data.
Definition: sendlib.c:347
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:543
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:151
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:556
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:1462
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:375
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:56
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:397
#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 639 of file sendlib.c.

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

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

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

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

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

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

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

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

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

1450 {
1451  a->stamp = mutt_date_epoch();
1452 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:410
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 1462 of file sendlib.c.

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

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

1518 {
1519  char buf[1024];
1520  struct Body *body = NULL;
1521  FILE *fp = NULL;
1522  CopyMessageFlags cmflags;
1524 
1525  if (WithCrypto)
1526  {
1528  {
1530  return NULL;
1531  }
1532  }
1533 
1534  mutt_mktemp(buf, sizeof(buf));
1535  fp = mutt_file_fopen(buf, "w+");
1536  if (!fp)
1537  return NULL;
1538 
1539  body = mutt_body_new();
1540  body->type = TYPE_MESSAGE;
1541  body->subtype = mutt_str_strdup("rfc822");
1542  body->filename = mutt_str_strdup(buf);
1543  body->unlink = true;
1544  body->use_disp = false;
1545  body->disposition = DISP_INLINE;
1546  body->noconv = true;
1547 
1549 
1550  CopyHeaderFlags chflags = CH_XMIT;
1551  cmflags = MUTT_CM_NO_FLAGS;
1552 
1553  /* If we are attaching a message, ignore C_MimeForwardDecode */
1554  if (!attach_msg && C_MimeForwardDecode)
1555  {
1556  chflags |= CH_MIME | CH_TXTPLAIN;
1557  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1559  pgp &= ~PGP_ENCRYPT;
1561  pgp &= ~SMIME_ENCRYPT;
1562  }
1563  else if ((WithCrypto != 0) && C_ForwardDecrypt && (e->security & SEC_ENCRYPT))
1564  {
1565  if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_multipart_encrypted(e->content))
1566  {
1567  chflags |= CH_MIME | CH_NONEWLINE;
1568  cmflags = MUTT_CM_DECODE_PGP;
1569  pgp &= ~PGP_ENCRYPT;
1570  }
1571  else if (((WithCrypto & APPLICATION_PGP) != 0) &&
1573  {
1574  chflags |= CH_MIME | CH_TXTPLAIN;
1575  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1576  pgp &= ~PGP_ENCRYPT;
1577  }
1578  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
1580  {
1581  chflags |= CH_MIME | CH_TXTPLAIN;
1582  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1583  pgp &= ~SMIME_ENCRYPT;
1584  }
1585  }
1586 
1587  mutt_copy_message(fp, m, e, cmflags, chflags, 0);
1588 
1589  fflush(fp);
1590  rewind(fp);
1591 
1592  body->email = email_new();
1593  body->email->offset = 0;
1594  /* we don't need the user headers here */
1595  body->email->env = mutt_rfc822_read_header(fp, body->email, false, false);
1596  if (WithCrypto)
1597  body->email->security = pgp;
1598  mutt_update_encoding(body);
1599  body->parts = body->email->content;
1600 
1601  mutt_file_fclose(&fp);
1602 
1603  return body;
1604 }
#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:89
#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:147
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:453
void mutt_update_encoding(struct Body *a)
Update the encoding type.
Definition: sendlib.c:1486
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:559
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:76
#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:86
#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:618
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:1134
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 1612 of file sendlib.c.

1613 {
1614  FILE *fp = NULL, *fp_err = NULL;
1615  char *buf = NULL;
1616  size_t buflen;
1617  int dummy = 0;
1618  pid_t pid;
1619  struct Buffer *cmd = mutt_buffer_pool_get();
1620 
1622 
1623  pid = mutt_create_filter(mutt_b2s(cmd), NULL, &fp, &fp_err);
1624  if (pid < 0)
1625  {
1626  mutt_error(_("Error running \"%s\""), mutt_b2s(cmd));
1628  return;
1629  }
1631 
1632  buf = mutt_file_read_line(buf, &buflen, fp, &dummy, 0);
1633  if (buf)
1634  {
1635  if (strchr(buf, '/'))
1636  mutt_parse_content_type(buf, att);
1637  FREE(&buf);
1638  }
1639 
1640  mutt_file_fclose(&fp);
1641  mutt_file_fclose(&fp_err);
1642  mutt_wait_filter(pid);
1643 }
pid_t mutt_create_filter(const char *s, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:210
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:100
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:111
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:454
char * C_MimeTypeQueryCommand
Config: External command to determine the MIME type of an attachment.
Definition: sendlib.c:91
#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:1419
#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:221
+ 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 1651 of file sendlib.c.

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

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

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

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

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

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

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

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

Fold one header line.

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

Definition at line 1932 of file sendlib.c.

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

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

2075 {
2076  char *tagbuf = NULL, *valbuf = NULL, *t = NULL;
2077  bool is_from = ((end - start) > 5) && mutt_str_startswith(start, "from ", CASE_IGNORE);
2078 
2079  /* only pass through folding machinery if necessary for sending,
2080  * never wrap From_ headers on sending */
2081  if (!(chflags & CH_DISPLAY) && ((pfxw + max <= wraplen) || is_from))
2082  {
2083  valbuf = mutt_str_substr_dup(start, end);
2084  mutt_debug(LL_DEBUG5, "buf[%s%s] short enough, max width = %d <= %d\n",
2085  NONULL(pfx), valbuf, max, wraplen);
2086  if (pfx && *pfx)
2087  {
2088  if (fputs(pfx, fp) == EOF)
2089  {
2090  FREE(&valbuf);
2091  return -1;
2092  }
2093  }
2094 
2095  t = strchr(valbuf, ':');
2096  if (!t)
2097  {
2098  mutt_debug(LL_DEBUG1, "#1 warning: header not in 'key: value' format!\n");
2099  FREE(&valbuf);
2100  return 0;
2101  }
2102  if (print_val(fp, pfx, valbuf, chflags, mutt_str_strlen(pfx)) < 0)
2103  {
2104  FREE(&valbuf);
2105  return -1;
2106  }
2107  FREE(&valbuf);
2108  }
2109  else
2110  {
2111  t = strchr(start, ':');
2112  if (!t || (t > end))
2113  {
2114  mutt_debug(LL_DEBUG1, "#2 warning: header not in 'key: value' format!\n");
2115  return 0;
2116  }
2117  if (is_from)
2118  {
2119  tagbuf = NULL;
2120  valbuf = mutt_str_substr_dup(start, end);
2121  }
2122  else
2123  {
2124  tagbuf = mutt_str_substr_dup(start, t);
2125  /* skip over the colon separating the header field name and value */
2126  t++;
2127 
2128  /* skip over any leading whitespace (WSP, as defined in RFC5322)
2129  * NOTE: mutt_str_skip_email_wsp() does the wrong thing here.
2130  * See tickets 3609 and 3716. */
2131  while ((*t == ' ') || (*t == '\t'))
2132  t++;
2133 
2134  valbuf = mutt_str_substr_dup(t, end);
2135  }
2136  mutt_debug(LL_DEBUG2, "buf[%s%s] too long, max width = %d > %d\n",
2137  NONULL(pfx), NONULL(valbuf), max, wraplen);
2138  if (fold_one_header(fp, tagbuf, valbuf, pfx, wraplen, chflags) < 0)
2139  {
2140  FREE(&valbuf);
2141  FREE(&tagbuf);
2142  return -1;
2143  }
2144  FREE(&tagbuf);
2145  FREE(&valbuf);
2146  }
2147  return 0;
2148 }
#define NONULL(x)
Definition: string2.h:37
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:57
#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:56
static int fold_one_header(FILE *fp, const char *tag, const char *value, const char *pfx, int wraplen, CopyHeaderFlags chflags)
Fold one header line.
Definition: sendlib.c:1932
#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:49
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Log at debug level 5.
Definition: logging.h:60
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:1886
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 2164 of file sendlib.c.

2166 {
2167  char *last = NULL, *line = NULL;
2168  int max = 0, w, rc = -1;
2169  int pfxw = mutt_strwidth(pfx);
2170  char *v = mutt_str_strdup(value);
2171  bool display = (chflags & CH_DISPLAY);
2172 
2173  if (!display || C_Weed)
2174  v = unfold_header(v);
2175 
2176  /* when not displaying, use sane wrap value */
2177  if (!display)
2178  {
2179  if ((C_WrapHeaders < 78) || (C_WrapHeaders > 998))
2180  wraplen = 78;
2181  else
2182  wraplen = C_WrapHeaders;
2183  }
2184  else if (wraplen <= 0)
2185  wraplen = 78;
2186 
2187  if (tag)
2188  {
2189  /* if header is short enough, simply print it */
2190  if (!display && (mutt_strwidth(tag) + 2 + pfxw + mutt_strwidth(v) <= wraplen))
2191  {
2192  mutt_debug(LL_DEBUG5, "buf[%s%s: %s] is short enough\n", NONULL(pfx), tag, v);
2193  if (fprintf(fp, "%s%s: %s\n", NONULL(pfx), tag, v) <= 0)
2194  goto out;
2195  rc = 0;
2196  goto out;
2197  }
2198  else
2199  {
2200  rc = fold_one_header(fp, tag, v, pfx, wraplen, chflags);
2201  goto out;
2202  }
2203  }
2204 
2205  char *p = v;
2206  last = v;
2207  line = v;
2208  while (p && *p)
2209  {
2210  p = strchr(p, '\n');
2211 
2212  /* find maximum line width in current header */
2213  if (p)
2214  *p = '\0';
2215  w = mutt_mb_width(line, 0, display);
2216  if (w > max)
2217  max = w;
2218  if (p)
2219  *p = '\n';
2220 
2221  if (!p)
2222  break;
2223 
2224  line = ++p;
2225  if ((*p != ' ') && (*p != '\t'))
2226  {
2227  if (write_one_header(fp, pfxw, max, wraplen, pfx, last, p, chflags) < 0)
2228  goto out;
2229  last = p;
2230  max = 0;
2231  }
2232  }
2233 
2234  if (last && *last)
2235  if (write_one_header(fp, pfxw, max, wraplen, pfx, last, p, chflags) < 0)
2236  goto out;
2237 
2238  rc = 0;
2239 
2240 out:
2241  FREE(&v);
2242  return rc;
2243 }
short C_WrapHeaders
Config: Width to wrap headers in outgoing messages.
Definition: sendlib.c:98
#define NONULL(x)
Definition: string2.h:37
static char * unfold_header(char *s)
Unfold a wrapped email header.
Definition: sendlib.c:2031
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:1287
#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:2073
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
static int fold_one_header(FILE *fp, const char *tag, const char *value, const char *pfx, int wraplen, CopyHeaderFlags chflags)
Fold one header line.
Definition: sendlib.c:1932
#define FREE(x)
Definition: memory.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Log at debug level 5.
Definition: logging.h:60
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 2253 of file sendlib.c.

2254 {
2255  const char *ca = a;
2256  const char *cb = *(const char **) b;
2257  return mutt_str_strncasecmp(ca, cb, strlen(cb));
2258 }
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 2267 of file sendlib.c.

2268 {
2269  struct UserHdrsOverride overrides = { { 0 } };
2270 
2271  struct ListNode *tmp = NULL;
2272  STAILQ_FOREACH(tmp, userhdrs, entries)
2273  {
2274  char *const colon = strchr(tmp->data, ':');
2275  if (!colon)
2276  {
2277  continue;
2278  }
2279 
2280  const char *const value = mutt_str_skip_email_wsp(colon + 1);
2281  if (*value == '\0')
2282  {
2283  continue; /* don't emit empty fields. */
2284  }
2285 
2286  /* check whether the current user-header is an override */
2287  size_t curr_override = (size_t) -1;
2288  const char *const *idx = bsearch(tmp->data, userhdrs_override_headers,
2290  sizeof(char *), userhdrs_override_cmp);
2291  if (idx != NULL)
2292  {
2293  curr_override = idx - userhdrs_override_headers;
2294  overrides.is_overridden[curr_override] = true;
2295  }
2296 
2297  if (privacy && (curr_override == USERHDRS_OVERRIDE_USER_AGENT))
2298  {
2299  continue;
2300  }
2301 
2302  *colon = '\0';
2303  mutt_write_one_header(fp, tmp->data, value, NULL, 0, CH_NO_FLAGS);
2304  *colon = ':';
2305  }
2306 
2307  return overrides;
2308 }
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:129
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:2253
#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:350
bool is_overridden[mutt_array_size(userhdrs_override_headers)]
Definition: sendlib.c:142
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:2164
+ 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 2334 of file sendlib.c.

2337 {
2338  char buf[1024];
2339 
2340  if ((mode == MUTT_WRITE_HEADER_NORMAL) && !privacy)
2341  fputs(mutt_date_make_date(buf, sizeof(buf)), fp);
2342 
2343  /* UseFrom is not consulted here so that we can still write a From:
2344  * field if the user sets it with the 'my_hdr' command */
2345  if (!TAILQ_EMPTY(&env->from) && !privacy)
2346  {
2347  buf[0] = '\0';
2348  mutt_addrlist_write(buf, sizeof(buf), &env->from, false);
2349  fprintf(fp, "From: %s\n", buf);
2350  }
2351 
2352  if (!TAILQ_EMPTY(&env->sender) && !privacy)
2353  {
2354  buf[0] = '\0';
2355  mutt_addrlist_write(buf, sizeof(buf), &env->sender, false);
2356  fprintf(fp, "Sender: %s\n", buf);
2357  }
2358 
2359  if (!TAILQ_EMPTY(&env->to))
2360  {
2361  fputs("To: ", fp);
2362  mutt_write_addrlist(&env->to, fp, 4, 0);
2363  }
2364  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2365 #ifdef USE_NNTP
2366  if (!OptNewsSend)
2367 #endif
2368  fputs("To:\n", fp);
2369 
2370  if (!TAILQ_EMPTY(&env->cc))
2371  {
2372  fputs("Cc: ", fp);
2373  mutt_write_addrlist(&env->cc, fp, 4, 0);
2374  }
2375  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2376 #ifdef USE_NNTP
2377  if (!OptNewsSend)
2378 #endif
2379  fputs("Cc:\n", fp);
2380 
2381  if (!TAILQ_EMPTY(&env->bcc))
2382  {
2383  if ((mode == MUTT_WRITE_HEADER_POSTPONE) || (mode == MUTT_WRITE_HEADER_EDITHDRS) ||
2384  ((mode == MUTT_WRITE_HEADER_NORMAL) && C_WriteBcc))
2385  {
2386  fputs("Bcc: ", fp);
2387  mutt_write_addrlist(&env->bcc, fp, 5, 0);
2388  }
2389  }
2390  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2391 #ifdef USE_NNTP
2392  if (!OptNewsSend)
2393 #endif
2394  fputs("Bcc:\n", fp);
2395 
2396 #ifdef USE_NNTP
2397  if (env->newsgroups)
2398  fprintf(fp, "Newsgroups: %s\n", env->newsgroups);
2399  else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend)
2400  fputs("Newsgroups:\n", fp);
2401 
2402  if (env->followup_to)
2403  fprintf(fp, "Followup-To: %s\n", env->followup_to);
2404  else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend)
2405  fputs("Followup-To:\n", fp);
2406 
2407  if (env->x_comment_to)
2408  fprintf(fp, "X-Comment-To: %s\n", env->x_comment_to);
2409  else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend && C_XCommentTo)
2410  fputs("X-Comment-To:\n", fp);
2411 #endif
2412 
2413  if (env->subject)
2414  {
2415  if (hide_protected_subject &&
2416  ((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_POSTPONE)))
2418  else
2419  mutt_write_one_header(fp, "Subject", env->subject, NULL, 0, CH_NO_FLAGS);
2420  }
2421  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2422  fputs("Subject:\n", fp);
2423 
2424  /* save message id if the user has set it */
2425  if (env->message_id && !privacy)
2426  fprintf(fp, "Message-ID: %s\n", env->message_id);
2427 
2428  if (!TAILQ_EMPTY(&env->reply_to))
2429  {
2430  fputs("Reply-To: ", fp);
2431  mutt_write_addrlist(&env->reply_to, fp, 10, 0);
2432  }
2433  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2434  fputs("Reply-To:\n", fp);
2435 
2436  if (!TAILQ_EMPTY(&env->mail_followup_to))
2437  {
2438 #ifdef USE_NNTP
2439  if (!OptNewsSend)
2440 #endif
2441  {
2442  fputs("Mail-Followup-To: ", fp);
2443  mutt_write_addrlist(&env->mail_followup_to, fp, 18, 0);
2444  }
2445  }
2446 
2447  /* Add any user defined headers */
2448  struct UserHdrsOverride userhdrs_overrides = write_userhdrs(fp, &env->userhdrs, privacy);
2449 
2450  if ((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_POSTPONE))
2451  {
2452  if (!STAILQ_EMPTY(&env->references))
2453  {
2454  fputs("References:", fp);
2455  mutt_write_references(&env->references, fp, 10);
2456  fputc('\n', fp);
2457  }
2458 
2459  /* Add the MIME headers */
2460  if (!userhdrs_overrides.is_overridden[USERHDRS_OVERRIDE_CONTENT_TYPE])
2461  {
2462  fputs("MIME-Version: 1.0\n", fp);
2463  mutt_write_mime_header(attach, fp);
2464  }
2465  }
2466 
2467  if (!STAILQ_EMPTY(&env->in_reply_to))
2468  {
2469  fputs("In-Reply-To:", fp);
2470  mutt_write_references(&env->in_reply_to, fp, 0);
2471  fputc('\n', fp);
2472  }
2473 
2474 #ifdef USE_AUTOCRYPT
2475  if (C_Autocrypt)
2476  {
2477  if (mode == MUTT_WRITE_HEADER_NORMAL)
2479  if (mode == MUTT_WRITE_HEADER_MIME)
2481  }
2482 #endif
2483 
2484  if ((mode == MUTT_WRITE_HEADER_NORMAL) && !privacy && C_UserAgent &&
2485  !userhdrs_overrides.is_overridden[USERHDRS_OVERRIDE_USER_AGENT])
2486  {
2487  /* Add a vanity header */
2488  fprintf(fp, "User-Agent: NeoMutt/%s%s\n", PACKAGE_VERSION, GitVer);
2489  }
2490 
2491  return (ferror(fp) == 0) ? 0 : -1;
2492 }
WHERE bool C_Autocrypt
Config: Enables the Autocrypt feature.
Definition: globals.h:203
WHERE bool C_WriteBcc
Config: Write out the &#39;Bcc&#39; field when preparing to send a mail.
Definition: globals.h:271
struct AddressList mail_followup_to
Email&#39;s &#39;mail-followup-to&#39;.
Definition: envelope.h:63
struct AddressList reply_to
Email&#39;s &#39;reply-to&#39;.
Definition: envelope.h:62
struct AddressList bcc
Email&#39;s &#39;Bcc&#39; list.
Definition: envelope.h:60
WHERE char * C_CryptProtectedHeadersSubject
Config: Use this as the subject for encrypted emails.
Definition: globals.h:107
bool C_UserAgent
Config: Add a &#39;User-Agent&#39; head to outgoing mail.
Definition: sendlib.c:97
A normal Email, write full header + MIME headers.
Definition: sendlib.h:60
A postponed Email, just the envelope info.
Definition: sendlib.h:61
struct ListHead userhdrs
user defined headers
Definition: envelope.h:83
size_t mutt_addrlist_write(char *buf, size_t buflen, const struct AddressList *al, bool display)
Write an Address to a buffer.
Definition: address.c:1137
char * mutt_date_make_date(char *buf, size_t buflen)
Write a date in RFC822 format to a buffer.
Definition: date.c:371
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:2267
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:1843
const char * GitVer
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:50
"light" mode (used for edit_hdrs)
Definition: sendlib.h:62
void mutt_write_addrlist(struct AddressList *al, FILE *fp, int linelen, bool display)
wrapper around mutt_write_address()
Definition: sendlib.c:1797
bool is_overridden[mutt_array_size(userhdrs_override_headers)]
Definition: sendlib.c:142
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:292
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:397
#define STAILQ_EMPTY(head)
Definition: queue.h:346
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:63
#define TAILQ_EMPTY(head)
Definition: queue.h:715
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
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:2164
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 2500 of file sendlib.c.

2501 {
2502  char *tmp = NULL;
2503  char *p = NULL;
2504  int i;
2505 
2506  struct ListNode *np = NULL;
2507  STAILQ_FOREACH(np, h, entries)
2508  {
2509  p = strchr(np->data, ':');
2510  if (!p)
2511  continue;
2512 
2513  i = p - np->data;
2514  p = mutt_str_skip_email_wsp(p + 1);
2515  tmp = mutt_str_strdup(p);
2516 
2517  if (!tmp)
2518  continue;
2519 
2520  rfc2047_encode(&tmp, NULL, i + 2, C_SendCharset);
2521  mutt_mem_realloc(&np->data, i + 2 + mutt_str_strlen(tmp) + 1);
2522 
2523  sprintf(np->data + i + 2, "%s", tmp);
2524 
2525  FREE(&tmp);
2526  }
2527 }
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:350
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 2537 of file sendlib.c.

2538 {
2539  if (!C_Hostname || (C_Hostname[0] == '@'))
2540  return NULL;
2541 
2542  char *p = C_Hostname;
2543 
2544  if (may_hide_host && C_HiddenHost)
2545  {
2546  p = strchr(C_Hostname, '.');
2547  if (p)
2548  p++;
2549 
2550  // sanity check: don't hide the host if the fqdn is something like example.com
2551  if (!p || !strchr(p, '.'))
2552  p = C_Hostname;
2553  }
2554 
2555  return p;
2556 }
bool C_HiddenHost
Config: Don&#39;t use the hostname, just the domain, when generating the message id.
Definition: sendlib.c:87
WHERE char * C_Hostname
Config: Fully-qualified domain name of this machine.
Definition: globals.h:113
+ Here is the caller graph for this function:

◆ gen_msgid()

static char* gen_msgid ( void  )
static

Generate a unique Message ID.

Return values
ptrMessage ID
Note
The caller should free the string

Definition at line 2564 of file sendlib.c.

2565 {
2566  char buf[128];
2567  unsigned char rndid[MUTT_RANDTAG_LEN + 1];
2568 
2569  mutt_rand_base32(rndid, sizeof(rndid) - 1);
2570  rndid[MUTT_RANDTAG_LEN] = 0;
2571  const char *fqdn = mutt_fqdn(false);
2572  if (!fqdn)
2573  fqdn = NONULL(ShortHostname);
2574 
2575  struct tm tm = mutt_date_gmtime(MUTT_DATE_NOW);
2576  snprintf(buf, sizeof(buf), "<%d%02d%02d%02d%02d%02d.%s@%s>", tm.tm_year + 1900,
2577  tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, rndid, fqdn);
2578  return mutt_str_strdup(buf);
2579 }
#define NONULL(x)
Definition: string2.h:37
#define MUTT_RANDTAG_LEN
Definition: sendlib.c:100
#define MUTT_DATE_NOW
Constant representing the &#39;current time&#39;, see: mutt_date_gmtime(), mutt_date_localtime() ...
Definition: date.h:36
struct tm mutt_date_gmtime(time_t t)
Converts calendar time to a broken-down time structure expressed in UTC timezone. ...
Definition: date.c:754
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2537
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:52
void mutt_rand_base32(void *buf, size_t buflen)
Fill a buffer with a base32-encoded random string.
Definition: muttlib.c:529
+ 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 2585 of file sendlib.c.

2586 {
2587  SigAlrm = 1;
2588 }
WHERE SIG_ATOMIC_VOLATILE_T SigAlrm
true after SIGALRM is received
Definition: globals.h:80
+ 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 2602 of file sendlib.c.

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

2768 {
2769  /* weed out group mailboxes, since those are for display only */
2770  if (addr->mailbox && !addr->group)
2771  {
2772  if (*argslen == *argsmax)
2773  mutt_mem_realloc(&args, (*argsmax += 5) * sizeof(char *));
2774  args[(*argslen)++] = addr->mailbox;
2775  }
2776  return args;
2777 }
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 2787 of file sendlib.c.

2788 {
2789  if (!al)
2790  return args;
2791 
2792  struct Address *a = NULL;
2793  TAILQ_FOREACH(a, al, entries)
2794  {
2795  args = add_args_one(args, argslen, argsmax, a);
2796  }
2797  return args;
2798 }
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
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:2767
+ 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 2810 of file sendlib.c.

2811 {
2812  if (*argslen == *argsmax)
2813  mutt_mem_realloc(&args, (*argsmax += 5) * sizeof(char *));
2814  args[(*argslen)++] = s;
2815  return args;
2816 }
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 2829 of file sendlib.c.

2832 {
2833  char *ps = NULL, *path = NULL, *s = NULL, *childout = NULL;
2834  char **args = NULL;
2835  size_t argslen = 0, argsmax = 0;
2836  char **extra_args = NULL;
2837  int i;
2838 
2839 #ifdef USE_NNTP
2840  if (OptNewsSend)
2841  {
2842  char cmd[1024];
2843 
2844  mutt_expando_format(cmd, sizeof(cmd), 0, sizeof(cmd), NONULL(C_Inews),
2846  if (!*cmd)
2847  {
2848  i = nntp_post(Context->mailbox, msg);
2849  unlink(msg);
2850  return i;
2851  }
2852 
2853  s = mutt_str_strdup(cmd);
2854  }
2855  else
2856 #endif
2858 
2859  /* ensure that $sendmail is set to avoid a crash. http://dev.mutt.org/trac/ticket/3548 */
2860  if (!s)
2861  {
2862  mutt_error(_("$sendmail must be set in order to send mail"));
2863  return -1;
2864  }
2865 
2866  ps = s;
2867  i = 0;
2868  while ((ps = strtok(ps, " ")))
2869  {
2870  if (argslen == argsmax)
2871  mutt_mem_realloc(&args, sizeof(char *) * (argsmax += 5));
2872 
2873  if (i)
2874  {
2875  if (mutt_str_strcmp(ps, "--") == 0)
2876  break;
2877  args[argslen++] = ps;
2878  }
2879  else
2880  {
2881  path = mutt_str_strdup(ps);
2882  ps = strrchr(ps, '/');
2883  if (ps)
2884  ps++;
2885  else
2886  ps = path;
2887  args[argslen++] = ps;
2888  }
2889  ps = NULL;
2890  i++;
2891  }
2892 
2893 #ifdef USE_NNTP
2894  if (!OptNewsSend)
2895  {
2896 #endif
2897  size_t extra_argslen = 0;
2898  /* If C_Sendmail contained a "--", we save the recipients to append to
2899  * args after other possible options added below. */
2900  if (ps)
2901  {
2902  ps = NULL;
2903  size_t extra_argsmax = 0;
2904  while ((ps = strtok(ps, " ")))
2905  {
2906  if (extra_argslen == extra_argsmax)
2907  mutt_mem_realloc(&extra_args, sizeof(char *) * (extra_argsmax += 5));
2908 
2909  extra_args[extra_argslen++] = ps;
2910  ps = NULL;
2911  }
2912  }
2913 
2914  if (eightbit && C_Use8bitmime)
2915  args = add_option(args, &argslen, &argsmax, "-B8BITMIME");
2916 
2917  if (C_UseEnvelopeFrom)
2918  {
2920  {
2921  args = add_option(args, &argslen, &argsmax, "-f");
2922  args = add_args_one(args, &argslen, &argsmax, C_EnvelopeFromAddress);
2923  }
2924  else if (!TAILQ_EMPTY(from) && !TAILQ_NEXT(TAILQ_FIRST(from), entries))
2925  {
2926  args = add_option(args, &argslen, &argsmax, "-f");
2927  args = add_args(args, &argslen, &argsmax, from);
2928  }
2929  }
2930 
2931  if (C_DsnNotify)
2932  {
2933  args = add_option(args, &argslen, &argsmax, "-N");
2934  args = add_option(args, &argslen, &argsmax, C_DsnNotify);
2935  }
2936  if (C_DsnReturn)
2937  {
2938  args = add_option(args, &argslen, &argsmax, "-R");
2939  args = add_option(args, &argslen, &argsmax, C_DsnReturn);
2940  }
2941  args = add_option(args, &argslen, &argsmax, "--");
2942  for (i = 0; i < extra_argslen; i++)
2943  args = add_option(args, &argslen, &argsmax, extra_args[i]);
2944  args = add_args(args, &argslen, &argsmax, to);
2945  args = add_args(args, &argslen, &argsmax, cc);
2946  args = add_args(args, &argslen, &argsmax, bcc);
2947 #ifdef USE_NNTP
2948  }
2949 #endif
2950 
2951  if (argslen == argsmax)
2952  mutt_mem_realloc(&args, sizeof(char *) * (++argsmax));
2953 
2954  args[argslen++] = NULL;
2955 
2956  /* Some user's $sendmail command uses gpg for password decryption,
2957  * and is set up to prompt using ncurses pinentry. If we
2958  * mutt_endwin() it leaves other users staring at a blank screen.
2959  * So instead, just force a hard redraw on the next refresh. */
2960  if (!OptNoCurses)
2962 
2963  i = send_msg(path, args, msg, OptNoCurses ? NULL : &childout);
2964  if (i != (EX_OK & 0xff))
2965  {
2966  if (i != S_BKG)
2967  {
2968  const char *e = mutt_str_sysexit(i);
2969  mutt_error(_("Error sending message, child exited %d (%s)"), i, NONULL(e));
2970  if (childout)
2971  {
2972  struct stat st;
2973 
2974  if ((stat(childout, &st) == 0) && (st.st_size > 0))
2975  mutt_do_pager(_("Output of the delivery process"), childout,
2976  MUTT_PAGER_NO_FLAGS, NULL);
2977  }
2978  }
2979  }
2980  else if (childout)
2981  unlink(childout);
2982 
2983  FREE(&childout);
2984  FREE(&path);
2985  FREE(&s);
2986  FREE(&args);
2987  FREE(&extra_args);
2988 
2989  if (i == (EX_OK & 0xff))
2990  i = 0;
2991  else if (i == S_BKG)
2992  i = 1;
2993  else
2994  i = -1;
2995  return i;
2996 }
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:878
char * C_Sendmail
Config: External command to send email.
Definition: sendlib.c:93
#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:2602
#define TAILQ_FIRST(head)
Definition: queue.h:717
int nntp_post(struct Mailbox *m, const char *msg)
Post article.
Definition: nntp.c:1970
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:2787
#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:95
struct Mailbox * mailbox
Definition: context.h:50
char * C_Inews
Config: (nntp) External command to post news articles.
Definition: sendlib.c:88
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:2810
bool C_UseEnvelopeFrom
Config: Set the envelope sender of the message.
Definition: sendlib.c:96
WHERE char * C_DsnReturn
Config: What to send as a notification of message delivery or delay.
Definition: globals.h:110
int mutt_do_pager(const char *banner, const char *tempfile, PagerFlags do_color, struct Pager *info)
Display some page-able text to the user.
Definition: curs_lib.c:631
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:95
#define FREE(x)
Definition: memory.h:40
#define TAILQ_NEXT(elm, field)
Definition: queue.h:816
#define TAILQ_EMPTY(head)
Definition: queue.h:715
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:909
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition: curs_lib.c:127
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:109
static char ** add_args_one(char **args, size_t *argslen, size_t *argsmax, struct Address *addr)
Add an Address to a dynamic array.
Definition: sendlib.c:2767
#define EX_OK
Definition: sendlib.c:75
#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 3007 of file sendlib.c.

3008 {
3009  if (final)
3010  {
3011  if (!TAILQ_EMPTY(&env->bcc) && TAILQ_EMPTY(&env->to) && TAILQ_EMPTY(&env->cc))
3012  {
3013  /* some MTA's will put an Apparently-To: header field showing the Bcc:
3014  * recipients if there is no To: or Cc: field, so attempt to suppress
3015  * it by using an empty To: field. */
3016  struct Address *to = mutt_addr_new();
3017  to->group = true;
3018  mutt_addrlist_append(&env->to, to);
3020 
3021  char buf[1024];
3022  buf[0] = '\0';
3023  mutt_addr_cat(buf, sizeof(buf), "undisclosed-recipients", AddressSpecials);
3024 
3025  to->mailbox = mutt_str_strdup(buf);
3026  }
3027 
3028  mutt_set_followup_to(env);
3029 
3030  if (!env->message_id)
3031  env->message_id = gen_msgid();
3032  }
3033 
3034  /* Take care of 8-bit => 7-bit conversion. */
3036  encode_headers(&env->userhdrs);
3037 }
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:2564
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:384
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:1202
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:715
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:671
static void encode_headers(struct ListHead *h)
RFC2047-encode a list of headers.
Definition: sendlib.c:2500
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1401
+ 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 3046 of file sendlib.c.

3047 {
3048  struct ListNode *item = NULL;
3049  STAILQ_FOREACH(item, &env->userhdrs, entries)
3050  {
3051  rfc2047_decode(&item->data);
3052  }
3053 
3055 
3056  /* back conversions */
3058 }
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:1381
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:350
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 3070 of file sendlib.c.

3072 {
3073  if (!e)
3074  return -1;
3075 
3076  int rc = 0;
3077 
3078  struct Buffer *tempfile = mutt_buffer_pool_get();
3079  mutt_buffer_mktemp(tempfile);
3080  FILE *fp_tmp = mutt_file_fopen(mutt_b2s(tempfile), "w");
3081  if (fp_tmp)
3082  {
3083  char date[128];
3085 
3086  if (!C_BounceDelivered)
3087  chflags |= CH_WEED_DELIVERED;
3088 
3089  fseeko(fp, e->offset, SEEK_SET);
3090  fprintf(fp_tmp, "Resent-From: %s", resent_from);
3091  fprintf(fp_tmp, "\nResent-%s", mutt_date_make_date(date, sizeof(date)));
3092  char *msgid_str = gen_msgid();
3093  fprintf(fp_tmp, "Resent-Message-ID: %s\n", msgid_str);
3094  FREE(&msgid_str);
3095  fputs("Resent-To: ", fp_tmp);
3096  mutt_write_addrlist(to, fp_tmp, 11, 0);
3097  mutt_copy_header(fp, e, fp_tmp, chflags, NULL, 0);
3098  fputc('\n', fp_tmp);
3099  mutt_file_copy_bytes(fp, fp_tmp, e->content->length);
3100  if (mutt_file_fclose(&fp_tmp) != 0)
3101  {
3102  mutt_perror(mutt_b2s(tempfile));
3103  unlink(mutt_b2s(tempfile));
3104  return -1;
3105  }
3106 #ifdef USE_SMTP
3107  if (C_SmtpUrl)
3108  rc = mutt_smtp_send(env_from, to, NULL, NULL, mutt_b2s(tempfile),
3109  e->content->encoding == ENC_8BIT);
3110  else
3111 #endif
3112  rc = mutt_invoke_sendmail(env_from, to, NULL, NULL, mutt_b2s(tempfile),
3113  e->content->encoding == ENC_8BIT);
3114  }
3115 
3116  mutt_buffer_pool_release(&tempfile);
3117  return rc;
3118 }
WHERE char * C_SmtpUrl
Config: (smtp) Url of the SMTP server.
Definition: globals.h:144
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:79
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:100
#define mutt_perror(...)
Definition: logging.h:85
static char * gen_msgid(void)
Generate a unique Message ID.
Definition: sendlib.c:2564
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:111
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:371
#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:2829
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 around mutt_write_address()
Definition: sendlib.c:1797
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:84
#define CH_NOQFROM
Ignore ">From " line.
Definition: copy.h:66
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:49
int mutt_copy_header(FILE *fp_in, struct Email *e, FILE *fp_out, CopyHeaderFlags chflags, const char *prefix, int wraplen)
Copy Email header.
Definition: copy.c: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:735
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 3128 of file sendlib.c.

3129 {
3130  if (!fp || !e || !to || TAILQ_EMPTY(to))
3131  return -1;
3132 
3133  const char *fqdn = mutt_fqdn(true);
3134  char resent_from[256];
3135  char *err = NULL;
3136 
3137  resent_from[0] = '\0';
3138  struct Address *from = mutt_default_from();
3139  struct AddressList from_list = TAILQ_HEAD_INITIALIZER(from_list);
3140  mutt_addrlist_append(&from_list, from);
3141 
3142  /* mutt_default_from() does not use $realname if the real name is not set
3143  * in $from, so we add it here. The reason it is not added in
3144  * mutt_default_from() is that during normal sending, we execute
3145  * send-hooks and set the realname last so that it can be changed based
3146  * upon message criteria. */
3147  if (!from->personal)
3149 
3150  mutt_addrlist_qualify(&from_list, fqdn);
3151 
3152  rfc2047_encode_addrlist(&from_list, "Resent-From");
3153  if (mutt_addrlist_to_intl(&from_list, &err))
3154  {
3155  mutt_error(_("Bad IDN %s while preparing resent-from"), err);
3156  FREE(&err);
3157  mutt_addrlist_clear(&from_list);
3158  return -1;
3159  }
3160  mutt_addrlist_write(resent_from, sizeof(resent_from), &from_list, false);
3161 
3162 #ifdef USE_NNTP
3163  OptNewsSend = false;
3164 #endif
3165 
3166  /* prepare recipient list. idna conversion appears to happen before this
3167  * function is called, since the user receives confirmation of the address
3168  * list being bounced to. */
3169  struct AddressList resent_to = TAILQ_HEAD_INITIALIZER(resent_to);
3170  mutt_addrlist_copy(&resent_to, to, false);
3171  rfc2047_encode_addrlist(&resent_to, "Resent-To");
3172  int rc = bounce_message(fp, e, &resent_to, resent_from, &from_list);
3173  mutt_addrlist_clear(&resent_to);
3174  mutt_addrlist_clear(&from_list);
3175 
3176  return rc;
3177 }
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:3070
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1381
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:727
#define _(a)
Definition: message.h:28
An email address.
Definition: address.h:34
size_t mutt_addrlist_write(char *buf, size_t buflen, const struct AddressList *al, bool display)
Write an Address to a buffer.
Definition: address.c:1137
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:1322
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2537
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:640
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1216
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:140
#define TAILQ_EMPTY(head)
Definition: queue.h:715
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:44
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:631
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1401
+ 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 3184 of file sendlib.c.

3185 {
3186  for (; b; b = b->next)
3187  {
3188  if ((b->type == TYPE_MESSAGE) || (b->type == TYPE_MULTIPART))
3189  set_noconv_flags(b->parts, flag);
3190  else if ((b->type == TYPE_TEXT) && b->noconv)
3191  {
3192  if (flag)
3193  mutt_param_set(&b->parameter, "x-mutt-noconv", "yes");
3194  else
3195  mutt_param_delete(&b->parameter, "x-mutt-noconv");
3196  }
3197  }
3198 }
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:3184
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 3211 of file sendlib.c.

3213 {
3214  char fcc_tok[PATH_MAX];
3215  char fcc_expanded[PATH_MAX];
3216 
3217  mutt_str_strfcpy(fcc_tok, path, sizeof(fcc_tok));
3218 
3219  char *tok = strtok(fcc_tok, ",");
3220  if (!tok)
3221  return -1;
3222 
3223  mutt_debug(LL_DEBUG1, "Fcc: initial mailbox = '%s'\n", tok);
3224  /* mutt_expand_path already called above for the first token */
3225  int status = mutt_write_fcc(tok, e, msgid, post, fcc, finalpath);
3226  if (status != 0)
3227  return status;
3228 
3229  while ((tok = strtok(NULL, ",")))
3230  {
3231  if (!*tok)
3232  continue;
3233 
3234  /* Only call mutt_expand_path if tok has some data */
3235  mutt_debug(LL_DEBUG1, "Fcc: additional mailbox token = '%s'\n", tok);
3236  mutt_str_strfcpy(fcc_expanded, tok, sizeof(fcc_expanded));
3237  mutt_expand_path(fcc_expanded, sizeof(fcc_expanded));
3238  mutt_debug(LL_DEBUG1, " Additional mailbox expanded = '%s'\n", fcc_expanded);
3239  status = mutt_write_fcc(fcc_expanded, e, msgid, post, fcc, finalpath);
3240  if (status != 0)
3241  return status;
3242  }
3243 
3244  return 0;
3245 }
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:3258
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:134
#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:56
#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
[in]fccfcc setting to save (postpone only)
[out]finalpathFinal path of email
Return values
0Success
-1Failure

Definition at line 3258 of file sendlib.c.

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

◆ C_AttachCharset

char* C_AttachCharset

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

Definition at line 83 of file sendlib.c.

◆ C_BounceDelivered

bool C_BounceDelivered

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

Definition at line 84 of file sendlib.c.

◆ C_EncodeFrom

bool C_EncodeFrom

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

Definition at line 85 of file sendlib.c.

◆ C_ForwardDecrypt

bool C_ForwardDecrypt

Config: Decrypt the message when forwarding it.

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

◆ C_Inews

char* C_Inews

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

Definition at line 88 of file sendlib.c.

◆ C_MimeForwardDecode

bool C_MimeForwardDecode

Config: Decode the forwarded message before attaching it.

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

◆ C_MimeTypeQueryCommand

char* C_MimeTypeQueryCommand

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

Definition at line 91 of file sendlib.c.

◆ C_MimeTypeQueryFirst

bool C_MimeTypeQueryFirst

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

Definition at line 92 of file sendlib.c.

◆ C_Sendmail

char* C_Sendmail

Config: External command to send email.

Definition at line 93 of file sendlib.c.

◆ C_SendmailWait

short C_SendmailWait

Config: Time to wait for sendmail to finish.

Definition at line 94 of file sendlib.c.

◆ C_Use8bitmime

bool C_Use8bitmime

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

Definition at line 95 of file sendlib.c.

◆ C_UseEnvelopeFrom

bool C_UseEnvelopeFrom

Config: Set the envelope sender of the message.

Definition at line 96 of file sendlib.c.

◆ C_UserAgent

bool C_UserAgent

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

Definition at line 97 of file sendlib.c.

◆ C_WrapHeaders

short C_WrapHeaders

Config: Width to wrap headers in outgoing messages.

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