NeoMutt  2018-07-16 +1360-3df4a2
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 "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 72 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 100 of file sendlib.c.

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

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

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

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

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

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

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

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

307 {
308  struct B64Context bctx;
309  int ch, ch1 = EOF;
310 
311  b64_init(&bctx);
312 
313  while ((ch = mutt_ch_fgetconv(fc)) != EOF)
314  {
315  if (SigInt == 1)
316  {
317  SigInt = 0;
318  return;
319  }
320  if (istext && (ch == '\n') && (ch1 != '\r'))
321  b64_putc(&bctx, '\r', fp_out);
322  b64_putc(&bctx, ch, fp_out);
323  ch1 = ch;
324  }
325  b64_flush(&bctx, fp_out);
326  fputc('\n', fp_out);
327 }
static void b64_putc(struct B64Context *bctx, char c, FILE *fp_out)
Base64-encode one character.
Definition: sendlib.c:292
int mutt_ch_fgetconv(struct FgetConv *fc)
Convert a file&#39;s character set.
Definition: charset.c:864
WHERE SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: globals.h:91
static int b64_init(struct B64Context *bctx)
Set up the base64 conversion.
Definition: sendlib.c:243
static void b64_flush(struct B64Context *bctx, FILE *fp_out)
Save the bytes to the file.
Definition: sendlib.c:257
Cursor for the Base64 conversion.
Definition: sendlib.c:231

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

335 {
336  int ch;
337 
338  while ((ch = mutt_ch_fgetconv(fc)) != EOF)
339  {
340  if (SigInt == 1)
341  {
342  SigInt = 0;
343  return;
344  }
345  fputc(ch, fp_out);
346  }
347 }
int mutt_ch_fgetconv(struct FgetConv *fc)
Convert a file&#39;s character set.
Definition: charset.c:864
WHERE SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: globals.h:91

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

357 {
358  fprintf(fp, "Content-Type: %s/%s", TYPE(a), a->subtype);
359 
360  if (!TAILQ_EMPTY(&a->parameter))
361  {
362  size_t len = 25 + mutt_str_strlen(a->subtype); /* approximate len. of content-type */
363 
364  struct Parameter *np = NULL;
365  TAILQ_FOREACH(np, &a->parameter, entries)
366  {
367  char *tmp = NULL;
368 
369  if (!np->value)
370  continue;
371 
372  fputc(';', fp);
373 
374  char buf[256];
375  buf[0] = '\0';
376  tmp = mutt_str_strdup(np->value);
377  const int encode = rfc2231_encode_string(&tmp);
378  mutt_addr_cat(buf, sizeof(buf), tmp, MimeSpecials);
379 
380  /* Dirty hack to make messages readable by Outlook Express for the Mac:
381  * force quotes around the boundary parameter even when they aren't
382  * needed. */
383 
384  if ((mutt_str_strcasecmp(np->attribute, "boundary") == 0) && (strcmp(buf, tmp) == 0))
385  {
386  snprintf(buf, sizeof(buf), "\"%s\"", tmp);
387  }
388 
389  FREE(&tmp);
390 
391  const int tmplen = mutt_str_strlen(buf) + mutt_str_strlen(np->attribute) + 1;
392 
393  if (len + tmplen + 2 > 76)
394  {
395  fputs("\n\t", fp);
396  len = tmplen + 8;
397  }
398  else
399  {
400  fputc(' ', fp);
401  len += tmplen + 1;
402  }
403 
404  fprintf(fp, "%s%s=%s", np->attribute, encode ? "*" : "", buf);
405  }
406  }
407 
408  fputc('\n', fp);
409 
410  if (a->language)
411  fprintf(fp, "Content-Language: %s\n", a->language);
412 
413  if (a->description)
414  fprintf(fp, "Content-Description: %s\n", a->description);
415 
416  if (a->disposition != DISP_NONE)
417  {
418  const char *dispstr[] = { "inline", "attachment", "form-data" };
419 
420  if (a->disposition < sizeof(dispstr) / sizeof(char *))
421  {
422  fprintf(fp, "Content-Disposition: %s", dispstr[a->disposition]);
423 
424  if (a->use_disp && (a->disposition != DISP_INLINE))
425  {
426  char *fn = a->d_filename;
427  if (!fn)
428  fn = a->filename;
429 
430  if (fn)
431  {
432  char *tmp = NULL;
433 
434  /* Strip off the leading path... */
435  char *t = strrchr(fn, '/');
436  if (t)
437  t++;
438  else
439  t = fn;
440 
441  char buf[256];
442  buf[0] = '\0';
443  tmp = mutt_str_strdup(t);
444  const int encode = rfc2231_encode_string(&tmp);
445  mutt_addr_cat(buf, sizeof(buf), tmp, MimeSpecials);
446  FREE(&tmp);
447  fprintf(fp, "; filename%s=%s", encode ? "*" : "", buf);
448  }
449  }
450 
451  fputc('\n', fp);
452  }
453  else
454  {
455  mutt_debug(LL_DEBUG1, "ERROR: invalid content-disposition %d\n", a->disposition);
456  }
457  }
458 
459  if (a->encoding != ENC_7BIT)
460  fprintf(fp, "Content-Transfer-Encoding: %s\n", ENCODING(a->encoding));
461 
463  mutt_rfc822_write_header(fp, a->mime_headers, NULL, MUTT_WRITE_HEADER_MIME, false, false);
464 
465  /* Do NOT add the terminator here!!! */
466  return ferror(fp) ? -1 : 0;
467 }
char * attribute
Definition: parameter.h:39
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:68
#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:278
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:662
unsigned int disposition
content-disposition
Definition: body.h:72
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:2212
#define ENCODING(x)
Definition: mime.h:85
unsigned int encoding
content-transfer-encoding
Definition: body.h:71
char * subtype
content-type subtype
Definition: body.h:37
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:681
const char MimeSpecials[]
Characters that need special treatment in MIME.
Definition: mime.c:67
static int encode(const char *d, size_t dlen, int col, const char *fromcode, const char *charsets, char **e, size_t *elen, const char *specials)
RFC2047-encode a string.
Definition: rfc2047.c:427
char * description
content-description
Definition: body.h:40
#define TYPE(body)
Definition: mime.h:83
char * value
Definition: parameter.h:40
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:73
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:383
int rfc2231_encode_string(char **pd)
Encode a string to be suitable for an RFC2231 header.
Definition: rfc2231.c:322
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:624
Attribute associated with a MIME part.
Definition: parameter.h:37
#define FREE(x)
Definition: memory.h:40
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:85
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

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

475 {
476  return mutt_is_text_part(b) ||
478 }
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:525
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
Definition: muttlib.c:427
#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 487 of file sendlib.c.

488 {
489  FILE *fp_in = NULL;
490  struct FgetConv *fc = NULL;
491 
492  if (a->type == TYPE_MULTIPART)
493  {
494  /* First, find the boundary to use */
495  const char *p = mutt_param_get(&a->parameter, "boundary");
496  if (!p)
497  {
498  mutt_debug(LL_DEBUG1, "no boundary parameter found\n");
499  mutt_error(_("No boundary parameter found [report this error]"));
500  return -1;
501  }
502  char boundary[128];
503  mutt_str_strfcpy(boundary, p, sizeof(boundary));
504 
505  for (struct Body *t = a->parts; t; t = t->next)
506  {
507  fprintf(fp, "\n--%s\n", boundary);
508  if (mutt_write_mime_header(t, fp) == -1)
509  return -1;
510  fputc('\n', fp);
511  if (mutt_write_mime_body(t, fp) == -1)
512  return -1;
513  }
514  fprintf(fp, "\n--%s--\n", boundary);
515  return ferror(fp) ? -1 : 0;
516  }
517 
518  /* This is pretty gross, but it's the best solution for now... */
519  if (((WithCrypto & APPLICATION_PGP) != 0) && (a->type == TYPE_APPLICATION) &&
520  (mutt_str_strcmp(a->subtype, "pgp-encrypted") == 0))
521  {
522  fputs("Version: 1\n", fp);
523  return 0;
524  }
525 
526  fp_in = fopen(a->filename, "r");
527  if (!fp_in)
528  {
529  mutt_debug(LL_DEBUG1, "%s no longer exists\n", a->filename);
530  mutt_error(_("%s no longer exists"), a->filename);
531  return -1;
532  }
533 
534  if ((a->type == TYPE_TEXT) && (!a->noconv))
535  {
536  char send_charset[128];
538  fp_in, a->charset,
539  mutt_body_get_charset(a, send_charset, sizeof(send_charset)), 0);
540  }
541  else
542  fc = mutt_ch_fgetconv_open(fp_in, 0, 0, 0);
543 
545  if (a->encoding == ENC_QUOTED_PRINTABLE)
547  else if (a->encoding == ENC_BASE64)
549  else if ((a->type == TYPE_TEXT) && (!a->noconv))
550  encode_8bit(fc, fp);
551  else
552  mutt_file_copy_stream(fp_in, fp);
554 
556  mutt_file_fclose(&fp_in);
557 
558  if (SigInt == 1)
559  {
560  SigInt = 0;
561  return -1;
562  }
563  return ferror(fp) ? -1 : 0;
564 }
void mutt_sig_allow_interrupt(int disposition)
Allow/disallow Ctrl-C (SIGINT)
Definition: signal.c:230
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:48
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
WHERE SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: globals.h:91
static void encode_base64(struct FgetConv *fc, FILE *fp_out, int istext)
Base64-encode some data.
Definition: sendlib.c:306
bool noconv
don&#39;t do character set conversion
Definition: body.h:80
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:58
static bool write_as_text_part(struct Body *b)
Should the Body be written as a text MIME part.
Definition: sendlib.c:474
The body of an email.
Definition: body.h:34
unsigned int encoding
content-transfer-encoding
Definition: body.h:71
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:100
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:487
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:59
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:741
char * charset
charset of attached file
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:1404
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:334
unsigned int type
content-type primary type
Definition: body.h:70
#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:847
char * mutt_param_get(const struct ParameterList *p, const char *s)
Find a matching Parameter.
Definition: parameter.c:81
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
Log at debug level 1.
Definition: logging.h:56
#define mutt_error(...)
Definition: logging.h:88
Quoted-printable text.
Definition: mime.h:51
int mutt_write_mime_header(struct Body *a, FILE *fp)
Create a MIME header.
Definition: sendlib.c:356
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:263
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
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:817
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:611
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 570 of file sendlib.c.

571 {
572  char rs[MUTT_RANDTAG_LEN + 1];
573 
574  mutt_rand_base32(rs, sizeof(rs) - 1);
575  rs[MUTT_RANDTAG_LEN] = 0;
576  mutt_param_set(parm, "boundary", rs);
577 }
#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:107
void mutt_rand_base32(void *buf, size_t buflen)
Fill a buffer with a base32-encoded random string.
Definition: muttlib.c:507

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

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

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

902 {
903  char *fcode = NULL;
904  char **tcode = NULL;
905  const char *c = NULL, *c1 = NULL;
906  size_t ret;
907  int ncodes, i, cn;
908 
909  /* Count the tocodes */
910  ncodes = 0;
911  for (c = tocodes; c; c = c1 ? c1 + 1 : 0)
912  {
913  c1 = strchr(c, ':');
914  if (c1 == c)
915  continue;
916  ncodes++;
917  }
918 
919  /* Copy them */
920  tcode = mutt_mem_malloc(ncodes * sizeof(char *));
921  for (c = tocodes, i = 0; c; c = c1 ? c1 + 1 : 0, i++)
922  {
923  c1 = strchr(c, ':');
924  if (c1 == c)
925  continue;
926  tcode[i] = mutt_str_substr_dup(c, c1);
927  }
928 
929  ret = (size_t)(-1);
930  if (fromcode)
931  {
932  /* Try each fromcode in turn */
933  for (c = fromcodes; c; c = c1 ? c1 + 1 : 0)
934  {
935  c1 = strchr(c, ':');
936  if (c1 == c)
937  continue;
938  fcode = mutt_str_substr_dup(c, c1);
939 
940  ret = convert_file_to(fp, fcode, ncodes, (const char **) tcode, &cn, info);
941  if (ret != (size_t)(-1))
942  {
943  *fromcode = fcode;
944  *tocode = tcode[cn];
945  tcode[cn] = 0;
946  break;
947  }
948  FREE(&fcode);
949  }
950  }
951  else
952  {
953  /* There is only one fromcode */
954  ret = convert_file_to(fp, fromcodes, ncodes, (const char **) tcode, &cn, info);
955  if (ret != (size_t)(-1))
956  {
957  *tocode = tcode[cn];
958  tcode[cn] = 0;
959  }
960  }
961 
962  /* Free memory */
963  for (i = 0; i < ncodes; i++)
964  FREE(&tcode[i]);
965 
966  FREE(&tcode);
967 
968  return ret;
969 }
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:747
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:99
#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:575

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

