NeoMutt  2018-07-16 +2388-bcedc8
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...
 

Macros

#define EX_OK   0
 

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...
 
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, 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...
 

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

#define EX_OK   0

Definition at line 75 of file sendlib.c.

Function Documentation

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

107 {
108  int c, linelen = 0;
109  char line[77], savechar;
110 
111  while ((c = mutt_ch_fgetconv(fc)) != EOF)
112  {
113  /* Wrap the line if needed. */
114  if ((linelen == 76) && ((istext && (c != '\n')) || !istext))
115  {
116  /* If the last character is "quoted", then be sure to move all three
117  * characters to the next line. Otherwise, just move the last
118  * character... */
119  if (line[linelen - 3] == '=')
120  {
121  line[linelen - 3] = 0;
122  fputs(line, fp_out);
123  fputs("=\n", fp_out);
124  line[linelen] = 0;
125  line[0] = '=';
126  line[1] = line[linelen - 2];
127  line[2] = line[linelen - 1];
128  linelen = 3;
129  }
130  else
131  {
132  savechar = line[linelen - 1];
133  line[linelen - 1] = '=';
134  line[linelen] = 0;
135  fputs(line, fp_out);
136  fputc('\n', fp_out);
137  line[0] = savechar;
138  linelen = 1;
139  }
140  }
141 
142  /* Escape lines that begin with/only contain "the message separator". */
143  if ((linelen == 4) && mutt_str_startswith(line, "From", CASE_MATCH))
144  {
145  mutt_str_strfcpy(line, "=46rom", sizeof(line));
146  linelen = 6;
147  }
148  else if ((linelen == 4) && mutt_str_startswith(line, "from", CASE_MATCH))
149  {
150  mutt_str_strfcpy(line, "=66rom", sizeof(line));
151  linelen = 6;
152  }
153  else if ((linelen == 1) && (line[0] == '.'))
154  {
155  mutt_str_strfcpy(line, "=2E", sizeof(line));
156  linelen = 3;
157  }
158 
159  if ((c == '\n') && istext)
160  {
161  /* Check to make sure there is no trailing space on this line. */
162  if ((linelen > 0) && ((line[linelen - 1] == ' ') || (line[linelen - 1] == '\t')))
163  {
164  if (linelen < 74)
165  {
166  sprintf(line + linelen - 1, "=%2.2X", (unsigned char) line[linelen - 1]);
167  fputs(line, fp_out);
168  }
169  else
170  {
171  int savechar2 = line[linelen - 1];
172 
173  line[linelen - 1] = '=';
174  line[linelen] = 0;
175  fputs(line, fp_out);
176  fprintf(fp_out, "\n=%2.2X", (unsigned char) savechar2);
177  }
178  }
179  else
180  {
181  line[linelen] = 0;
182  fputs(line, fp_out);
183  }
184  fputc('\n', fp_out);
185  linelen = 0;
186  }
187  else if ((c != 9) && ((c < 32) || (c > 126) || (c == '=')))
188  {
189  /* Check to make sure there is enough room for the quoted character.
190  * If not, wrap to the next line. */
191  if (linelen > 73)
192  {
193  line[linelen++] = '=';
194  line[linelen] = 0;
195  fputs(line, fp_out);
196  fputc('\n', fp_out);
197  linelen = 0;
198  }
199  sprintf(line + linelen, "=%2.2X", (unsigned char) c);
200  linelen += 3;
201  }
202  else
203  {
204  /* Don't worry about wrapping the line here. That will happen during
205  * the next iteration when I'll also know what the next character is. */
206  line[linelen++] = c;
207  }
208  }
209 
210  /* Take care of anything left in the buffer */
211  if (linelen > 0)
212  {
213  if ((line[linelen - 1] == ' ') || (line[linelen - 1] == '\t'))
214  {
215  /* take care of trailing whitespace */
216  if (linelen < 74)
217  sprintf(line + linelen - 1, "=%2.2X", (unsigned char) line[linelen - 1]);
218  else
219  {
220  savechar = line[linelen - 1];
221  line[linelen - 1] = '=';
222  line[linelen] = 0;
223  fputs(line, fp_out);
224  fputc('\n', fp_out);
225  sprintf(line, "=%2.2X", (unsigned char) savechar);
226  }
227  }
228  else
229  line[linelen] = 0;
230  fputs(line, fp_out);
231  }
232 }
int mutt_ch_fgetconv(struct FgetConv *fc)
Convert a file&#39;s character set.
Definition: charset.c:877
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:

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

250 {
251  memset(bctx->buffer, '\0', sizeof(bctx->buffer));
252  bctx->size = 0;
253  bctx->linelen = 0;
254 
255  return 0;
256 }
char buffer[3]
Definition: sendlib.c:239
short size
Definition: sendlib.c:240
short linelen
Definition: sendlib.c:241

+ Here is the caller graph for this function:

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

264 {
265  /* for some reasons, mutt_b64_encode expects the
266  * output buffer to be larger than 10B */
267  char encoded[11];
268  size_t ret;
269 
270  if (bctx->size == 0)
271  return;
272 
273  if (bctx->linelen >= 72)
274  {
275  fputc('\n', fp_out);
276  bctx->linelen = 0;
277  }
278 
279  /* ret should always be equal to 4 here, because bctx->size
280  * is a value between 1 and 3 (included), but let's not hardcode it
281  * and prefer the return value of the function */
282  ret = mutt_b64_encode(bctx->buffer, bctx->size, encoded, sizeof(encoded));
283  for (size_t i = 0; i < ret; i++)
284  {
285  fputc(encoded[i], fp_out);
286  bctx->linelen++;
287  }
288 
289  bctx->size = 0;
290 }
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:239
static const char encoded[]
short size
Definition: sendlib.c:240
short linelen
Definition: sendlib.c:241

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

299 {
300  if (bctx->size == 3)
301  b64_flush(bctx, fp_out);
302 
303  bctx->buffer[bctx->size++] = c;
304 }
char buffer[3]
Definition: sendlib.c:239
short size
Definition: sendlib.c:240
static void b64_flush(struct B64Context *bctx, FILE *fp_out)
Save the bytes to the file.
Definition: sendlib.c:263

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

313 {
314  struct B64Context bctx;
315  int ch, ch1 = EOF;
316 
317  b64_init(&bctx);
318 
319  while ((ch = mutt_ch_fgetconv(fc)) != EOF)
320  {
321  if (SigInt == 1)
322  {
323  SigInt = 0;
324  return;
325  }
326  if (istext && (ch == '\n') && (ch1 != '\r'))
327  b64_putc(&bctx, '\r', fp_out);
328  b64_putc(&bctx, ch, fp_out);
329  ch1 = ch;
330  }
331  b64_flush(&bctx, fp_out);
332  fputc('\n', fp_out);
333 }
static void b64_putc(struct B64Context *bctx, char c, FILE *fp_out)
Base64-encode one character.
Definition: sendlib.c:298
int mutt_ch_fgetconv(struct FgetConv *fc)
Convert a file&#39;s character set.
Definition: charset.c:877
WHERE SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: globals.h:83
static int b64_init(struct B64Context *bctx)
Set up the base64 conversion.
Definition: sendlib.c:249
static void b64_flush(struct B64Context *bctx, FILE *fp_out)
Save the bytes to the file.
Definition: sendlib.c:263
Cursor for the Base64 conversion.
Definition: sendlib.c:237

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

341 {
342  int ch;
343 
344  while ((ch = mutt_ch_fgetconv(fc)) != EOF)
345  {
346  if (SigInt == 1)
347  {
348  SigInt = 0;
349  return;
350  }
351  fputc(ch, fp_out);
352  }
353 }
int mutt_ch_fgetconv(struct FgetConv *fc)
Convert a file&#39;s character set.
Definition: charset.c:877
WHERE SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: globals.h:83

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

363 {
364  if (!a || !fp)
365  return -1;
366 
367  int len;
368  int tmplen;
369  char buf[256] = { 0 };
370 
371  fprintf(fp, "Content-Type: %s/%s", TYPE(a), a->subtype);
372 
373  if (!TAILQ_EMPTY(&a->parameter))
374  {
375  len = 25 + mutt_str_strlen(a->subtype); /* approximate len. of content-type */
376 
377  struct Parameter *np = NULL;
378  TAILQ_FOREACH(np, &a->parameter, entries)
379  {
380  if (!np->attribute || !np->value)
381  continue;
382 
383  struct ParameterList pl_conts = rfc2231_encode_string(np->attribute, np->value);
384  struct Parameter *cont = NULL;
385  TAILQ_FOREACH(cont, &pl_conts, entries)
386  {
387  fputc(';', fp);
388 
389  buf[0] = 0;
390  mutt_addr_cat(buf, sizeof(buf), cont->value, MimeSpecials);
391 
392  /* Dirty hack to make messages readable by Outlook Express
393  * for the Mac: force quotes around the boundary parameter
394  * even when they aren't needed.
395  */
396  if (!mutt_str_strcasecmp(cont->attribute, "boundary") &&
397  !mutt_str_strcmp(buf, cont->value))
398  snprintf(buf, sizeof(buf), "\"%s\"", cont->value);
399 
400  tmplen = mutt_str_strlen(buf) + mutt_str_strlen(cont->attribute) + 1;
401  if (len + tmplen + 2 > 76)
402  {
403  fputs("\n\t", fp);
404  len = tmplen + 1;
405  }
406  else
407  {
408  fputc(' ', fp);
409  len += tmplen + 1;
410  }
411 
412  fprintf(fp, "%s=%s", cont->attribute, buf);
413  }
414 
415  mutt_param_free(&pl_conts);
416  }
417  }
418 
419  fputc('\n', fp);
420 
421  if (a->language)
422  fprintf(fp, "Content-Language: %s\n", a->language);
423 
424  if (a->description)
425  fprintf(fp, "Content-Description: %s\n", a->description);
426 
427  if (a->disposition != DISP_NONE)
428  {
429  const char *dispstr[] = { "inline", "attachment", "form-data" };
430 
431  if (a->disposition < sizeof(dispstr) / sizeof(char *))
432  {
433  fprintf(fp, "Content-Disposition: %s", dispstr[a->disposition]);
434  len = 21 + mutt_str_strlen(dispstr[a->disposition]);
435 
436  if (a->use_disp && (a->disposition != DISP_INLINE))
437  {
438  char *fn = a->d_filename;
439  if (!fn)
440  fn = a->filename;
441 
442  if (fn)
443  {
444  /* Strip off the leading path... */
445  char *t = strrchr(fn, '/');
446  if (t)
447  t++;
448  else
449  t = fn;
450 
451  struct ParameterList pl_conts = rfc2231_encode_string("filename", t);
452  struct Parameter *cont = NULL;
453  TAILQ_FOREACH(cont, &pl_conts, entries)
454  {
455  fputc(';', fp);
456  buf[0] = 0;
457  mutt_addr_cat(buf, sizeof(buf), cont->value, MimeSpecials);
458 
459  tmplen = mutt_str_strlen(buf) + mutt_str_strlen(cont->attribute) + 1;
460  if (len + tmplen + 2 > 76)
461  {
462  fputs("\n\t", fp);
463  len = tmplen + 1;
464  }
465  else
466  {
467  fputc(' ', fp);
468  len += tmplen + 1;
469  }
470 
471  fprintf(fp, "%s=%s", cont->attribute, buf);
472  }
473 
474  mutt_param_free(&pl_conts);
475  }
476  }
477 
478  fputc('\n', fp);
479  }
480  else
481  {
482  mutt_debug(LL_DEBUG1, "ERROR: invalid content-disposition %d\n", a->disposition);
483  }
484  }
485 
486  if (a->encoding != ENC_7BIT)
487  fprintf(fp, "Content-Transfer-Encoding: %s\n", ENCODING(a->encoding));
488 
490 #ifdef USE_AUTOCRYPT
491  || C_Autocrypt
492 #endif
493  ) &&
494  a->mime_headers)
495  {
496  mutt_rfc822_write_header(fp, a->mime_headers, NULL, MUTT_WRITE_HEADER_MIME, false, false);
497  }
498 
499  /* Do NOT add the terminator here!!! */
500  return ferror(fp) ? -1 : 0;
501 }
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:209
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:287
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:2238
#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:329
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:668

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

509 {
510  return mutt_is_text_part(b) ||
512 }
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:560
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
Definition: muttlib.c:433
#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:

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

