NeoMutt  2018-07-16 +1783-b00bd9
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 "config/lib.h"
#include "email/lib.h"
#include "mutt.h"
#include "sendlib.h"
#include "context.h"
#include "copy.h"
#include "curs_lib.h"
#include "filter.h"
#include "globals.h"
#include "handler.h"
#include "hook.h"
#include "mailbox.h"
#include "mutt_parse.h"
#include "mutt_window.h"
#include "muttlib.h"
#include "mx.h"
#include "ncrypt/ncrypt.h"
#include "options.h"
#include "send.h"
#include "smtp.h"
#include "state.h"
#include "nntp/nntp.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 *parm)
 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, const char **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...
 
int 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_address_list (struct Address *addr, 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 (char **args, size_t *argslen, size_t *argsmax, struct Address *addr)
 Add an Address 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 Address *from, struct Address *to, struct Address *cc, struct Address *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 Address *to, const char *resent_from, struct Address *env_from)
 Bounce an email message. More...
 
int mutt_bounce_message (FILE *fp, struct Email *e, struct Address *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

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

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

245 {
246  memset(bctx->buffer, '\0', sizeof(bctx->buffer));
247  bctx->size = 0;
248  bctx->linelen = 0;
249 
250  return 0;
251 }
char buffer[3]
Definition: sendlib.c:234
short size
Definition: sendlib.c:235
short linelen
Definition: sendlib.c:236

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

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

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

294 {
295  if (bctx->size == 3)
296  b64_flush(bctx, fp_out);
297 
298  bctx->buffer[bctx->size++] = c;
299 }
char buffer[3]
Definition: sendlib.c:234
short size
Definition: sendlib.c:235
static void b64_flush(struct B64Context *bctx, FILE *fp_out)
Save the bytes to the file.
Definition: sendlib.c:258

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

308 {
309  struct B64Context bctx;
310  int ch, ch1 = EOF;
311 
312  b64_init(&bctx);
313 
314  while ((ch = mutt_ch_fgetconv(fc)) != EOF)
315  {
316  if (SigInt == 1)
317  {
318  SigInt = 0;
319  return;
320  }
321  if (istext && (ch == '\n') && (ch1 != '\r'))
322  b64_putc(&bctx, '\r', fp_out);
323  b64_putc(&bctx, ch, fp_out);
324  ch1 = ch;
325  }
326  b64_flush(&bctx, fp_out);
327  fputc('\n', fp_out);
328 }
static void b64_putc(struct B64Context *bctx, char c, FILE *fp_out)
Base64-encode one character.
Definition: sendlib.c:293
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:244
static void b64_flush(struct B64Context *bctx, FILE *fp_out)
Save the bytes to the file.
Definition: sendlib.c:258
Cursor for the Base64 conversion.
Definition: sendlib.c:232

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

336 {
337  int ch;
338 
339  while ((ch = mutt_ch_fgetconv(fc)) != EOF)
340  {
341  if (SigInt == 1)
342  {
343  SigInt = 0;
344  return;
345  }
346  fputc(ch, fp_out);
347  }
348 }
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 357 of file sendlib.c.

358 {
359  int len;
360  int tmplen;
361  char buf[256] = { 0 };
362 
363  fprintf(fp, "Content-Type: %s/%s", TYPE(a), a->subtype);
364 
365  if (!TAILQ_EMPTY(&a->parameter))
366  {
367  len = 25 + mutt_str_strlen(a->subtype); /* approximate len. of content-type */
368 
369  struct Parameter *np = NULL;
370  TAILQ_FOREACH(np, &a->parameter, entries)
371  {
372  if (!np->value)
373  continue;
374 
375  struct ParameterList param_conts = rfc2231_encode_string(np->attribute, np->value);
376  struct Parameter *cont = NULL;
377  TAILQ_FOREACH(cont, &param_conts, entries)
378  {
379  fputc(';', fp);
380 
381  buf[0] = 0;
382  mutt_addr_cat(buf, sizeof(buf), cont->value, MimeSpecials);
383 
384  /* Dirty hack to make messages readable by Outlook Express
385  * for the Mac: force quotes around the boundary parameter
386  * even when they aren't needed.
387  */
388  if (!mutt_str_strcasecmp(cont->attribute, "boundary") &&
389  !mutt_str_strcmp(buf, cont->value))
390  snprintf(buf, sizeof(buf), "\"%s\"", cont->value);
391 
392  tmplen = mutt_str_strlen(buf) + mutt_str_strlen(cont->attribute) + 1;
393  if (len + tmplen + 2 > 76)
394  {
395  fputs("\n\t", fp);
396  len = tmplen + 1;
397  }
398  else
399  {
400  fputc(' ', fp);
401  len += tmplen + 1;
402  }
403 
404  fprintf(fp, "%s=%s", cont->attribute, buf);
405  }
406 
407  mutt_param_free(&param_conts);
408  }
409  }
410 
411  fputc('\n', fp);
412 
413  if (a->language)
414  fprintf(fp, "Content-Language: %s\n", a->language);
415 
416  if (a->description)
417  fprintf(fp, "Content-Description: %s\n", a->description);
418 
419  if (a->disposition != DISP_NONE)
420  {
421  const char *dispstr[] = { "inline", "attachment", "form-data" };
422 
423  if (a->disposition < sizeof(dispstr) / sizeof(char *))
424  {
425  fprintf(fp, "Content-Disposition: %s", dispstr[a->disposition]);
426  len = 21 + mutt_str_strlen(dispstr[a->disposition]);
427 
428  if (a->use_disp && (a->disposition != DISP_INLINE))
429  {
430  char *fn = a->d_filename;
431  if (!fn)
432  fn = a->filename;
433 
434  if (fn)
435  {
436  /* Strip off the leading path... */
437  char *t = strrchr(fn, '/');
438  if (t)
439  t++;
440  else
441  t = fn;
442 
443  struct ParameterList param_conts = rfc2231_encode_string("filename", t);
444  struct Parameter *cont = NULL;
445  TAILQ_FOREACH(cont, &param_conts, entries)
446  {
447  fputc(';', fp);
448  buf[0] = 0;
449  mutt_addr_cat(buf, sizeof(buf), cont->value, MimeSpecials);
450 
451  tmplen = mutt_str_strlen(buf) + mutt_str_strlen(cont->attribute) + 1;
452  if (len + tmplen + 2 > 76)
453  {
454  fputs("\n\t", fp);
455  len = tmplen + 1;
456  }
457  else
458  {
459  fputc(' ', fp);
460  len += tmplen + 1;
461  }
462 
463  fprintf(fp, "%s=%s", cont->attribute, buf);
464  }
465 
466  mutt_param_free(&param_conts);
467  }
468  }
469 
470  fputc('\n', fp);
471  }
472  else
473  {
474  mutt_debug(LL_DEBUG1, "ERROR: invalid content-disposition %d\n", a->disposition);
475  }
476  }
477 
478  if (a->encoding != ENC_7BIT)
479  fprintf(fp, "Content-Transfer-Encoding: %s\n", ENCODING(a->encoding));
480 
482  mutt_rfc822_write_header(fp, a->mime_headers, NULL, MUTT_WRITE_HEADER_MIME, false, false);
483 
484  /* Do NOT add the terminator here!!! */
485  return ferror(fp) ? -1 : 0;
486 }
char * attribute
Definition: parameter.h:34
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:48
struct Envelope * mime_headers
memory hole protected headers
Definition: body.h:70
#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:270
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:669
unsigned int disposition
content-disposition
Definition: body.h:74
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:2233
#define ENCODING(x)
Definition: mime.h:85
unsigned int encoding
content-transfer-encoding
Definition: body.h:73
char * subtype
content-type subtype
Definition: body.h:37
void mutt_param_free(struct ParameterList *p)
Free a ParameterList.
Definition: parameter.c:61
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
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:75
struct ParameterList rfc2231_encode_string(const char *attribute, char *value)
Encode a string to be suitable for an RFC2231 header.
Definition: rfc2231.c:324
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:631
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:50
#define mutt_debug(LEVEL,...)
Definition: logging.h:80
Write protected headers.
Definition: sendlib.h:65
#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:618
void mutt_addr_cat(char *buf, size_t buflen, const char *value, const char *specials)
Copy a string and escape the specified characters.
Definition: address.c:695

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

494 {
495  return mutt_is_text_part(b) ||
497 }
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:524
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
Definition: muttlib.c:437
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:129
#define WithCrypto
Definition: ncrypt.h:155

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

507 {
508  FILE *fp_in = NULL;
509  struct FgetConv *fc = NULL;
510 
511  if (a->type == TYPE_MULTIPART)
512  {
513  /* First, find the boundary to use */
514  const char *p = mutt_param_get(&a->parameter, "boundary");
515  if (!p)
516  {
517  mutt_debug(LL_DEBUG1, "no boundary parameter found\n");
518  mutt_error(_("No boundary parameter found [report this error]"));
519  return -1;
520  }
521  char boundary[128];
522  mutt_str_strfcpy(boundary, p, sizeof(boundary));
523 
524  for (struct Body *t = a->parts; t; t = t->next)
525  {
526  fprintf(fp, "\n--%s\n", boundary);
527  if (mutt_write_mime_header(t, fp) == -1)
528  return -1;
529  fputc('\n', fp);
530  if (mutt_write_mime_body(t, fp) == -1)
531  return -1;
532  }
533  fprintf(fp, "\n--%s--\n", boundary);
534  return ferror(fp) ? -1 : 0;
535  }
536 
537  /* This is pretty gross, but it's the best solution for now... */
538  if (((WithCrypto & APPLICATION_PGP) != 0) && (a->type == TYPE_APPLICATION) &&
539  (mutt_str_strcmp(a->subtype, "pgp-encrypted") == 0))
540  {
541  fputs("Version: 1\n", fp);
542  return 0;
543  }
544 
545  fp_in = fopen(a->filename, "r");
546  if (!fp_in)
547  {
548  mutt_debug(LL_DEBUG1, "%s no longer exists\n", a->filename);
549  mutt_error(_("%s no longer exists"), a->filename);
550  return -1;
551  }
552 
553  if ((a->type == TYPE_TEXT) && (!a->noconv))
554  {
555  char send_charset[128];
557  fp_in, a->charset,
558  mutt_body_get_charset(a, send_charset, sizeof(send_charset)), 0);
559  }
560  else
561  fc = mutt_ch_fgetconv_open(fp_in, 0, 0, 0);
562 
564  if (a->encoding == ENC_QUOTED_PRINTABLE)
566  else if (a->encoding == ENC_BASE64)
568  else if ((a->type == TYPE_TEXT) && (!a->noconv))
569  encode_8bit(fc, fp);
570  else
571  mutt_file_copy_stream(fp_in, fp);
573 
575  mutt_file_fclose(&fp_in);
576 
577  if (SigInt == 1)
578  {
579  SigInt = 0;
580  return -1;
581  }
582  return ferror(fp) ? -1 : 0;
583 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:48
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:307
bool noconv
don&#39;t do character set conversion
Definition: body.h:82
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:60
static bool write_as_text_part(struct Body *b)
Should the Body be written as a text MIME part.
Definition: sendlib.c:493
void mutt_sig_allow_interrupt(bool allow)
Allow/disallow Ctrl-C (SIGINT)
Definition: signal.c:230
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:73
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:101
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:506
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:61
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:753
char * charset
send mode: charset of attached file as stored on disk.
Definition: body.h:53
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body&#39;s character set.
Definition: sendlib.c:1423
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:335
unsigned int type
content-type primary type
Definition: body.h:72
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:129
void mutt_ch_fgetconv_close(struct FgetConv **fc)
Close an fgetconv handle.
Definition: charset.c:857
char * mutt_param_get(const struct ParameterList *p, const char *s)
Find a matching Parameter.
Definition: parameter.c:83
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:264
#define mutt_error(...)
Definition: logging.h:83
Quoted-printable text.
Definition: mime.h:51
int mutt_write_mime_header(struct Body *a, FILE *fp)
Create a MIME header.
Definition: sendlib.c:357
#define mutt_debug(LEVEL,...)
Definition: logging.h:80
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:155
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:618
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 *  parm)