980 {
981  struct Content *info = NULL;
982  struct ContentState state = { 0 };
983  FILE *fp = NULL;
984  char *fromcode = NULL;
985  char *tocode = NULL;
986  char buf[100];
987  size_t r;
988 
989  struct stat sb;
990 
991  if (b && !fname)
992  fname = b->filename;
993 
994  if (stat(fname, &sb) == -1)
995  {
996  mutt_error(_("Can't stat %s: %s"), fname, strerror(errno));
997  return NULL;
998  }
999 
1000  if (!S_ISREG(sb.st_mode))
1001  {
1002  mutt_error(_("%s isn't a regular file"), fname);
1003  return NULL;
1004  }
1005 
1006  fp = fopen(fname, "r");
1007  if (!fp)
1008  {
1009  mutt_debug(LL_DEBUG1, "%s: %s (errno %d).\n", fname, strerror(errno), errno);
1010  return NULL;
1011  }
1012 
1013  info = mutt_mem_calloc(1, sizeof(struct Content));
1014 
1015  if (b && (b->type == TYPE_TEXT) && (!b->noconv && !b->force_charset))
1016  {
1017  char *chs = mutt_param_get(&b->parameter, "charset");
1018  char *fchs = b->use_disp ?
1020  C_Charset;
1021  if (C_Charset && (chs || C_SendCharset) &&
1022  (convert_file_from_to(fp, fchs, chs ? chs : C_SendCharset, &fromcode,
1023  &tocode, info) != (size_t)(-1)))
1024  {
1025  if (!chs)
1026  {
1027  char chsbuf[256];
1028  mutt_ch_canonical_charset(chsbuf, sizeof(chsbuf), tocode);
1029  mutt_param_set(&b->parameter, "charset", chsbuf);
1030  }
1031  FREE(&b->charset);
1032  b->charset = fromcode;
1033  FREE(&tocode);
1034  mutt_file_fclose(&fp);
1035  return info;
1036  }
1037  }
1038 
1039  rewind(fp);
1040  while ((r = fread(buf, 1, sizeof(buf), fp)))
1041  update_content_info(info, &state, buf, r);
1042  update_content_info(info, &state, 0, 0);
1043 
1044  mutt_file_fclose(&fp);
1045 
1046  if (b && (b->type == TYPE_TEXT) && (!b->noconv && !b->force_charset))
1047  {
1048  mutt_param_set(&b->parameter, "charset",
1049  (!info->hibin ?
1050  "us-ascii" :
1051  C_Charset && !mutt_ch_is_us_ascii(C_Charset) ? C_Charset : "unknown-8bit"));
1052  }
1053 
1054  return info;
1055 }
Info about the body of an email.
Definition: sendlib.c:582
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:598
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
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
bool noconv
don&#39;t do character set conversion
Definition: body.h:80
#define _(a)
Definition: message.h:28
long hibin
8-bit characters
Definition: content.h:35
char * C_SendCharset
Config: Character sets for outgoing mail ///< Config: List of character sets for outgoing messages...
Definition: email_globals.c:37
bool force_charset
send mode: don&#39;t adjust the character set when in send-mode.
Definition: body.h:81
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:77
void mutt_param_set(struct ParameterList *p, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:107
char * charset
charset of attached file
Definition: body.h:53
unsigned int type
content-type primary type
Definition: body.h:70
char * mutt_param_get(const struct ParameterList *p, const char *s)
Find a matching Parameter.
Definition: parameter.c:81
Log at debug level 1.
Definition: logging.h:56
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:73
#define mutt_error(...)
Definition: logging.h:88
#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:85
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:900

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

1070 {
1071  FILE *fp = NULL;
1072  char *p = NULL, *q = NULL, *ct = NULL;
1073  char buf[PATH_MAX];
1074  char subtype[256], xtype[256];
1075  int szf, sze, cur_sze;
1076  int type;
1077  bool found_mimetypes = false;
1078 
1079  *subtype = '\0';
1080  *xtype = '\0';
1081  type = TYPE_OTHER;
1082  cur_sze = 0;
1083 
1084  szf = mutt_str_strlen(path);
1085 
1086  for (int count = 0; count < 4; count++)
1087  {
1088  /* can't use strtok() because we use it in an inner loop below, so use
1089  * a switch statement here instead. */
1090  switch (count)
1091  {
1092  /* last file with last entry to match wins type/xtype */
1093  case 0:
1094  /* check default unix mimetypes location first */
1095  mutt_str_strfcpy(buf, "/etc/mime.types", sizeof(buf));
1096  break;
1097  case 1:
1098  mutt_str_strfcpy(buf, SYSCONFDIR "/mime.types", sizeof(buf));
1099  break;
1100  case 2:
1101  mutt_str_strfcpy(buf, PKGDATADIR "/mime.types", sizeof(buf));
1102  break;
1103  case 3:
1104  snprintf(buf, sizeof(buf), "%s/.mime.types", NONULL(HomeDir));
1105  break;
1106  default:
1107  mutt_debug(LL_DEBUG1, "Internal error, count = %d.\n", count);
1108  goto bye; /* shouldn't happen */
1109  }
1110 
1111  fp = fopen(buf, "r");
1112  if (fp)
1113  {
1114  found_mimetypes = true;
1115 
1116  while (fgets(buf, sizeof(buf) - 1, fp))
1117  {
1118  /* weed out any comments */
1119  p = strchr(buf, '#');
1120  if (p)
1121  *p = '\0';
1122 
1123  /* remove any leading space. */
1124  ct = buf;
1125  SKIPWS(ct);
1126 
1127  /* position on the next field in this line */
1128  p = strpbrk(ct, " \t");
1129  if (!p)
1130  continue;
1131  *p++ = 0;
1132  SKIPWS(p);
1133 
1134  /* cycle through the file extensions */
1135  while ((p = strtok(p, " \t\n")))
1136  {
1137  sze = mutt_str_strlen(p);
1138  if ((sze > cur_sze) && (szf >= sze) &&
1139  ((mutt_str_strcasecmp(path + szf - sze, p) == 0) ||
1140  (mutt_str_strcasecmp(path + szf - sze, p) == 0)) &&
1141  ((szf == sze) || (path[szf - sze - 1] == '.')))
1142  {
1143  /* get the content-type */
1144 
1145  p = strchr(ct, '/');
1146  if (!p)
1147  {
1148  /* malformed line, just skip it. */
1149  break;
1150  }
1151  *p++ = 0;
1152 
1153  for (q = p; *q && !ISSPACE(*q); q++)
1154  ;
1155 
1156  mutt_str_substr_cpy(subtype, p, q, sizeof(subtype));
1157 
1158  type = mutt_check_mime_type(ct);
1159  if (type == TYPE_OTHER)
1160  mutt_str_strfcpy(xtype, ct, sizeof(xtype));
1161 
1162  cur_sze = sze;
1163  }
1164  p = NULL;
1165  }
1166  }
1167  mutt_file_fclose(&fp);
1168  }
1169  }
1170 
1171 bye:
1172 
1173  /* no mime.types file found */
1174  if (!found_mimetypes)
1175  {
1176  mutt_error(_("Could not find any mime.types file."));
1177  }
1178 
1179  if ((type != TYPE_OTHER) || (*xtype != '\0'))
1180  {
1181  att->type = type;
1182  mutt_str_replace(&att->subtype, subtype);
1183  mutt_str_replace(&att->xtype, xtype);
1184  }
1185 
1186  return type;
1187 }
Unknown Content-Type.
Definition: mime.h:31
#define NONULL(x)
Definition: string2.h:36
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
#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:553
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:662
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:48
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:741
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:459
#define ISSPACE(ch)
Definition: string2.h:37
unsigned int type
content-type primary type
Definition: body.h:70
Log at debug level 1.
Definition: logging.h:56
#define mutt_error(...)
Definition: logging.h:88
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:624
int mutt_check_mime_type(const char *s)
Check a MIME type string.
Definition: parse.c:294
#define mutt_debug(LEVEL,...)
Definition: logging.h:85

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

1195 {
1196  char buf[PATH_MAX];
1197  struct State s = { 0 };
1198  struct stat sb;
1199 
1200  for (; a; a = a->next)
1201  {
1202  if (a->type == TYPE_MULTIPART)
1203  {
1204  if (a->encoding != ENC_7BIT)
1205  a->encoding = ENC_7BIT;
1206 
1207  transform_to_7bit(a->parts, fp_in);
1208  }
1209  else if (mutt_is_message_type(a->type, a->subtype))
1210  {
1211  mutt_message_to_7bit(a, fp_in);
1212  }
1213  else
1214  {
1215  a->noconv = true;
1216  a->force_charset = true;
1217 
1218  mutt_mktemp(buf, sizeof(buf));
1219  s.fp_out = mutt_file_fopen(buf, "w");
1220  if (!s.fp_out)
1221  {
1222  mutt_perror("fopen");
1223  return;
1224  }
1225  s.fp_in = fp_in;
1226  mutt_decode_attachment(a, &s);
1228  FREE(&a->d_filename);
1229  a->d_filename = a->filename;
1230  a->filename = mutt_str_strdup(buf);
1231  a->unlink = true;
1232  if (stat(a->filename, &sb) == -1)
1233  {
1234  mutt_perror("stat");
1235  return;
1236  }
1237  a->length = sb.st_size;
1238 
1240  if (a->encoding == ENC_8BIT)
1242  else if (a->encoding == ENC_BINARY)
1243  a->encoding = ENC_BASE64;
1244  }
1245  }
1246 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1748
void mutt_message_to_7bit(struct Body *a, FILE *fp)
Convert an email&#39;s MIME parts to 7-bit.
Definition: sendlib.c:1253
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:1255
#define mutt_perror(...)
Definition: logging.h:89
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
7-bit text
Definition: mime.h:49
bool noconv
don&#39;t do character set conversion
Definition: body.h:80
struct Body * next
next attachment in the list
Definition: body.h:58
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:1194
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:1428
bool force_charset
send mode: don&#39;t adjust the character set when in send-mode.
Definition: body.h:81
unsigned int encoding
content-transfer-encoding
Definition: body.h:71
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:72
LOFF_T length
length (in bytes) of attachment
Definition: body.h:47
#define PATH_MAX
Definition: mutt.h:48
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:59
unsigned int type
content-type primary type
Definition: body.h:70
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:546
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:383
bool unlink
flag to indicate the file named by "filename" should be unlink()ed before free()ing this structure ...
Definition: body.h:74
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

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

1254 {
1255  char temp[PATH_MAX];
1256  char *line = NULL;
1257  FILE *fp_in = NULL;
1258  FILE *fp_out = NULL;
1259  struct stat sb;
1260 
1261  if (!a->filename && fp)
1262  fp_in = fp;
1263  else if (!a->filename || !(fp_in = fopen(a->filename, "r")))
1264  {
1265  mutt_error(_("Could not open %s"), a->filename ? a->filename : "(null)");
1266  return;
1267  }
1268  else
1269  {
1270  a->offset = 0;
1271  if (stat(a->filename, &sb) == -1)
1272  {
1273  mutt_perror("stat");
1274  mutt_file_fclose(&fp_in);
1275  }
1276  a->length = sb.st_size;
1277  }
1278 
1279  mutt_mktemp(temp, sizeof(temp));
1280  fp_out = mutt_file_fopen(temp, "w+");
1281  if (!fp_out)
1282  {
1283  mutt_perror("fopen");
1284  goto cleanup;
1285  }
1286 
1287  if (!fp_in)
1288  goto cleanup;
1289 
1290  fseeko(fp_in, a->offset, SEEK_SET);
1291  a->parts = mutt_rfc822_parse_message(fp_in, a);
1292 
1293  transform_to_7bit(a->parts, fp_in);
1294 
1295  mutt_copy_hdr(fp_in, fp_out, a->offset, a->offset + a->length,
1296  CH_MIME | CH_NONEWLINE | CH_XMIT, NULL);
1297 
1298  fputs("MIME-Version: 1.0\n", fp_out);
1299  mutt_write_mime_header(a->parts, fp_out);
1300  fputc('\n', fp_out);
1301  mutt_write_mime_body(a->parts, fp_out);
1302 
1303 cleanup:
1304  FREE(&line);
1305 
1306  if (fp_in && (fp_in != fp))
1307  mutt_file_fclose(&fp_in);
1308  if (fp_out)
1309  mutt_file_fclose(&fp_out);
1310  else
1311  return;
1312 
1313  a->encoding = ENC_7BIT;
1314  FREE(&a->d_filename);
1315  a->d_filename = a->filename;
1316  if (a->filename && a->unlink)
1317  unlink(a->filename);
1318  a->filename = mutt_str_strdup(temp);
1319  a->unlink = true;
1320  if (stat(a->filename, &sb) == -1)
1321  {
1322  mutt_perror("stat");
1323  return;
1324  }
1325  a->length = sb.st_size;
1326  mutt_body_free(&a->parts);
1327  a->email->content = NULL;
1328 }
#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:89
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
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:1194
struct Body * mutt_rfc822_parse_message(FILE *fp, struct Body *parent)
parse a Message/RFC822 body
Definition: parse.c:1421
unsigned int encoding
content-transfer-encoding
Definition: body.h:71
const char * line
Definition: common.c:35
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:72
LOFF_T length
length (in bytes) of attachment
Definition: body.h:47
#define PATH_MAX
Definition: mutt.h:48
int mutt_write_mime_body(struct Body *a, FILE *fp)
Write a MIME part.
Definition: sendlib.c:487
#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:59
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:546
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:383
#define mutt_error(...)
Definition: logging.h:88
bool unlink
flag to indicate the file named by "filename" should be unlink()ed before free()ing this structure ...
Definition: body.h:74
#define FREE(x)
Definition: memory.h:40
int mutt_write_mime_header(struct Body *a, FILE *fp)
Create a MIME header.
Definition: sendlib.c:356
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:50
struct Email * email
header information for message/rfc822
Definition: body.h:60
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:72
#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 1335 of file sendlib.c.

1336 {
1337  if (b->type == TYPE_TEXT)
1338  {
1339  char send_charset[128];
1340  char *chsname = mutt_body_get_charset(b, send_charset, sizeof(send_charset));
1341  if ((info->lobin && !mutt_str_startswith(chsname, "iso-2022", CASE_IGNORE)) ||
1342  (info->linemax > 990) || (info->from && C_EncodeFrom))
1343  {
1345  }
1346  else if (info->hibin)
1347  {
1349  }
1350  else
1351  {
1352  b->encoding = ENC_7BIT;
1353  }
1354  }
1355  else if ((b->type == TYPE_MESSAGE) || (b->type == TYPE_MULTIPART))
1356  {
1357  if (info->lobin || info->hibin)
1358  {
1359  if (C_Allow8bit && !info->lobin)
1360  b->encoding = ENC_8BIT;
1361  else
1362  mutt_message_to_7bit(b, NULL);
1363  }
1364  else
1365  b->encoding = ENC_7BIT;
1366  }
1367  else if ((b->type == TYPE_APPLICATION) &&
1368  (mutt_str_strcasecmp(b->subtype, "pgp-keys") == 0))
1369  {
1370  b->encoding = ENC_7BIT;
1371  }
1372  else
1373  {
1374  /* Determine which encoding is smaller */
1375  if (1.33 * (float) (info->lobin + info->hibin + info->ascii) <
1376  3.0 * (float) (info->lobin + info->hibin) + (float) info->ascii)
1377  {
1378  b->encoding = ENC_BASE64;
1379  }
1380  else
1381  {
1383  }
1384  }
1385 }
void mutt_message_to_7bit(struct Body *a, FILE *fp)
Convert an email&#39;s MIME parts to 7-bit.
Definition: sendlib.c:1253
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:79
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:71
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:1404
unsigned int type
content-type primary type
Definition: body.h:70
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:165
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:624
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:76
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 1391 of file sendlib.c.

1392 {
1393  a->stamp = time(NULL);
1394 }
time_t stamp
time stamp of last encoding update.
Definition: body.h:66

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

1405 {
1406  char *p = NULL;
1407 
1408  if (b && (b->type != TYPE_TEXT))
1409  return NULL;
1410 
1411  if (b)
1412  p = mutt_param_get(&b->parameter, "charset");
1413 
1414  if (p)
1415  mutt_ch_canonical_charset(buf, buflen, p);
1416  else
1417  mutt_str_strfcpy(buf, "us-ascii", buflen);
1418 
1419  return buf;
1420 }
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:741
unsigned int type
content-type primary type
Definition: body.h:70
char * mutt_param_get(const struct ParameterList *p, const char *s)
Find a matching Parameter.
Definition: parameter.c:81
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 1428 of file sendlib.c.

1429 {
1430  struct Content *info = NULL;
1431  char chsbuf[256];
1432 
1433  /* override noconv when it's us-ascii */
1434  if (mutt_ch_is_us_ascii(mutt_body_get_charset(a, chsbuf, sizeof(chsbuf))))
1435  a->noconv = false;
1436 
1437  if (!a->force_charset && !a->noconv)
1438  mutt_param_delete(&a->parameter, "charset");
1439 
1440  info = mutt_get_content_info(a->filename, a);
1441  if (!info)
1442  return;
1443 
1444  set_encoding(a, info);
1446 
1447  FREE(&a->content);
1448  a->content = info;
1449 }
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:1391
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:54
bool noconv
don&#39;t do character set conversion
Definition: body.h:80
struct Content * mutt_get_content_info(const char *fname, struct Body *b)
Analyze file to determine MIME encoding to use.
Definition: sendlib.c:979
bool force_charset
send mode: don&#39;t adjust the character set when in send-mode.
Definition: body.h:81
#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:1335
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body&#39;s character set.
Definition: sendlib.c:1404
#define FREE(x)
Definition: memory.h:40
void mutt_param_delete(struct ParameterList *p, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:139
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 1459 of file sendlib.c.

1460 {
1461  char buf[1024];
1462  struct Body *body = NULL;
1463  FILE *fp = NULL;
1464  CopyMessageFlags cmflags;
1466 
1467  if (WithCrypto)
1468  {
1470  {
1472  return NULL;
1473  }
1474  }
1475 
1476  mutt_mktemp(buf, sizeof(buf));
1477  fp = mutt_file_fopen(buf, "w+");
1478  if (!fp)
1479  return NULL;
1480 
1481  body = mutt_body_new();
1482  body->type = TYPE_MESSAGE;
1483  body->subtype = mutt_str_strdup("rfc822");
1484  body->filename = mutt_str_strdup(buf);
1485  body->unlink = true;
1486  body->use_disp = false;
1487  body->disposition = DISP_INLINE;
1488  body->noconv = true;
1489 
1491 
1492  CopyHeaderFlags chflags = CH_XMIT;
1493  cmflags = MUTT_CM_NO_FLAGS;
1494 
1495  /* If we are attaching a message, ignore C_MimeForwardDecode */
1496  if (!attach_msg && C_MimeForwardDecode)
1497  {
1498  chflags |= CH_MIME | CH_TXTPLAIN;
1499  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1501  pgp &= ~PGP_ENCRYPT;
1503  pgp &= ~SMIME_ENCRYPT;
1504  }
1505  else if ((WithCrypto != 0) && C_ForwardDecrypt && (e->security & SEC_ENCRYPT))
1506  {
1507  if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_multipart_encrypted(e->content))
1508  {
1509  chflags |= CH_MIME | CH_NONEWLINE;
1510  cmflags = MUTT_CM_DECODE_PGP;
1511  pgp &= ~PGP_ENCRYPT;
1512  }
1513  else if (((WithCrypto & APPLICATION_PGP) != 0) &&
1515  {
1516  chflags |= CH_MIME | CH_TXTPLAIN;
1517  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1518  pgp &= ~PGP_ENCRYPT;
1519  }
1520  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
1522  {
1523  chflags |= CH_MIME | CH_TXTPLAIN;
1524  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1525  pgp &= ~SMIME_ENCRYPT;
1526  }
1527  }
1528 
1529  mutt_copy_message_ctx(fp, m, e, cmflags, chflags);
1530 
1531  fflush(fp);
1532  rewind(fp);
1533 
1534  body->email = mutt_email_new();
1535  body->email->offset = 0;
1536  /* we don't need the user headers here */
1537  body->email->env = mutt_rfc822_read_header(fp, body->email, false, false);
1538  if (WithCrypto)
1539  body->email->security = pgp;
1540  mutt_update_encoding(body);
1541  body->parts = body->email->content;
1542 
1543  mutt_file_fclose(&fp);
1544 
1545  return body;
1546 }
#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:83
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
#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:80
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:72
int crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:144
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:418
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:799
void mutt_update_encoding(struct Body *a)
Update the encoding type.
Definition: sendlib.c:1428
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:525
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:72
#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:80
#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:59
SecurityFlags mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
Definition: crypt.c:584
SecurityFlags security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:39
unsigned int type
content-type primary type
Definition: body.h:70
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
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:546
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:73
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:383
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:74
#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
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:1011
struct Email * email
header information for message/rfc822
Definition: body.h:60
#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 1554 of file sendlib.c.

1555 {
1556  FILE *fp, *fp_err;
1557  char cmd[STR_COMMAND];
1558  char *buf = NULL;
1559  size_t buflen;
1560  int dummy = 0;
1561  pid_t pid;
1562 
1564 
1565  pid = mutt_create_filter(cmd, NULL, &fp, &fp_err);
1566  if (pid < 0)
1567  {
1568  mutt_error(_("Error running \"%s\""), cmd);
1569  return;
1570  }
1571 
1572  buf = mutt_file_read_line(buf, &buflen, fp, &dummy, 0);
1573  if (buf)
1574  {
1575  if (strchr(buf, '/'))
1576  mutt_parse_content_type(buf, att);
1577  FREE(&buf);
1578  }
1579 
1580  mutt_file_fclose(&fp);
1581  mutt_file_fclose(&fp_err);
1582  mutt_wait_filter(pid);
1583 }
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
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:630
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
#define _(a)
Definition: message.h:28
#define STR_COMMAND
Enough space for a long command line.
Definition: string2.h:34
void mutt_parse_content_type(const char *s, struct Body *ct)
Parse a content type.
Definition: parse.c:432
char * C_MimeTypeQueryCommand
Config: External command to determine the MIME type of an attachment.
Definition: sendlib.c:85
#define mutt_error(...)
Definition: logging.h:88
void mutt_file_expand_fmt_quote(char *dest, size_t destlen, const char *fmt, const char *src)
Replace s in a string with a filename.
Definition: file.c:1320
#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

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

1592 {
1593  struct Body *att = mutt_body_new();
1594  att->filename = mutt_str_strdup(path);
1595 
1597  run_mime_type_query(att);
1598 
1599  /* Attempt to determine the appropriate content-type based on the filename
1600  * suffix. */
1601  if (!att->subtype)
1602  mutt_lookup_mime_type(att, path);
1603 
1605  {
1606  run_mime_type_query(att);
1607  }
1608 
1609  struct Content *info = mutt_get_content_info(path, att);
1610  if (!info)
1611  {
1612  mutt_body_free(&att);
1613  return NULL;
1614  }
1615 
1616  if (!att->subtype)
1617  {
1618  if ((info->nulbin == 0) &&
1619  ((info->lobin == 0) || ((info->lobin + info->hibin + info->ascii) / info->lobin >= 10)))
1620  {
1621  /* Statistically speaking, there should be more than 10% "lobin"
1622  * chars if this is really a binary file... */
1623  att->type = TYPE_TEXT;
1624  att->subtype = mutt_str_strdup("plain");
1625  }
1626  else
1627  {
1628  att->type = TYPE_APPLICATION;
1629  att->subtype = mutt_str_strdup("octet-stream");
1630  }
1631  }
1632 
1633  FREE(&info);
1634  mutt_update_encoding(att);
1635  return att;
1636 }
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:1554
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:979
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:1428
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:1069
unsigned int type
content-type primary type
Definition: body.h:70
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:383
char * C_MimeTypeQueryCommand
Config: External command to determine the MIME type of an attachment.
Definition: sendlib.c:85
#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:86

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

1644 {
1645  int e = ENC_7BIT;
1646 
1647  for (; a; a = a->next)
1648  {
1649  if (a->encoding == ENC_BINARY)
1650  return ENC_BINARY;
1651  else if (a->encoding == ENC_8BIT)
1652  e = ENC_8BIT;
1653  }
1654 
1655  return e;
1656 }
7-bit text
Definition: mime.h:49
struct Body * next
next attachment in the list
Definition: body.h:58
8-bit text
Definition: mime.h:50
unsigned int encoding
content-transfer-encoding
Definition: body.h:71
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 1664 of file sendlib.c.

1665 {
1666  char *p = NULL;
1667 
1668  if (b->parts && check_boundary(boundary, b->parts))
1669  return true;
1670 
1671  if (b->next && check_boundary(boundary, b->next))
1672  return true;
1673 
1674  p = mutt_param_get(&b->parameter, "boundary");
1675  if (p && (mutt_str_strcmp(p, boundary) == 0))
1676  {
1677  return true;
1678  }
1679  return false;
1680 }
struct Body * next
next attachment in the list
Definition: body.h:58
static bool check_boundary(const char *boundary, struct Body *b)
check for duplicate boundary
Definition: sendlib.c:1664
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:59
char * mutt_param_get(const struct ParameterList *p, const char *s)
Find a matching Parameter.
Definition: parameter.c:81
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:611

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

1688 {
1689  struct Body *new = mutt_body_new();
1690  new->type = TYPE_MULTIPART;
1691  new->subtype = mutt_str_strdup("mixed");
1692  new->encoding = get_toplevel_encoding(b);
1693  do
1694  {
1695  mutt_generate_boundary(&new->parameter);
1696  if (check_boundary(mutt_param_get(&new->parameter, "boundary"), b))
1697  mutt_param_delete(&new->parameter, "boundary");
1698  } while (!mutt_param_get(&new->parameter, "boundary"));
1699  new->use_disp = false;
1700  new->disposition = DISP_INLINE;
1701  new->parts = b;
1702 
1703  return new;
1704 }
static int get_toplevel_encoding(struct Body *a)
Find the most restrictive encoding type.
Definition: sendlib.c:1643
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:570
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:1664
char * mutt_param_get(const struct ParameterList *p, const char *s)
Find a matching Parameter.
Definition: parameter.c:81
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:383
void mutt_param_delete(struct ParameterList *p, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:139
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 1713 of file sendlib.c.

1714 {
1715  struct Body *t = NULL;
1716 
1717  if (b->parts)
1718  {
1719  t = b;
1720  b = b->parts;
1721  t->parts = NULL;
1722  mutt_body_free(&t);
1723  }
1724  return b;
1725 }
The body of an email.
Definition: body.h:34
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:59
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 1737 of file sendlib.c.

1738 {
1739  struct Address *tmp = NULL;
1740  char buf[1024];
1741  int count = 0;
1742 
1743  while (addr)
1744  {
1745  tmp = addr->next;
1746  addr->next = NULL;
1747  buf[0] = '\0';
1748  mutt_addr_write(buf, sizeof(buf), addr, display);
1749  size_t len = mutt_str_strlen(buf);
1750  if (count && (linelen + len > 74))
1751  {
1752  fputs("\n\t", fp);
1753  linelen = len + 8; /* tab is usually about 8 spaces... */
1754  }
1755  else
1756  {
1757  if (count && addr->mailbox)
1758  {
1759  fputc(' ', fp);
1760  linelen++;
1761  }
1762  linelen += len;
1763  }
1764  fputs(buf, fp);
1765  addr->next = tmp;
1766  if (!addr->group && addr->next && addr->next->mailbox)
1767  {
1768  linelen++;
1769  fputc(',', fp);
1770  }
1771  addr = addr->next;
1772  count++;
1773  }
1774  fputc('\n', fp);
1775 }
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:662
size_t mutt_addr_write(char *buf, size_t buflen, struct Address *addr, bool display)
Write an Address to a buffer.
Definition: address.c:1146
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 1786 of file sendlib.c.

1787 {
1788  struct ListNode *np = NULL;
1789  size_t length = 0;
1790 
1791  STAILQ_FOREACH(np, r, entries)
1792  {
1793  if (++length == trim)
1794  break;
1795  }
1796 
1797  struct ListNode **ref = mutt_mem_calloc(length, sizeof(struct ListNode *));
1798 
1799  // store in reverse order
1800  size_t tmp = length;
1801  STAILQ_FOREACH(np, r, entries)
1802  {
1803  ref[--tmp] = np;
1804  if (tmp == 0)
1805  break;
1806  }
1807 
1808  for (size_t i = 0; i < length; i++)
1809  {
1810  fputc(' ', fp);
1811  fputs(ref[i]->data, fp);
1812  if (i != length - 1)
1813  fputc('\n', fp);
1814  }
1815 
1816  FREE(&ref);
1817 }
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 1829 of file sendlib.c.

1831 {
1832  while (value && *value)
1833  {
1834  if (fputc(*value, fp) == EOF)
1835  return -1;
1836  /* corner-case: break words longer than 998 chars by force,
1837  * mandated by RFC5322 */
1838  if (!(chflags & CH_DISPLAY) && (++col >= 998))
1839  {
1840  if (fputs("\n ", fp) < 0)
1841  return -1;
1842  col = 1;
1843  }
1844  if (*value == '\n')
1845  {
1846  if (*(value + 1) && pfx && *pfx && (fputs(pfx, fp) == EOF))
1847  return -1;
1848  /* for display, turn folding spaces into folding tabs */
1849  if ((chflags & CH_DISPLAY) && ((*(value + 1) == ' ') || (*(value + 1) == '\t')))
1850  {
1851  value++;
1852  while (*value && (*value == ' ' || *value == '\t'))
1853  value++;
1854  if (fputc('\t', fp) == EOF)
1855  return -1;
1856  continue;
1857  }
1858  }
1859  value++;
1860  }
1861  return 0;
1862 }
#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 1875 of file sendlib.c.

1877 {
1878  const char *p = value;
1879  char buf[8192] = "";
1880  int first = 1, col = 0, l = 0;
1881  const bool display = (chflags & CH_DISPLAY);
1882 
1883  mutt_debug(5, "pfx=[%s], tag=[%s], flags=%d value=[%s]\n", pfx, tag, chflags,
1884  NONULL(value));
1885 
1886  if (tag && *tag && (fprintf(fp, "%s%s: ", NONULL(pfx), tag) < 0))
1887  return -1;
1888  col = mutt_str_strlen(tag) + (tag && *tag ? 2 : 0) + mutt_str_strlen(pfx);
1889 
1890  while (p && *p)
1891  {
1892  int fold = 0;
1893 
1894  /* find the next word and place it in 'buf'. it may start with
1895  * whitespace we can fold before */
1896  const char *next = mutt_str_find_word(p);
1897  l = MIN(sizeof(buf) - 1, next - p);
1898  memcpy(buf, p, l);
1899  buf[l] = '\0';
1900 
1901  /* determine width: character cells for display, bytes for sending
1902  * (we get pure ascii only) */
1903  const int w = mutt_mb_width(buf, col, display);
1904  const int enc = mutt_str_startswith(buf, "=?", CASE_MATCH);
1905 
1906  mutt_debug(5, "word=[%s], col=%d, w=%d, next=[0x0%x]\n", buf, col, w, *next);
1907 
1908  /* insert a folding \n before the current word's lwsp except for
1909  * header name, first word on a line (word longer than wrap width)
1910  * and encoded words */
1911  if (!first && !enc && col && (col + w >= wraplen))
1912  {
1913  col = mutt_str_strlen(pfx);
1914  fold = 1;
1915  if (fprintf(fp, "\n%s", NONULL(pfx)) <= 0)
1916  return -1;
1917  }
1918 
1919  /* print the actual word; for display, ignore leading ws for word
1920  * and fold with tab for readability */
1921  if (display && fold)
1922  {
1923  char *pc = buf;
1924  while (*pc && (*pc == ' ' || *pc == '\t'))
1925  {
1926  pc++;
1927  col--;
1928  }
1929  if (fputc('\t', fp) == EOF)
1930  return -1;
1931  if (print_val(fp, pfx, pc, chflags, col) < 0)
1932  return -1;
1933  col += 8;
1934  }
1935  else if (print_val(fp, pfx, buf, chflags, col) < 0)
1936  return -1;
1937  col += w;
1938 
1939  /* if the current word ends in \n, ignore all its trailing spaces
1940  * and reset column; this prevents us from putting only spaces (or
1941  * even none) on a line if the trailing spaces are located at our
1942  * current line width
1943  * XXX this covers ASCII space only, for display we probably
1944  * want something like iswspace() here */
1945  const char *sp = next;
1946  while (*sp && (*sp == ' ' || *sp == '\t'))
1947  sp++;
1948  if (*sp == '\n')
1949  {
1950  next = sp;
1951  col = 0;
1952  }
1953 
1954  p = next;
1955  first = 0;
1956  }
1957 
1958  /* if we have printed something but didn't \n-terminate it, do it
1959  * except the last word we printed ended in \n already */
1960  if (col && ((l == 0) || (buf[l - 1] != '\n')))
1961  if (putc('\n', fp) == EOF)
1962  return -1;
1963 
1964  return 0;
1965 }
#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:662
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:165
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
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:1829
const char * mutt_str_find_word(const char *src)
Find the next word (non-space)
Definition: string.c:997

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

1975 {
1976  char *p = s, *q = s;
1977 
1978  while (p && *p)
1979  {
1980  /* remove CRLF prior to FWSP, turn \t into ' ' */
1981  if ((*p == '\r') && *(p + 1) && (*(p + 1) == '\n') && *(p + 2) &&
1982  ((*(p + 2) == ' ') || (*(p + 2) == '\t')))
1983  {
1984  *q++ = ' ';
1985  p += 3;
1986  continue;
1987  }
1988  /* remove LF prior to FWSP, turn \t into ' ' */
1989  else if ((*p == '\n') && *(p + 1) && ((*(p + 1) == ' ') || (*(p + 1) == '\t')))
1990  {
1991  *q++ = ' ';
1992  p += 2;
1993  continue;
1994  }
1995  *q++ = *p++;
1996  }
1997  if (q)
1998  *q = '\0';
1999 
2000  return s;
2001 }

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

2018 {
2019  char *tagbuf = NULL, *valbuf = NULL, *t = NULL;
2020  bool is_from = ((end - start) > 5) && mutt_str_startswith(start, "from ", CASE_IGNORE);
2021 
2022  /* only pass through folding machinery if necessary for sending,
2023  * never wrap From_ headers on sending */
2024  if (!(chflags & CH_DISPLAY) && ((pfxw + max <= wraplen) || is_from))
2025  {
2026  valbuf = mutt_str_substr_dup(start, end);
2027  mutt_debug(5, "buf[%s%s] short enough, max width = %d <= %d\n", NONULL(pfx),
2028  valbuf, max, wraplen);
2029  if (pfx && *pfx)
2030  {
2031  if (fputs(pfx, fp) == EOF)
2032  {
2033  FREE(&valbuf);
2034  return -1;
2035  }
2036  }
2037 
2038  t = strchr(valbuf, ':');
2039  if (!t)
2040  {
2041  mutt_debug(LL_DEBUG1, "#1 warning: header not in 'key: value' format!\n");
2042  FREE(&valbuf);
2043  return 0;
2044  }
2045  if (print_val(fp, pfx, valbuf, chflags, mutt_str_strlen(pfx)) < 0)
2046  {
2047  FREE(&valbuf);
2048  return -1;
2049  }
2050  FREE(&valbuf);
2051  }
2052  else
2053  {
2054  t = strchr(start, ':');
2055  if (!t || (t > end))
2056  {
2057  mutt_debug(LL_DEBUG1, "#2 warning: header not in 'key: value' format!\n");
2058  return 0;
2059  }
2060  if (is_from)
2061  {
2062  tagbuf = NULL;
2063  valbuf = mutt_str_substr_dup(start, end);
2064  }
2065  else
2066  {
2067  tagbuf = mutt_str_substr_dup(start, t);
2068  /* skip over the colon separating the header field name and value */
2069  t++;
2070 
2071  /* skip over any leading whitespace (WSP, as defined in RFC5322)
2072  * NOTE: mutt_str_skip_email_wsp() does the wrong thing here.
2073  * See tickets 3609 and 3716. */
2074  while (*t == ' ' || *t == '\t')
2075  t++;
2076 
2077  valbuf = mutt_str_substr_dup(t, end);
2078  }
2079  mutt_debug(LL_DEBUG2, "buf[%s%s] too long, max width = %d > %d\n",
2080  NONULL(pfx), NONULL(valbuf), max, wraplen);
2081  if (fold_one_header(fp, tagbuf, valbuf, pfx, wraplen, chflags) < 0)
2082  {
2083  FREE(&valbuf);
2084  FREE(&tagbuf);
2085  return -1;
2086  }
2087  FREE(&tagbuf);
2088  FREE(&valbuf);
2089  }
2090  return 0;
2091 }
#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:662
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:165
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:1875
#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:85
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:1829
char * mutt_str_substr_dup(const char *begin, const char *end)
Duplicate a sub-string.
Definition: string.c:575

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

2109 {
2110  char *p = (char *) value, *last = NULL, *line = NULL;
2111  int max = 0, w, rc = -1;
2112  int pfxw = mutt_strwidth(pfx);
2113  char *v = mutt_str_strdup(value);
2114  bool display = (chflags & CH_DISPLAY);
2115 
2116  if (!display || C_Weed)
2117  v = unfold_header(v);
2118 
2119  /* when not displaying, use sane wrap value */
2120  if (!display)
2121  {
2122  if ((C_WrapHeaders < 78) || (C_WrapHeaders > 998))
2123  wraplen = 78;
2124  else
2125  wraplen = C_WrapHeaders;
2126  }
2127  else if ((wraplen <= 0) || (wraplen > MuttIndexWindow->cols))
2128  wraplen = MuttIndexWindow->cols;
2129 
2130  if (tag)
2131  {
2132  /* if header is short enough, simply print it */
2133  if (!display && (mutt_strwidth(tag) + 2 + pfxw + mutt_strwidth(v) <= wraplen))
2134  {
2135  mutt_debug(5, "buf[%s%s: %s] is short enough\n", NONULL(pfx), tag, v);
2136  if (fprintf(fp, "%s%s: %s\n", NONULL(pfx), tag, v) <= 0)
2137  goto out;
2138  rc = 0;
2139  goto out;
2140  }
2141  else
2142  {
2143  rc = fold_one_header(fp, tag, v, pfx, wraplen, chflags);
2144  goto out;
2145  }
2146  }
2147 
2148  p = v;
2149  last = v;
2150  line = v;
2151  while (p && *p)
2152  {
2153  p = strchr(p, '\n');
2154 
2155  /* find maximum line width in current header */
2156  if (p)
2157  *p = '\0';
2158  w = mutt_mb_width(line, 0, display);
2159  if (w > max)
2160  max = w;
2161  if (p)
2162  *p = '\n';
2163 
2164  if (!p)
2165  break;
2166 
2167  line = ++p;
2168  if ((*p != ' ') && (*p != '\t'))
2169  {
2170  if (write_one_header(fp, pfxw, max, wraplen, pfx, last, p, chflags) < 0)
2171  goto out;
2172  last = p;
2173  max = 0;
2174  }
2175  }
2176 
2177  if (last && *last)
2178  if (write_one_header(fp, pfxw, max, wraplen, pfx, last, p, chflags) < 0)
2179  goto out;
2180 
2181  rc = 0;
2182 
2183 out:
2184  FREE(&v);
2185  return rc;
2186 }
short C_WrapHeaders
Config: Width to wrap headers in outgoing messages.
Definition: sendlib.c:92
#define NONULL(x)
Definition: string2.h:36
static char * unfold_header(char *s)
Unfold a wrapped email header.
Definition: sendlib.c:1974
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:1176
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:2016
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:383
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:1875
#define FREE(x)
Definition: memory.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: email_globals.c:39

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

2215 {
2216  char buf[1024];
2217  char *p = NULL, *q = NULL;
2218  bool has_agent = false; /* user defined user-agent header field exists */
2219 
2220  if ((mode == MUTT_WRITE_HEADER_NORMAL) && !privacy)
2221  fputs(mutt_date_make_date(buf, sizeof(buf)), fp);
2222 
2223  /* UseFrom is not consulted here so that we can still write a From:
2224  * field if the user sets it with the 'my_hdr' command */
2225  if (env->from && !privacy)
2226  {
2227  buf[0] = '\0';
2228  mutt_addr_write(buf, sizeof(buf), env->from, false);
2229  fprintf(fp, "From: %s\n", buf);
2230  }
2231 
2232  if (env->sender && !privacy)
2233  {
2234  buf[0] = '\0';
2235  mutt_addr_write(buf, sizeof(buf), env->sender, false);
2236  fprintf(fp, "Sender: %s\n", buf);
2237  }
2238 
2239  if (env->to)
2240  {
2241  fputs("To: ", fp);
2242  mutt_write_address_list(env->to, fp, 4, 0);
2243  }
2244  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2245 #ifdef USE_NNTP
2246  if (!OptNewsSend)
2247 #endif
2248  fputs("To:\n", fp);
2249 
2250  if (env->cc)
2251  {
2252  fputs("Cc: ", fp);
2253  mutt_write_address_list(env->cc, fp, 4, 0);
2254  }
2255  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2256 #ifdef USE_NNTP
2257  if (!OptNewsSend)
2258 #endif
2259  fputs("Cc:\n", fp);
2260 
2261  if (env->bcc)
2262  {
2263  if ((mode == MUTT_WRITE_HEADER_POSTPONE) || (mode == MUTT_WRITE_HEADER_EDITHDRS) ||
2264  ((mode == MUTT_WRITE_HEADER_NORMAL) && C_WriteBcc))
2265  {
2266  fputs("Bcc: ", fp);
2267  mutt_write_address_list(env->bcc, fp, 5, 0);
2268  }
2269  }
2270  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2271 #ifdef USE_NNTP
2272  if (!OptNewsSend)
2273 #endif
2274  fputs("Bcc:\n", fp);
2275 
2276 #ifdef USE_NNTP
2277  if (env->newsgroups)
2278  fprintf(fp, "Newsgroups: %s\n", env->newsgroups);
2279  else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend)
2280  fputs("Newsgroups:\n", fp);
2281 
2282  if (env->followup_to)
2283  fprintf(fp, "Followup-To: %s\n", env->followup_to);
2284  else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend)
2285  fputs("Followup-To:\n", fp);
2286 
2287  if (env->x_comment_to)
2288  fprintf(fp, "X-Comment-To: %s\n", env->x_comment_to);
2289  else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend && C_XCommentTo)
2290  fputs("X-Comment-To:\n", fp);
2291 #endif
2292 
2293  if (env->subject)
2294  {
2295  if (hide_protected_subject &&
2296  ((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_POSTPONE)))
2297  mutt_write_one_header(fp, "Subject", C_CryptProtectedHeadersSubject, NULL, 0, 0);
2298  else
2299  mutt_write_one_header(fp, "Subject", env->subject, NULL, 0, 0);
2300  }
2301  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2302  fputs("Subject:\n", fp);
2303 
2304  /* save message id if the user has set it */
2305  if (env->message_id && !privacy)
2306  fprintf(fp, "Message-ID: %s\n", env->message_id);
2307 
2308  if (env->reply_to)
2309  {
2310  fputs("Reply-To: ", fp);
2311  mutt_write_address_list(env->reply_to, fp, 10, 0);
2312  }
2313  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2314  fputs("Reply-To:\n", fp);
2315 
2316  if (env->mail_followup_to)
2317 #ifdef USE_NNTP
2318  if (!OptNewsSend)
2319 #endif
2320  {
2321  fputs("Mail-Followup-To: ", fp);
2322  mutt_write_address_list(env->mail_followup_to, fp, 18, 0);
2323  }
2324 
2325  if ((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_POSTPONE))
2326  {
2327  if (!STAILQ_EMPTY(&env->references))
2328  {
2329  fputs("References:", fp);
2330  mutt_write_references(&env->references, fp, 10);
2331  fputc('\n', fp);
2332  }
2333 
2334  /* Add the MIME headers */
2335  fputs("MIME-Version: 1.0\n", fp);
2336  mutt_write_mime_header(attach, fp);
2337  }
2338 
2339  if (!STAILQ_EMPTY(&env->in_reply_to))
2340  {
2341  fputs("In-Reply-To:", fp);
2342  mutt_write_references(&env->in_reply_to, fp, 0);
2343  fputc('\n', fp);
2344  }
2345 
2346  /* Add any user defined headers */
2347  struct ListNode *tmp = NULL;
2348  STAILQ_FOREACH(tmp, &env->userhdrs, entries)
2349  {
2350  p = strchr(tmp->data, ':');
2351  if (p)
2352  {
2353  q = p;
2354 
2355  *p = '\0';
2356 
2357  p = mutt_str_skip_email_wsp(p + 1);
2358  if (!*p)
2359  {
2360  *q = ':';
2361  continue; /* don't emit empty fields. */
2362  }
2363 
2364  /* check to see if the user has overridden the user-agent field */
2365  if (mutt_str_startswith(tmp->data, "user-agent", CASE_IGNORE))
2366  {
2367  has_agent = true;
2368  if (privacy)
2369  {
2370  *q = ':';
2371  continue;
2372  }
2373  }
2374 
2375  mutt_write_one_header(fp, tmp->data, p, NULL, 0, 0);
2376  *q = ':';
2377  }
2378  }
2379 
2380  if ((mode == MUTT_WRITE_HEADER_NORMAL) && !privacy && C_UserAgent && !has_agent)
2381  {
2382  /* Add a vanity header */
2383  fprintf(fp, "User-Agent: NeoMutt/%s%s\n", PACKAGE_VERSION, GitVer);
2384  }
2385 
2386  return ferror(fp) == 0 ? 0 : -1;
2387 }
WHERE bool C_WriteBcc
Config: Write out the &#39;Bcc&#39; field when preparing to send a mail.
Definition: globals.h:268
struct Address * to
Definition: envelope.h:42
WHERE char * C_CryptProtectedHeadersSubject
Config: Use this as the subject for encrypted emails.
Definition: globals.h:108
bool C_UserAgent
Config: Add a &#39;User-Agent&#39; head to outgoing mail.
Definition: sendlib.c:91
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:380
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:1737
size_t mutt_addr_write(char *buf, size_t buflen, struct Address *addr, bool display)
Write an Address to a buffer.
Definition: address.c:1146
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
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:1786
const char * GitVer
"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:767
#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:165
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:289
char * followup_to
Definition: envelope.h:61
int mutt_write_mime_header(struct Body *a, FILE *fp)
Create a MIME header.
Definition: sendlib.c:356
#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:2107
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 2395 of file sendlib.c.

2396 {
2397  char *tmp = NULL;
2398  char *p = NULL;
2399  int i;
2400 
2401  struct ListNode *np = NULL;
2402  STAILQ_FOREACH(np, h, entries)
2403  {
2404  p = strchr(np->data, ':');
2405  if (!p)
2406  continue;
2407 
2408  i = p - np->data;
2409  p = mutt_str_skip_email_wsp(p + 1);
2410  tmp = mutt_str_strdup(p);
2411 
2412  if (!tmp)
2413  continue;
2414 
2415  rfc2047_encode(&tmp, NULL, i + 2, C_SendCharset);
2416  mutt_mem_realloc(&np->data, i + 2 + mutt_str_strlen(tmp) + 1);
2417 
2418  sprintf(np->data + i + 2, "%s", tmp);
2419 
2420  FREE(&tmp);
2421  }
2422 }
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:662
char * C_SendCharset
Config: Character sets for outgoing mail ///< Config: List of character sets for outgoing messages...
Definition: email_globals.c:37
void rfc2047_encode(char **pd, const char *specials, int col, const char *charsets)
RFC-2047-encode a string.
Definition: rfc2047.c:626
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:124
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:767
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
char * data
Definition: list.h:35
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:383
#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 2432 of file sendlib.c.

2433 {
2434  if (!C_Hostname || (C_Hostname[0] == '@'))
2435  return NULL;
2436 
2437  char *p = C_Hostname;
2438 
2439  if (may_hide_host && C_HiddenHost)
2440  {
2441  p = strchr(C_Hostname, '.');
2442  if (p)
2443  p++;
2444 
2445  // sanity check: don't hide the host if the fqdn is something like example.com
2446  if (!p || !strchr(p, '.'))
2447  p = C_Hostname;
2448  }
2449 
2450  return p;
2451 }
bool C_HiddenHost
Config: Don&#39;t use the hostname, just the domain, when generating the message id.
Definition: sendlib.c:81
WHERE char * C_Hostname
Config: Fully-qualified domain name of this machine.
Definition: globals.h:114

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

2460 {
2461  char buf[128];
2462  time_t now;
2463  unsigned char rndid[MUTT_RANDTAG_LEN + 1];
2464 
2465  mutt_rand_base32(rndid, sizeof(rndid) - 1);
2466  rndid[MUTT_RANDTAG_LEN] = 0;
2467  now = time(NULL);
2468  struct tm *tm = gmtime(&now);
2469  const char *fqdn = mutt_fqdn(false);
2470  if (!fqdn)
2471  fqdn = NONULL(ShortHostname);
2472 
2473  snprintf(buf, sizeof(buf), "<%d%02d%02d%02d%02d%02d.%s@%s>", tm->tm_year + 1900,
2474  tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, rndid, fqdn);
2475  return mutt_str_strdup(buf);
2476 }
#define NONULL(x)
Definition: string2.h:36
#define MUTT_RANDTAG_LEN
Definition: muttlib.h:43
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2432
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:383
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:507

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

2483 {
2484  SigAlrm = 1;
2485 }
WHERE SIG_ATOMIC_VOLATILE_T SigAlrm
true after SIGALRM is received
Definition: globals.h:90

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

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

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

2665 {
2666  for (; addr; addr = addr->next)
2667  {
2668  /* weed out group mailboxes, since those are for display only */
2669  if (addr->mailbox && !addr->group)
2670  {
2671  if (*argslen == *argsmax)
2672  mutt_mem_realloc(&args, (*argsmax += 5) * sizeof(char *));
2673  args[(*argslen)++] = addr->mailbox;
2674  }
2675  }
2676  return args;
2677 }
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:124
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 2689 of file sendlib.c.

2690 {
2691  if (*argslen == *argsmax)
2692  mutt_mem_realloc(&args, (*argsmax += 5) * sizeof(char *));
2693  args[(*argslen)++] = s;
2694  return args;
2695 }
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:124

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

2710 {
2711  char *ps = NULL, *path = NULL, *s = NULL, *childout = NULL;
2712  char **args = NULL;
2713  size_t argslen = 0, argsmax = 0;
2714  char **extra_args = NULL;
2715  int i;
2716 
2717 #ifdef USE_NNTP
2718  if (OptNewsSend)
2719  {
2720  char cmd[1024];
2721 
2722  mutt_expando_format(cmd, sizeof(cmd), 0, MuttIndexWindow->cols,
2723  NONULL(C_Inews), nntp_format_str, 0, 0);
2724  if (!*cmd)
2725  {
2726  i = nntp_post(Context->mailbox, msg);
2727  unlink(msg);
2728  return i;
2729  }
2730 
2731  s = mutt_str_strdup(cmd);
2732  }
2733  else
2734 #endif
2736 
2737  /* ensure that $sendmail is set to avoid a crash. http://dev.mutt.org/trac/ticket/3548 */
2738  if (!s)
2739  {
2740  mutt_error(_("$sendmail must be set in order to send mail"));
2741  return -1;
2742  }
2743 
2744  ps = s;
2745  i = 0;
2746  while ((ps = strtok(ps, " ")))
2747  {
2748  if (argslen == argsmax)
2749  mutt_mem_realloc(&args, sizeof(char *) * (argsmax += 5));
2750 
2751  if (i)
2752  {
2753  if (mutt_str_strcmp(ps, "--") == 0)
2754  break;
2755  args[argslen++] = ps;
2756  }
2757  else
2758  {
2759  path = mutt_str_strdup(ps);
2760  ps = strrchr(ps, '/');
2761  if (ps)
2762  ps++;
2763  else
2764  ps = path;
2765  args[argslen++] = ps;
2766  }
2767  ps = NULL;
2768  i++;
2769  }
2770 
2771 #ifdef USE_NNTP
2772  if (!OptNewsSend)
2773  {
2774 #endif
2775  size_t extra_argslen = 0;
2776  /* If C_Sendmail contained a "--", we save the recipients to append to
2777  * args after other possible options added below. */
2778  if (ps)
2779  {
2780  ps = NULL;
2781  size_t extra_argsmax = 0;
2782  while ((ps = strtok(ps, " ")))
2783  {
2784  if (extra_argslen == extra_argsmax)
2785  mutt_mem_realloc(&extra_args, sizeof(char *) * (extra_argsmax += 5));
2786 
2787  extra_args[extra_argslen++] = ps;
2788  ps = NULL;
2789  }
2790  }
2791 
2792  if (eightbit && C_Use8bitmime)
2793  args = add_option(args, &argslen, &argsmax, "-B8BITMIME");
2794 
2795  if (C_UseEnvelopeFrom)
2796  {
2798  {
2799  args = add_option(args, &argslen, &argsmax, "-f");
2800  args = add_args(args, &argslen, &argsmax, C_EnvelopeFromAddress);
2801  }
2802  else if (from && !from->next)
2803  {
2804  args = add_option(args, &argslen, &argsmax, "-f");
2805  args = add_args(args, &argslen, &argsmax, from);
2806  }
2807  }
2808 
2809  if (C_DsnNotify)
2810  {
2811  args = add_option(args, &argslen, &argsmax, "-N");
2812  args = add_option(args, &argslen, &argsmax, C_DsnNotify);
2813  }
2814  if (C_DsnReturn)
2815  {
2816  args = add_option(args, &argslen, &argsmax, "-R");
2817  args = add_option(args, &argslen, &argsmax, C_DsnReturn);
2818  }
2819  args = add_option(args, &argslen, &argsmax, "--");
2820  for (i = 0; i < extra_argslen; i++)
2821  args = add_option(args, &argslen, &argsmax, extra_args[i]);
2822  args = add_args(args, &argslen, &argsmax, to);
2823  args = add_args(args, &argslen, &argsmax, cc);
2824  args = add_args(args, &argslen, &argsmax, bcc);
2825 #ifdef USE_NNTP
2826  }
2827 #endif
2828 
2829  if (argslen == argsmax)
2830  mutt_mem_realloc(&args, sizeof(char *) * (++argsmax));
2831 
2832  args[argslen++] = NULL;
2833 
2834  /* Some user's $sendmail command uses gpg for password decryption,
2835  * and is set up to prompt using ncurses pinentry. If we
2836  * mutt_endwin() it leaves other users staring at a blank screen.
2837  * So instead, just force a hard redraw on the next refresh. */
2838  if (!OptNoCurses)
2840 
2841  i = send_msg(path, args, msg, OptNoCurses ? NULL : &childout);
2842  if (i != (EX_OK & 0xff))
2843  {
2844  if (i != S_BKG)
2845  {
2846  const char *e = mutt_str_sysexit(i);
2847  mutt_error(_("Error sending message, child exited %d (%s)"), i, NONULL(e));
2848  if (childout)
2849  {
2850  struct stat st;
2851 
2852  if ((stat(childout, &st) == 0) && (st.st_size > 0))
2853  mutt_do_pager(_("Output of the delivery process"), childout, 0, NULL);
2854  }
2855  }
2856  }
2857  else if (childout)
2858  unlink(childout);
2859 
2860  FREE(&childout);
2861  FREE(&path);
2862  FREE(&s);
2863  FREE(&args);
2864  FREE(&extra_args);
2865 
2866  if (i == (EX_OK & 0xff))
2867  i = 0;
2868  else if (i == S_BKG)
2869  i = 1;
2870  else
2871  i = -1;
2872  return i;
2873 }
The "current" mailbox.
Definition: context.h:37
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t *callback, unsigned long data, MuttFormatFlags flags)
Expand expandos (x) in a string.
Definition: muttlib.c:811
char * C_Sendmail
Config: External command to send email.
Definition: sendlib.c:87
#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:2499
int nntp_post(struct Mailbox *m, const char *msg)
Post article.
Definition: nntp.c:1980
#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
bool C_Use8bitmime
Config: Use 8-bit messages and ESMTP to send messages.
Definition: sendlib.c:89
struct Mailbox * mailbox
Definition: context.h:51
char * C_Inews
Config: (nntp) External command to post news articles.
Definition: sendlib.c:82
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:2664
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:124
static char ** add_option(char **args, size_t *argslen, size_t *argsmax, char *s)
Add a string to a dynamic array.
Definition: sendlib.c:2689
bool C_UseEnvelopeFrom
Config: Set the envelope sender of the message.
Definition: sendlib.c:90
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:111
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:569
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:383
#define mutt_error(...)
Definition: logging.h:88
WHERE struct Address * C_EnvelopeFromAddress
Config: Manually set the sender for outgoing messages.
Definition: globals.h:100
#define FREE(x)
Definition: memory.h:40
const char * mutt_str_sysexit(int e)
Return a string matching an error code.
Definition: string.c:107
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:919
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:611
WHERE char * C_DsnNotify
Config: Request notification for message delivery or delay.
Definition: globals.h:110
#define EX_OK
Definition: sendlib.c:72
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 2884 of file sendlib.c.