522 {
523  FILE *fp_in = NULL;
524  struct FgetConv *fc = NULL;
525 
526  if (a->type == TYPE_MULTIPART)
527  {
528  /* First, find the boundary to use */
529  const char *p = mutt_param_get(&a->parameter, "boundary");
530  if (!p)
531  {
532  mutt_debug(LL_DEBUG1, "no boundary parameter found\n");
533  mutt_error(_("No boundary parameter found [report this error]"));
534  return -1;
535  }
536  char boundary[128];
537  mutt_str_strfcpy(boundary, p, sizeof(boundary));
538 
539  for (struct Body *t = a->parts; t; t = t->next)
540  {
541  fprintf(fp, "\n--%s\n", boundary);
542  if (mutt_write_mime_header(t, fp) == -1)
543  return -1;
544  fputc('\n', fp);
545  if (mutt_write_mime_body(t, fp) == -1)
546  return -1;
547  }
548  fprintf(fp, "\n--%s--\n", boundary);
549  return ferror(fp) ? -1 : 0;
550  }
551 
552  /* This is pretty gross, but it's the best solution for now... */
553  if (((WithCrypto & APPLICATION_PGP) != 0) && (a->type == TYPE_APPLICATION) &&
554  (mutt_str_strcmp(a->subtype, "pgp-encrypted") == 0))
555  {
556  fputs("Version: 1\n", fp);
557  return 0;
558  }
559 
560  fp_in = fopen(a->filename, "r");
561  if (!fp_in)
562  {
563  mutt_debug(LL_DEBUG1, "%s no longer exists\n", a->filename);
564  mutt_error(_("%s no longer exists"), a->filename);
565  return -1;
566  }
567 
568  if ((a->type == TYPE_TEXT) && (!a->noconv))
569  {
570  char send_charset[128];
572  fp_in, a->charset,
573  mutt_body_get_charset(a, send_charset, sizeof(send_charset)), 0);
574  }
575  else
576  fc = mutt_ch_fgetconv_open(fp_in, 0, 0, 0);
577 
579  if (a->encoding == ENC_QUOTED_PRINTABLE)
581  else if (a->encoding == ENC_BASE64)
583  else if ((a->type == TYPE_TEXT) && (!a->noconv))
584  encode_8bit(fc, fp);
585  else
586  mutt_file_copy_stream(fp_in, fp);
588 
590  mutt_file_fclose(&fp_in);
591 
592  if (SigInt == 1)
593  {
594  SigInt = 0;
595  return -1;
596  }
597  return ferror(fp) ? -1 : 0;
598 }
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:83
static void encode_base64(struct FgetConv *fc, FILE *fp_out, int istext)
Base64-encode some data.
Definition: sendlib.c:312
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:508
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:149
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:106
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:521
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:1431
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:340
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:857
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:267
#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:362
#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:827
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:

void mutt_generate_boundary ( struct ParameterList *  pl)

Create a unique boundary id for a MIME part.

Parameters
plMIME part

Definition at line 604 of file sendlib.c.

605 {
606  char rs[MUTT_RANDTAG_LEN + 1];
607 
608  mutt_rand_base32(rs, sizeof(rs) - 1);
609  rs[MUTT_RANDTAG_LEN] = 0;
610  mutt_param_set(pl, "boundary", rs);
611 }
#define MUTT_RANDTAG_LEN
Definition: muttlib.h:43
void mutt_rand_base32(void *buf, size_t buflen)
Fill a buffer with a base32-encoded random string.
Definition: muttlib.c:513
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:

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

634 {
635  bool from = s->from;
636  int whitespace = s->whitespace;
637  bool dot = s->dot;
638  int linelen = s->linelen;
639  bool was_cr = s->was_cr;
640 
641  if (!buf) /* This signals EOF */
642  {
643  if (was_cr)
644  info->binary = true;
645  if (linelen > info->linemax)
646  info->linemax = linelen;
647 
648  return;
649  }
650 
651  for (; buflen; buf++, buflen--)
652  {
653  char ch = *buf;
654 
655  if (was_cr)
656  {
657  was_cr = false;
658  if (ch != '\n')
659  {
660  info->binary = true;
661  }
662  else
663  {
664  if (whitespace)
665  info->space = true;
666  if (dot)
667  info->dot = true;
668  if (linelen > info->linemax)
669  info->linemax = linelen;
670  whitespace = 0;
671  dot = false;
672  linelen = 0;
673  continue;
674  }
675  }
676 
677  linelen++;
678  if (ch == '\n')
679  {
680  info->crlf++;
681  if (whitespace)
682  info->space = true;
683  if (dot)
684  info->dot = true;
685  if (linelen > info->linemax)
686  info->linemax = linelen;
687  whitespace = 0;
688  linelen = 0;
689  dot = false;
690  }
691  else if (ch == '\r')
692  {
693  info->crlf++;
694  info->cr = true;
695  was_cr = true;
696  continue;
697  }
698  else if (ch & 0x80)
699  info->hibin++;
700  else if ((ch == '\t') || (ch == '\f'))
701  {
702  info->ascii++;
703  whitespace++;
704  }
705  else if (ch == 0)
706  {
707  info->nulbin++;
708  info->lobin++;
709  }
710  else if ((ch < 32) || (ch == 127))
711  info->lobin++;
712  else
713  {
714  if (linelen == 1)
715  {
716  if ((ch == 'F') || (ch == 'f'))
717  from = true;
718  else
719  from = false;
720  if (ch == '.')
721  dot = true;
722  else
723  dot = false;
724  }
725  else if (from)
726  {
727  if ((linelen == 2) && (ch != 'r'))
728  from = false;
729  else if ((linelen == 3) && (ch != 'o'))
730  from = false;
731  else if (linelen == 4)
732  {
733  if (ch == 'm')
734  info->from = true;
735  from = false;
736  }
737  }
738  if (ch == ' ')
739  whitespace++;
740  info->ascii++;
741  }
742 
743  if (linelen > 1)
744  dot = false;
745  if ((ch != ' ') && (ch != '\t'))
746  whitespace = 0;
747  }
748 
749  s->from = from;
750  s->whitespace = whitespace;
751  s->dot = dot;
752  s->linelen = linelen;
753  s->was_cr = was_cr;
754 }
int whitespace
Definition: sendlib.c:619
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:620
long hibin
8-bit characters
Definition: content.h:35
bool was_cr
Definition: sendlib.c:622
bool from
Definition: sendlib.c:618
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:621
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:

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

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

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

936 {
937  char *fcode = NULL;
938  char **tcode = NULL;
939  const char *c = NULL, *c1 = NULL;
940  size_t ret;
941  int ncodes, i, cn;
942 
943  /* Count the tocodes */
944  ncodes = 0;
945  for (c = tocodes; c; c = c1 ? c1 + 1 : 0)
946  {
947  c1 = strchr(c, ':');
948  if (c1 == c)
949  continue;
950  ncodes++;
951  }
952 
953  /* Copy them */
954  tcode = mutt_mem_malloc(ncodes * sizeof(char *));
955  for (c = tocodes, i = 0; c; c = c1 ? c1 + 1 : 0, i++)
956  {
957  c1 = strchr(c, ':');
958  if (c1 == c)
959  continue;
960  tcode[i] = mutt_str_substr_dup(c, c1);
961  }
962 
963  ret = (size_t)(-1);
964  if (fromcode)
965  {
966  /* Try each fromcode in turn */
967  for (c = fromcodes; c; c = c1 ? c1 + 1 : 0)
968  {
969  c1 = strchr(c, ':');
970  if (c1 == c)
971  continue;
972  fcode = mutt_str_substr_dup(c, c1);
973 
974  ret = convert_file_to(fp, fcode, ncodes, (char const *const *) tcode, &cn, info);
975  if (ret != (size_t)(-1))
976  {
977  *fromcode = fcode;
978  *tocode = tcode[cn];
979  tcode[cn] = 0;
980  break;
981  }
982  FREE(&fcode);
983  }
984  }
985  else
986  {
987  /* There is only one fromcode */
988  ret = convert_file_to(fp, fromcodes, ncodes, (char const *const *) tcode, &cn, info);
989  if (ret != (size_t)(-1))
990  {
991  *tocode = tcode[cn];
992  tcode[cn] = 0;
993  }
994  }
995 
996  /* Free memory */
997  for (i = 0; i < ncodes; i++)
998  FREE(&tcode[i]);
999 
1000  FREE(&tcode);
1001 
1002  return ret;
1003 }
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:781
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:

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

1014 {
1015  struct Content *info = NULL;
1016  struct ContentState state = { 0 };
1017  FILE *fp = NULL;
1018  char *fromcode = NULL;
1019  char *tocode = NULL;
1020  char buf[100];
1021  size_t r;
1022 
1023  struct stat sb;
1024 
1025  if (b && !fname)
1026  fname = b->filename;
1027 
1028  if (stat(fname, &sb) == -1)
1029  {
1030  mutt_error(_("Can't stat %s: %s"), fname, strerror(errno));
1031  return NULL;
1032  }
1033 
1034  if (!S_ISREG(sb.st_mode))
1035  {
1036  mutt_error(_("%s isn't a regular file"), fname);
1037  return NULL;
1038  }
1039 
1040  fp = fopen(fname, "r");
1041  if (!fp)
1042  {
1043  mutt_debug(LL_DEBUG1, "%s: %s (errno %d)\n", fname, strerror(errno), errno);
1044  return NULL;
1045  }
1046 
1047  info = mutt_mem_calloc(1, sizeof(struct Content));
1048 
1049  if (b && (b->type == TYPE_TEXT) && (!b->noconv && !b->force_charset))
1050  {
1051  char *chs = mutt_param_get(&b->parameter, "charset");
1052  char *fchs = b->use_disp ? (C_AttachCharset ? C_AttachCharset : C_Charset) : C_Charset;
1053  if (C_Charset && (chs || C_SendCharset) &&
1054  (convert_file_from_to(fp, fchs, chs ? chs : C_SendCharset, &fromcode,
1055  &tocode, info) != (size_t)(-1)))
1056  {
1057  if (!chs)
1058  {
1059  char chsbuf[256];
1060  mutt_ch_canonical_charset(chsbuf, sizeof(chsbuf), tocode);
1061  mutt_param_set(&b->parameter, "charset", chsbuf);
1062  }
1063  FREE(&b->charset);
1064  b->charset = fromcode;
1065  FREE(&tocode);
1066  mutt_file_fclose(&fp);
1067  return info;
1068  }
1069  }
1070 
1071  rewind(fp);
1072  while ((r = fread(buf, 1, sizeof(buf), fp)))
1073  update_content_info(info, &state, buf, r);
1074  update_content_info(info, &state, 0, 0);
1075 
1076  mutt_file_fclose(&fp);
1077 
1078  if (b && (b->type == TYPE_TEXT) && (!b->noconv && !b->force_charset))
1079  {
1080  mutt_param_set(&b->parameter, "charset",
1081  (!info->hibin ?
1082  "us-ascii" :
1083  C_Charset && !mutt_ch_is_us_ascii(C_Charset) ? C_Charset : "unknown-8bit"));
1084  }
1085 
1086  return info;
1087 }
Info about the body of an email.
Definition: sendlib.c:616
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:632
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:149
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:314
#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:934

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1102 {
1103  FILE *fp = NULL;
1104  char *p = NULL, *q = NULL, *ct = NULL;
1105  char buf[PATH_MAX];
1106  char subtype[256] = { 0 };
1107  char xtype[256] = { 0 };
1108  int sze, cur_sze = 0;
1109  bool found_mimetypes = false;
1110  enum ContentType type = TYPE_OTHER;
1111 
1112  int szf = mutt_str_strlen(path);
1113 
1114  for (int count = 0; count < 4; count++)
1115  {
1116  /* can't use strtok() because we use it in an inner loop below, so use
1117  * a switch statement here instead. */
1118  switch (count)
1119  {
1120  /* last file with last entry to match wins type/xtype */
1121  case 0:
1122  /* check default unix mimetypes location first */
1123  mutt_str_strfcpy(buf, "/etc/mime.types", sizeof(buf));
1124  break;
1125  case 1:
1126  mutt_str_strfcpy(buf, SYSCONFDIR "/mime.types", sizeof(buf));
1127  break;
1128  case 2:
1129  mutt_str_strfcpy(buf, PKGDATADIR "/mime.types", sizeof(buf));
1130  break;
1131  case 3:
1132  snprintf(buf, sizeof(buf), "%s/.mime.types", NONULL(HomeDir));
1133  break;
1134  default:
1135  mutt_debug(LL_DEBUG1, "Internal error, count = %d\n", count);
1136  goto bye; /* shouldn't happen */
1137  }
1138 
1139  fp = fopen(buf, "r");
1140  if (fp)
1141  {
1142  found_mimetypes = true;
1143 
1144  while (fgets(buf, sizeof(buf) - 1, fp))
1145  {
1146  /* weed out any comments */
1147  p = strchr(buf, '#');
1148  if (p)
1149  *p = '\0';
1150 
1151  /* remove any leading space. */
1152  ct = buf;
1153  SKIPWS(ct);
1154 
1155  /* position on the next field in this line */
1156  p = strpbrk(ct, " \t");
1157  if (!p)
1158  continue;
1159  *p++ = 0;
1160  SKIPWS(p);
1161 
1162  /* cycle through the file extensions */
1163  while ((p = strtok(p, " \t\n")))
1164  {
1165  sze = mutt_str_strlen(p);
1166  if ((sze > cur_sze) && (szf >= sze) &&
1167  (mutt_str_strcasecmp(path + szf - sze, p) == 0) &&
1168  ((szf == sze) || (path[szf - sze - 1] == '.')))
1169  {
1170  /* get the content-type */
1171 
1172  p = strchr(ct, '/');
1173  if (!p)
1174  {
1175  /* malformed line, just skip it. */
1176  break;
1177  }
1178  *p++ = 0;
1179 
1180  for (q = p; *q && !IS_SPACE(*q); q++)
1181  ;
1182 
1183  mutt_str_substr_copy(p, q, subtype, sizeof(subtype));
1184 
1185  type = mutt_check_mime_type(ct);
1186  if (type == TYPE_OTHER)
1187  mutt_str_strfcpy(xtype, ct, sizeof(xtype));
1188 
1189  cur_sze = sze;
1190  }
1191  p = NULL;
1192  }
1193  }
1194  mutt_file_fclose(&fp);
1195  }
1196  }
1197 
1198 bye:
1199 
1200  /* no mime.types file found */
1201  if (!found_mimetypes)
1202  {
1203  mutt_error(_("Could not find any mime.types file."));
1204  }
1205 
1206  if ((type != TYPE_OTHER) || (*xtype != '\0'))
1207  {
1208  att->type = type;
1209  mutt_str_replace(&att->subtype, subtype);
1210  mutt_str_replace(&att->xtype, xtype);
1211  }
1212 
1213  return type;
1214 }
Unknown Content-Type.
Definition: mime.h:31
#define NONULL(x)
Definition: string2.h:37
#define _(a)
Definition: message.h:28
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
enum ContentType mutt_check_mime_type(const char *s)
Check a MIME type string.
Definition: parse.c:319
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
WHERE char * HomeDir
User&#39;s home directory.
Definition: globals.h:48
#define SKIPWS(ch)
Definition: string2.h:47
char * subtype
content-type subtype
Definition: body.h:37
#define PATH_MAX
Definition: mutt.h:51
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:

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