Create a unique boundary id for a MIME part.

Parameters
parmMIME part

Definition at line 589 of file sendlib.c.

590 {
591  char rs[MUTT_RANDTAG_LEN + 1];
592 
593  mutt_rand_base32(rs, sizeof(rs) - 1);
594  rs[MUTT_RANDTAG_LEN] = 0;
595  mutt_param_set(parm, "boundary", rs);
596 }
#define MUTT_RANDTAG_LEN
Definition: muttlib.h:43
void mutt_param_set(struct ParameterList *p, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:109
void mutt_rand_base32(void *buf, size_t buflen)
Fill a buffer with a base32-encoded random string.
Definition: muttlib.c:517

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

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

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

921 {
922  char *fcode = NULL;
923  char **tcode = NULL;
924  const char *c = NULL, *c1 = NULL;
925  size_t ret;
926  int ncodes, i, cn;
927 
928  /* Count the tocodes */
929  ncodes = 0;
930  for (c = tocodes; c; c = c1 ? c1 + 1 : 0)
931  {
932  c1 = strchr(c, ':');
933  if (c1 == c)
934  continue;
935  ncodes++;
936  }
937 
938  /* Copy them */
939  tcode = mutt_mem_malloc(ncodes * sizeof(char *));
940  for (c = tocodes, i = 0; c; c = c1 ? c1 + 1 : 0, i++)
941  {
942  c1 = strchr(c, ':');
943  if (c1 == c)
944  continue;
945  tcode[i] = mutt_str_substr_dup(c, c1);
946  }
947 
948  ret = (size_t)(-1);
949  if (fromcode)
950  {
951  /* Try each fromcode in turn */
952  for (c = fromcodes; c; c = c1 ? c1 + 1 : 0)
953  {
954  c1 = strchr(c, ':');
955  if (c1 == c)
956  continue;
957  fcode = mutt_str_substr_dup(c, c1);
958 
959  ret = convert_file_to(fp, fcode, ncodes, (const char **) tcode, &cn, info);
960  if (ret != (size_t)(-1))
961  {
962  *fromcode = fcode;
963  *tocode = tcode[cn];
964  tcode[cn] = 0;
965  break;
966  }
967  FREE(&fcode);
968  }
969  }
970  else
971  {
972  /* There is only one fromcode */
973  ret = convert_file_to(fp, fromcodes, ncodes, (const char **) tcode, &cn, info);
974  if (ret != (size_t)(-1))
975  {
976  *tocode = tcode[cn];
977  tcode[cn] = 0;
978  }
979  }
980 
981  /* Free memory */
982  for (i = 0; i < ncodes; i++)
983  FREE(&tcode[i]);
984 
985  FREE(&tcode);
986 
987  return ret;
988 }
static size_t convert_file_to(FILE *fp, const char *fromcode, int ncodes, const char **tocodes, int *tocode, struct Content *info)
Change the encoding of a file.
Definition: sendlib.c:766
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:97
#define FREE(x)
Definition: memory.h:40
char * mutt_str_substr_dup(const char *begin, const char *end)
Duplicate a sub-string.
Definition: string.c:582

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

999 {
1000  struct Content *info = NULL;
1001  struct ContentState state = { 0 };
1002  FILE *fp = NULL;
1003  char *fromcode = NULL;
1004  char *tocode = NULL;
1005  char buf[100];
1006  size_t r;
1007 
1008  struct stat sb;
1009 
1010  if (b && !fname)
1011  fname = b->filename;
1012 
1013  if (stat(fname, &sb) == -1)
1014  {
1015  mutt_error(_("Can't stat %s: %s"), fname, strerror(errno));
1016  return NULL;
1017  }
1018 
1019  if (!S_ISREG(sb.st_mode))
1020  {
1021  mutt_error(_("%s isn't a regular file"), fname);
1022  return NULL;
1023  }
1024 
1025  fp = fopen(fname, "r");
1026  if (!fp)
1027  {
1028  mutt_debug(LL_DEBUG1, "%s: %s (errno %d)\n", fname, strerror(errno), errno);
1029  return NULL;
1030  }
1031 
1032  info = mutt_mem_calloc(1, sizeof(struct Content));
1033 
1034  if (b && (b->type == TYPE_TEXT) && (!b->noconv && !b->force_charset))
1035  {
1036  char *chs = mutt_param_get(&b->parameter, "charset");
1037  char *fchs = b->use_disp ?
1039  C_Charset;
1040  if (C_Charset && (chs || C_SendCharset) &&
1041  (convert_file_from_to(fp, fchs, chs ? chs : C_SendCharset, &fromcode,
1042  &tocode, info) != (size_t)(-1)))
1043  {
1044  if (!chs)
1045  {
1046  char chsbuf[256];
1047  mutt_ch_canonical_charset(chsbuf, sizeof(chsbuf), tocode);
1048  mutt_param_set(&b->parameter, "charset", chsbuf);
1049  }
1050  FREE(&b->charset);
1051  b->charset = fromcode;
1052  FREE(&tocode);
1053  mutt_file_fclose(&fp);
1054  return info;
1055  }
1056  }
1057 
1058  rewind(fp);
1059  while ((r = fread(buf, 1, sizeof(buf), fp)))
1060  update_content_info(info, &state, buf, r);
1061  update_content_info(info, &state, 0, 0);
1062 
1063  mutt_file_fclose(&fp);
1064 
1065  if (b && (b->type == TYPE_TEXT) && (!b->noconv && !b->force_charset))
1066  {
1067  mutt_param_set(&b->parameter, "charset",
1068  (!info->hibin ?
1069  "us-ascii" :
1070  C_Charset && !mutt_ch_is_us_ascii(C_Charset) ? C_Charset : "unknown-8bit"));
1071  }
1072 
1073  return info;
1074 }
Info about the body of an email.
Definition: sendlib.c:601
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:617
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:48
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:51
bool noconv
don&#39;t do character set conversion
Definition: body.h:82
#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:83
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:78
void mutt_param_set(struct ParameterList *p, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:109
char * charset
send mode: charset of attached file as stored on disk.
Definition: body.h:53
unsigned int type
content-type primary type
Definition: body.h:72
char * mutt_param_get(const struct ParameterList *p, const char *s)
Find a matching Parameter.
Definition: parameter.c:83
Log at debug level 1.
Definition: logging.h:56
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:75
#define mutt_error(...)
Definition: logging.h:83
#define FREE(x)
Definition: memory.h:40
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:54
#define mutt_debug(LEVEL,...)
Definition: logging.h:80
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
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:919

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1089 {
1090  FILE *fp = NULL;
1091  char *p = NULL, *q = NULL, *ct = NULL;
1092  char buf[PATH_MAX];
1093  char subtype[256], xtype[256];
1094  int szf, sze, cur_sze;
1095  int type;
1096  bool found_mimetypes = false;
1097 
1098  *subtype = '\0';
1099  *xtype = '\0';
1100  type = TYPE_OTHER;
1101  cur_sze = 0;
1102 
1103  szf = mutt_str_strlen(path);
1104 
1105  for (int count = 0; count < 4; count++)
1106  {
1107  /* can't use strtok() because we use it in an inner loop below, so use
1108  * a switch statement here instead. */
1109  switch (count)
1110  {
1111  /* last file with last entry to match wins type/xtype */
1112  case 0:
1113  /* check default unix mimetypes location first */
1114  mutt_str_strfcpy(buf, "/etc/mime.types", sizeof(buf));
1115  break;
1116  case 1:
1117  mutt_str_strfcpy(buf, SYSCONFDIR "/mime.types", sizeof(buf));
1118  break;
1119  case 2:
1120  mutt_str_strfcpy(buf, PKGDATADIR "/mime.types", sizeof(buf));
1121  break;
1122  case 3:
1123  snprintf(buf, sizeof(buf), "%s/.mime.types", NONULL(HomeDir));
1124  break;
1125  default:
1126  mutt_debug(LL_DEBUG1, "Internal error, count = %d\n", count);
1127  goto bye; /* shouldn't happen */
1128  }
1129 
1130  fp = fopen(buf, "r");
1131  if (fp)
1132  {
1133  found_mimetypes = true;
1134 
1135  while (fgets(buf, sizeof(buf) - 1, fp))
1136  {
1137  /* weed out any comments */
1138  p = strchr(buf, '#');
1139  if (p)
1140  *p = '\0';
1141 
1142  /* remove any leading space. */
1143  ct = buf;
1144  SKIPWS(ct);
1145 
1146  /* position on the next field in this line */
1147  p = strpbrk(ct, " \t");
1148  if (!p)
1149  continue;
1150  *p++ = 0;
1151  SKIPWS(p);
1152 
1153  /* cycle through the file extensions */
1154  while ((p = strtok(p, " \t\n")))
1155  {
1156  sze = mutt_str_strlen(p);
1157  if ((sze > cur_sze) && (szf >= sze) &&
1158  ((mutt_str_strcasecmp(path + szf - sze, p) == 0) ||
1159  (mutt_str_strcasecmp(path + szf - sze, p) == 0)) &&
1160  ((szf == sze) || (path[szf - sze - 1] == '.')))
1161  {
1162  /* get the content-type */
1163 
1164  p = strchr(ct, '/');
1165  if (!p)
1166  {
1167  /* malformed line, just skip it. */
1168  break;
1169  }
1170  *p++ = 0;
1171 
1172  for (q = p; *q && !IS_SPACE(*q); q++)
1173  ;
1174 
1175  mutt_str_substr_cpy(subtype, p, q, sizeof(subtype));
1176 
1177  type = mutt_check_mime_type(ct);
1178  if (type == TYPE_OTHER)
1179  mutt_str_strfcpy(xtype, ct, sizeof(xtype));
1180 
1181  cur_sze = sze;
1182  }
1183  p = NULL;
1184  }
1185  }
1186  mutt_file_fclose(&fp);
1187  }
1188  }
1189 
1190 bye:
1191 
1192  /* no mime.types file found */
1193  if (!found_mimetypes)
1194  {
1195  mutt_error(_("Could not find any mime.types file."));
1196  }
1197 
1198  if ((type != TYPE_OTHER) || (*xtype != '\0'))
1199  {
1200  att->type = type;
1201  mutt_str_replace(&att->subtype, subtype);
1202  mutt_str_replace(&att->xtype, xtype);
1203  }
1204 
1205  return type;
1206 }
Unknown Content-Type.
Definition: mime.h:31
#define NONULL(x)
Definition: string2.h:36
#define _(a)
Definition: message.h:28
char * mutt_str_substr_cpy(char *dest, const char *begin, const char *end, size_t destlen)
Copy a sub-string into a buffer.
Definition: string.c:559
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:669
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:46
char * subtype
content-type subtype
Definition: body.h:37
#define PATH_MAX
Definition: mutt.h:49
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:753
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:456
unsigned int type
content-type primary type
Definition: body.h:72
#define IS_SPACE(ch)
Definition: string2.h:37
Log at debug level 1.
Definition: logging.h:56
#define mutt_error(...)
Definition: logging.h:83
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:631
int mutt_check_mime_type(const char *s)
Check a MIME type string.
Definition: parse.c:287
#define mutt_debug(LEVEL,...)
Definition: logging.h:80

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

1214 {
1215  char buf[PATH_MAX];
1216  struct State s = { 0 };
1217  struct stat sb;
1218 
1219  for (; a; a = a->next)
1220  {
1221  if (a->type == TYPE_MULTIPART)
1222  {
1223  if (a->encoding != ENC_7BIT)
1224  a->encoding = ENC_7BIT;
1225 
1226  transform_to_7bit(a->parts, fp_in);
1227  }
1228  else if (mutt_is_message_type(a->type, a->subtype))
1229  {
1230  mutt_message_to_7bit(a, fp_in);
1231  }
1232  else
1233  {
1234  a->noconv = true;
1235  a->force_charset = true;
1236 
1237  mutt_mktemp(buf, sizeof(buf));
1238  s.fp_out = mutt_file_fopen(buf, "w");
1239  if (!s.fp_out)
1240  {
1241  mutt_perror("fopen");
1242  return;
1243  }
1244  s.fp_in = fp_in;
1245  mutt_decode_attachment(a, &s);
1247  FREE(&a->d_filename);
1248  a->d_filename = a->filename;
1249  a->filename = mutt_str_strdup(buf);
1250  a->unlink = true;
1251  if (stat(a->filename, &sb) == -1)
1252  {
1253  mutt_perror("stat");
1254  return;
1255  }
1256  a->length = sb.st_size;
1257 
1259  if (a->encoding == ENC_8BIT)
1261  else if (a->encoding == ENC_BINARY)
1262  a->encoding = ENC_BASE64;
1263  }
1264  }
1265 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1789
void mutt_message_to_7bit(struct Body *a, FILE *fp)
Convert an email&#39;s MIME parts to 7-bit.
Definition: sendlib.c:1272
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:48
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1260
#define mutt_perror(...)
Definition: logging.h:84
7-bit text
Definition: mime.h:49
bool noconv
don&#39;t do character set conversion
Definition: body.h:82
struct Body * next
next attachment in the list
Definition: body.h:60
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:1213
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:1447
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:83
unsigned int encoding
content-transfer-encoding
Definition: body.h:73
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:74
LOFF_T length
length (in bytes) of attachment
Definition: body.h:47
#define PATH_MAX
Definition: mutt.h:49
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:61
unsigned int type
content-type primary type
Definition: body.h:72
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
flag to indicate the file named by "filename" should be unlink()ed before free()ing this structure ...
Definition: body.h:76
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:50
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:578

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

1273 {
1274  char temp[PATH_MAX];
1275  char *line = NULL;
1276  FILE *fp_in = NULL;
1277  FILE *fp_out = NULL;
1278  struct stat sb;
1279 
1280  if (!a->filename && fp)
1281  fp_in = fp;
1282  else if (!a->filename || !(fp_in = fopen(a->filename, "r")))
1283  {
1284  mutt_error(_("Could not open %s"), a->filename ? a->filename : "(null)");
1285  return;
1286  }
1287  else
1288  {
1289  a->offset = 0;
1290  if (stat(a->filename, &sb) == -1)
1291  {
1292  mutt_perror("stat");
1293  mutt_file_fclose(&fp_in);
1294  }
1295  a->length = sb.st_size;
1296  }
1297 
1298  mutt_mktemp(temp, sizeof(temp));
1299  fp_out = mutt_file_fopen(temp, "w+");
1300  if (!fp_out)
1301  {
1302  mutt_perror("fopen");
1303  goto cleanup;
1304  }
1305 
1306  if (!fp_in)
1307  goto cleanup;
1308 
1309  fseeko(fp_in, a->offset, SEEK_SET);
1310  a->parts = mutt_rfc822_parse_message(fp_in, a);
1311 
1312  transform_to_7bit(a->parts, fp_in);
1313 
1314  mutt_copy_hdr(fp_in, fp_out, a->offset, a->offset + a->length,
1315  CH_MIME | CH_NONEWLINE | CH_XMIT, NULL);
1316 
1317  fputs("MIME-Version: 1.0\n", fp_out);
1318  mutt_write_mime_header(a->parts, fp_out);
1319  fputc('\n', fp_out);
1320  mutt_write_mime_body(a->parts, fp_out);
1321 
1322 cleanup:
1323  FREE(&line);
1324 
1325  if (fp_in && (fp_in != fp))
1326  mutt_file_fclose(&fp_in);
1327  if (fp_out)
1328  mutt_file_fclose(&fp_out);
1329  else
1330  return;
1331 
1332  a->encoding = ENC_7BIT;
1333  FREE(&a->d_filename);
1334  a->d_filename = a->filename;
1335  if (a->filename && a->unlink)
1336  unlink(a->filename);
1337  a->filename = mutt_str_strdup(temp);
1338  a->unlink = true;
1339  if (stat(a->filename, &sb) == -1)
1340  {
1341  mutt_perror("stat");
1342  return;
1343  }
1344  a->length = sb.st_size;
1345  mutt_body_free(&a->parts);
1346  a->email->content = NULL;
1347 }
#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:48
#define mutt_perror(...)
Definition: logging.h:84
7-bit text
Definition: mime.h:49
struct Body * content
list of MIME parts
Definition: email.h:93
LOFF_T offset
offset where the actual data begins
Definition: body.h:46
#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:1213
struct Body * mutt_rfc822_parse_message(FILE *fp, struct Body *parent)
parse a Message/RFC822 body
Definition: parse.c:1432
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:73
const char * line
Definition: common.c:35
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:74
LOFF_T length
length (in bytes) of attachment
Definition: body.h:47
#define PATH_MAX
Definition: mutt.h:49
int mutt_write_mime_body(struct Body *a, FILE *fp)
Write a MIME part.
Definition: sendlib.c:506
#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:61
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:83
bool unlink
flag to indicate the file named by "filename" should be unlink()ed before free()ing this structure ...
Definition: body.h:76
#define FREE(x)
Definition: memory.h:40
int mutt_write_mime_header(struct Body *a, FILE *fp)
Create a MIME header.
Definition: sendlib.c:357
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:50
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:578
struct Email * email
header information for message/rfc822
Definition: body.h:62
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:73
#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 1354 of file sendlib.c.

1355 {
1356  if (b->type == TYPE_TEXT)
1357  {
1358  char send_charset[128];
1359  char *chsname = mutt_body_get_charset(b, send_charset, sizeof(send_charset));
1360  if ((info->lobin && !mutt_str_startswith(chsname, "iso-2022", CASE_IGNORE)) ||
1361  (info->linemax > 990) || (info->from && C_EncodeFrom))
1362  {
1364  }
1365  else if (info->hibin)
1366  {
1368  }
1369  else
1370  {
1371  b->encoding = ENC_7BIT;
1372  }
1373  }
1374  else if ((b->type == TYPE_MESSAGE) || (b->type == TYPE_MULTIPART))
1375  {
1376  if (info->lobin || info->hibin)
1377  {
1378  if (C_Allow8bit && !info->lobin)
1379  b->encoding = ENC_8BIT;
1380  else
1381  mutt_message_to_7bit(b, NULL);
1382  }
1383  else
1384  b->encoding = ENC_7BIT;
1385  }
1386  else if ((b->type == TYPE_APPLICATION) &&
1387  (mutt_str_strcasecmp(b->subtype, "pgp-keys") == 0))
1388  {
1389  b->encoding = ENC_7BIT;
1390  }
1391  else
1392  {
1393  /* Determine which encoding is smaller */
1394  if (1.33 * (float) (info->lobin + info->hibin + info->ascii) <
1395  3.0 * (float) (info->lobin + info->hibin) + (float) info->ascii)
1396  {
1397  b->encoding = ENC_BASE64;
1398  }
1399  else
1400  {
1402  }
1403  }
1404 }
void mutt_message_to_7bit(struct Body *a, FILE *fp)
Convert an email&#39;s MIME parts to 7-bit.
Definition: sendlib.c:1272
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:80
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:73
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:67
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body&#39;s character set.
Definition: sendlib.c:1423
unsigned int type
content-type primary type
Definition: body.h:72
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:631
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:77
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 1410 of file sendlib.c.

1411 {
1412  a->stamp = time(NULL);
1413 }
time_t stamp
time stamp of last encoding update.
Definition: body.h:68

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

1424 {
1425  char *p = NULL;
1426 
1427  if (b && (b->type != TYPE_TEXT))
1428  return NULL;
1429 
1430  if (b)
1431  p = mutt_param_get(&b->parameter, "charset");
1432 
1433  if (p)
1434  mutt_ch_canonical_charset(buf, buflen, p);
1435  else
1436  mutt_str_strfcpy(buf, "us-ascii", buflen);
1437 
1438  return buf;
1439 }
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:753
unsigned int type
content-type primary type
Definition: body.h:72
char * mutt_param_get(const struct ParameterList *p, const char *s)
Find a matching Parameter.
Definition: parameter.c:83
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 1447 of file sendlib.c.

1448 {
1449  struct Content *info = NULL;
1450  char chsbuf[256];
1451 
1452  /* override noconv when it's us-ascii */
1453  if (mutt_ch_is_us_ascii(mutt_body_get_charset(a, chsbuf, sizeof(chsbuf))))
1454  a->noconv = false;
1455 
1456  if (!a->force_charset && !a->noconv)
1457  mutt_param_delete(&a->parameter, "charset");
1458 
1459  info = mutt_get_content_info(a->filename, a);
1460  if (!info)
1461  return;
1462 
1463  set_encoding(a, info);
1465 
1466  FREE(&a->content);
1467  a->content = info;
1468 }
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:1410
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:48
struct Content * content
structure used to store detailed info about the content of the attachment.
Definition: body.h:56
bool noconv
don&#39;t do character set conversion
Definition: body.h:82
struct Content * mutt_get_content_info(const char *fname, struct Body *b)
Analyze file to determine MIME encoding to use.
Definition: sendlib.c:998
bool force_charset
send mode: don&#39;t adjust the character set when in send-mode.
Definition: body.h:83
#define mutt_ch_is_us_ascii(str)
Definition: charset.h:107
Info about an attachment.
Definition: content.h:33
static void set_encoding(struct Body *b, struct Content *info)
determine which Content-Transfer-Encoding to use
Definition: sendlib.c:1354
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body&#39;s character set.
Definition: sendlib.c:1423
#define FREE(x)
Definition: memory.h:40
void mutt_param_delete(struct ParameterList *p, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:141
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 1478 of file sendlib.c.

1479 {
1480  char buf[1024];
1481  struct Body *body = NULL;
1482  FILE *fp = NULL;
1483  CopyMessageFlags cmflags;
1485 
1486  if (WithCrypto)
1487  {
1489  {
1491  return NULL;
1492  }
1493  }
1494 
1495  mutt_mktemp(buf, sizeof(buf));
1496  fp = mutt_file_fopen(buf, "w+");
1497  if (!fp)
1498  return NULL;
1499 
1500  body = mutt_body_new();
1501  body->type = TYPE_MESSAGE;
1502  body->subtype = mutt_str_strdup("rfc822");
1503  body->filename = mutt_str_strdup(buf);
1504  body->unlink = true;
1505  body->use_disp = false;
1506  body->disposition = DISP_INLINE;
1507  body->noconv = true;
1508 
1510 
1511  CopyHeaderFlags chflags = CH_XMIT;
1512  cmflags = MUTT_CM_NO_FLAGS;
1513 
1514  /* If we are attaching a message, ignore C_MimeForwardDecode */
1515  if (!attach_msg && C_MimeForwardDecode)
1516  {
1517  chflags |= CH_MIME | CH_TXTPLAIN;
1518  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1520  pgp &= ~PGP_ENCRYPT;
1522  pgp &= ~SMIME_ENCRYPT;
1523  }
1524  else if ((WithCrypto != 0) && C_ForwardDecrypt && (e->security & SEC_ENCRYPT))
1525  {
1526  if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_multipart_encrypted(e->content))
1527  {
1528  chflags |= CH_MIME | CH_NONEWLINE;
1529  cmflags = MUTT_CM_DECODE_PGP;
1530  pgp &= ~PGP_ENCRYPT;
1531  }
1532  else if (((WithCrypto & APPLICATION_PGP) != 0) &&
1534  {
1535  chflags |= CH_MIME | CH_TXTPLAIN;
1536  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1537  pgp &= ~PGP_ENCRYPT;
1538  }
1539  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
1541  {
1542  chflags |= CH_MIME | CH_TXTPLAIN;
1543  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1544  pgp &= ~SMIME_ENCRYPT;
1545  }
1546  }
1547 
1548  mutt_copy_message_ctx(fp, m, e, cmflags, chflags);
1549 
1550  fflush(fp);
1551  rewind(fp);
1552 
1553  body->email = mutt_email_new();
1554  body->email->offset = 0;
1555  /* we don't need the user headers here */
1556  body->email->env = mutt_rfc822_read_header(fp, body->email, false, false);
1557  if (WithCrypto)
1558  body->email->security = pgp;
1559  mutt_update_encoding(body);
1560  body->parts = body->email->content;
1561 
1562  mutt_file_fclose(&fp);
1563 
1564  return body;
1565 }
#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:48
bool C_MimeForwardDecode
Config: Decode the forwarded message before attaching it.
Definition: sendlib.c:84
#define SEC_NO_FLAGS
No flags are set.
Definition: ncrypt.h:119
struct Body * content
list of MIME parts
Definition: email.h:93
bool noconv
don&#39;t do character set conversion
Definition: body.h:82
void mutt_parse_mime_message(struct Mailbox *m, struct Email *e)
Parse a MIME email.
Definition: mutt_parse.c:50
struct Email * mutt_email_new(void)
Create a new Email.
Definition: email.c:63
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:120
#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:74
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:143
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:417
int mutt_copy_message_ctx(FILE *fp_out, struct Mailbox *src, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags)
Copy a message from a Context.
Definition: copy.c:801
void mutt_update_encoding(struct Body *a)
Update the encoding type.
Definition: sendlib.c:1447
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:92
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:524
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:74
#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:81
#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:61
SecurityFlags mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
Definition: crypt.c:583
SecurityFlags security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:39
unsigned int type
content-type primary type
Definition: body.h:72
LOFF_T offset
where in the stream does this message begin?
Definition: email.h:86
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:129
Type: &#39;message/*&#39;.
Definition: mime.h:35
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:75
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:141
bool unlink
flag to indicate the file named by "filename" should be unlink()ed before free()ing this structure ...
Definition: body.h:76
#define MUTT_CM_DECODE_PGP
Used for decoding PGP messages.
Definition: copy.h:44
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: ncrypt.h:118
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:578
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:1013
struct Email * email
header information for message/rfc822
Definition: body.h:62
#define WithCrypto
Definition: ncrypt.h:155
#define PGP_ENCRYPT
Definition: ncrypt.h:135
#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:130

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

1574 {
1575  FILE *fp, *fp_err;
1576  char *buf = NULL;
1577  size_t buflen;
1578  int dummy = 0;
1579  pid_t pid;
1580  struct Buffer *cmd = mutt_buffer_pool_get();
1581 
1583 
1584  pid = mutt_create_filter(mutt_b2s(cmd), NULL, &fp, &fp_err);
1585  if (pid < 0)
1586  {
1587  mutt_error(_("Error running \"%s\""), mutt_b2s(cmd));
1589  return;
1590  }
1592 
1593  buf = mutt_file_read_line(buf, &buflen, fp, &dummy, 0);
1594  if (buf)
1595  {
1596  if (strchr(buf, '/'))
1597  mutt_parse_content_type(buf, att);
1598  FREE(&buf);
1599  }
1600 
1601  mutt_file_fclose(&fp);
1602  mutt_file_fclose(&fp_err);
1603  mutt_wait_filter(pid);
1604 }
pid_t mutt_create_filter(const char *s, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:216
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:48
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:657
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:42
void mutt_parse_content_type(const char *s, struct Body *ct)
Parse a content type.
Definition: parse.c:425
char * C_MimeTypeQueryCommand
Config: External command to determine the MIME type of an attachment.
Definition: sendlib.c:86
#define mutt_error(...)
Definition: logging.h:83
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:1393
#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:227
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: buffer.c:409
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: buffer.c:398

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

1613 {
1614  struct Body *att = mutt_body_new();
1615  att->filename = mutt_str_strdup(path);
1616 
1618  run_mime_type_query(att);
1619 
1620  /* Attempt to determine the appropriate content-type based on the filename
1621  * suffix. */
1622  if (!att->subtype)
1623  mutt_lookup_mime_type(att, path);
1624 
1626  {
1627  run_mime_type_query(att);
1628  }
1629 
1630  struct Content *info = mutt_get_content_info(path, att);
1631  if (!info)
1632  {
1633  mutt_body_free(&att);
1634  return NULL;
1635  }
1636 
1637  if (!att->subtype)
1638  {
1639  if ((info->nulbin == 0) &&
1640  ((info->lobin == 0) || ((info->lobin + info->hibin + info->ascii) / info->lobin >= 10)))
1641  {
1642  /* Statistically speaking, there should be more than 10% "lobin"
1643  * chars if this is really a binary file... */
1644  att->type = TYPE_TEXT;
1645  att->subtype = mutt_str_strdup("plain");
1646  }
1647  else
1648  {
1649  att->type = TYPE_APPLICATION;
1650  att->subtype = mutt_str_strdup("octet-stream");
1651  }
1652  }
1653 
1654  FREE(&info);
1655  mutt_update_encoding(att);
1656  return att;
1657 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:48
static void run_mime_type_query(struct Body *att)
Run an external command to determine the MIME type.
Definition: sendlib.c:1573
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:998
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:1447
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
int mutt_lookup_mime_type(struct Body *att, const char *path)
Find the MIME type for an attachment.
Definition: sendlib.c:1088
unsigned int type
content-type primary type
Definition: body.h:72
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
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:86
#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:87

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

1665 {
1666  int e = ENC_7BIT;
1667 
1668  for (; a; a = a->next)
1669  {
1670  if (a->encoding == ENC_BINARY)
1671  return ENC_BINARY;
1672  else if (a->encoding == ENC_8BIT)
1673  e = ENC_8BIT;
1674  }
1675 
1676  return e;
1677 }
7-bit text
Definition: mime.h:49
struct Body * next
next attachment in the list
Definition: body.h:60
8-bit text
Definition: mime.h:50
unsigned int encoding
content-transfer-encoding
Definition: body.h:73
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 1685 of file sendlib.c.

1686 {
1687  char *p = NULL;
1688 
1689  if (b->parts && check_boundary(boundary, b->parts))
1690  return true;
1691 
1692  if (b->next && check_boundary(boundary, b->next))
1693  return true;
1694 
1695  p = mutt_param_get(&b->parameter, "boundary");
1696  if (p && (mutt_str_strcmp(p, boundary) == 0))
1697  {
1698  return true;
1699  }
1700  return false;
1701 }
struct Body * next
next attachment in the list
Definition: body.h:60
static bool check_boundary(const char *boundary, struct Body *b)
check for duplicate boundary
Definition: sendlib.c:1685
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:61
char * mutt_param_get(const struct ParameterList *p, const char *s)
Find a matching Parameter.
Definition: parameter.c:83
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:618

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

1709 {
1710  struct Body *new = mutt_body_new();
1711  new->type = TYPE_MULTIPART;
1712  new->subtype = mutt_str_strdup("mixed");
1713  new->encoding = get_toplevel_encoding(b);
1714  do
1715  {
1716  mutt_generate_boundary(&new->parameter);
1717  if (check_boundary(mutt_param_get(&new->parameter, "boundary"), b))
1718  mutt_param_delete(&new->parameter, "boundary");
1719  } while (!mutt_param_get(&new->parameter, "boundary"));
1720  new->use_disp = false;
1721  new->disposition = DISP_INLINE;
1722  new->parts = b;
1723 
1724  return new;
1725 }
static int get_toplevel_encoding(struct Body *a)
Find the most restrictive encoding type.
Definition: sendlib.c:1664
The body of an email.
Definition: body.h:34
void mutt_generate_boundary(struct ParameterList *parm)
Create a unique boundary id for a MIME part.
Definition: sendlib.c:589
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
static bool check_boundary(const char *boundary, struct Body *b)
check for duplicate boundary
Definition: sendlib.c:1685
char * mutt_param_get(const struct ParameterList *p, const char *s)
Find a matching Parameter.
Definition: parameter.c:83
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
void mutt_param_delete(struct ParameterList *p, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:141
Content is inline.
Definition: mime.h:62

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

1735 {
1736  struct Body *t = NULL;
1737 
1738  if (b->parts)
1739  {
1740  t = b;
1741  b = b->parts;
1742  t->parts = NULL;
1743  mutt_body_free(&t);
1744  }
1745  return b;
1746 }
The body of an email.
Definition: body.h:34
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:61
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_address_list ( struct Address addr,
FILE *  fp,
int  linelen,
bool  display 
)

wrapper around mutt_write_address()

Parameters
addrAddress 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 1758 of file sendlib.c.

1759 {
1760  struct Address *tmp = NULL;
1761  char buf[1024];
1762  int count = 0;
1763 
1764  while (addr)
1765  {
1766  tmp = addr->next;
1767  addr->next = NULL;
1768  buf[0] = '\0';
1769  mutt_addr_write(buf, sizeof(buf), addr, display);
1770  size_t len = mutt_str_strlen(buf);
1771  if (count && (linelen + len > 74))
1772  {
1773  fputs("\n\t", fp);
1774  linelen = len + 8; /* tab is usually about 8 spaces... */
1775  }
1776  else
1777  {
1778  if (count && addr->mailbox)
1779  {
1780  fputc(' ', fp);
1781  linelen++;
1782  }
1783  linelen += len;
1784  }
1785  fputs(buf, fp);
1786  addr->next = tmp;
1787  if (!addr->group && addr->next && addr->next->mailbox)
1788  {
1789  linelen++;
1790  fputc(',', fp);
1791  }
1792  addr = addr->next;
1793  count++;
1794  }
1795  fputc('\n', fp);
1796 }
An email address.
Definition: address.h:32
char * mailbox
mailbox and host address
Definition: address.h:35
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:669
size_t mutt_addr_write(char *buf, size_t buflen, struct Address *addr, bool display)
Write an Address to a buffer.
Definition: address.c:1184
bool group
group mailbox?
Definition: address.h:36
struct Address * next
Definition: address.h:39

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

1808 {
1809  struct ListNode *np = NULL;
1810  size_t length = 0;
1811 
1812  STAILQ_FOREACH(np, r, entries)
1813  {
1814  if (++length == trim)
1815  break;
1816  }
1817 
1818  struct ListNode **ref = mutt_mem_calloc(length, sizeof(struct ListNode *));
1819 
1820  // store in reverse order
1821  size_t tmp = length;
1822  STAILQ_FOREACH(np, r, entries)
1823  {
1824  ref[--tmp] = np;
1825  if (tmp == 0)
1826  break;
1827  }
1828 
1829  for (size_t i = 0; i < length; i++)
1830  {
1831  fputc(' ', fp);
1832  fputs(ref[i]->data, fp);
1833  if (i != length - 1)
1834  fputc('\n', fp);
1835  }
1836 
1837  FREE(&ref);
1838 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:51
#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 1850 of file sendlib.c.

1852 {
1853  while (value && *value)
1854  {
1855  if (fputc(*value, fp) == EOF)
1856  return -1;
1857  /* corner-case: break words longer than 998 chars by force,
1858  * mandated by RFC5322 */
1859  if (!(chflags & CH_DISPLAY) && (++col >= 998))
1860  {
1861  if (fputs("\n ", fp) < 0)
1862  return -1;
1863  col = 1;
1864  }
1865  if (*value == '\n')
1866  {
1867  if (*(value + 1) && pfx && *pfx && (fputs(pfx, fp) == EOF))
1868  return -1;
1869  /* for display, turn folding spaces into folding tabs */
1870  if ((chflags & CH_DISPLAY) && ((*(value + 1) == ' ') || (*(value + 1) == '\t')))
1871  {
1872  value++;
1873  while (*value && ((*value == ' ') || (*value == '\t')))
1874  value++;
1875  if (fputc('\t', fp) == EOF)
1876  return -1;
1877  continue;
1878  }
1879  }
1880  value++;
1881  }
1882  return 0;
1883 }
#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 1896 of file sendlib.c.

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

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

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

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

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

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

2130 {
2131  char *p = (char *) value, *last = NULL, *line = NULL;
2132  int max = 0, w, rc = -1;
2133  int pfxw = mutt_strwidth(pfx);
2134  char *v = mutt_str_strdup(value);
2135  bool display = (chflags & CH_DISPLAY);
2136 
2137  if (!display || C_Weed)
2138  v = unfold_header(v);
2139 
2140  /* when not displaying, use sane wrap value */
2141  if (!display)
2142  {
2143  if ((C_WrapHeaders < 78) || (C_WrapHeaders > 998))
2144  wraplen = 78;
2145  else
2146  wraplen = C_WrapHeaders;
2147  }
2148  else if ((wraplen <= 0) || (wraplen > MuttIndexWindow->cols))
2149  wraplen = MuttIndexWindow->cols;
2150 
2151  if (tag)
2152  {
2153  /* if header is short enough, simply print it */
2154  if (!display && (mutt_strwidth(tag) + 2 + pfxw + mutt_strwidth(v) <= wraplen))
2155  {
2156  mutt_debug(5, "buf[%s%s: %s] is short enough\n", NONULL(pfx), tag, v);
2157  if (fprintf(fp, "%s%s: %s\n", NONULL(pfx), tag, v) <= 0)
2158  goto out;
2159  rc = 0;
2160  goto out;
2161  }
2162  else
2163  {
2164  rc = fold_one_header(fp, tag, v, pfx, wraplen, chflags);
2165  goto out;
2166  }
2167  }
2168 
2169  p = v;
2170  last = v;
2171  line = v;
2172  while (p && *p)
2173  {
2174  p = strchr(p, '\n');
2175 
2176  /* find maximum line width in current header */
2177  if (p)
2178  *p = '\0';
2179  w = mutt_mb_width(line, 0, display);
2180  if (w > max)
2181  max = w;
2182  if (p)
2183  *p = '\n';
2184 
2185  if (!p)
2186  break;
2187 
2188  line = ++p;
2189  if ((*p != ' ') && (*p != '\t'))
2190  {
2191  if (write_one_header(fp, pfxw, max, wraplen, pfx, last, p, chflags) < 0)
2192  goto out;
2193  last = p;
2194  max = 0;
2195  }
2196  }
2197 
2198  if (last && *last)
2199  if (write_one_header(fp, pfxw, max, wraplen, pfx, last, p, chflags) < 0)
2200  goto out;
2201 
2202  rc = 0;
2203 
2204 out:
2205  FREE(&v);
2206  return rc;
2207 }
short C_WrapHeaders
Config: Width to wrap headers in outgoing messages.
Definition: sendlib.c:93
#define NONULL(x)
Definition: string2.h:36
static char * unfold_header(char *s)
Unfold a wrapped email header.
Definition: sendlib.c:1995
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:35
int mutt_strwidth(const char *s)
Measure a string&#39;s width in screen cells.
Definition: curs_lib.c:1239
struct MuttWindow * MuttIndexWindow
Index Window.
Definition: mutt_window.c:39
#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:2037
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:1896
#define FREE(x)
Definition: memory.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:80
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 2233 of file sendlib.c.

2236 {
2237  char buf[1024];
2238  char *p = NULL, *q = NULL;
2239  bool has_agent = false; /* user defined user-agent header field exists */
2240 
2241  if ((mode == MUTT_WRITE_HEADER_NORMAL) && !privacy)
2242  fputs(mutt_date_make_date(buf, sizeof(buf)), fp);
2243 
2244  /* UseFrom is not consulted here so that we can still write a From:
2245  * field if the user sets it with the 'my_hdr' command */
2246  if (env->from && !privacy)
2247  {
2248  buf[0] = '\0';
2249  mutt_addr_write(buf, sizeof(buf), env->from, false);
2250  fprintf(fp, "From: %s\n", buf);
2251  }
2252 
2253  if (env->sender && !privacy)
2254  {
2255  buf[0] = '\0';
2256  mutt_addr_write(buf, sizeof(buf), env->sender, false);
2257  fprintf(fp, "Sender: %s\n", buf);
2258  }
2259 
2260  if (env->to)
2261  {
2262  fputs("To: ", fp);
2263  mutt_write_address_list(env->to, fp, 4, 0);
2264  }
2265  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2266 #ifdef USE_NNTP
2267  if (!OptNewsSend)
2268 #endif
2269  fputs("To:\n", fp);
2270 
2271  if (env->cc)
2272  {
2273  fputs("Cc: ", fp);
2274  mutt_write_address_list(env->cc, fp, 4, 0);
2275  }
2276  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2277 #ifdef USE_NNTP
2278  if (!OptNewsSend)
2279 #endif
2280  fputs("Cc:\n", fp);
2281 
2282  if (env->bcc)
2283  {
2284  if ((mode == MUTT_WRITE_HEADER_POSTPONE) || (mode == MUTT_WRITE_HEADER_EDITHDRS) ||
2285  ((mode == MUTT_WRITE_HEADER_NORMAL) && C_WriteBcc))
2286  {
2287  fputs("Bcc: ", fp);
2288  mutt_write_address_list(env->bcc, fp, 5, 0);
2289  }
2290  }
2291  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2292 #ifdef USE_NNTP
2293  if (!OptNewsSend)
2294 #endif
2295  fputs("Bcc:\n", fp);
2296 
2297 #ifdef USE_NNTP
2298  if (env->newsgroups)
2299  fprintf(fp, "Newsgroups: %s\n", env->newsgroups);
2300  else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend)
2301  fputs("Newsgroups:\n", fp);
2302 
2303  if (env->followup_to)
2304  fprintf(fp, "Followup-To: %s\n", env->followup_to);
2305  else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend)
2306  fputs("Followup-To:\n", fp);
2307 
2308  if (env->x_comment_to)
2309  fprintf(fp, "X-Comment-To: %s\n", env->x_comment_to);
2310  else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend && C_XCommentTo)
2311  fputs("X-Comment-To:\n", fp);
2312 #endif
2313 
2314  if (env->subject)
2315  {
2316  if (hide_protected_subject &&
2317  ((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_POSTPONE)))
2319  else
2320  mutt_write_one_header(fp, "Subject", env->subject, NULL, 0, CH_NO_FLAGS);
2321  }
2322  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2323  fputs("Subject:\n", fp);
2324 
2325  /* save message id if the user has set it */
2326  if (env->message_id && !privacy)
2327  fprintf(fp, "Message-ID: %s\n", env->message_id);
2328 
2329  if (env->reply_to)
2330  {
2331  fputs("Reply-To: ", fp);
2332  mutt_write_address_list(env->reply_to, fp, 10, 0);
2333  }
2334  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2335  fputs("Reply-To:\n", fp);
2336 
2337  if (env->mail_followup_to)
2338 #ifdef USE_NNTP
2339  if (!OptNewsSend)
2340 #endif
2341  {
2342  fputs("Mail-Followup-To: ", fp);
2343  mutt_write_address_list(env->mail_followup_to, fp, 18, 0);
2344  }
2345 
2346  if ((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_POSTPONE))
2347  {
2348  if (!STAILQ_EMPTY(&env->references))
2349  {
2350  fputs("References:", fp);
2351  mutt_write_references(&env->references, fp, 10);
2352  fputc('\n', fp);
2353  }
2354 
2355  /* Add the MIME headers */
2356  fputs("MIME-Version: 1.0\n", fp);
2357  mutt_write_mime_header(attach, fp);
2358  }
2359 
2360  if (!STAILQ_EMPTY(&env->in_reply_to))
2361  {
2362  fputs("In-Reply-To:", fp);
2363  mutt_write_references(&env->in_reply_to, fp, 0);
2364  fputc('\n', fp);
2365  }
2366 
2367  /* Add any user defined headers */
2368  struct ListNode *tmp = NULL;
2369  STAILQ_FOREACH(tmp, &env->userhdrs, entries)
2370  {
2371  p = strchr(tmp->data, ':');
2372  if (p)
2373  {
2374  q = p;
2375 
2376  *p = '\0';
2377 
2378  p = mutt_str_skip_email_wsp(p + 1);
2379  if (!*p)
2380  {
2381  *q = ':';
2382  continue; /* don't emit empty fields. */
2383  }
2384 
2385  /* check to see if the user has overridden the user-agent field */
2386  if (mutt_str_startswith(tmp->data, "user-agent", CASE_IGNORE))
2387  {
2388  has_agent = true;
2389  if (privacy)
2390  {
2391  *q = ':';
2392  continue;
2393  }
2394  }
2395 
2396  mutt_write_one_header(fp, tmp->data, p, NULL, 0, CH_NO_FLAGS);
2397  *q = ':';
2398  }
2399  }
2400 
2401  if ((mode == MUTT_WRITE_HEADER_NORMAL) && !privacy && C_UserAgent && !has_agent)
2402  {
2403  /* Add a vanity header */
2404  fprintf(fp, "User-Agent: NeoMutt/%s%s\n", PACKAGE_VERSION, GitVer);
2405  }
2406 
2407  return (ferror(fp) == 0) ? 0 : -1;
2408 }
WHERE bool C_WriteBcc
Config: Write out the &#39;Bcc&#39; field when preparing to send a mail.
Definition: globals.h:260
struct Address * to
Definition: envelope.h:42
WHERE char * C_CryptProtectedHeadersSubject
Config: Use this as the subject for encrypted emails.
Definition: globals.h:100
bool C_UserAgent
Config: Add a &#39;User-Agent&#39; head to outgoing mail.
Definition: sendlib.c:92
A normal Email, write full header + MIME headers.
Definition: sendlib.h:62
A postponed Email, just the envelope info.
Definition: sendlib.h:63
struct ListHead userhdrs
user defined headers
Definition: envelope.h:67
struct Address * sender
Definition: envelope.h:45
char * mutt_date_make_date(char *buf, size_t buflen)
Write a date in RFC822 format to a buffer.
Definition: date.c:382
struct Address * reply_to
Definition: envelope.h:46
void mutt_write_address_list(struct Address *addr, FILE *fp, int linelen, bool display)
wrapper around mutt_write_address()
Definition: sendlib.c:1758
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:66
char * message_id
Definition: envelope.h:53
struct Address * mail_followup_to
Definition: envelope.h:47
struct Address * from
Definition: envelope.h:41
size_t mutt_addr_write(char *buf, size_t buflen, struct Address *addr, bool display)
Write an Address to a buffer.
Definition: address.c:1184
char * x_comment_to
Definition: envelope.h:62
struct Address * bcc
Definition: envelope.h:44
void mutt_write_references(const struct ListHead *r, FILE *fp, size_t trim)
Add the message references to a list.
Definition: sendlib.c:1807
const char * GitVer
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:50
"light" mode (used for edit_hdrs)
Definition: sendlib.h:64
Ignore case when comparing strings.
Definition: string2.h:67
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:779
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
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
Definition: envelope.h:50
char * newsgroups
Definition: envelope.h:59
WHERE bool C_XCommentTo
Config: (nntp) Add &#39;X-Comment-To&#39; header that contains article author.
Definition: globals.h:281
char * followup_to
Definition: envelope.h:61
int mutt_write_mime_header(struct Body *a, FILE *fp)
Create a MIME header.
Definition: sendlib.c:357
#define STAILQ_EMPTY(head)
Definition: queue.h:346
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:43
struct ListHead references
message references (in reverse order)
Definition: envelope.h:65
A List node for strings.
Definition: list.h:33
int mutt_write_one_header(FILE *fp, const char *tag, const char *value, const char *pfx, int wraplen, CopyHeaderFlags chflags)
Write one header line to a file.
Definition: sendlib.c:2128
struct Address * cc
Definition: envelope.h:43

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

2417 {
2418  char *tmp = NULL;
2419  char *p = NULL;
2420  int i;
2421 
2422  struct ListNode *np = NULL;
2423  STAILQ_FOREACH(np, h, entries)
2424  {
2425  p = strchr(np->data, ':');
2426  if (!p)
2427  continue;
2428 
2429  i = p - np->data;
2430  p = mutt_str_skip_email_wsp(p + 1);
2431  tmp = mutt_str_strdup(p);
2432 
2433  if (!tmp)
2434  continue;
2435 
2436  rfc2047_encode(&tmp, NULL, i + 2, C_SendCharset);
2437  mutt_mem_realloc(&np->data, i + 2 + mutt_str_strlen(tmp) + 1);
2438 
2439  sprintf(np->data + i + 2, "%s", tmp);
2440 
2441  FREE(&tmp);
2442  }
2443 }
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:669
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:121
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:779
#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:626
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 2453 of file sendlib.c.

2454 {
2455  if (!C_Hostname || (C_Hostname[0] == '@'))
2456  return NULL;
2457 
2458  char *p = C_Hostname;
2459 
2460  if (may_hide_host && C_HiddenHost)
2461  {
2462  p = strchr(C_Hostname, '.');
2463  if (p)
2464  p++;
2465 
2466  // sanity check: don't hide the host if the fqdn is something like example.com
2467  if (!p || !strchr(p, '.'))
2468  p = C_Hostname;
2469  }
2470 
2471  return p;
2472 }
bool C_HiddenHost
Config: Don&#39;t use the hostname, just the domain, when generating the message id.
Definition: sendlib.c:82
WHERE char * C_Hostname
Config: Fully-qualified domain name of this machine.
Definition: globals.h:106

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

2481 {
2482  char buf[128];
2483  unsigned char rndid[MUTT_RANDTAG_LEN + 1];
2484 
2485  mutt_rand_base32(rndid, sizeof(rndid) - 1);
2486  rndid[MUTT_RANDTAG_LEN] = 0;
2487  const char *fqdn = mutt_fqdn(false);
2488  if (!fqdn)
2489  fqdn = NONULL(ShortHostname);
2490 
2491  struct tm tm = mutt_date_gmtime(MUTT_DATE_NOW);
2492  snprintf(buf, sizeof(buf), "<%d%02d%02d%02d%02d%02d.%s@%s>", tm.tm_year + 1900,
2493  tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, rndid, fqdn);
2494  return mutt_str_strdup(buf);
2495 }
#define NONULL(x)
Definition: string2.h:36
#define MUTT_DATE_NOW
Constant representing the &#39;current time&#39;, see: mutt_date_gmtime(), mutt_date_localtime() ...
Definition: date.h:29
#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:743
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2453
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:517

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

2502 {
2503  SigAlrm = 1;
2504 }
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 2518 of file sendlib.c.

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

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

2684 {
2685  for (; addr; addr = addr->next)
2686  {
2687  /* weed out group mailboxes, since those are for display only */
2688  if (addr->mailbox && !addr->group)
2689  {
2690  if (*argslen == *argsmax)
2691  mutt_mem_realloc(&args, (*argsmax += 5) * sizeof(char *));
2692  args[(*argslen)++] = addr->mailbox;
2693  }
2694  }
2695  return args;
2696 }
char * mailbox
mailbox and host address
Definition: address.h:35
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:121
bool group
group mailbox?
Definition: address.h:36
struct Address * next
Definition: address.h:39

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

2709 {
2710  if (*argslen == *argsmax)
2711  mutt_mem_realloc(&args, (*argsmax += 5) * sizeof(char *));
2712  args[(*argslen)++] = s;
2713  return args;
2714 }
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:121

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_invoke_sendmail ( struct Address from,
struct Address to,
struct Address cc,
struct Address 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 2727 of file sendlib.c.

2729 {
2730  char *ps = NULL, *path = NULL, *s = NULL, *childout = NULL;
2731  char **args = NULL;
2732  size_t argslen = 0, argsmax = 0;
2733  char **extra_args = NULL;
2734  int i;
2735 
2736 #ifdef USE_NNTP
2737  if (OptNewsSend)
2738  {
2739  char cmd[1024];
2740 
2741  mutt_expando_format(cmd, sizeof(cmd), 0, MuttIndexWindow->cols,
2743  if (!*cmd)
2744  {
2745  i = nntp_post(Context->mailbox, msg);
2746  unlink(msg);
2747  return i;
2748  }
2749 
2750  s = mutt_str_strdup(cmd);
2751  }
2752  else
2753 #endif
2755 
2756  /* ensure that $sendmail is set to avoid a crash. http://dev.mutt.org/trac/ticket/3548 */
2757  if (!s)
2758  {
2759  mutt_error(_("$sendmail must be set in order to send mail"));
2760  return -1;
2761  }
2762 
2763  ps = s;
2764  i = 0;
2765  while ((ps = strtok(ps, " ")))
2766  {
2767  if (argslen == argsmax)
2768  mutt_mem_realloc(&args, sizeof(char *) * (argsmax += 5));
2769 
2770  if (i)
2771  {
2772  if (mutt_str_strcmp(ps, "--") == 0)
2773  break;
2774  args[argslen++] = ps;
2775  }
2776  else
2777  {
2778  path = mutt_str_strdup(ps);
2779  ps = strrchr(ps, '/');
2780  if (ps)
2781  ps++;
2782  else
2783  ps = path;
2784  args[argslen++] = ps;
2785  }
2786  ps = NULL;
2787  i++;
2788  }
2789 
2790 #ifdef USE_NNTP
2791  if (!OptNewsSend)
2792  {
2793 #endif
2794  size_t extra_argslen = 0;
2795  /* If C_Sendmail contained a "--", we save the recipients to append to
2796  * args after other possible options added below. */
2797  if (ps)
2798  {
2799  ps = NULL;
2800  size_t extra_argsmax = 0;
2801  while ((ps = strtok(ps, " ")))
2802  {
2803  if (extra_argslen == extra_argsmax)
2804  mutt_mem_realloc(&extra_args, sizeof(char *) * (extra_argsmax += 5));
2805 
2806  extra_args[extra_argslen++] = ps;
2807  ps = NULL;
2808  }
2809  }
2810 
2811  if (eightbit && C_Use8bitmime)
2812  args = add_option(args, &argslen, &argsmax, "-B8BITMIME");
2813 
2814  if (C_UseEnvelopeFrom)
2815  {
2817  {
2818  args = add_option(args, &argslen, &argsmax, "-f");
2819  args = add_args(args, &argslen, &argsmax, C_EnvelopeFromAddress);
2820  }
2821  else if (from && !from->next)
2822  {
2823  args = add_option(args, &argslen, &argsmax, "-f");
2824  args = add_args(args, &argslen, &argsmax, from);
2825  }
2826  }
2827 
2828  if (C_DsnNotify)
2829  {
2830  args = add_option(args, &argslen, &argsmax, "-N");
2831  args = add_option(args, &argslen, &argsmax, C_DsnNotify);
2832  }
2833  if (C_DsnReturn)
2834  {
2835  args = add_option(args, &argslen, &argsmax, "-R");
2836  args = add_option(args, &argslen, &argsmax, C_DsnReturn);
2837  }
2838  args = add_option(args, &argslen, &argsmax, "--");
2839  for (i = 0; i < extra_argslen; i++)
2840  args = add_option(args, &argslen, &argsmax, extra_args[i]);
2841  args = add_args(args, &argslen, &argsmax, to);
2842  args = add_args(args, &argslen, &argsmax, cc);
2843  args = add_args(args, &argslen, &argsmax, bcc);
2844 #ifdef USE_NNTP
2845  }
2846 #endif
2847 
2848  if (argslen == argsmax)
2849  mutt_mem_realloc(&args, sizeof(char *) * (++argsmax));
2850 
2851  args[argslen++] = NULL;
2852 
2853  /* Some user's $sendmail command uses gpg for password decryption,
2854  * and is set up to prompt using ncurses pinentry. If we
2855  * mutt_endwin() it leaves other users staring at a blank screen.
2856  * So instead, just force a hard redraw on the next refresh. */
2857  if (!OptNoCurses)
2859 
2860  i = send_msg(path, args, msg, OptNoCurses ? NULL : &childout);
2861  if (i != (EX_OK & 0xff))
2862  {
2863  if (i != S_BKG)
2864  {
2865  const char *e = mutt_str_sysexit(i);
2866  mutt_error(_("Error sending message, child exited %d (%s)"), i, NONULL(e));
2867  if (childout)
2868  {
2869  struct stat st;
2870 
2871  if ((stat(childout, &st) == 0) && (st.st_size > 0))
2872  mutt_do_pager(_("Output of the delivery process"), childout,
2873  MUTT_PAGER_NO_FLAGS, NULL);
2874  }
2875  }
2876  }
2877  else if (childout)
2878  unlink(childout);
2879 
2880  FREE(&childout);
2881  FREE(&path);
2882  FREE(&s);
2883  FREE(&args);
2884  FREE(&extra_args);
2885 
2886  if (i == (EX_OK & 0xff))
2887  i = 0;
2888  else if (i == S_BKG)
2889  i = 1;
2890  else
2891  i = -1;
2892  return i;
2893 }
The "current" mailbox.
Definition: context.h:38
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:836
char * C_Sendmail
Config: External command to send email.
Definition: sendlib.c:88
#define NONULL(x)
Definition: string2.h:36
static int send_msg(const char *path, char **args, const char *msg, char **tempfile)
invoke sendmail in a subshell
Definition: sendlib.c:2518
int nntp_post(struct Mailbox *m, const char *msg)
Post article.
Definition: nntp.c:1966
#define _(a)
Definition: message.h:28
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:45
#define S_BKG
Definition: string2.h:42
#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:90
struct Mailbox * mailbox
Definition: context.h:52
char * C_Inews
Config: (nntp) External command to post news articles.
Definition: sendlib.c:83
static char ** add_args(char **args, size_t *argslen, size_t *argsmax, struct Address *addr)
Add an Address to a dynamic array.
Definition: sendlib.c:2683
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:121
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:2708
bool C_UseEnvelopeFrom
Config: Set the envelope sender of the message.
Definition: sendlib.c:91
struct MuttWindow * MuttIndexWindow
Index Window.
Definition: mutt_window.c:39
WHERE char * C_DsnReturn
Config: What to send as a notification of message delivery or delay.
Definition: globals.h:103
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:570
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define mutt_error(...)
Definition: logging.h:83
WHERE struct Address * C_EnvelopeFromAddress
Config: Manually set the sender for outgoing messages.
Definition: globals.h:92
#define FREE(x)
Definition: memory.h:40
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:43
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:121
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:618
WHERE char * C_DsnNotify
Config: Request notification for message delivery or delay.
Definition: globals.h:102
#define EX_OK
Definition: sendlib.c:73
#define MUTT_PAGER_NO_FLAGS
No flags are set.
Definition: pager.h:43
struct Address * next
Definition: address.h:39

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

2905 {
2906  if (final)
2907  {
2908  if (env->bcc && !(env->to || env->cc))
2909  {
2910  /* some MTA's will put an Apparently-To: header field showing the Bcc:
2911  * recipients if there is no To: or Cc: field, so attempt to suppress
2912  * it by using an empty To: field. */
2913  env->to = mutt_addr_new();
2914  env->to->group = 1;
2915  env->to->next = mutt_addr_new();
2916 
2917  char buf[1024];
2918  buf[0] = '\0';
2919  mutt_addr_cat(buf, sizeof(buf), "undisclosed-recipients", AddressSpecials);
2920 
2921  env->to->mailbox = mutt_str_strdup(buf);
2922  }
2923 
2924  mutt_set_followup_to(env);
2925 
2926  if (!env->message_id)
2927  env->message_id = gen_msgid();
2928  }
2929 
2930  /* Take care of 8-bit => 7-bit conversion. */
2932  encode_headers(&env->userhdrs);
2933 }
void rfc2047_encode_envelope(struct Envelope *env)
Encode the fields of an Envelope.
Definition: rfc2047.c:806
static char * gen_msgid(void)
Generate a unique Message ID.
Definition: sendlib.c:2480
struct Address * to
Definition: envelope.h:42
const char AddressSpecials[]
Characters with special meaning for email addresses.
Definition: address.c:41
struct ListHead userhdrs
user defined headers
Definition: envelope.h:67
struct Address * mutt_addr_new(void)
Create a new Address.
Definition: address.c:401
char * mailbox
mailbox and host address
Definition: address.h:35
char * message_id
Definition: envelope.h:53
void mutt_set_followup_to(struct Envelope *env)
Set followup-to field.
Definition: send.c:1213
struct Address * bcc
Definition: envelope.h:44
bool group
group mailbox?
Definition: address.h:36
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
void mutt_addr_cat(char *buf, size_t buflen, const char *value, const char *specials)
Copy a string and escape the specified characters.
Definition: address.c:695
struct Address * cc
Definition: envelope.h:43
static void encode_headers(struct ListHead *h)
RFC2047-encode a list of headers.
Definition: sendlib.c:2416
struct Address * next
Definition: address.h:39

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

2943 {
2944  struct ListNode *item = NULL;
2945  STAILQ_FOREACH(item, &env->userhdrs, entries)
2946  {
2947  rfc2047_decode(&item->data);
2948  }
2949 
2951 
2952  /* back conversions */
2954 }
struct ListHead userhdrs
user defined headers
Definition: envelope.h:67
void rfc2047_decode_envelope(struct Envelope *env)
Decode the fields of an Envelope.
Definition: rfc2047.c:786
struct Address * mail_followup_to
Definition: envelope.h:47
void rfc2047_decode(char **pd)
Decode any RFC2047-encoded header fields.
Definition: rfc2047.c:650
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
char * data
Definition: list.h:35
void mutt_addr_free(struct Address **p)
Free a list of Addresses.
Definition: address.c:451
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 Address to,
const char *  resent_from,
struct Address 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 2966 of file sendlib.c.

2968 {
2969  if (!e)
2970  return -1;
2971 
2972  int rc = 0;
2973  char tempfile[PATH_MAX];
2974 
2975  mutt_mktemp(tempfile, sizeof(tempfile));
2976  FILE *fp_tmp = mutt_file_fopen(tempfile, "w");
2977  if (fp_tmp)
2978  {
2979  char date[128];
2981 
2982  if (!C_BounceDelivered)
2983  chflags |= CH_WEED_DELIVERED;
2984 
2985  fseeko(fp, e->offset, SEEK_SET);
2986  fprintf(fp_tmp, "Resent-From: %s", resent_from);
2987  fprintf(fp_tmp, "\nResent-%s", mutt_date_make_date(date, sizeof(date)));
2988  char *msgid_str = gen_msgid();
2989  fprintf(fp_tmp, "Resent-Message-ID: %s\n", msgid_str);
2990  FREE(&msgid_str);
2991  fputs("Resent-To: ", fp_tmp);
2992  mutt_write_address_list(to, fp_tmp, 11, 0);
2993  mutt_copy_header(fp, e, fp_tmp, chflags, NULL);
2994  fputc('\n', fp_tmp);
2995  mutt_file_copy_bytes(fp, fp_tmp, e->content->length);
2996  if (mutt_file_fclose(&fp_tmp) != 0)
2997  {
2998  mutt_perror(tempfile);
2999  unlink(tempfile);
3000  return -1;
3001  }
3002 #ifdef USE_SMTP
3003  if (C_SmtpUrl)
3004  rc = mutt_smtp_send(env_from, to, NULL, NULL, tempfile, e->content->encoding == ENC_8BIT);
3005  else
3006 #endif
3007  rc = mutt_invoke_sendmail(env_from, to, NULL, NULL, tempfile,
3008  e->content->encoding == ENC_8BIT);
3009  }
3010 
3011  return rc;
3012 }
WHERE char * C_SmtpUrl
Config: (smtp) Url of the SMTP server.
Definition: globals.h:140
#define mutt_perror(...)
Definition: logging.h:84
static char * gen_msgid(void)
Generate a unique Message ID.
Definition: sendlib.c:2480
struct Body * content
list of MIME parts
Definition: email.h:93
8-bit text
Definition: mime.h:50
int mutt_invoke_sendmail(struct Address *from, struct Address *to, struct Address *cc, struct Address *bcc, const char *msg, int eightbit)
Run sendmail.
Definition: sendlib.c:2727
char * mutt_date_make_date(char *buf, size_t buflen)
Write a date in RFC822 format to a buffer.
Definition: date.c:382
int mutt_copy_header(FILE *fp_in, struct Email *e, FILE *fp_out, CopyHeaderFlags chflags, const char *prefix)
Copy Email header.
Definition: copy.c:388
void mutt_write_address_list(struct Address *addr, FILE *fp, int linelen, bool display)
wrapper around mutt_write_address()
Definition: sendlib.c:1758
#define CH_WEED_DELIVERED
Weed eventual Delivered-To headers.
Definition: copy.h:64
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:73
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:74
LOFF_T length
length (in bytes) of attachment
Definition: body.h:47
#define PATH_MAX
Definition: mutt.h:49
#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:234
LOFF_T offset
where in the stream does this message begin?
Definition: email.h:86
bool C_BounceDelivered
Config: Add &#39;Delivered-To&#39; to bounced messages.
Definition: sendlib.c:79
#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 Address *from, const struct Address *to, const struct Address *cc, const struct Address *bcc, const char *msgfile, bool eightbit)
Send a message using SMTP.
Definition: smtp.c:740
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:578
#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 Address to 
)

Bounce an email message.

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

Definition at line 3022 of file sendlib.c.

3023 {
3024  if (!fp || !e || !to)
3025  return -1;
3026 
3027  const char *fqdn = mutt_fqdn(true);
3028  char resent_from[256];
3029  char *err = NULL;
3030 
3031  resent_from[0] = '\0';
3032  struct Address *from = mutt_default_from();
3033 
3034  /* mutt_default_from() does not use $realname if the real name is not set
3035  * in $from, so we add it here. The reason it is not added in
3036  * mutt_default_from() is that during normal sending, we execute
3037  * send-hooks and set the realname last so that it can be changed based
3038  * upon message criteria. */
3039  if (!from->personal)
3041 
3042  if (fqdn)
3043  mutt_addr_qualify(from, fqdn);
3044 
3045  rfc2047_encode_addrlist(from, "Resent-From");
3046  if (mutt_addrlist_to_intl(from, &err))
3047  {
3048  mutt_error(_("Bad IDN %s while preparing resent-from"), err);
3049  FREE(&err);
3050  mutt_addr_free(&from);
3051  return -1;
3052  }
3053  mutt_addr_write(resent_from, sizeof(resent_from), from, false);
3054 
3055 #ifdef USE_NNTP
3056  OptNewsSend = false;
3057 #endif
3058 
3059  /* prepare recipient list. idna conversion appears to happen before this
3060  * function is called, since the user receives confirmation of the address
3061  * list being bounced to. */
3062  struct Address *resent_to = mutt_addr_copy_list(to, false);
3063  rfc2047_encode_addrlist(resent_to, "Resent-To");
3064 
3065  int rc = bounce_message(fp, e, resent_to, resent_from, from);
3066 
3067  mutt_addr_free(&resent_to);
3068  mutt_addr_free(&from);
3069 
3070  return rc;
3071 }
#define _(a)
Definition: message.h:28
struct Address * mutt_addr_copy_list(struct Address *addr, bool prune)
Copy a list of addresses.
Definition: address.c:750
An email address.
Definition: address.h:32
size_t mutt_addr_write(char *buf, size_t buflen, struct Address *addr, bool display)
Write an Address to a buffer.
Definition: address.c:1184
struct Address * mutt_default_from(void)
Get a default &#39;from&#39; Address.
Definition: send.c:1319
int mutt_addrlist_to_intl(struct Address *a, char **err)
Convert an Address list to Punycode.
Definition: address.c:1249
static int bounce_message(FILE *fp, struct Email *e, struct Address *to, const char *resent_from, struct Address *env_from)
Bounce an email message.
Definition: sendlib.c:2966
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2453
void mutt_addr_qualify(struct Address *addr, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:674
char * personal
real name of address
Definition: address.h:34
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define mutt_error(...)
Definition: logging.h:83
#define FREE(x)
Definition: memory.h:40
void mutt_addr_free(struct Address **p)
Free a list of Addresses.
Definition: address.c:451
WHERE char * C_Realname
Config: Real name of the user.
Definition: globals.h:136
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:43
void rfc2047_encode_addrlist(struct Address *addr, const char *tag)
Encode any RFC2047 headers, where required, in an Address list.
Definition: rfc2047.c:749

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

3079 {
3080  for (; b; b = b->next)
3081  {
3082  if ((b->type == TYPE_MESSAGE) || (b->type == TYPE_MULTIPART))
3083  set_noconv_flags(b->parts, flag);
3084  else if ((b->type == TYPE_TEXT) && b->noconv)
3085  {
3086  if (flag)
3087  mutt_param_set(&b->parameter, "x-mutt-noconv", "yes");
3088  else
3089  mutt_param_delete(&b->parameter, "x-mutt-noconv");
3090  }
3091  }
3092 }
bool noconv
don&#39;t do character set conversion
Definition: body.h:82
struct Body * next
next attachment in the list
Definition: body.h:60
Type: &#39;text/*&#39;.
Definition: mime.h:38
void mutt_param_set(struct ParameterList *p, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:109
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:61
unsigned int type
content-type primary type
Definition: body.h:72
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:3078
void mutt_param_delete(struct ParameterList *p, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:141
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:

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

3107 {
3108  char fcc_tok[PATH_MAX];
3109  char fcc_expanded[PATH_MAX];
3110 
3111  mutt_str_strfcpy(fcc_tok, path, sizeof(fcc_tok));
3112 
3113  char *tok = strtok(fcc_tok, ",");
3114  if (!tok)
3115  return -1;
3116 
3117  mutt_debug(LL_DEBUG1, "Fcc: initial mailbox = '%s'\n", tok);
3118  /* mutt_expand_path already called above for the first token */
3119  int status = mutt_write_fcc(tok, e, msgid, post, fcc, finalpath);
3120  if (status != 0)
3121  return status;
3122 
3123  while ((tok = strtok(NULL, ",")))
3124  {
3125  if (!*tok)
3126  continue;
3127 
3128  /* Only call mutt_expand_path if tok has some data */
3129  mutt_debug(LL_DEBUG1, "Fcc: additional mailbox token = '%s'\n", tok);
3130  mutt_str_strfcpy(fcc_expanded, tok, sizeof(fcc_expanded));
3131  mutt_expand_path(fcc_expanded, sizeof(fcc_expanded));
3132  mutt_debug(LL_DEBUG1, " Additional mailbox expanded = '%s'\n", fcc_expanded);
3133  status = mutt_write_fcc(fcc_expanded, e, msgid, post, fcc, finalpath);
3134  if (status != 0)
3135  return status;
3136  }
3137 
3138  return 0;
3139 }
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:127
#define PATH_MAX
Definition: mutt.h:49
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:753
Log at debug level 1.
Definition: logging.h:56
#define mutt_debug(LEVEL,...)
Definition: logging.h:80
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:3152

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

3154 {
3155  struct Message *msg = NULL;
3156  char tempfile[PATH_MAX];
3157  FILE *fp_tmp = NULL;
3158  int rc = -1;
3159  bool need_mailbox_cleanup = false;
3160  struct stat st;
3161  char buf[128];
3162  MsgOpenFlags onm_flags;
3163 
3164  if (post)
3165  set_noconv_flags(e->content, true);
3166 
3167 #ifdef RECORD_FOLDER_HOOK
3168  mutt_folder_hook(path, NULL);
3169 #endif
3170  struct Mailbox *m_fcc = mx_path_resolve(path);
3171  bool old_append = m_fcc->append;
3172  struct Context *ctx_fcc = mx_mbox_open(m_fcc, MUTT_APPEND | MUTT_QUIET);
3173  if (!ctx_fcc)
3174  {
3175  mutt_debug(LL_DEBUG1, "unable to open mailbox %s in append-mode, aborting\n", path);
3176  mailbox_free(&m_fcc);
3177  goto done;
3178  }
3179 
3180  /* We need to add a Content-Length field to avoid problems where a line in
3181  * the message body begins with "From " */
3182  if ((ctx_fcc->mailbox->magic == MUTT_MMDF) || (ctx_fcc->mailbox->magic == MUTT_MBOX))
3183  {
3184  mutt_mktemp(tempfile, sizeof(tempfile));
3185  fp_tmp = mutt_file_fopen(tempfile, "w+");
3186  if (!fp_tmp)
3187  {
3188  mutt_perror(tempfile);
3189  mx_mbox_close(&ctx_fcc);
3190  goto done;
3191  }
3192  /* remember new mail status before appending message */
3193  need_mailbox_cleanup = true;
3194  stat(path, &st);
3195  }
3196 
3197  e->read = !post; /* make sure to put it in the 'cur' directory (maildir) */
3198  onm_flags = MUTT_ADD_FROM;
3199  if (post)
3200  onm_flags |= MUTT_SET_DRAFT;
3201  msg = mx_msg_open_new(ctx_fcc->mailbox, e, onm_flags);
3202  if (!msg)
3203  {
3204  mutt_file_fclose(&fp_tmp);
3205  mx_mbox_close(&ctx_fcc);
3206  goto done;
3207  }
3208 
3209  /* post == 1 => postpone message.
3210  * post == 0 => Normal mode. */
3214 
3215  /* (postponement) if this was a reply of some sort, <msgid> contains the
3216  * Message-ID: of message replied to. Save it using a special X-Mutt-
3217  * header so it can be picked up if the message is recalled at a later
3218  * point in time. This will allow the message to be marked as replied if
3219  * the same mailbox is still open. */
3220  if (post && msgid)
3221  fprintf(msg->fp, "X-Mutt-References: %s\n", msgid);
3222 
3223  /* (postponement) save the Fcc: using a special X-Mutt- header so that
3224  * it can be picked up when the message is recalled */
3225  if (post && fcc)
3226  fprintf(msg->fp, "X-Mutt-Fcc: %s\n", fcc);
3227 
3228  if ((ctx_fcc->mailbox->magic == MUTT_MMDF) || (ctx_fcc->mailbox->magic == MUTT_MBOX))
3229  fprintf(msg->fp, "Status: RO\n");
3230 
3231  /* mutt_rfc822_write_header() only writes out a Date: header with
3232  * mode == 0, i.e. _not_ postponement; so write out one ourself */
3233  if (post)
3234  fprintf(msg->fp, "%s", mutt_date_make_date(buf, sizeof(buf)));
3235 
3236  /* (postponement) if the mail is to be signed or encrypted, save this info */
3237  if (((WithCrypto & APPLICATION_PGP) != 0) && post && (e->security & APPLICATION_PGP))
3238  {
3239  fputs("X-Mutt-PGP: ", msg->fp);
3240  if (e->security & SEC_ENCRYPT)
3241  fputc('E', msg->fp);
3242  if (e->security & SEC_OPPENCRYPT)
3243  fputc('O', msg->fp);
3244  if (e->security & SEC_SIGN)
3245  {
3246  fputc('S', msg->fp);
3247  if (C_PgpSignAs && *C_PgpSignAs)
3248  fprintf(msg->fp, "<%s>", C_PgpSignAs);
3249  }
3250  if (e->security & SEC_INLINE)
3251  fputc('I', msg->fp);
3252  fputc('\n', msg->fp);
3253  }
3254 
3255  /* (postponement) if the mail is to be signed or encrypted, save this info */
3256  if (((WithCrypto & APPLICATION_SMIME) != 0) && post && (e->security & APPLICATION_SMIME))
3257  {
3258  fputs("X-Mutt-SMIME: ", msg->fp);
3259  if (e->security & SEC_ENCRYPT)
3260  {
3261  fputc('E', msg->fp);
3263  fprintf(msg->fp, "C<%s>", C_SmimeEncryptWith);
3264  }
3265  if (e->security & SEC_OPPENCRYPT)
3266  fputc('O', msg->fp);
3267  if (e->security & SEC_SIGN)
3268  {
3269  fputc('S', msg->fp);
3270  if (C_SmimeSignAs && *C_SmimeSignAs)
3271  fprintf(msg->fp, "<%s>", C_SmimeSignAs);
3272  }
3273  if (e->security & SEC_INLINE)
3274  fputc('I', msg->fp);
3275  fputc('\n', msg->fp);
3276  }
3277 
3278 #ifdef MIXMASTER
3279  /* (postponement) if the mail is to be sent through a mixmaster
3280  * chain, save that information */
3281 
3282  if (post && !STAILQ_EMPTY(&e->chain))
3283  {
3284  fputs("X-Mutt-Mix:", msg->fp);
3285  struct ListNode *p = NULL;
3286  STAILQ_FOREACH(p, &e->chain, entries)
3287  {
3288  fprintf(msg->fp, " %s", (char *) p->data);
3289  }
3290 
3291  fputc('\n', msg->fp);
3292  }
3293 #endif
3294 
3295  if (fp_tmp)
3296  {
3297  mutt_write_mime_body(e->content, fp_tmp);
3298 
3299  /* make sure the last line ends with a newline. Emacs doesn't ensure this
3300  * will happen, and it can cause problems parsing the mailbox later. */
3301  fseek(fp_tmp, -1, SEEK_END);
3302  if (fgetc(fp_tmp) != '\n')
3303  {
3304  fseek(fp_tmp, 0, SEEK_END);
3305  fputc('\n', fp_tmp);
3306  }
3307 
3308  fflush(fp_tmp);
3309  if (ferror(fp_tmp))
3310  {
3311  mutt_debug(LL_DEBUG1, "%s: write failed\n", tempfile);
3312  mutt_file_fclose(&fp_tmp);
3313  unlink(tempfile);
3314  mx_msg_commit(ctx_fcc->mailbox, msg); /* XXX really? */
3315  mx_msg_close(ctx_fcc->mailbox, &msg);
3316  mx_mbox_close(&ctx_fcc);
3317  goto done;
3318  }
3319 
3320  /* count the number of lines */
3321  int lines = 0;
3322  char line_buf[1024];
3323  rewind(fp_tmp);
3324  while (fgets(line_buf, sizeof(line_buf), fp_tmp))
3325  lines++;
3326  fprintf(msg->fp, "Content-Length: " OFF_T_FMT "\n", (LOFF_T) ftello(fp_tmp));
3327  fprintf(msg->fp, "Lines: %d\n\n", lines);
3328 
3329  /* copy the body and clean up */
3330  rewind(fp_tmp);
3331  rc = mutt_file_copy_stream(fp_tmp, msg->fp);
3332  if (fclose(fp_tmp) != 0)
3333  rc = -1;
3334  /* if there was an error, leave the temp version */
3335  if (rc == 0)
3336  unlink(tempfile);
3337  }
3338  else
3339  {
3340  fputc('\n', msg->fp); /* finish off the header */
3341  rc = mutt_write_mime_body(e->content, msg->fp);
3342  }
3343 
3344  if (mx_msg_commit(ctx_fcc->mailbox, msg) != 0)
3345  rc = -1;
3346  else if (finalpath)
3347  *finalpath = mutt_str_strdup(msg->committed_path);
3348  mx_msg_close(ctx_fcc->mailbox, &msg);
3349  mx_mbox_close(&ctx_fcc);
3350 
3351  if (!post && need_mailbox_cleanup)
3352  mutt_mailbox_cleanup(path, &st);
3353 
3354  if (post)
3355  set_noconv_flags(e->content, false);
3356 
3357 done:
3358  m_fcc->append = old_append;
3359 #ifdef RECORD_FOLDER_HOOK
3360  /* We ran a folder hook for the destination mailbox,
3361  * now we run it for the user's current mailbox */
3362  if (Context && Context->mailbox->path)
3364 #endif
3365 
3366  return rc;
3367 }
#define MUTT_APPEND
Open mailbox for appending messages.
Definition: mx.h:50
The "current" mailbox.
Definition: context.h:38
#define mutt_perror(...)
Definition: logging.h:84
int mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:546
char * desc
Definition: mailbox.h:87
A normal Email, write full header + MIME headers.
Definition: sendlib.h:62
bool mutt_should_hide_protected_subject(struct Email *e)
Should NeoMutt hide the protected subject?
Definition: crypt.c:1032
struct Body * content
list of MIME parts
Definition: email.h:93
&#39;mmdf&#39; Mailbox type
Definition: magic.h:38
A postponed Email, just the envelope info.
Definition: sendlib.h:63
void mutt_mailbox_cleanup(const char *path, struct stat *st)
Restore the timestamp of a mailbox.
Definition: mailbox.c:216
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:247
#define SEC_INLINE
Email has an inline signature.
Definition: ncrypt.h:127
#define SEC_ENCRYPT
Email is encrypted.
Definition: ncrypt.h:120
char * mutt_date_make_date(char *buf, size_t buflen)
Write a date in RFC822 format to a buffer.
Definition: date.c:382
#define MUTT_SET_DRAFT
set the message draft flag
Definition: mx.h:63
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:2233
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1077
void mutt_folder_hook(const char *path, const char *desc)
Perform a folder hook.
Definition: hook.c:514
bool read
Definition: email.h:51
struct Mailbox * mailbox
Definition: context.h:52
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:105
enum MailboxType magic
mailbox type
Definition: mailbox.h:105
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:92
struct Message * mx_msg_open_new(struct Mailbox *m, struct Email *e, MsgOpenFlags flags)
Open a new message.
Definition: mx.c:946
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:74
#define SEC_SIGN
Email is signed.
Definition: ncrypt.h:121
&#39;mbox&#39; Mailbox type
Definition: magic.h:37
A local copy of an email.
Definition: mx.h:79
A mailbox.
Definition: mailbox.h:83
#define PATH_MAX
Definition: mutt.h:49
int mutt_write_mime_body(struct Body *a, FILE *fp)
Write a MIME part.
Definition: sendlib.c:506
WHERE char * C_SmimeEncryptWith
Config: Algorithm for encryption.
Definition: globals.h:168
bool append
mailbox is opened in append mode
Definition: mailbox.h:113
#define MUTT_QUIET
Do not print any messages.
Definition: mx.h:52
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
SecurityFlags security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:39
WHERE bool C_CryptProtectedHeadersRead
Config: Display protected headers (Memory Hole) in the pager.
Definition: globals.h:268
uint8_t MsgOpenFlags
Flags for mx_msg_open_new(), e.g. MUTT_ADD_FROM.
Definition: mx.h:60
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: ncrypt.h:128
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:129
char * committed_path
the final path generated by mx_msg_commit()
Definition: mx.h:83
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:264
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:1056
FILE * fp
pointer to the message data
Definition: mx.h:81
struct Mailbox * mx_path_resolve(const char *path)
XXX.
Definition: mx.c:1531
static void set_noconv_flags(struct Body *b, bool flag)
Set/reset the "x-mutt-noconv" flag.
Definition: sendlib.c:3078
#define STAILQ_EMPTY(head)
Definition: queue.h:346
#define mutt_debug(LEVEL,...)
Definition: logging.h:80
WHERE char * C_PgpSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:163
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:578
WHERE char * C_SmimeSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:167
A List node for strings.
Definition: list.h:33
#define MUTT_ADD_FROM
add a From_ line
Definition: mx.h:62
#define WithCrypto
Definition: ncrypt.h:155
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: ncrypt.h:130

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

char* C_AttachCharset

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

Definition at line 78 of file sendlib.c.

bool C_BounceDelivered

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

Definition at line 79 of file sendlib.c.

bool C_EncodeFrom

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

Definition at line 80 of file sendlib.c.

bool C_ForwardDecrypt

Config: Decrypt the message when forwarding it.

Definition at line 81 of file sendlib.c.

bool C_HiddenHost

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

Definition at line 82 of file sendlib.c.

char* C_Inews

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

Definition at line 83 of file sendlib.c.

bool C_MimeForwardDecode

Config: Decode the forwarded message before attaching it.

Definition at line 84 of file sendlib.c.

bool C_MimeSubject

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

encode subject line with RFC2047

Definition at line 85 of file sendlib.c.

char* C_MimeTypeQueryCommand

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

Definition at line 86 of file sendlib.c.

bool C_MimeTypeQueryFirst

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

Definition at line 87 of file sendlib.c.

char* C_Sendmail

Config: External command to send email.

Definition at line 88 of file sendlib.c.

short C_SendmailWait

Config: Time to wait for sendmail to finish.

Definition at line 89 of file sendlib.c.

bool C_Use8bitmime

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

Definition at line 90 of file sendlib.c.

bool C_UseEnvelopeFrom

Config: Set the envelope sender of the message.

Definition at line 91 of file sendlib.c.

bool C_UserAgent

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

Definition at line 92 of file sendlib.c.

short C_WrapHeaders

Config: Width to wrap headers in outgoing messages.

Definition at line 93 of file sendlib.c.