2885 {
2886  if (final)
2887  {
2888  if (env->bcc && !(env->to || env->cc))
2889  {
2890  /* some MTA's will put an Apparently-To: header field showing the Bcc:
2891  * recipients if there is no To: or Cc: field, so attempt to suppress
2892  * it by using an empty To: field. */
2893  env->to = mutt_addr_new();
2894  env->to->group = 1;
2895  env->to->next = mutt_addr_new();
2896 
2897  char buf[1024];
2898  buf[0] = '\0';
2899  mutt_addr_cat(buf, sizeof(buf), "undisclosed-recipients", AddressSpecials);
2900 
2901  env->to->mailbox = mutt_str_strdup(buf);
2902  }
2903 
2904  mutt_set_followup_to(env);
2905 
2906  if (!env->message_id)
2907  env->message_id = gen_msgid();
2908  }
2909 
2910  /* Take care of 8-bit => 7-bit conversion. */
2912  encode_headers(&env->userhdrs);
2913 }
static char * gen_msgid(void)
Generate a unique Message ID.
Definition: sendlib.c:2459
struct Address * to
Definition: envelope.h:42
struct ListHead userhdrs
user defined headers
Definition: envelope.h:67
char * mailbox
mailbox and host address
Definition: address.h:35
void rfc2047_encode_envelope(struct Envelope *env)
Encode the fields of an Envelope.
Definition: rfc2047.c:804
const char AddressSpecials[]
Characters with special meaning for email addresses.
Definition: address.c:41
char * message_id
Definition: envelope.h:53
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:681
void mutt_set_followup_to(struct Envelope *env)
Set followup-to field.
Definition: send.c:1094
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:383
struct Address * mutt_addr_new(void)
Create a new Address.
Definition: address.c:401
struct Address * cc
Definition: envelope.h:43
static void encode_headers(struct ListHead *h)
RFC2047-encode a list of headers.
Definition: sendlib.c:2395
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 2922 of file sendlib.c.