1222 {
1223  char buf[PATH_MAX];
1224  struct State s = { 0 };
1225  struct stat sb;
1226 
1227  for (; a; a = a->next)
1228  {
1229  if (a->type == TYPE_MULTIPART)
1230  {
1231  if (a->encoding != ENC_7BIT)
1232  a->encoding = ENC_7BIT;
1233 
1234  transform_to_7bit(a->parts, fp_in);
1235  }
1236  else if (mutt_is_message_type(a->type, a->subtype))
1237  {
1238  mutt_message_to_7bit(a, fp_in);
1239  }
1240  else
1241  {
1242  a->noconv = true;
1243  a->force_charset = true;
1244 
1245  mutt_mktemp(buf, sizeof(buf));
1246  s.fp_out = mutt_file_fopen(buf, "w");
1247  if (!s.fp_out)
1248  {
1249  mutt_perror("fopen");
1250  return;
1251  }
1252  s.fp_in = fp_in;
1253  mutt_decode_attachment(a, &s);
1255  FREE(&a->d_filename);
1256  a->d_filename = a->filename;
1257  a->filename = mutt_str_strdup(buf);
1258  a->unlink = true;
1259  if (stat(a->filename, &sb) == -1)
1260  {
1261  mutt_perror("stat");
1262  return;
1263  }
1264  a->length = sb.st_size;
1265 
1267  if (a->encoding == ENC_8BIT)
1269  else if (a->encoding == ENC_BINARY)
1270  a->encoding = ENC_BASE64;
1271  }
1272  }
1273 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1790
void mutt_message_to_7bit(struct Body *a, FILE *fp)
Convert an email&#39;s MIME parts to 7-bit.
Definition: sendlib.c:1280
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:1385
#define mutt_perror(...)
Definition: logging.h:85
7-bit text
Definition: mime.h:49
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
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:1221
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:1455
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
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_mktemp(buf, buflen)
Definition: muttlib.h:76
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
#define PATH_MAX
Definition: mutt.h:51
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
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
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:584

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1281 {
1282  char temp[PATH_MAX];
1283  char *line = NULL;
1284  FILE *fp_in = NULL;
1285  FILE *fp_out = NULL;
1286  struct stat sb;
1287 
1288  if (!a->filename && fp)
1289  fp_in = fp;
1290  else if (!a->filename || !(fp_in = fopen(a->filename, "r")))
1291  {
1292  mutt_error(_("Could not open %s"), a->filename ? a->filename : "(null)");
1293  return;
1294  }
1295  else
1296  {
1297  a->offset = 0;
1298  if (stat(a->filename, &sb) == -1)
1299  {
1300  mutt_perror("stat");
1301  mutt_file_fclose(&fp_in);
1302  }
1303  a->length = sb.st_size;
1304  }
1305 
1306  mutt_mktemp(temp, sizeof(temp));
1307  fp_out = mutt_file_fopen(temp, "w+");
1308  if (!fp_out)
1309  {
1310  mutt_perror("fopen");
1311  goto cleanup;
1312  }
1313 
1314  if (!fp_in)
1315  goto cleanup;
1316 
1317  fseeko(fp_in, a->offset, SEEK_SET);
1318  a->parts = mutt_rfc822_parse_message(fp_in, a);
1319 
1320  transform_to_7bit(a->parts, fp_in);
1321 
1322  mutt_copy_hdr(fp_in, fp_out, a->offset, a->offset + a->length,
1323  CH_MIME | CH_NONEWLINE | CH_XMIT, NULL);
1324 
1325  fputs("MIME-Version: 1.0\n", fp_out);
1326  mutt_write_mime_header(a->parts, fp_out);
1327  fputc('\n', fp_out);
1328  mutt_write_mime_body(a->parts, fp_out);
1329 
1330 cleanup:
1331  FREE(&line);
1332 
1333  if (fp_in && (fp_in != fp))
1334  mutt_file_fclose(&fp_in);
1335  if (fp_out)
1336  mutt_file_fclose(&fp_out);
1337  else
1338  return;
1339 
1340  a->encoding = ENC_7BIT;
1341  FREE(&a->d_filename);
1342  a->d_filename = a->filename;
1343  if (a->filename && a->unlink)
1344  unlink(a->filename);
1345  a->filename = mutt_str_strdup(temp);
1346  a->unlink = true;
1347  if (stat(a->filename, &sb) == -1)
1348  {
1349  mutt_perror("stat");
1350  return;
1351  }
1352  a->length = sb.st_size;
1353  mutt_body_free(&a->parts);
1354  a->email->content = NULL;
1355 }
#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:92
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:1221
struct Body * mutt_rfc822_parse_message(FILE *fp, struct Body *parent)
parse a Message/RFC822 body
Definition: parse.c:1558
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
const char * line
Definition: common.c:36
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:76
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
#define PATH_MAX
Definition: mutt.h:51
int mutt_write_mime_body(struct Body *a, FILE *fp)
Write a MIME part.
Definition: sendlib.c:521
#define CH_XMIT
Transmitting this message? (Ignore Lines: and Content-Length:)
Definition: copy.h:54
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
void mutt_body_free(struct Body **p)
Free a Body.
Definition: body.c:57
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#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
#define FREE(x)
Definition: memory.h:40
int mutt_write_mime_header(struct Body *a, FILE *fp)
Create a MIME header.
Definition: sendlib.c:362
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:584
struct Email * email
header information for message/rfc822
Definition: body.h:55
int mutt_copy_hdr(FILE *fp_in, FILE *fp_out, LOFF_T off_start, LOFF_T off_end, CopyHeaderFlags chflags, const char *prefix)
Copy header from one file to another.
Definition: copy.c:76
#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:

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

1363 {
1364  if (b->type == TYPE_TEXT)
1365  {
1366  char send_charset[128];
1367  char *chsname = mutt_body_get_charset(b, send_charset, sizeof(send_charset));
1368  if ((info->lobin && !mutt_str_startswith(chsname, "iso-2022", CASE_IGNORE)) ||
1369  (info->linemax > 990) || (info->from && C_EncodeFrom))
1370  {
1372  }
1373  else if (info->hibin)
1374  {
1376  }
1377  else
1378  {
1379  b->encoding = ENC_7BIT;
1380  }
1381  }
1382  else if ((b->type == TYPE_MESSAGE) || (b->type == TYPE_MULTIPART))
1383  {
1384  if (info->lobin || info->hibin)
1385  {
1386  if (C_Allow8bit && !info->lobin)
1387  b->encoding = ENC_8BIT;
1388  else
1389  mutt_message_to_7bit(b, NULL);
1390  }
1391  else
1392  b->encoding = ENC_7BIT;
1393  }
1394  else if ((b->type == TYPE_APPLICATION) &&
1395  (mutt_str_strcasecmp(b->subtype, "pgp-keys") == 0))
1396  {
1397  b->encoding = ENC_7BIT;
1398  }
1399  else
1400  {
1401  /* Determine which encoding is smaller */
1402  if (1.33 * (float) (info->lobin + info->hibin + info->ascii) <
1403  3.0 * (float) (info->lobin + info->hibin) + (float) info->ascii)
1404  {
1405  b->encoding = ENC_BASE64;
1406  }
1407  else
1408  {
1410  }
1411  }
1412 }
void mutt_message_to_7bit(struct Body *a, FILE *fp)
Convert an email&#39;s MIME parts to 7-bit.
Definition: sendlib.c:1280
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:1431
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:

void mutt_stamp_attachment ( struct Body a)

Timestamp an Attachment.

Parameters
aAttachment

Definition at line 1418 of file sendlib.c.

1419 {
1420  a->stamp = time(NULL);
1421 }
time_t stamp
Time stamp of last encoding update.
Definition: body.h:61

+ Here is the caller graph for this function:

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

1432 {
1433  char *p = NULL;
1434 
1435  if (b && (b->type != TYPE_TEXT))
1436  return NULL;
1437 
1438  if (b)
1439  p = mutt_param_get(&b->parameter, "charset");
1440 
1441  if (p)
1442  mutt_ch_canonical_charset(buf, buflen, p);
1443  else
1444  mutt_str_strfcpy(buf, "us-ascii", buflen);
1445 
1446  return buf;
1447 }
void mutt_ch_canonical_charset(char *buf, size_t buflen, const char *name)
Canonicalise the charset of a string.
Definition: charset.c:314
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:

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

1456 {
1457  struct Content *info = NULL;
1458  char chsbuf[256];
1459 
1460  /* override noconv when it's us-ascii */
1461  if (mutt_ch_is_us_ascii(mutt_body_get_charset(a, chsbuf, sizeof(chsbuf))))
1462  a->noconv = false;
1463 
1464  if (!a->force_charset && !a->noconv)
1465  mutt_param_delete(&a->parameter, "charset");
1466 
1467  info = mutt_get_content_info(a->filename, a);
1468  if (!info)
1469  return;
1470 
1471  set_encoding(a, info);
1473 
1474  FREE(&a->content);
1475  a->content = info;
1476 }
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:1418
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:1013
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:1362
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body&#39;s character set.
Definition: sendlib.c:1431
#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:

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

1487 {
1488  char buf[1024];
1489  struct Body *body = NULL;
1490  FILE *fp = NULL;
1491  CopyMessageFlags cmflags;
1493 
1494  if (WithCrypto)
1495  {
1497  {
1499  return NULL;
1500  }
1501  }
1502 
1503  mutt_mktemp(buf, sizeof(buf));
1504  fp = mutt_file_fopen(buf, "w+");
1505  if (!fp)
1506  return NULL;
1507 
1508  body = mutt_body_new();
1509  body->type = TYPE_MESSAGE;
1510  body->subtype = mutt_str_strdup("rfc822");
1511  body->filename = mutt_str_strdup(buf);
1512  body->unlink = true;
1513  body->use_disp = false;
1514  body->disposition = DISP_INLINE;
1515  body->noconv = true;
1516 
1518 
1519  CopyHeaderFlags chflags = CH_XMIT;
1520  cmflags = MUTT_CM_NO_FLAGS;
1521 
1522  /* If we are attaching a message, ignore C_MimeForwardDecode */
1523  if (!attach_msg && C_MimeForwardDecode)
1524  {
1525  chflags |= CH_MIME | CH_TXTPLAIN;
1526  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1528  pgp &= ~PGP_ENCRYPT;
1530  pgp &= ~SMIME_ENCRYPT;
1531  }
1532  else if ((WithCrypto != 0) && C_ForwardDecrypt && (e->security & SEC_ENCRYPT))
1533  {
1534  if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_multipart_encrypted(e->content))
1535  {
1536  chflags |= CH_MIME | CH_NONEWLINE;
1537  cmflags = MUTT_CM_DECODE_PGP;
1538  pgp &= ~PGP_ENCRYPT;
1539  }
1540  else if (((WithCrypto & APPLICATION_PGP) != 0) &&
1542  {
1543  chflags |= CH_MIME | CH_TXTPLAIN;
1544  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1545  pgp &= ~PGP_ENCRYPT;
1546  }
1547  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
1549  {
1550  chflags |= CH_MIME | CH_TXTPLAIN;
1551  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1552  pgp &= ~SMIME_ENCRYPT;
1553  }
1554  }
1555 
1556  mutt_copy_message(fp, m, e, cmflags, chflags);
1557 
1558  fflush(fp);
1559  rewind(fp);
1560 
1561  body->email = email_new();
1562  body->email->offset = 0;
1563  /* we don't need the user headers here */
1564  body->email->env = mutt_rfc822_read_header(fp, body->email, false, false);
1565  if (WithCrypto)
1566  body->email->security = pgp;
1567  mutt_update_encoding(body);
1568  body->parts = body->email->content;
1569 
1570  mutt_file_fclose(&fp);
1571 
1572  return body;
1573 }
#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:92
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:48
int mutt_copy_message(FILE *fp_out, struct Mailbox *m, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags)
Copy a message from a Mailbox.
Definition: copy.c:806
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:1455
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
struct Envelope * env
Envelope information.
Definition: email.h:91
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:560
#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:619
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:41
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:85
#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:584
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:1130
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:

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

1582 {
1583  FILE *fp = NULL, *fp_err = NULL;
1584  char *buf = NULL;
1585  size_t buflen;
1586  int dummy = 0;
1587  pid_t pid;
1588  struct Buffer *cmd = mutt_buffer_pool_get();
1589 
1591 
1592  pid = mutt_create_filter(mutt_b2s(cmd), NULL, &fp, &fp_err);
1593  if (pid < 0)
1594  {
1595  mutt_error(_("Error running \"%s\""), mutt_b2s(cmd));
1597  return;
1598  }
1600 
1601  buf = mutt_file_read_line(buf, &buflen, fp, &dummy, 0);
1602  if (buf)
1603  {
1604  if (strchr(buf, '/'))
1605  mutt_parse_content_type(buf, att);
1606  FREE(&buf);
1607  }
1608 
1609  mutt_file_fclose(&fp);
1610  mutt_file_fclose(&fp_err);
1611  mutt_wait_filter(pid);
1612 }
pid_t mutt_create_filter(const char *s, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:217
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:75
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:86
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:663
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
#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:457
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:1418
#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:228

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1621 {
1622  struct Body *att = mutt_body_new();
1623  att->filename = mutt_str_strdup(path);
1624 
1626  run_mime_type_query(att);
1627 
1628  /* Attempt to determine the appropriate content-type based on the filename
1629  * suffix. */
1630  if (!att->subtype)
1631  mutt_lookup_mime_type(att, path);
1632 
1634  {
1635  run_mime_type_query(att);
1636  }
1637 
1638  struct Content *info = mutt_get_content_info(path, att);
1639  if (!info)
1640  {
1641  mutt_body_free(&att);
1642  return NULL;
1643  }
1644 
1645  if (!att->subtype)
1646  {
1647  if ((info->nulbin == 0) &&
1648  ((info->lobin == 0) || ((info->lobin + info->hibin + info->ascii) / info->lobin >= 10)))
1649  {
1650  /* Statistically speaking, there should be more than 10% "lobin"
1651  * chars if this is really a binary file... */
1652  att->type = TYPE_TEXT;
1653  att->subtype = mutt_str_strdup("plain");
1654  }
1655  else
1656  {
1657  att->type = TYPE_APPLICATION;
1658  att->subtype = mutt_str_strdup("octet-stream");
1659  }
1660  }
1661 
1662  FREE(&info);
1663  mutt_update_encoding(att);
1664  return att;
1665 }
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:1581
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:1013
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:1455
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
void mutt_body_free(struct Body **p)
Free a Body.
Definition: body.c:57
enum ContentType mutt_lookup_mime_type(struct Body *att, const char *path)
Find the MIME type for an attachment.
Definition: sendlib.c:1101
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
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:

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

1673 {
1674  int e = ENC_7BIT;
1675 
1676  for (; a; a = a->next)
1677  {
1678  if (a->encoding == ENC_BINARY)
1679  return ENC_BINARY;
1680  else if (a->encoding == ENC_8BIT)
1681  e = ENC_8BIT;
1682  }
1683 
1684  return e;
1685 }
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:

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

1694 {
1695  char *p = NULL;
1696 
1697  if (b->parts && check_boundary(boundary, b->parts))
1698  return true;
1699 
1700  if (b->next && check_boundary(boundary, b->next))
1701  return true;
1702 
1703  p = mutt_param_get(&b->parameter, "boundary");
1704  if (p && (mutt_str_strcmp(p, boundary) == 0))
1705  {
1706  return true;
1707  }
1708  return false;
1709 }
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:1693
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:

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

1717 {
1718  struct Body *new_body = mutt_body_new();
1719  new_body->type = TYPE_MULTIPART;
1720  new_body->subtype = mutt_str_strdup("mixed");
1721  new_body->encoding = get_toplevel_encoding(b);
1722  do
1723  {
1724  mutt_generate_boundary(&new_body->parameter);
1725  if (check_boundary(mutt_param_get(&new_body->parameter, "boundary"), b))
1726  mutt_param_delete(&new_body->parameter, "boundary");
1727  } while (!mutt_param_get(&new_body->parameter, "boundary"));
1728  new_body->use_disp = false;
1729  new_body->disposition = DISP_INLINE;
1730  new_body->parts = b;
1731 
1732  return new_body;
1733 }
static int get_toplevel_encoding(struct Body *a)
Find the most restrictive encoding type.
Definition: sendlib.c:1672
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:604
static bool check_boundary(const char *boundary, struct Body *b)
check for duplicate boundary
Definition: sendlib.c:1693
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:

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

1743 {
1744  struct Body *t = NULL;
1745 
1746  if (b->parts)
1747  {
1748  t = b;
1749  b = b->parts;
1750  t->parts = NULL;
1751  mutt_body_free(&t);
1752  }
1753  return b;
1754 }
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 **p)
Free a Body.
Definition: body.c:57

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1767 {
1768  char buf[1024];
1769  int count = 0;
1770 
1771  struct Address *a = NULL;
1772  TAILQ_FOREACH(a, al, entries)
1773  {
1774  buf[0] = '\0';
1775  mutt_addr_write(buf, sizeof(buf), a, display);
1776  size_t len = mutt_str_strlen(buf);
1777  if (count && (linelen + len > 74))
1778  {
1779  fputs("\n\t", fp);
1780  linelen = len + 8; /* tab is usually about 8 spaces... */
1781  }
1782  else
1783  {
1784  if (count && a->mailbox)
1785  {
1786  fputc(' ', fp);
1787  linelen++;
1788  }
1789  linelen += len;
1790  }
1791  fputs(buf, fp);
1792  struct Address *next = TAILQ_NEXT(a, entries);
1793  if (!a->group && next && next->mailbox)
1794  {
1795  linelen++;
1796  fputc(',', fp);
1797  }
1798  count++;
1799  }
1800  fputc('\n', fp);
1801 }
#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:1012
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:

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

1813 {
1814  struct ListNode *np = NULL;
1815  size_t length = 0;
1816 
1817  STAILQ_FOREACH(np, r, entries)
1818  {
1819  if (++length == trim)
1820  break;
1821  }
1822 
1823  struct ListNode **ref = mutt_mem_calloc(length, sizeof(struct ListNode *));
1824 
1825  // store in reverse order
1826  size_t tmp = length;
1827  STAILQ_FOREACH(np, r, entries)
1828  {
1829  ref[--tmp] = np;
1830  if (tmp == 0)
1831  break;
1832  }
1833 
1834  for (size_t i = 0; i < length; i++)
1835  {
1836  fputc(' ', fp);
1837  fputs(ref[i]->data, fp);
1838  if (i != length - 1)
1839  fputc('\n', fp);
1840  }
1841 
1842  FREE(&ref);
1843 }
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
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:

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

1857 {
1858  while (value && (value[0] != '\0'))
1859  {
1860  if (fputc(*value, fp) == EOF)
1861  return -1;
1862  /* corner-case: break words longer than 998 chars by force,
1863  * mandated by RFC5322 */
1864  if (!(chflags & CH_DISPLAY) && (++col >= 998))
1865  {
1866  if (fputs("\n ", fp) < 0)
1867  return -1;
1868  col = 1;
1869  }
1870  if (*value == '\n')
1871  {
1872  if ((value[1] != '\0') && pfx && (pfx[0] != '\0') && (fputs(pfx, fp) == EOF))
1873  return -1;
1874  /* for display, turn folding spaces into folding tabs */
1875  if ((chflags & CH_DISPLAY) && ((value[1] == ' ') || (value[1] == '\t')))
1876  {
1877  value++;
1878  while ((value[0] != '\0') && ((value[0] == ' ') || (value[0] == '\t')))
1879  value++;
1880  if (fputc('\t', fp) == EOF)
1881  return -1;
1882  continue;
1883  }
1884  }
1885  value++;
1886  }
1887  return 0;
1888 }
#define CH_DISPLAY
Display result to user.
Definition: copy.h:69

+ Here is the caller graph for this function:

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

1903 {
1904  const char *p = value;
1905  char buf[8192] = { 0 };
1906  int first = 1, col = 0, l = 0;
1907  const bool display = (chflags & CH_DISPLAY);
1908 
1909  mutt_debug(LL_DEBUG5, "pfx=[%s], tag=[%s], flags=%d value=[%s]\n", pfx, tag,
1910  chflags, NONULL(value));
1911 
1912  if (tag && *tag && (fprintf(fp, "%s%s: ", NONULL(pfx), tag) < 0))
1913  return -1;
1914  col = mutt_str_strlen(tag) + ((tag && (tag[0] != '\0')) ? 2 : 0) + mutt_str_strlen(pfx);
1915 
1916  while (p && (p[0] != '\0'))
1917  {
1918  int fold = 0;
1919 
1920  /* find the next word and place it in 'buf'. it may start with
1921  * whitespace we can fold before */
1922  const char *next = mutt_str_find_word(p);
1923  l = MIN(sizeof(buf) - 1, next - p);
1924  memcpy(buf, p, l);
1925  buf[l] = '\0';
1926 
1927  /* determine width: character cells for display, bytes for sending
1928  * (we get pure ascii only) */
1929  const int w = mutt_mb_width(buf, col, display);
1930  const int enc = mutt_str_startswith(buf, "=?", CASE_MATCH);
1931 
1932  mutt_debug(LL_DEBUG5, "word=[%s], col=%d, w=%d, next=[0x0%x]\n", buf, col, w, *next);
1933 
1934  /* insert a folding \n before the current word's lwsp except for
1935  * header name, first word on a line (word longer than wrap width)
1936  * and encoded words */
1937  if (!first && !enc && col && ((col + w) >= wraplen))
1938  {
1939  col = mutt_str_strlen(pfx);
1940  fold = 1;
1941  if (fprintf(fp, "\n%s", NONULL(pfx)) <= 0)
1942  return -1;
1943  }
1944 
1945  /* print the actual word; for display, ignore leading ws for word
1946  * and fold with tab for readability */
1947  if (display && fold)
1948  {
1949  char *pc = buf;
1950  while ((pc[0] != '\0') && ((pc[0] == ' ') || (pc[0] == '\t')))
1951  {
1952  pc++;
1953  col--;
1954  }
1955  if (fputc('\t', fp) == EOF)
1956  return -1;
1957  if (print_val(fp, pfx, pc, chflags, col) < 0)
1958  return -1;
1959  col += 8;
1960  }
1961  else if (print_val(fp, pfx, buf, chflags, col) < 0)
1962  return -1;
1963  col += w;
1964 
1965  /* if the current word ends in \n, ignore all its trailing spaces
1966  * and reset column; this prevents us from putting only spaces (or
1967  * even none) on a line if the trailing spaces are located at our
1968  * current line width
1969  * XXX this covers ASCII space only, for display we probably
1970  * want something like iswspace() here */
1971  const char *sp = next;
1972  while ((sp[0] != '\0') && ((sp[0] == ' ') || (sp[0] == '\t')))
1973  sp++;
1974  if (sp[0] == '\n')
1975  {
1976  next = sp;
1977  col = 0;
1978  }
1979 
1980  p = next;
1981  first = 0;
1982  }
1983 
1984  /* if we have printed something but didn't \n-terminate it, do it
1985  * except the last word we printed ended in \n already */
1986  if (col && ((l == 0) || (buf[l - 1] != '\n')))
1987  if (putc('\n', fp) == EOF)
1988  return -1;
1989 
1990  return 0;
1991 }
#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:1855
const char * mutt_str_find_word(const char *src)
Find the end of a word (non-space)
Definition: string.c:1029

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

2001 {
2002  char *p = s;
2003  char *q = s;
2004 
2005  while (p && (p[0] != '\0'))
2006  {
2007  /* remove CRLF prior to FWSP, turn \t into ' ' */
2008  if ((p[0] == '\r') && (p[1] == '\n') && ((p[2] == ' ') || (p[2] == '\t')))
2009  {
2010  *q++ = ' ';
2011  p += 3;
2012  continue;
2013  }
2014  /* remove LF prior to FWSP, turn \t into ' ' */
2015  else if ((p[0] == '\n') && ((p[1] == ' ') || (p[1] == '\t')))
2016  {
2017  *q++ = ' ';
2018  p += 2;
2019  continue;
2020  }
2021  *q++ = *p++;
2022  }
2023  if (q)
2024  q[0] = '\0';
2025 
2026  return s;
2027 }

+ Here is the caller graph for this function:

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

2044 {
2045  char *tagbuf = NULL, *valbuf = NULL, *t = NULL;
2046  bool is_from = ((end - start) > 5) && mutt_str_startswith(start, "from ", CASE_IGNORE);
2047 
2048  /* only pass through folding machinery if necessary for sending,
2049  * never wrap From_ headers on sending */
2050  if (!(chflags & CH_DISPLAY) && ((pfxw + max <= wraplen) || is_from))
2051  {
2052  valbuf = mutt_str_substr_dup(start, end);
2053  mutt_debug(LL_DEBUG5, "buf[%s%s] short enough, max width = %d <= %d\n",
2054  NONULL(pfx), valbuf, max, wraplen);
2055  if (pfx && *pfx)
2056  {
2057  if (fputs(pfx, fp) == EOF)
2058  {
2059  FREE(&valbuf);
2060  return -1;
2061  }
2062  }
2063 
2064  t = strchr(valbuf, ':');
2065  if (!t)
2066  {
2067  mutt_debug(LL_DEBUG1, "#1 warning: header not in 'key: value' format!\n");
2068  FREE(&valbuf);
2069  return 0;
2070  }
2071  if (print_val(fp, pfx, valbuf, chflags, mutt_str_strlen(pfx)) < 0)
2072  {
2073  FREE(&valbuf);
2074  return -1;
2075  }
2076  FREE(&valbuf);
2077  }
2078  else
2079  {
2080  t = strchr(start, ':');
2081  if (!t || (t > end))
2082  {
2083  mutt_debug(LL_DEBUG1, "#2 warning: header not in 'key: value' format!\n");
2084  return 0;
2085  }
2086  if (is_from)
2087  {
2088  tagbuf = NULL;
2089  valbuf = mutt_str_substr_dup(start, end);
2090  }
2091  else
2092  {
2093  tagbuf = mutt_str_substr_dup(start, t);
2094  /* skip over the colon separating the header field name and value */
2095  t++;
2096 
2097  /* skip over any leading whitespace (WSP, as defined in RFC5322)
2098  * NOTE: mutt_str_skip_email_wsp() does the wrong thing here.
2099  * See tickets 3609 and 3716. */
2100  while ((*t == ' ') || (*t == '\t'))
2101  t++;
2102 
2103  valbuf = mutt_str_substr_dup(t, end);
2104  }
2105  mutt_debug(LL_DEBUG2, "buf[%s%s] too long, max width = %d > %d\n",
2106  NONULL(pfx), NONULL(valbuf), max, wraplen);
2107  if (fold_one_header(fp, tagbuf, valbuf, pfx, wraplen, chflags) < 0)
2108  {
2109  FREE(&valbuf);
2110  FREE(&tagbuf);
2111  return -1;
2112  }
2113  FREE(&tagbuf);
2114  FREE(&valbuf);
2115  }
2116  return 0;
2117 }
#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:1901
#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:1855
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:

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

2135 {
2136  char *last = NULL, *line = NULL;
2137  int max = 0, w, rc = -1;
2138  int pfxw = mutt_strwidth(pfx);
2139  char *v = mutt_str_strdup(value);
2140  bool display = (chflags & CH_DISPLAY);
2141 
2142  if (!display || C_Weed)
2143  v = unfold_header(v);
2144 
2145  /* when not displaying, use sane wrap value */
2146  if (!display)
2147  {
2148  if ((C_WrapHeaders < 78) || (C_WrapHeaders > 998))
2149  wraplen = 78;
2150  else
2151  wraplen = C_WrapHeaders;
2152  }
2153  else if ((wraplen <= 0) || (wraplen > MuttIndexWindow->cols))
2154  wraplen = MuttIndexWindow->cols;
2155 
2156  if (tag)
2157  {
2158  /* if header is short enough, simply print it */
2159  if (!display && (mutt_strwidth(tag) + 2 + pfxw + mutt_strwidth(v) <= wraplen))
2160  {
2161  mutt_debug(LL_DEBUG5, "buf[%s%s: %s] is short enough\n", NONULL(pfx), tag, v);
2162  if (fprintf(fp, "%s%s: %s\n", NONULL(pfx), tag, v) <= 0)
2163  goto out;
2164  rc = 0;
2165  goto out;
2166  }
2167  else
2168  {
2169  rc = fold_one_header(fp, tag, v, pfx, wraplen, chflags);
2170  goto out;
2171  }
2172  }
2173 
2174  char *p = v;
2175  last = v;
2176  line = v;
2177  while (p && *p)
2178  {
2179  p = strchr(p, '\n');
2180 
2181  /* find maximum line width in current header */
2182  if (p)
2183  *p = '\0';
2184  w = mutt_mb_width(line, 0, display);
2185  if (w > max)
2186  max = w;
2187  if (p)
2188  *p = '\n';
2189 
2190  if (!p)
2191  break;
2192 
2193  line = ++p;
2194  if ((*p != ' ') && (*p != '\t'))
2195  {
2196  if (write_one_header(fp, pfxw, max, wraplen, pfx, last, p, chflags) < 0)
2197  goto out;
2198  last = p;
2199  max = 0;
2200  }
2201  }
2202 
2203  if (last && *last)
2204  if (write_one_header(fp, pfxw, max, wraplen, pfx, last, p, chflags) < 0)
2205  goto out;
2206 
2207  rc = 0;
2208 
2209 out:
2210  FREE(&v);
2211  return rc;
2212 }
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:2000
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:1262
struct MuttWindow * MuttIndexWindow
Index Window.
Definition: mutt_window.c:40
#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:2042
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:1901
#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:

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

2241 {
2242  char buf[1024];
2243  char *p = NULL, *q = NULL;
2244  bool has_agent = false; /* user defined user-agent header field exists */
2245 
2246  if ((mode == MUTT_WRITE_HEADER_NORMAL) && !privacy)
2247  fputs(mutt_date_make_date(buf, sizeof(buf)), fp);
2248 
2249  /* UseFrom is not consulted here so that we can still write a From:
2250  * field if the user sets it with the 'my_hdr' command */
2251  if (!TAILQ_EMPTY(&env->from) && !privacy)
2252  {
2253  buf[0] = '\0';
2254  mutt_addrlist_write(buf, sizeof(buf), &env->from, false);
2255  fprintf(fp, "From: %s\n", buf);
2256  }
2257 
2258  if (!TAILQ_EMPTY(&env->sender) && !privacy)
2259  {
2260  buf[0] = '\0';
2261  mutt_addrlist_write(buf, sizeof(buf), &env->sender, false);
2262  fprintf(fp, "Sender: %s\n", buf);
2263  }
2264 
2265  if (!TAILQ_EMPTY(&env->to))
2266  {
2267  fputs("To: ", fp);
2268  mutt_write_addrlist(&env->to, fp, 4, 0);
2269  }
2270  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2271 #ifdef USE_NNTP
2272  if (!OptNewsSend)
2273 #endif
2274  fputs("To:\n", fp);
2275 
2276  if (!TAILQ_EMPTY(&env->cc))
2277  {
2278  fputs("Cc: ", fp);
2279  mutt_write_addrlist(&env->cc, fp, 4, 0);
2280  }
2281  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2282 #ifdef USE_NNTP
2283  if (!OptNewsSend)
2284 #endif
2285  fputs("Cc:\n", fp);
2286 
2287  if (!TAILQ_EMPTY(&env->bcc))
2288  {
2289  if ((mode == MUTT_WRITE_HEADER_POSTPONE) || (mode == MUTT_WRITE_HEADER_EDITHDRS) ||
2290  ((mode == MUTT_WRITE_HEADER_NORMAL) && C_WriteBcc))
2291  {
2292  fputs("Bcc: ", fp);
2293  mutt_write_addrlist(&env->bcc, fp, 5, 0);
2294  }
2295  }
2296  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2297 #ifdef USE_NNTP
2298  if (!OptNewsSend)
2299 #endif
2300  fputs("Bcc:\n", fp);
2301 
2302 #ifdef USE_NNTP
2303  if (env->newsgroups)
2304  fprintf(fp, "Newsgroups: %s\n", env->newsgroups);
2305  else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend)
2306  fputs("Newsgroups:\n", fp);
2307 
2308  if (env->followup_to)
2309  fprintf(fp, "Followup-To: %s\n", env->followup_to);
2310  else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend)
2311  fputs("Followup-To:\n", fp);
2312 
2313  if (env->x_comment_to)
2314  fprintf(fp, "X-Comment-To: %s\n", env->x_comment_to);
2315  else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend && C_XCommentTo)
2316  fputs("X-Comment-To:\n", fp);
2317 #endif
2318 
2319  if (env->subject)
2320  {
2321  if (hide_protected_subject &&
2322  ((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_POSTPONE)))
2324  else
2325  mutt_write_one_header(fp, "Subject", env->subject, NULL, 0, CH_NO_FLAGS);
2326  }
2327  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2328  fputs("Subject:\n", fp);
2329 
2330  /* save message id if the user has set it */
2331  if (env->message_id && !privacy)
2332  fprintf(fp, "Message-ID: %s\n", env->message_id);
2333 
2334  if (!TAILQ_EMPTY(&env->reply_to))
2335  {
2336  fputs("Reply-To: ", fp);
2337  mutt_write_addrlist(&env->reply_to, fp, 10, 0);
2338  }
2339  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2340  fputs("Reply-To:\n", fp);
2341 
2342  if (!TAILQ_EMPTY(&env->mail_followup_to))
2343 #ifdef USE_NNTP
2344  if (!OptNewsSend)
2345 #endif
2346  {
2347  fputs("Mail-Followup-To: ", fp);
2348  mutt_write_addrlist(&env->mail_followup_to, fp, 18, 0);
2349  }
2350 
2351  if ((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_POSTPONE))
2352  {
2353  if (!STAILQ_EMPTY(&env->references))
2354  {
2355  fputs("References:", fp);
2356  mutt_write_references(&env->references, fp, 10);
2357  fputc('\n', fp);
2358  }
2359 
2360  /* Add the MIME headers */
2361  fputs("MIME-Version: 1.0\n", fp);
2362  mutt_write_mime_header(attach, fp);
2363  }
2364 
2365  if (!STAILQ_EMPTY(&env->in_reply_to))
2366  {
2367  fputs("In-Reply-To:", fp);
2368  mutt_write_references(&env->in_reply_to, fp, 0);
2369  fputc('\n', fp);
2370  }
2371 
2372 #ifdef USE_AUTOCRYPT
2373  if (C_Autocrypt)
2374  {
2375  if (mode == MUTT_WRITE_HEADER_NORMAL)
2377  if (mode == MUTT_WRITE_HEADER_MIME)
2379  }
2380 #endif
2381 
2382  /* Add any user defined headers */
2383  struct ListNode *tmp = NULL;
2384  STAILQ_FOREACH(tmp, &env->userhdrs, entries)
2385  {
2386  p = strchr(tmp->data, ':');
2387  if (p)
2388  {
2389  q = p;
2390 
2391  *p = '\0';
2392 
2393  p = mutt_str_skip_email_wsp(p + 1);
2394  if (!*p)
2395  {
2396  *q = ':';
2397  continue; /* don't emit empty fields. */
2398  }
2399 
2400  /* check to see if the user has overridden the user-agent field */
2401  if (mutt_str_startswith(tmp->data, "user-agent", CASE_IGNORE))
2402  {
2403  has_agent = true;
2404  if (privacy)
2405  {
2406  *q = ':';
2407  continue;
2408  }
2409  }
2410 
2411  mutt_write_one_header(fp, tmp->data, p, NULL, 0, CH_NO_FLAGS);
2412  *q = ':';
2413  }
2414  }
2415 
2416  if ((mode == MUTT_WRITE_HEADER_NORMAL) && !privacy && C_UserAgent && !has_agent)
2417  {
2418  /* Add a vanity header */
2419  fprintf(fp, "User-Agent: NeoMutt/%s%s\n", PACKAGE_VERSION, GitVer);
2420  }
2421 
2422  return (ferror(fp) == 0) ? 0 : -1;
2423 }
WHERE bool C_Autocrypt
Config: Enables the Autocrypt feature.
Definition: globals.h:209
WHERE bool C_WriteBcc
Config: Write out the &#39;Bcc&#39; field when preparing to send a mail.
Definition: globals.h:277
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:109
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:1134
char * mutt_date_make_date(char *buf, size_t buflen)
Write a date in RFC822 format to a buffer.
Definition: date.c:370
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
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:1812
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
Ignore case when comparing strings.
Definition: string2.h:68
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 mutt_write_addrlist(struct AddressList *al, FILE *fp, int linelen, bool display)
wrapper around mutt_write_address()
Definition: sendlib.c:1766
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
char * data
Definition: list.h:35
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:298
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:362
#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
A List node for strings.
Definition: list.h:33
int mutt_autocrypt_write_gossip_headers(struct Envelope *env, FILE *fp)
Write the Autocrypt gossip headers to a file.
Definition: autocrypt.c:782
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:2133
int mutt_autocrypt_write_autocrypt_header(struct Envelope *env, FILE *fp)
Write the Autocrypt header to a file.
Definition: autocrypt.c:745

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