2923 {
2924  struct ListNode *item = NULL;
2925  STAILQ_FOREACH(item, &env->userhdrs, entries)
2926  {
2927  rfc2047_decode(&item->data);
2928  }
2929 
2931 
2932  /* back conversions */
2934 }
void rfc2047_decode(char **pd)
Decode any RFC2047-encoded header fields.
Definition: rfc2047.c:650
struct ListHead userhdrs
user defined headers
Definition: envelope.h:67
struct Address * mail_followup_to
Definition: envelope.h:47
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
char * data
Definition: list.h:35
void rfc2047_decode_envelope(struct Envelope *env)
Decode the fields of an Envelope.
Definition: rfc2047.c:786
void mutt_addr_free(struct Address **p)
Free a list of Addresses.
Definition: address.c:446
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 2946 of file sendlib.c.

2948 {
2949  if (!e)
2950  return -1;
2951 
2952  int rc = 0;
2953  char tempfile[PATH_MAX];
2954 
2955  mutt_mktemp(tempfile, sizeof(tempfile));
2956  FILE *fp_tmp = mutt_file_fopen(tempfile, "w");
2957  if (fp_tmp)
2958  {
2959  char date[128];
2961 
2962  if (!C_BounceDelivered)
2963  chflags |= CH_WEED_DELIVERED;
2964 
2965  fseeko(fp, e->offset, SEEK_SET);
2966  fprintf(fp_tmp, "Resent-From: %s", resent_from);
2967  fprintf(fp_tmp, "\nResent-%s", mutt_date_make_date(date, sizeof(date)));
2968  char *msgid_str = gen_msgid();
2969  fprintf(fp_tmp, "Resent-Message-ID: %s\n", msgid_str);
2970  FREE(&msgid_str);
2971  fputs("Resent-To: ", fp_tmp);
2972  mutt_write_address_list(to, fp_tmp, 11, 0);
2973  mutt_copy_header(fp, e, fp_tmp, chflags, NULL);
2974  fputc('\n', fp_tmp);
2975  mutt_file_copy_bytes(fp, fp_tmp, e->content->length);
2976  if (mutt_file_fclose(&fp_tmp) != 0)
2977  {
2978  mutt_perror(tempfile);
2979  unlink(tempfile);
2980  return -1;
2981  }
2982 #ifdef USE_SMTP
2983  if (C_SmtpUrl)
2984  rc = mutt_smtp_send(env_from, to, NULL, NULL, tempfile, e->content->encoding == ENC_8BIT);
2985  else
2986 #endif
2987  rc = mutt_invoke_sendmail(env_from, to, NULL, NULL, tempfile,
2988  e->content->encoding == ENC_8BIT);
2989  }
2990 
2991  return rc;
2992 }
WHERE char * C_SmtpUrl
Config: (smtp) Url of the SMTP server.
Definition: globals.h:148
#define mutt_perror(...)
Definition: logging.h:89
static char * gen_msgid(void)
Generate a unique Message ID.
Definition: sendlib.c:2459
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
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:2708
char * mutt_date_make_date(char *buf, size_t buflen)
Write a date in RFC822 format to a buffer.
Definition: date.c:380
int mutt_copy_header(FILE *fp_in, struct Email *e, FILE *fp_out, CopyHeaderFlags chflags, const char *prefix)
Copy Email header.
Definition: copy.c:386
void mutt_write_address_list(struct Address *addr, FILE *fp, int linelen, bool display)
wrapper around mutt_write_address()
Definition: sendlib.c:1737
#define CH_WEED_DELIVERED
Weed eventual Delivered-To headers.
Definition: copy.h:64
unsigned int encoding
content-transfer-encoding
Definition: body.h:71
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:72
LOFF_T length
length (in bytes) of attachment
Definition: body.h:47
#define PATH_MAX
Definition: mutt.h:48
#define CH_XMIT
Transmitting this message? (Ignore Lines: and Content-Length:)
Definition: copy.h:54
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:78
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:546
#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:741
#define CH_NONEWLINE
Don&#39;t output terminating newline after the header.
Definition: copy.h:59
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:236

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