2432 {
2433  char *tmp = NULL;
2434  char *p = NULL;
2435  int i;
2436 
2437  struct ListNode *np = NULL;
2438  STAILQ_FOREACH(np, h, entries)
2439  {
2440  p = strchr(np->data, ':');
2441  if (!p)
2442  continue;
2443 
2444  i = p - np->data;
2445  p = mutt_str_skip_email_wsp(p + 1);
2446  tmp = mutt_str_strdup(p);
2447 
2448  if (!tmp)
2449  continue;
2450 
2451  rfc2047_encode(&tmp, NULL, i + 2, C_SendCharset);
2452  mutt_mem_realloc(&np->data, i + 2 + mutt_str_strlen(tmp) + 1);
2453 
2454  sprintf(np->data + i + 2, "%s", tmp);
2455 
2456  FREE(&tmp);
2457  }
2458 }
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:625
char * data
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:

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

2469 {
2470  if (!C_Hostname || (C_Hostname[0] == '@'))
2471  return NULL;
2472 
2473  char *p = C_Hostname;
2474 
2475  if (may_hide_host && C_HiddenHost)
2476  {
2477  p = strchr(C_Hostname, '.');
2478  if (p)
2479  p++;
2480 
2481  // sanity check: don't hide the host if the fqdn is something like example.com
2482  if (!p || !strchr(p, '.'))
2483  p = C_Hostname;
2484  }
2485 
2486  return p;
2487 }
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:115

+ Here is the caller graph for this function:

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

2496 {
2497  char buf[128];
2498  unsigned char rndid[MUTT_RANDTAG_LEN + 1];
2499 
2500  mutt_rand_base32(rndid, sizeof(rndid) - 1);
2501  rndid[MUTT_RANDTAG_LEN] = 0;
2502  const char *fqdn = mutt_fqdn(false);
2503  if (!fqdn)
2504  fqdn = NONULL(ShortHostname);
2505 
2506  struct tm tm = mutt_date_gmtime(MUTT_DATE_NOW);
2507  snprintf(buf, sizeof(buf), "<%d%02d%02d%02d%02d%02d.%s@%s>", tm.tm_year + 1900,
2508  tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, rndid, fqdn);
2509  return mutt_str_strdup(buf);
2510 }
#define NONULL(x)
Definition: string2.h:37
#define MUTT_DATE_NOW
Constant representing the &#39;current time&#39;, see: mutt_date_gmtime(), mutt_date_localtime() ...
Definition: date.h:36
#define MUTT_RANDTAG_LEN
Definition: muttlib.h:43
struct tm mutt_date_gmtime(time_t t)
Converts calendar time to a broken-down time structure expressed in UTC timezone. ...
Definition: date.c:731
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2468
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:49
void mutt_rand_base32(void *buf, size_t buflen)
Fill a buffer with a base32-encoded random string.
Definition: muttlib.c:513

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void alarm_handler ( int  sig)
static