3003 {
3004  if (!fp || !e || !to)
3005  return -1;
3006 
3007  const char *fqdn = mutt_fqdn(true);
3008  char resent_from[256];
3009  char *err = NULL;
3010 
3011  resent_from[0] = '\0';
3012  struct Address *from = mutt_default_from();
3013 
3014  /* mutt_default_from() does not use $realname if the real name is not set
3015  * in $from, so we add it here. The reason it is not added in
3016  * mutt_default_from() is that during normal sending, we execute
3017  * send-hooks and set the realname last so that it can be changed based
3018  * upon message criteria. */
3019  if (!from->personal)
3021 
3022  if (fqdn)
3023  mutt_addr_qualify(from, fqdn);
3024 
3025  rfc2047_encode_addrlist(from, "Resent-From");
3026  if (mutt_addrlist_to_intl(from, &err))
3027  {
3028  mutt_error(_("Bad IDN %s while preparing resent-from"), err);
3029  FREE(&err);
3030  mutt_addr_free(&from);
3031  return -1;
3032  }
3033  mutt_addr_write(resent_from, sizeof(resent_from), from, false);
3034 
3035 #ifdef USE_NNTP
3036  OptNewsSend = false;
3037 #endif
3038 
3039  /* prepare recipient list. idna conversion appears to happen before this
3040  * function is called, since the user receives confirmation of the address
3041  * list being bounced to. */
3042  struct Address *resent_to = mutt_addr_copy_list(to, false);
3043  rfc2047_encode_addrlist(resent_to, "Resent-To");
3044 
3045  int rc = bounce_message(fp, e, resent_to, resent_from, from);
3046 
3047  mutt_addr_free(&resent_to);
3048  mutt_addr_free(&from);
3049 
3050  return rc;
3051 }
void rfc2047_encode_addrlist(struct Address *addr, const char *tag)
Encode any RFC2047 headers, where required, in an Address list.
Definition: rfc2047.c:749
#define _(a)
Definition: message.h:28
An email address.
Definition: address.h:32
int mutt_addrlist_to_intl(struct Address *a, char **err)
Convert an Address list to Punycode.
Definition: address.c:1208
size_t mutt_addr_write(char *buf, size_t buflen, struct Address *addr, bool display)
Write an Address to a buffer.
Definition: address.c:1146
struct Address * mutt_default_from(void)
Get a default &#39;from&#39; Address.
Definition: send.c:1200
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:2946
void mutt_addr_qualify(struct Address *addr, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:660
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2432
char * personal
real name of address
Definition: address.h:34
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:383
#define mutt_error(...)
Definition: logging.h:88
#define FREE(x)
Definition: memory.h:40
WHERE char * C_Realname
Config: Real name of the user.
Definition: globals.h:144
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:43
struct Address * mutt_addr_copy_list(struct Address *addr, bool prune)
Copy a list of addresses.
Definition: address.c:730
void mutt_addr_free(struct Address **p)
Free a list of Addresses.
Definition: address.c:446

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

3059 {
3060  for (; b; b = b->next)
3061  {
3062  if ((b->type == TYPE_MESSAGE) || (b->type == TYPE_MULTIPART))
3063  set_noconv_flags(b->parts, flag);
3064  else if ((b->type == TYPE_TEXT) && b->noconv)
3065  {
3066  if (flag)
3067  mutt_param_set(&b->parameter, "x-mutt-noconv", "yes");
3068  else
3069  mutt_param_delete(&b->parameter, "x-mutt-noconv");
3070  }
3071  }
3072 }
bool noconv
don&#39;t do character set conversion
Definition: body.h:80
struct Body * next
next attachment in the list
Definition: body.h:58
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:107
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:59
unsigned int type
content-type primary type
Definition: body.h:70
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:3058
void mutt_param_delete(struct ParameterList *p, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:139
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 3085 of file sendlib.c.

3087 {
3088  char fcc_tok[PATH_MAX];
3089  char fcc_expanded[PATH_MAX];
3090 
3091  mutt_str_strfcpy(fcc_tok, path, sizeof(fcc_tok));
3092 
3093  char *tok = strtok(fcc_tok, ",");
3094  if (!tok)
3095  return -1;
3096 
3097  mutt_debug(LL_DEBUG1, "Fcc: initial mailbox = '%s'\n", tok);
3098  /* mutt_expand_path already called above for the first token */
3099  int status = mutt_write_fcc(tok, e, msgid, post, fcc, finalpath);
3100  if (status != 0)
3101  return status;
3102 
3103  while ((tok = strtok(NULL, ",")))
3104  {
3105  if (!*tok)
3106  continue;
3107 
3108  /* Only call mutt_expand_path if tok has some data */
3109  mutt_debug(LL_DEBUG1, "Fcc: additional mailbox token = '%s'\n", tok);
3110  mutt_str_strfcpy(fcc_expanded, tok, sizeof(fcc_expanded));
3111  mutt_expand_path(fcc_expanded, sizeof(fcc_expanded));
3112  mutt_debug(LL_DEBUG1, " Additional mailbox expanded = '%s'\n", fcc_expanded);
3113  status = mutt_write_fcc(fcc_expanded, e, msgid, post, fcc, finalpath);
3114  if (status != 0)
3115  return status;
3116  }
3117 
3118  return 0;
3119 }
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:157
#define PATH_MAX
Definition: mutt.h:48
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:741
Log at debug level 1.
Definition: logging.h:56
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
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:3132

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

3134 {
3135  struct Message *msg = NULL;
3136  char tempfile[PATH_MAX];
3137  FILE *fp_tmp = NULL;
3138  int rc = -1;
3139  bool need_mailbox_cleanup = false;
3140  struct stat st;
3141  char buf[128];
3142  MsgOpenFlags onm_flags;
3143 
3144  if (post)
3145  set_noconv_flags(e->content, true);
3146 
3147 #ifdef RECORD_FOLDER_HOOK
3148  mutt_folder_hook(path, NULL);
3149 #endif
3150  struct Mailbox *m_fcc = mx_path_resolve(path);
3151  struct Context *ctx_fcc = mx_mbox_open(m_fcc, MUTT_APPEND | MUTT_QUIET);
3152  if (!ctx_fcc)
3153  {
3154  mutt_debug(LL_DEBUG1, "unable to open mailbox %s in append-mode, aborting.\n", path);
3155  mailbox_free(&m_fcc);
3156  goto done;
3157  }
3158 
3159  /* We need to add a Content-Length field to avoid problems where a line in
3160  * the message body begins with "From " */
3161  if ((ctx_fcc->mailbox->magic == MUTT_MMDF) || (ctx_fcc->mailbox->magic == MUTT_MBOX))
3162  {
3163  mutt_mktemp(tempfile, sizeof(tempfile));
3164  fp_tmp = mutt_file_fopen(tempfile, "w+");
3165  if (!fp_tmp)
3166  {
3167  mutt_perror(tempfile);
3168  mx_mbox_close(&ctx_fcc);
3169  goto done;
3170  }
3171  /* remember new mail status before appending message */
3172  need_mailbox_cleanup = true;
3173  stat(path, &st);
3174  }
3175 
3176  e->read = !post; /* make sure to put it in the 'cur' directory (maildir) */
3177  onm_flags = MUTT_ADD_FROM;
3178  if (post)
3179  onm_flags |= MUTT_SET_DRAFT;
3180  msg = mx_msg_open_new(ctx_fcc->mailbox, e, onm_flags);
3181  if (!msg)
3182  {
3183  mutt_file_fclose(&fp_tmp);
3184  mx_mbox_close(&ctx_fcc);
3185  goto done;
3186  }
3187 
3188  /* post == 1 => postpone message.
3189  * post == 0 => Normal mode. */
3193 
3194  /* (postponement) if this was a reply of some sort, <msgid> contains the
3195  * Message-ID: of message replied to. Save it using a special X-Mutt-
3196  * header so it can be picked up if the message is recalled at a later
3197  * point in time. This will allow the message to be marked as replied if
3198  * the same mailbox is still open. */
3199  if (post && msgid)
3200  fprintf(msg->fp, "X-Mutt-References: %s\n", msgid);
3201 
3202  /* (postponement) save the Fcc: using a special X-Mutt- header so that
3203  * it can be picked up when the message is recalled */
3204  if (post && fcc)
3205  fprintf(msg->fp, "X-Mutt-Fcc: %s\n", fcc);
3206 
3207  if ((ctx_fcc->mailbox->magic == MUTT_MMDF) || (ctx_fcc->mailbox->magic == MUTT_MBOX))
3208  fprintf(msg->fp, "Status: RO\n");
3209 
3210  /* mutt_rfc822_write_header() only writes out a Date: header with
3211  * mode == 0, i.e. _not_ postponement; so write out one ourself */
3212  if (post)
3213  fprintf(msg->fp, "%s", mutt_date_make_date(buf, sizeof(buf)));
3214 
3215  /* (postponement) if the mail is to be signed or encrypted, save this info */
3216  if (((WithCrypto & APPLICATION_PGP) != 0) && post && (e->security & APPLICATION_PGP))
3217  {
3218  fputs("X-Mutt-PGP: ", msg->fp);
3219  if (e->security & SEC_ENCRYPT)
3220  fputc('E', msg->fp);
3221  if (e->security & SEC_OPPENCRYPT)
3222  fputc('O', msg->fp);
3223  if (e->security & SEC_SIGN)
3224  {
3225  fputc('S', msg->fp);
3226  if (C_PgpSignAs && *C_PgpSignAs)
3227  fprintf(msg->fp, "<%s>", C_PgpSignAs);
3228  }
3229  if (e->security & SEC_INLINE)
3230  fputc('I', msg->fp);
3231  fputc('\n', msg->fp);
3232  }
3233 
3234  /* (postponement) if the mail is to be signed or encrypted, save this info */
3235  if (((WithCrypto & APPLICATION_SMIME) != 0) && post && (e->security & APPLICATION_SMIME))
3236  {
3237  fputs("X-Mutt-SMIME: ", msg->fp);
3238  if (e->security & SEC_ENCRYPT)
3239  {
3240  fputc('E', msg->fp);
3242  fprintf(msg->fp, "C<%s>", C_SmimeEncryptWith);
3243  }
3244  if (e->security & SEC_OPPENCRYPT)
3245  fputc('O', msg->fp);
3246  if (e->security & SEC_SIGN)
3247  {
3248  fputc('S', msg->fp);
3249  if (C_SmimeSignAs && *C_SmimeSignAs)
3250  fprintf(msg->fp, "<%s>", C_SmimeSignAs);
3251  }
3252  if (e->security & SEC_INLINE)
3253  fputc('I', msg->fp);
3254  fputc('\n', msg->fp);
3255  }
3256 
3257 #ifdef MIXMASTER
3258  /* (postponement) if the mail is to be sent through a mixmaster
3259  * chain, save that information */
3260 
3261  if (post && !STAILQ_EMPTY(&e->chain))
3262  {
3263  fputs("X-Mutt-Mix:", msg->fp);
3264  struct ListNode *p = NULL;
3265  STAILQ_FOREACH(p, &e->chain, entries)
3266  {
3267  fprintf(msg->fp, " %s", (char *) p->data);
3268  }
3269 
3270  fputc('\n', msg->fp);
3271  }
3272 #endif
3273 
3274  if (fp_tmp)
3275  {
3276  char sasha[1024];
3277  int lines = 0;
3278 
3279  mutt_write_mime_body(e->content, fp_tmp);
3280 
3281  /* make sure the last line ends with a newline. Emacs doesn't ensure this
3282  * will happen, and it can cause problems parsing the mailbox later. */
3283  fseek(fp_tmp, -1, SEEK_END);
3284  if (fgetc(fp_tmp) != '\n')
3285  {
3286  fseek(fp_tmp, 0, SEEK_END);
3287  fputc('\n', fp_tmp);
3288  }
3289 
3290  fflush(fp_tmp);
3291  if (ferror(fp_tmp))
3292  {
3293  mutt_debug(LL_DEBUG1, "%s: write failed.\n", tempfile);
3294  mutt_file_fclose(&fp_tmp);
3295  unlink(tempfile);
3296  mx_msg_commit(ctx_fcc->mailbox, msg); /* XXX really? */
3297  mx_msg_close(ctx_fcc->mailbox, &msg);
3298  mx_mbox_close(&ctx_fcc);
3299  goto done;
3300  }
3301 
3302  /* count the number of lines */
3303  rewind(fp_tmp);
3304  while (fgets(sasha, sizeof(sasha), fp_tmp))
3305  lines++;
3306  fprintf(msg->fp, "Content-Length: " OFF_T_FMT "\n", (LOFF_T) ftello(fp_tmp));
3307  fprintf(msg->fp, "Lines: %d\n\n", lines);
3308 
3309  /* copy the body and clean up */
3310  rewind(fp_tmp);
3311  rc = mutt_file_copy_stream(fp_tmp, msg->fp);
3312  if (fclose(fp_tmp) != 0)
3313  rc = -1;
3314  /* if there was an error, leave the temp version */
3315  if (!rc)
3316  unlink(tempfile);
3317  }
3318  else
3319  {
3320  fputc('\n', msg->fp); /* finish off the header */
3321  rc = mutt_write_mime_body(e->content, msg->fp);
3322  }
3323 
3324  if (mx_msg_commit(ctx_fcc->mailbox, msg) != 0)
3325  rc = -1;
3326  else if (finalpath)
3327  *finalpath = mutt_str_strdup(msg->committed_path);
3328  mx_msg_close(ctx_fcc->mailbox, &msg);
3329  mx_mbox_close(&ctx_fcc);
3330 
3331  if (!post && need_mailbox_cleanup)
3332  mutt_mailbox_cleanup(path, &st);
3333 
3334  if (post)
3335  set_noconv_flags(e->content, false);
3336 
3337 done:
3338 #ifdef RECORD_FOLDER_HOOK
3339  /* We ran a folder hook for the destination mailbox,
3340  * now we run it for the user's current mailbox */
3341  if (Context && Context->mailbox->path)
3343 #endif
3344 
3345  return rc;
3346 }
#define MUTT_APPEND
Open mailbox for appending messages.
Definition: mx.h:52
The "current" mailbox.
Definition: context.h:37
#define mutt_perror(...)
Definition: logging.h:89
int mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:529
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
char * desc
Definition: mailbox.h:88
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:1037
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:211
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:246
#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:380
#define MUTT_SET_DRAFT
set the message draft flag
Definition: mx.h:65
int mutt_rfc822_write_header(FILE *fp, struct Envelope *env, struct Body *attach, enum MuttWriteHeaderMode mode, bool privacy, bool hide_protected_subject)
Write out one RFC822 header line.
Definition: sendlib.c:2212
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1058
void mutt_folder_hook(const char *path, const char *desc)
Perform a folder hook.
Definition: hook.c:374
bool read
Definition: email.h:51
struct Mailbox * mailbox
Definition: context.h:51
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:103
enum MailboxType magic
mailbox type
Definition: mailbox.h:106
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:927
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:72
#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:81
A mailbox.
Definition: mailbox.h:83
#define PATH_MAX
Definition: mutt.h:48
int mutt_write_mime_body(struct Body *a, FILE *fp)
Write a MIME part.
Definition: sendlib.c:487
WHERE char * C_SmimeEncryptWith
Config: Algorithm for encryption.
Definition: globals.h:176
#define MUTT_QUIET
Do not print any messages.
Definition: mx.h:54
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
SecurityFlags security
bit 0-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:276
uint8_t MsgOpenFlags
Flags for mx_msg_open_new(), e.g. MUTT_ADD_FROM.
Definition: mx.h:62
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: ncrypt.h:128
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:129
char path[PATH_MAX]
Definition: mailbox.h:85
char * committed_path
the final path generated by mx_msg_commit()
Definition: mx.h:85
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:546
char * data
Definition: list.h:35
Log at debug level 1.
Definition: logging.h:56
static const char * lines[]
Definition: file.c:8
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:383
int mx_msg_commit(struct Mailbox *m, struct Message *msg)
Commit a message to a folder - Wrapper for MxOps::msg_commit()
Definition: mx.c:1037
FILE * fp
pointer to the message data
Definition: mx.h:83
struct Mailbox * mx_path_resolve(const char *path)
XXX.
Definition: mx.c:1506
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:263
static void set_noconv_flags(struct Body *b, bool flag)
Set/reset the "x-mutt-noconv" flag.
Definition: sendlib.c:3058
#define STAILQ_EMPTY(head)
Definition: queue.h:346
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
WHERE char * C_PgpSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:171
WHERE char * C_SmimeSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:175
A List node for strings.
Definition: list.h:33
#define MUTT_ADD_FROM
add a From_ line
Definition: mx.h:64
#define WithCrypto
Definition: ncrypt.h: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 76 of file sendlib.c.

char* C_AttachCharset

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

Definition at line 77 of file sendlib.c.

bool C_BounceDelivered

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

Definition at line 78 of file sendlib.c.

bool C_EncodeFrom

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

Definition at line 79 of file sendlib.c.

bool C_ForwardDecrypt

Config: Decrypt the message when forwarding it.

Definition at line 80 of file sendlib.c.

bool C_HiddenHost

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

Definition at line 81 of file sendlib.c.

char* C_Inews

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

Definition at line 82 of file sendlib.c.

bool C_MimeForwardDecode

Config: Decode the forwarded message before attaching it.

Definition at line 83 of file sendlib.c.

bool C_MimeSubject

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

encode subject line with RFC2047

Definition at line 84 of file sendlib.c.

char* C_MimeTypeQueryCommand

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

Definition at line 85 of file sendlib.c.

bool C_MimeTypeQueryFirst

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

Definition at line 86 of file sendlib.c.

char* C_Sendmail

Config: External command to send email.

Definition at line 87 of file sendlib.c.

short C_SendmailWait

Config: Time to wait for sendmail to finish.

Definition at line 88 of file sendlib.c.

bool C_Use8bitmime

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

Definition at line 89 of file sendlib.c.

bool C_UseEnvelopeFrom

Config: Set the envelope sender of the message.

Definition at line 90 of file sendlib.c.

bool C_UserAgent

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

Definition at line 91 of file sendlib.c.

short C_WrapHeaders

Config: Width to wrap headers in outgoing messages.

Definition at line 92 of file sendlib.c.