Async notification of an alarm signal.

Parameters
sigSignal, (SIGALRM)

Definition at line 2516 of file sendlib.c.

2517 {
2518  SigAlrm = 1;
2519 }
WHERE SIG_ATOMIC_VOLATILE_T SigAlrm
true after SIGALRM is received
Definition: globals.h:82

+ Here is the caller graph for this function:

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

2534 {
2535  sigset_t set;
2536  int st;
2537 
2539 
2540  sigemptyset(&set);
2541  /* we also don't want to be stopped right now */
2542  sigaddset(&set, SIGTSTP);
2543  sigprocmask(SIG_BLOCK, &set, NULL);
2544 
2545  if ((C_SendmailWait >= 0) && tempfile)
2546  {
2547  char tmp[PATH_MAX];
2548 
2549  mutt_mktemp(tmp, sizeof(tmp));
2550  *tempfile = mutt_str_strdup(tmp);
2551  }
2552 
2553  pid_t pid = fork();
2554  if (pid == 0)
2555  {
2556  struct sigaction act, oldalrm;
2557 
2558  /* save parent's ID before setsid() */
2559  pid_t ppid = getppid();
2560 
2561  /* we want the delivery to continue even after the main process dies,
2562  * so we put ourselves into another session right away */
2563  setsid();
2564 
2565  /* next we close all open files */
2566  close(0);
2567 #ifdef OPEN_MAX
2568  for (int fd = tempfile ? 1 : 3; fd < OPEN_MAX; fd++)
2569  close(fd);
2570 #elif defined(_POSIX_OPEN_MAX)
2571  for (int fd = tempfile ? 1 : 3; fd < _POSIX_OPEN_MAX; fd++)
2572  close(fd);
2573 #else
2574  if (tempfile)
2575  {
2576  close(1);
2577  close(2);
2578  }
2579 #endif
2580 
2581  /* now the second fork() */
2582  pid = fork();
2583  if (pid == 0)
2584  {
2585  /* "msg" will be opened as stdin */
2586  if (open(msg, O_RDONLY, 0) < 0)
2587  {
2588  unlink(msg);
2589  _exit(S_ERR);
2590  }
2591  unlink(msg);
2592 
2593  if ((C_SendmailWait >= 0) && tempfile && *tempfile)
2594  {
2595  /* *tempfile will be opened as stdout */
2596  if (open(*tempfile, O_WRONLY | O_APPEND | O_CREAT | O_EXCL, 0600) < 0)
2597  _exit(S_ERR);
2598  /* redirect stderr to *tempfile too */
2599  if (dup(1) < 0)
2600  _exit(S_ERR);
2601  }
2602  else if (tempfile)
2603  {
2604  if (open("/dev/null", O_WRONLY | O_APPEND) < 0) /* stdout */
2605  _exit(S_ERR);
2606  if (open("/dev/null", O_RDWR | O_APPEND) < 0) /* stderr */
2607  _exit(S_ERR);
2608  }
2609 
2610  /* execvpe is a glibc extension */
2611  /* execvpe (path, args, mutt_envlist_getlist()); */
2612  execvp(path, args);
2613  _exit(S_ERR);
2614  }
2615  else if (pid == -1)
2616  {
2617  unlink(msg);
2618  FREE(tempfile);
2619  _exit(S_ERR);
2620  }
2621 
2622  /* C_SendmailWait > 0: interrupt waitpid() after C_SendmailWait seconds
2623  * C_SendmailWait = 0: wait forever
2624  * C_SendmailWait < 0: don't wait */
2625  if (C_SendmailWait > 0)
2626  {
2627  SigAlrm = 0;
2628  act.sa_handler = alarm_handler;
2629 #ifdef SA_INTERRUPT
2630  /* need to make sure waitpid() is interrupted on SIGALRM */
2631  act.sa_flags = SA_INTERRUPT;
2632 #else
2633  act.sa_flags = 0;
2634 #endif
2635  sigemptyset(&act.sa_mask);
2636  sigaction(SIGALRM, &act, &oldalrm);
2637  alarm(C_SendmailWait);
2638  }
2639  else if (C_SendmailWait < 0)
2640  _exit(0xff & EX_OK);
2641 
2642  if (waitpid(pid, &st, 0) > 0)
2643  {
2644  st = WIFEXITED(st) ? WEXITSTATUS(st) : S_ERR;
2645  if (C_SendmailWait && (st == (0xff & EX_OK)) && tempfile && *tempfile)
2646  {
2647  unlink(*tempfile); /* no longer needed */
2648  FREE(tempfile);
2649  }
2650  }
2651  else
2652  {
2653  st = ((C_SendmailWait > 0) && (errno == EINTR) && SigAlrm) ? S_BKG : S_ERR;
2654  if ((C_SendmailWait > 0) && tempfile && *tempfile)
2655  {
2656  unlink(*tempfile);
2657  FREE(tempfile);
2658  }
2659  }
2660 
2661  if (C_SendmailWait > 0)
2662  {
2663  /* reset alarm; not really needed, but... */
2664  alarm(0);
2665  sigaction(SIGALRM, &oldalrm, NULL);
2666  }
2667 
2668  if ((kill(ppid, 0) == -1) && (errno == ESRCH) && tempfile && *tempfile)
2669  {
2670  /* the parent is already dead */
2671  unlink(*tempfile);
2672  FREE(tempfile);
2673  }
2674 
2675  _exit(st);
2676  }
2677 
2678  sigprocmask(SIG_UNBLOCK, &set, NULL);
2679 
2680  if ((pid != -1) && (waitpid(pid, &st, 0) > 0))
2681  st = WIFEXITED(st) ? WEXITSTATUS(st) : S_ERR; /* return child status */
2682  else
2683  st = S_ERR; /* error */
2684 
2686 
2687  return st;
2688 }
#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:82
#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:2516
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:76
#define PATH_MAX
Definition: mutt.h:51
short C_SendmailWait
Config: Time to wait for sendmail to finish.
Definition: sendlib.c:94
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#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:

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

2699 {
2700  /* weed out group mailboxes, since those are for display only */
2701  if (addr->mailbox && !addr->group)
2702  {
2703  if (*argslen == *argsmax)
2704  mutt_mem_realloc(&args, (*argsmax += 5) * sizeof(char *));
2705  args[(*argslen)++] = addr->mailbox;
2706  }
2707  return args;
2708 }
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:

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

2719 {
2720  if (!al)
2721  return args;
2722 
2723  struct Address *a = NULL;
2724  TAILQ_FOREACH(a, al, entries)
2725  {
2726  args = add_args_one(args, argslen, argsmax, a);
2727  }
2728  return args;
2729 }
#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:2698

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

2742 {
2743  if (*argslen == *argsmax)
2744  mutt_mem_realloc(&args, (*argsmax += 5) * sizeof(char *));
2745  args[(*argslen)++] = s;
2746  return args;
2747 }
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:

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

2763 {
2764  char *ps = NULL, *path = NULL, *s = NULL, *childout = NULL;
2765  char **args = NULL;
2766  size_t argslen = 0, argsmax = 0;
2767  char **extra_args = NULL;
2768  int i;
2769 
2770 #ifdef USE_NNTP
2771  if (OptNewsSend)
2772  {
2773  char cmd[1024];
2774 
2775  mutt_expando_format(cmd, sizeof(cmd), 0, MuttIndexWindow->cols,
2777  if (!*cmd)
2778  {
2779  i = nntp_post(Context->mailbox, msg);
2780  unlink(msg);
2781  return i;
2782  }
2783 
2784  s = mutt_str_strdup(cmd);
2785  }
2786  else
2787 #endif
2789 
2790  /* ensure that $sendmail is set to avoid a crash. http://dev.mutt.org/trac/ticket/3548 */
2791  if (!s)
2792  {
2793  mutt_error(_("$sendmail must be set in order to send mail"));
2794  return -1;
2795  }
2796 
2797  ps = s;
2798  i = 0;
2799  while ((ps = strtok(ps, " ")))
2800  {
2801  if (argslen == argsmax)
2802  mutt_mem_realloc(&args, sizeof(char *) * (argsmax += 5));
2803 
2804  if (i)
2805  {
2806  if (mutt_str_strcmp(ps, "--") == 0)
2807  break;
2808  args[argslen++] = ps;
2809  }
2810  else
2811  {
2812  path = mutt_str_strdup(ps);
2813  ps = strrchr(ps, '/');
2814  if (ps)
2815  ps++;
2816  else
2817  ps = path;
2818  args[argslen++] = ps;
2819  }
2820  ps = NULL;
2821  i++;
2822  }
2823 
2824 #ifdef USE_NNTP
2825  if (!OptNewsSend)
2826  {
2827 #endif
2828  size_t extra_argslen = 0;
2829  /* If C_Sendmail contained a "--", we save the recipients to append to
2830  * args after other possible options added below. */
2831  if (ps)
2832  {
2833  ps = NULL;
2834  size_t extra_argsmax = 0;
2835  while ((ps = strtok(ps, " ")))
2836  {
2837  if (extra_argslen == extra_argsmax)
2838  mutt_mem_realloc(&extra_args, sizeof(char *) * (extra_argsmax += 5));
2839 
2840  extra_args[extra_argslen++] = ps;
2841  ps = NULL;
2842  }
2843  }
2844 
2845  if (eightbit && C_Use8bitmime)
2846  args = add_option(args, &argslen, &argsmax, "-B8BITMIME");
2847 
2848  if (C_UseEnvelopeFrom)
2849  {
2851  {
2852  args = add_option(args, &argslen, &argsmax, "-f");
2853  args = add_args_one(args, &argslen, &argsmax, C_EnvelopeFromAddress);
2854  }
2855  else if (!TAILQ_EMPTY(from) && !TAILQ_NEXT(TAILQ_FIRST(from), entries))
2856  {
2857  args = add_option(args, &argslen, &argsmax, "-f");
2858  args = add_args(args, &argslen, &argsmax, from);
2859  }
2860  }
2861 
2862  if (C_DsnNotify)
2863  {
2864  args = add_option(args, &argslen, &argsmax, "-N");
2865  args = add_option(args, &argslen, &argsmax, C_DsnNotify);
2866  }
2867  if (C_DsnReturn)
2868  {
2869  args = add_option(args, &argslen, &argsmax, "-R");
2870  args = add_option(args, &argslen, &argsmax, C_DsnReturn);
2871  }
2872  args = add_option(args, &argslen, &argsmax, "--");
2873  for (i = 0; i < extra_argslen; i++)
2874  args = add_option(args, &argslen, &argsmax, extra_args[i]);
2875  args = add_args(args, &argslen, &argsmax, to);
2876  args = add_args(args, &argslen, &argsmax, cc);
2877  args = add_args(args, &argslen, &argsmax, bcc);
2878 #ifdef USE_NNTP
2879  }
2880 #endif
2881 
2882  if (argslen == argsmax)
2883  mutt_mem_realloc(&args, sizeof(char *) * (++argsmax));
2884 
2885  args[argslen++] = NULL;
2886 
2887  /* Some user's $sendmail command uses gpg for password decryption,
2888  * and is set up to prompt using ncurses pinentry. If we
2889  * mutt_endwin() it leaves other users staring at a blank screen.
2890  * So instead, just force a hard redraw on the next refresh. */
2891  if (!OptNoCurses)
2893 
2894  i = send_msg(path, args, msg, OptNoCurses ? NULL : &childout);
2895  if (i != (EX_OK & 0xff))
2896  {
2897  if (i != S_BKG)
2898  {
2899  const char *e = mutt_str_sysexit(i);
2900  mutt_error(_("Error sending message, child exited %d (%s)"), i, NONULL(e));
2901  if (childout)
2902  {
2903  struct stat st;
2904 
2905  if ((stat(childout, &st) == 0) && (st.st_size > 0))
2906  mutt_do_pager(_("Output of the delivery process"), childout,
2907  MUTT_PAGER_NO_FLAGS, NULL);
2908  }
2909  }
2910  }
2911  else if (childout)
2912  unlink(childout);
2913 
2914  FREE(&childout);
2915  FREE(&path);
2916  FREE(&s);
2917  FREE(&args);
2918  FREE(&extra_args);
2919 
2920  if (i == (EX_OK & 0xff))
2921  i = 0;
2922  else if (i == S_BKG)
2923  i = 1;
2924  else
2925  i = -1;
2926  return i;
2927 }
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:838
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:2533
#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:2718
#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:112
static char ** add_option(char **args, size_t *argslen, size_t *argsmax, char *s)
Add a string to a dynamic array.
Definition: sendlib.c:2741
bool C_UseEnvelopeFrom
Config: Set the envelope sender of the message.
Definition: sendlib.c:96
struct MuttWindow * MuttIndexWindow
Index Window.
Definition: mutt_window.c:40
WHERE char * C_DsnReturn
Config: What to send as a notification of message delivery or delay.
Definition: globals.h:112
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:582
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:97
#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:116
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:111
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:2698
#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:

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

2939 {
2940  if (final)
2941  {
2942  if (!TAILQ_EMPTY(&env->bcc) && TAILQ_EMPTY(&env->to) && TAILQ_EMPTY(&env->cc))
2943  {
2944  /* some MTA's will put an Apparently-To: header field showing the Bcc:
2945  * recipients if there is no To: or Cc: field, so attempt to suppress
2946  * it by using an empty To: field. */
2947  struct Address *to = mutt_addr_new();
2948  to->group = true;
2949  mutt_addrlist_append(&env->to, to);
2951 
2952  char buf[1024];
2953  buf[0] = '\0';
2954  mutt_addr_cat(buf, sizeof(buf), "undisclosed-recipients", AddressSpecials);
2955 
2956  to->mailbox = mutt_str_strdup(buf);
2957  }
2958 
2959  mutt_set_followup_to(env);
2960 
2961  if (!env->message_id)
2962  env->message_id = gen_msgid();
2963  }
2964 
2965  /* Take care of 8-bit => 7-bit conversion. */
2967  encode_headers(&env->userhdrs);
2968 }
void rfc2047_encode_envelope(struct Envelope *env)
Encode the fields of an Envelope.
Definition: rfc2047.c:809
static char * gen_msgid(void)
Generate a unique Message ID.
Definition: sendlib.c:2495
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:1187
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:668
static void encode_headers(struct ListHead *h)
RFC2047-encode a list of headers.
Definition: sendlib.c:2431
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1398

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

2978 {
2979  struct ListNode *item = NULL;
2980  STAILQ_FOREACH(item, &env->userhdrs, entries)
2981  {
2982  rfc2047_decode(&item->data);
2983  }
2984 
2986 
2987  /* back conversions */
2989 }
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:1378
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:789
void rfc2047_decode(char **pd)
Decode any RFC2047-encoded header fields.
Definition: rfc2047.c:649
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
char * data
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:

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

3003 {
3004  if (!e)
3005  return -1;
3006 
3007  int rc = 0;
3008  char tempfile[PATH_MAX];
3009 
3010  mutt_mktemp(tempfile, sizeof(tempfile));
3011  FILE *fp_tmp = mutt_file_fopen(tempfile, "w");
3012  if (fp_tmp)
3013  {
3014  char date[128];
3016 
3017  if (!C_BounceDelivered)
3018  chflags |= CH_WEED_DELIVERED;
3019 
3020  fseeko(fp, e->offset, SEEK_SET);
3021  fprintf(fp_tmp, "Resent-From: %s", resent_from);
3022  fprintf(fp_tmp, "\nResent-%s", mutt_date_make_date(date, sizeof(date)));
3023  char *msgid_str = gen_msgid();
3024  fprintf(fp_tmp, "Resent-Message-ID: %s\n", msgid_str);
3025  FREE(&msgid_str);
3026  fputs("Resent-To: ", fp_tmp);
3027  mutt_write_addrlist(to, fp_tmp, 11, 0);
3028  mutt_copy_header(fp, e, fp_tmp, chflags, NULL);
3029  fputc('\n', fp_tmp);
3030  mutt_file_copy_bytes(fp, fp_tmp, e->content->length);
3031  if (mutt_file_fclose(&fp_tmp) != 0)
3032  {
3033  mutt_perror(tempfile);
3034  unlink(tempfile);
3035  return -1;
3036  }
3037 #ifdef USE_SMTP
3038  if (C_SmtpUrl)
3039  rc = mutt_smtp_send(env_from, to, NULL, NULL, tempfile, e->content->encoding == ENC_8BIT);
3040  else
3041 #endif
3042  rc = mutt_invoke_sendmail(env_from, to, NULL, NULL, tempfile,
3043  e->content->encoding == ENC_8BIT);
3044  }
3045 
3046  return rc;
3047 }
WHERE char * C_SmtpUrl
Config: (smtp) Url of the SMTP server.
Definition: globals.h:149
#define mutt_perror(...)
Definition: logging.h:85
static char * gen_msgid(void)
Generate a unique Message ID.
Definition: sendlib.c:2495
struct Body * content
List of MIME parts.
Definition: email.h:92
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:370
int mutt_copy_header(FILE *fp_in, struct Email *e, FILE *fp_out, CopyHeaderFlags chflags, const char *prefix)
Copy Email header.
Definition: copy.c:391
#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:2760
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:76
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
#define PATH_MAX
Definition: mutt.h:51
#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:237
void mutt_write_addrlist(struct AddressList *al, FILE *fp, int linelen, bool display)
wrapper around mutt_write_address()
Definition: sendlib.c:1766
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:85
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
#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:731
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:584
#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:

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

3058 {
3059  if (!fp || !e || !to || TAILQ_EMPTY(to))
3060  return -1;
3061 
3062  const char *fqdn = mutt_fqdn(true);
3063  char resent_from[256];
3064  char *err = NULL;
3065 
3066  resent_from[0] = '\0';
3067  struct Address *from = mutt_default_from();
3068  struct AddressList from_list = TAILQ_HEAD_INITIALIZER(from_list);
3069  mutt_addrlist_append(&from_list, from);
3070 
3071  /* mutt_default_from() does not use $realname if the real name is not set
3072  * in $from, so we add it here. The reason it is not added in
3073  * mutt_default_from() is that during normal sending, we execute
3074  * send-hooks and set the realname last so that it can be changed based
3075  * upon message criteria. */
3076  if (!from->personal)
3078 
3079  mutt_addrlist_qualify(&from_list, fqdn);
3080 
3081  rfc2047_encode_addrlist(&from_list, "Resent-From");
3082  if (mutt_addrlist_to_intl(&from_list, &err))
3083  {
3084  mutt_error(_("Bad IDN %s while preparing resent-from"), err);
3085  FREE(&err);
3086  mutt_addrlist_clear(&from_list);
3087  return -1;
3088  }
3089  mutt_addrlist_write(resent_from, sizeof(resent_from), &from_list, false);
3090 
3091 #ifdef USE_NNTP
3092  OptNewsSend = false;
3093 #endif
3094 
3095  /* prepare recipient list. idna conversion appears to happen before this
3096  * function is called, since the user receives confirmation of the address
3097  * list being bounced to. */
3098  struct AddressList resent_to = TAILQ_HEAD_INITIALIZER(resent_to);
3099  mutt_addrlist_copy(&resent_to, to, false);
3100  rfc2047_encode_addrlist(&resent_to, "Resent-To");
3101  int rc = bounce_message(fp, e, &resent_to, resent_from, &from_list);
3102  mutt_addrlist_clear(&resent_to);
3103  mutt_addrlist_clear(&from_list);
3104 
3105  return rc;
3106 }
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:3001
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1378
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:724
#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:1134
void rfc2047_encode_addrlist(struct AddressList *al, const char *tag)
Encode any RFC2047 headers, where required, in an Address list.
Definition: rfc2047.c:748
struct Address * mutt_default_from(void)
Get a default &#39;from&#39; Address.
Definition: send.c:1307
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2468
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:637
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1213
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:145
#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:1398

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

3114 {
3115  for (; b; b = b->next)
3116  {
3117  if ((b->type == TYPE_MESSAGE) || (b->type == TYPE_MULTIPART))
3118  set_noconv_flags(b->parts, flag);
3119  else if ((b->type == TYPE_TEXT) && b->noconv)
3120  {
3121  if (flag)
3122  mutt_param_set(&b->parameter, "x-mutt-noconv", "yes");
3123  else
3124  mutt_param_delete(&b->parameter, "x-mutt-noconv");
3125  }
3126  }
3127 }
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:3113
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:

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

3142 {
3143  char fcc_tok[PATH_MAX];
3144  char fcc_expanded[PATH_MAX];
3145 
3146  mutt_str_strfcpy(fcc_tok, path, sizeof(fcc_tok));
3147 
3148  char *tok = strtok(fcc_tok, ",");
3149  if (!tok)
3150  return -1;
3151 
3152  mutt_debug(LL_DEBUG1, "Fcc: initial mailbox = '%s'\n", tok);
3153  /* mutt_expand_path already called above for the first token */
3154  int status = mutt_write_fcc(tok, e, msgid, post, fcc, finalpath);
3155  if (status != 0)
3156  return status;
3157 
3158  while ((tok = strtok(NULL, ",")))
3159  {
3160  if (!*tok)
3161  continue;
3162 
3163  /* Only call mutt_expand_path if tok has some data */
3164  mutt_debug(LL_DEBUG1, "Fcc: additional mailbox token = '%s'\n", tok);
3165  mutt_str_strfcpy(fcc_expanded, tok, sizeof(fcc_expanded));
3166  mutt_expand_path(fcc_expanded, sizeof(fcc_expanded));
3167  mutt_debug(LL_DEBUG1, " Additional mailbox expanded = '%s'\n", fcc_expanded);
3168  status = mutt_write_fcc(fcc_expanded, e, msgid, post, fcc, finalpath);
3169  if (status != 0)
3170  return status;
3171  }
3172 
3173  return 0;
3174 }
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:128
#define PATH_MAX
Definition: mutt.h:51
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
int mutt_write_fcc(const char *path, struct Email *e, const char *msgid, bool post, char *fcc, char **finalpath)
Write email to FCC mailbox.
Definition: sendlib.c:3187

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_write_fcc ( const char *  path,
struct Email e,
const char *  msgid,
bool  post,
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 3187 of file sendlib.c.

3189 {
3190  struct Message *msg = NULL;
3191  char tempfile[PATH_MAX];
3192  FILE *fp_tmp = NULL;
3193  int rc = -1;
3194  bool need_mailbox_cleanup = false;
3195  struct stat st;
3196  char buf[128];
3197  MsgOpenFlags onm_flags;
3198 
3199  if (post)
3200  set_noconv_flags(e->content, true);
3201 
3202 #ifdef RECORD_FOLDER_HOOK
3203  mutt_folder_hook(path, NULL);
3204 #endif
3205  struct Mailbox *m_fcc = mx_path_resolve(path);
3206  bool old_append = m_fcc->append;
3207  struct Context *ctx_fcc = mx_mbox_open(m_fcc, MUTT_APPEND | MUTT_QUIET);
3208  if (!ctx_fcc)
3209  {
3210  mutt_debug(LL_DEBUG1, "unable to open mailbox %s in append-mode, aborting\n", path);
3211  mailbox_free(&m_fcc);
3212  goto done;
3213  }
3214 
3215  /* We need to add a Content-Length field to avoid problems where a line in
3216  * the message body begins with "From " */
3217  if ((ctx_fcc->mailbox->magic == MUTT_MMDF) || (ctx_fcc->mailbox->magic == MUTT_MBOX))
3218  {
3219  mutt_mktemp(tempfile, sizeof(tempfile));
3220  fp_tmp = mutt_file_fopen(tempfile, "w+");
3221  if (!fp_tmp)
3222  {
3223  mutt_perror(tempfile);
3224  mx_mbox_close(&ctx_fcc);
3225  goto done;
3226  }
3227  /* remember new mail status before appending message */
3228  need_mailbox_cleanup = true;
3229  stat(path, &st);
3230  }
3231 
3232  e->read = !post; /* make sure to put it in the 'cur' directory (maildir) */
3233  onm_flags = MUTT_ADD_FROM;
3234  if (post)
3235  onm_flags |= MUTT_SET_DRAFT;
3236  msg = mx_msg_open_new(ctx_fcc->mailbox, e, onm_flags);
3237  if (!msg)
3238  {
3239  mutt_file_fclose(&fp_tmp);
3240  mx_mbox_close(&ctx_fcc);
3241  goto done;
3242  }
3243 
3244  /* post == 1 => postpone message.
3245  * post == 0 => Normal mode. */
3249 
3250  /* (postponement) if this was a reply of some sort, <msgid> contains the
3251  * Message-ID: of message replied to. Save it using a special X-Mutt-
3252  * header so it can be picked up if the message is recalled at a later
3253  * point in time. This will allow the message to be marked as replied if
3254  * the same mailbox is still open. */
3255  if (post && msgid)
3256  fprintf(msg->fp, "X-Mutt-References: %s\n", msgid);
3257 
3258  /* (postponement) save the Fcc: using a special X-Mutt- header so that
3259  * it can be picked up when the message is recalled */
3260  if (post && fcc)
3261  fprintf(msg->fp, "X-Mutt-Fcc: %s\n", fcc);
3262 
3263  if ((ctx_fcc->mailbox->magic == MUTT_MMDF) || (ctx_fcc->mailbox->magic == MUTT_MBOX))
3264  fprintf(msg->fp, "Status: RO\n");
3265 
3266  /* mutt_rfc822_write_header() only writes out a Date: header with
3267  * mode == 0, i.e. _not_ postponement; so write out one ourself */
3268  if (post)
3269  fprintf(msg->fp, "%s", mutt_date_make_date(buf, sizeof(buf)));
3270 
3271  /* (postponement) if the mail is to be signed or encrypted, save this info */
3272  if (((WithCrypto & APPLICATION_PGP) != 0) && post && (e->security & APPLICATION_PGP))
3273  {
3274  fputs("X-Mutt-PGP: ", msg->fp);
3275  if (e->security & SEC_ENCRYPT)
3276  fputc('E', msg->fp);
3277  if (e->security & SEC_OPPENCRYPT)
3278  fputc('O', msg->fp);
3279  if (e->security & SEC_SIGN)
3280  {
3281  fputc('S', msg->fp);
3282  if (C_PgpSignAs)
3283  fprintf(msg->fp, "<%s>", C_PgpSignAs);
3284  }
3285  if (e->security & SEC_INLINE)
3286  fputc('I', msg->fp);
3287 #ifdef USE_AUTOCRYPT
3288  if (e->security & SEC_AUTOCRYPT)
3289  fputc('A', msg->fp);
3291  fputc('Z', msg->fp);
3292 #endif
3293  fputc('\n', msg->fp);
3294  }
3295 
3296  /* (postponement) if the mail is to be signed or encrypted, save this info */
3297  if (((WithCrypto & APPLICATION_SMIME) != 0) && post && (e->security & APPLICATION_SMIME))
3298  {
3299  fputs("X-Mutt-SMIME: ", msg->fp);
3300  if (e->security & SEC_ENCRYPT)
3301  {
3302  fputc('E', msg->fp);
3303  if (C_SmimeEncryptWith)
3304  fprintf(msg->fp, "C<%s>", C_SmimeEncryptWith);
3305  }
3306  if (e->security & SEC_OPPENCRYPT)
3307  fputc('O', msg->fp);
3308  if (e->security & SEC_SIGN)
3309  {
3310  fputc('S', msg->fp);
3311  if (C_SmimeSignAs)
3312  fprintf(msg->fp, "<%s>", C_SmimeSignAs);
3313  }
3314  if (e->security & SEC_INLINE)
3315  fputc('I', msg->fp);
3316  fputc('\n', msg->fp);
3317  }
3318 
3319 #ifdef MIXMASTER
3320  /* (postponement) if the mail is to be sent through a mixmaster
3321  * chain, save that information */
3322 
3323  if (post && !STAILQ_EMPTY(&e->chain))
3324  {
3325  fputs("X-Mutt-Mix:", msg->fp);
3326  struct ListNode *p = NULL;
3327  STAILQ_FOREACH(p, &e->chain, entries)
3328  {
3329  fprintf(msg->fp, " %s", (char *) p->data);
3330  }
3331 
3332  fputc('\n', msg->fp);
3333  }
3334 #endif
3335 
3336  if (fp_tmp)
3337  {
3338  mutt_write_mime_body(e->content, fp_tmp);
3339 
3340  /* make sure the last line ends with a newline. Emacs doesn't ensure this
3341  * will happen, and it can cause problems parsing the mailbox later. */
3342  fseek(fp_tmp, -1, SEEK_END);
3343  if (fgetc(fp_tmp) != '\n')
3344  {
3345  fseek(fp_tmp, 0, SEEK_END);
3346  fputc('\n', fp_tmp);
3347  }
3348 
3349  fflush(fp_tmp);
3350  if (ferror(fp_tmp))
3351  {
3352  mutt_debug(LL_DEBUG1, "%s: write failed\n", tempfile);
3353  mutt_file_fclose(&fp_tmp);
3354  unlink(tempfile);
3355  mx_msg_commit(ctx_fcc->mailbox, msg); /* XXX really? */
3356  mx_msg_close(ctx_fcc->mailbox, &msg);
3357  mx_mbox_close(&ctx_fcc);
3358  goto done;
3359  }
3360 
3361  /* count the number of lines */
3362  int lines = 0;
3363  char line_buf[1024];
3364  rewind(fp_tmp);
3365  while (fgets(line_buf, sizeof(line_buf), fp_tmp))
3366  lines++;
3367  fprintf(msg->fp, "Content-Length: " OFF_T_FMT "\n", (LOFF_T) ftello(fp_tmp));
3368  fprintf(msg->fp, "Lines: %d\n\n", lines);
3369 
3370  /* copy the body and clean up */
3371  rewind(fp_tmp);
3372  rc = mutt_file_copy_stream(fp_tmp, msg->fp);
3373  if (fclose(fp_tmp) != 0)
3374  rc = -1;
3375  /* if there was an error, leave the temp version */
3376  if (rc == 0)
3377  unlink(tempfile);
3378  }
3379  else
3380  {
3381  fputc('\n', msg->fp); /* finish off the header */
3382  rc = mutt_write_mime_body(e->content, msg->fp);
3383  }
3384 
3385  if (mx_msg_commit(ctx_fcc->mailbox, msg) != 0)
3386  rc = -1;
3387  else if (finalpath)
3388  *finalpath = mutt_str_strdup(msg->committed_path);
3389  mx_msg_close(ctx_fcc->mailbox, &msg);
3390  mx_mbox_close(&ctx_fcc);
3391 
3392  if (!post && need_mailbox_cleanup)
3393  mutt_mailbox_cleanup(path, &st);
3394 
3395  if (post)
3396  set_noconv_flags(e->content, false);
3397 
3398 done:
3399  m_fcc->append = old_append;
3400 #ifdef RECORD_FOLDER_HOOK
3401  /* We ran a folder hook for the destination mailbox,
3402  * now we run it for the user's current mailbox */
3403  if (Context && Context->mailbox->path)
3405 #endif
3406 
3407  return rc;
3408 }
#define MUTT_APPEND
Open mailbox for appending messages.
Definition: mx.h:52
The "current" mailbox.
Definition: context.h:36
#define SEC_AUTOCRYPT
Message will be, or was Autocrypt encrypt+signed.
Definition: ncrypt.h:131
#define mutt_perror(...)
Definition: logging.h:85
int mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:558
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
struct Body * content
List of MIME parts.
Definition: email.h:92
A postponed Email, just the envelope info.
Definition: sendlib.h:61
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:254
#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:370
#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:2238
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1089
void mutt_folder_hook(const char *path, const char *desc)
Perform a folder hook.
Definition: hook.c:516
bool read
Email is read.
Definition: email.h:53
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:149
struct Envelope * env
Envelope information.
Definition: email.h:91
struct Message * mx_msg_open_new(struct Mailbox *m, struct Email *e, MsgOpenFlags flags)
Open a new message.
Definition: mx.c:958
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:76
#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
#define PATH_MAX
Definition: mutt.h:51
int mutt_write_mime_body(struct Body *a, FILE *fp)
Write a MIME part.
Definition: sendlib.c:521
WHERE char * C_SmimeEncryptWith
Config: Algorithm for encryption.
Definition: globals.h:177
&#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:41
WHERE bool C_CryptProtectedHeadersRead
Config: Display protected headers (Memory Hole) in the pager.
Definition: globals.h:285
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
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:267
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:1068
FILE * fp
pointer to the message data
Definition: mx.h:83
struct Mailbox * mx_path_resolve(const char *path)
XXX.
Definition: mx.c:1541
static void set_noconv_flags(struct Body *b, bool flag)
Set/reset the "x-mutt-noconv" flag.
Definition: sendlib.c:3113
#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:172
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:584
WHERE char * C_SmimeSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:176
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

bool C_Allow8bit

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

Definition at line 82 of file sendlib.c.

char* C_AttachCharset

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

Definition at line 83 of file sendlib.c.

bool C_BounceDelivered

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

Definition at line 84 of file sendlib.c.

bool C_EncodeFrom

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

Definition at line 85 of file sendlib.c.

bool C_ForwardDecrypt

Config: Decrypt the message when forwarding it.

Definition at line 86 of file sendlib.c.

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.

char* C_Inews

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

Definition at line 88 of file sendlib.c.

bool C_MimeForwardDecode

Config: Decode the forwarded message before attaching it.

Definition at line 89 of file sendlib.c.

bool C_MimeSubject

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

encode subject line with RFC2047

Definition at line 90 of file sendlib.c.

char* C_MimeTypeQueryCommand

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

Definition at line 91 of file sendlib.c.

bool C_MimeTypeQueryFirst

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

Definition at line 92 of file sendlib.c.

char* C_Sendmail

Config: External command to send email.

Definition at line 93 of file sendlib.c.

short C_SendmailWait

Config: Time to wait for sendmail to finish.

Definition at line 94 of file sendlib.c.

bool C_Use8bitmime

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

Definition at line 95 of file sendlib.c.

bool C_UseEnvelopeFrom

Config: Set the envelope sender of the message.

Definition at line 96 of file sendlib.c.

bool C_UserAgent

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

Definition at line 97 of file sendlib.c.

short C_WrapHeaders

Config: Width to wrap headers in outgoing messages.

Definition at line 98 of file sendlib.c.