NeoMutt  2018-07-16 +952-a2da0a
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 *fout, bool istext)
 Encode text as quoted printable. More...
 
static int b64_init (struct B64Context *ctx)
 Set up the base64 conversion. More...
 
static void b64_flush (struct B64Context *ctx, FILE *fout)
 Save the bytes to the file. More...
 
static void b64_putc (struct B64Context *ctx, char c, FILE *fout)
 Base64-encode one character. More...
 
static void encode_base64 (struct FgetConv *fc, FILE *fout, int istext)
 Base64-encode some data. More...
 
static void encode_8bit (struct FgetConv *fc, FILE *fout)
 Write the data as raw 8-bit data. More...
 
int mutt_write_mime_header (struct Body *a, FILE *f)
 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 *f)
 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 *file, 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 *file, 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 *fpin)
 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 *f, size_t trim)
 Add the message references to a list. More...
 
static int print_val (FILE *fp, const char *pfx, const char *value, int flags, 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, int flags)
 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, int flags)
 Write out one header line. More...
 
int mutt_write_one_header (FILE *fp, const char *tag, const char *value, const char *pfx, int wraplen, int flags)
 Write one header line to a file. More...
 
int mutt_rfc822_write_header (FILE *fp, struct Envelope *env, struct Body *attach, int mode, bool privacy)
 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 Allow8bit
 Config: Allow 8-bit messages, don't use quoted-printable or base64. More...
 
char * AttachCharset
 Config: When attaching files, use one of these character sets. More...
 
bool BounceDelivered
 Config: Add 'Delivered-To' to bounced messages. More...
 
bool EncodeFrom
 Config: Encode 'From ' as 'quote-printable' at the beginning of lines. More...
 
bool ForwardDecrypt
 Config: Decrypt the message when forwarding it. More...
 
bool HiddenHost
 Config: Don't use the hostname, just the domain, when generating the message id. More...
 
char * Inews
 Config: (nntp) External command to post news articles. More...
 
bool MimeForwardDecode
 Config: Decode the forwarded message before attaching it. More...
 
bool MimeSubject
 Config: (nntp) Encode the article subject in base64. More...
 
char * MimeTypeQueryCommand
 Config: External command to determine the MIME type of an attachment. More...
 
bool MimeTypeQueryFirst
 Config: Run the MimeTypeQueryCommand before the mime.types lookup. More...
 
char * Sendmail
 Config: External command to send email. More...
 
short SendmailWait
 Config: Time to wait for sendmail to finish. More...
 
bool Use8bitmime
 Config: Use 8-bit messages and ESMTP to send messages. More...
 
bool UseEnvelopeFrom
 Config: Set the envelope sender of the message. More...
 
bool UserAgent
 Config: Add a 'User-Agent' head to outgoing mail. More...
 
short 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 *  fout,
bool  istext 
)
static

Encode text as quoted printable.

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int b64_init ( struct B64Context ctx)
static

Set up the base64 conversion.

Parameters
ctxCursor for the base64 conversion
Return values
0Always

Definition at line 246 of file sendlib.c.

247 {
248  memset(ctx->buffer, '\0', sizeof(ctx->buffer));
249  ctx->size = 0;
250  ctx->linelen = 0;
251 
252  return 0;
253 }
char buffer[3]
Definition: sendlib.c:236
short size
Definition: sendlib.c:237
short linelen
Definition: sendlib.c:238

+ Here is the caller graph for this function:

static void b64_flush ( struct B64Context ctx,
FILE *  fout 
)
static

Save the bytes to the file.

Parameters
ctxCursor for the base64 conversion
foutFile to save the output

Definition at line 260 of file sendlib.c.

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void b64_putc ( struct B64Context ctx,
char  c,
FILE *  fout 
)
static

Base64-encode one character.

Parameters
ctxCursor for the base64 conversion
cCharacter to encode
foutFile to save the output

Definition at line 295 of file sendlib.c.

296 {
297  if (ctx->size == 3)
298  b64_flush(ctx, fout);
299 
300  ctx->buffer[ctx->size++] = c;
301 }
char buffer[3]
Definition: sendlib.c:236
short size
Definition: sendlib.c:237
static void b64_flush(struct B64Context *ctx, FILE *fout)
Save the bytes to the file.
Definition: sendlib.c:260

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void encode_base64 ( struct FgetConv fc,
FILE *  fout,
int  istext 
)
static

Base64-encode some data.

Parameters
fcCursor for converting a file's encoding
foutFile to store the result
istextIs the input text?

Definition at line 309 of file sendlib.c.

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void encode_8bit ( struct FgetConv fc,
FILE *  fout 
)
static

Write the data as raw 8-bit data.

Parameters
fcCursor for converting a file's encoding
foutFile to store the result

Definition at line 337 of file sendlib.c.

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

+ 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 *  f 
)

Create a MIME header.

Parameters
aBody part
fFile to write to
Return values
0Success
-1Failure

Definition at line 359 of file sendlib.c.

360 {
361  fprintf(f, "Content-Type: %s/%s", TYPE(a), a->subtype);
362 
363  if (!TAILQ_EMPTY(&a->parameter))
364  {
365  size_t len = 25 + mutt_str_strlen(a->subtype); /* approximate len. of content-type */
366 
367  struct Parameter *np = NULL;
368  TAILQ_FOREACH(np, &a->parameter, entries)
369  {
370  char *tmp = NULL;
371 
372  if (!np->value)
373  continue;
374 
375  fputc(';', f);
376 
377  char buf[STRING];
378  buf[0] = 0;
379  tmp = mutt_str_strdup(np->value);
380  const int encode = rfc2231_encode_string(&tmp);
381  mutt_addr_cat(buf, sizeof(buf), tmp, MimeSpecials);
382 
383  /* Dirty hack to make messages readable by Outlook Express
384  * for the Mac: force quotes around the boundary parameter
385  * even when they aren't needed.
386  */
387 
388  if ((mutt_str_strcasecmp(np->attribute, "boundary") == 0) && (strcmp(buf, tmp) == 0))
389  {
390  snprintf(buf, sizeof(buf), "\"%s\"", tmp);
391  }
392 
393  FREE(&tmp);
394 
395  const int tmplen = mutt_str_strlen(buf) + mutt_str_strlen(np->attribute) + 1;
396 
397  if (len + tmplen + 2 > 76)
398  {
399  fputs("\n\t", f);
400  len = tmplen + 8;
401  }
402  else
403  {
404  fputc(' ', f);
405  len += tmplen + 1;
406  }
407 
408  fprintf(f, "%s%s=%s", np->attribute, encode ? "*" : "", buf);
409  }
410  }
411 
412  fputc('\n', f);
413 
414  if (a->language)
415  fprintf(f, "Content-Language: %s\n", a->language);
416 
417  if (a->description)
418  fprintf(f, "Content-Description: %s\n", a->description);
419 
420  if (a->disposition != DISP_NONE)
421  {
422  const char *dispstr[] = { "inline", "attachment", "form-data" };
423 
424  if (a->disposition < sizeof(dispstr) / sizeof(char *))
425  {
426  fprintf(f, "Content-Disposition: %s", dispstr[a->disposition]);
427 
428  if (a->use_disp && (a->disposition != DISP_INLINE))
429  {
430  char *fn = a->d_filename;
431  if (!fn)
432  fn = a->filename;
433 
434  if (fn)
435  {
436  char *tmp = NULL;
437 
438  /* Strip off the leading path... */
439  char *t = strrchr(fn, '/');
440  if (t)
441  t++;
442  else
443  t = fn;
444 
445  char buf[STRING];
446  buf[0] = 0;
447  tmp = mutt_str_strdup(t);
448  const int encode = rfc2231_encode_string(&tmp);
449  mutt_addr_cat(buf, sizeof(buf), tmp, MimeSpecials);
450  FREE(&tmp);
451  fprintf(f, "; filename%s=%s", encode ? "*" : "", buf);
452  }
453  }
454 
455  fputc('\n', f);
456  }
457  else
458  {
459  mutt_debug(1, "ERROR: invalid content-disposition %d\n", a->disposition);
460  }
461  }
462 
463  if (a->encoding != ENC_7BIT)
464  fprintf(f, "Content-Transfer-Encoding: %s\n", ENCODING(a->encoding));
465 
466  /* Do NOT add the terminator here!!! */
467  return ferror(f) ? -1 : 0;
468 }
char * attribute
Definition: parameter.h:39
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:47
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
7-bit text
Definition: mime.h:49
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:663
unsigned int disposition
content-disposition
Definition: body.h:69
#define ENCODING(X)
Definition: mime.h:84
unsigned int encoding
content-transfer-encoding
Definition: body.h:68
char * subtype
content-type subtype
Definition: body.h:36
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:426
#define TYPE(X)
Definition: mime.h:82
char * description
content-description
Definition: body.h:39
char * value
Definition: parameter.h:40
#define STRING
Definition: string2.h:35
No preferred disposition.
Definition: mime.h:65
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:70
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
int rfc2231_encode_string(char **pd)
Encode a string to be suitable for an RFC2231 header.
Definition: rfc2231.c:323
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:625
Attribute associated with a MIME part.
Definition: parameter.h:37
#define FREE(x)
Definition: memory.h:46
char * language
content-language (RFC8255)
Definition: body.h:37
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:49
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
#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:38

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

476 {
477  return mutt_is_text_part(b) ||
479 }
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
Definition: muttlib.c:429
int mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:510
#define APPLICATION_PGP
Definition: ncrypt.h:129
#define WithCrypto
Definition: ncrypt.h:154

+ 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 *  f 
)

Write a MIME part.

Parameters
aBody to use
fFile to write to
Return values
0Success
-1Failure

Definition at line 488 of file sendlib.c.

489 {
490  FILE *fpin = NULL;
491  struct FgetConv *fc = NULL;
492 
493  if (a->type == TYPE_MULTIPART)
494  {
495  /* First, find the boundary to use */
496  const char *p = mutt_param_get(&a->parameter, "boundary");
497  if (!p)
498  {
499  mutt_debug(1, "no boundary parameter found\n");
500  mutt_error(_("No boundary parameter found [report this error]"));
501  return -1;
502  }
503  char boundary[SHORT_STRING];
504  mutt_str_strfcpy(boundary, p, sizeof(boundary));
505 
506  for (struct Body *t = a->parts; t; t = t->next)
507  {
508  fprintf(f, "\n--%s\n", boundary);
509  if (mutt_write_mime_header(t, f) == -1)
510  return -1;
511  fputc('\n', f);
512  if (mutt_write_mime_body(t, f) == -1)
513  return -1;
514  }
515  fprintf(f, "\n--%s--\n", boundary);
516  return ferror(f) ? -1 : 0;
517  }
518 
519  /* This is pretty gross, but it's the best solution for now... */
520  if (((WithCrypto & APPLICATION_PGP) != 0) && a->type == TYPE_APPLICATION &&
521  (mutt_str_strcmp(a->subtype, "pgp-encrypted") == 0))
522  {
523  fputs("Version: 1\n", f);
524  return 0;
525  }
526 
527  fpin = fopen(a->filename, "r");
528  if (!fpin)
529  {
530  mutt_debug(1, "%s no longer exists\n", a->filename);
531  mutt_error(_("%s no longer exists"), a->filename);
532  return -1;
533  }
534 
535  if (a->type == TYPE_TEXT && (!a->noconv))
536  {
537  char send_charset[SHORT_STRING];
539  fpin, a->charset, mutt_body_get_charset(a, send_charset, sizeof(send_charset)), 0);
540  }
541  else
542  fc = mutt_ch_fgetconv_open(fpin, 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, f);
551  else
552  mutt_file_copy_stream(fpin, f);
554 
556  mutt_file_fclose(&fpin);
557 
558  if (SigInt == 1)
559  {
560  SigInt = 0;
561  return -1;
562  }
563  return ferror(f) ? -1 : 0;
564 }
void mutt_sig_allow_interrupt(int disposition)
Allow/disallow Ctrl-C (SIGINT)
Definition: signal.c:231
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:47
#define SHORT_STRING
Definition: string2.h:34
static void encode_quoted(struct FgetConv *fc, FILE *fout, bool istext)
Encode text as quoted printable.
Definition: sendlib.c:100
WHERE SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: globals.h:90
bool noconv
don&#39;t do character set conversion
Definition: body.h:77
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:57
int mutt_write_mime_header(struct Body *a, FILE *f)
Create a MIME header.
Definition: sendlib.c:359
static bool write_as_text_part(struct Body *b)
Should the Body be written as a text MIME part.
Definition: sendlib.c:475
The body of an email.
Definition: body.h:33
int mutt_write_mime_body(struct Body *a, FILE *f)
Write a MIME part.
Definition: sendlib.c:488
static void encode_8bit(struct FgetConv *fc, FILE *fout)
Write the data as raw 8-bit data.
Definition: sendlib.c:337
unsigned int encoding
content-transfer-encoding
Definition: body.h:68
Base-64 encoded text.
Definition: mime.h:52
char * subtype
content-type subtype
Definition: body.h:36
static void encode_base64(struct FgetConv *fc, FILE *fout, int istext)
Base64-encode some data.
Definition: sendlib.c:309
int mutt_file_copy_stream(FILE *fin, FILE *fout)
Copy the contents of one file into another.
Definition: file.c:264
Type: &#39;text/*&#39;.
Definition: mime.h:38
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:58
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:742
char * charset
charset of attached file
Definition: body.h:52
struct FgetConv * mutt_ch_fgetconv_open(FILE *file, const char *from, const char *to, int flags)
Prepare a file for charset conversion.
Definition: charset.c:815
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
unsigned int type
content-type primary type
Definition: body.h:67
#define APPLICATION_PGP
Definition: ncrypt.h:129
void mutt_ch_fgetconv_close(struct FgetConv **fc)
Close an fgetconv handle.
Definition: charset.c:845
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
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
#define mutt_error(...)
Definition: logging.h:88
Quoted-printable text.
Definition: mime.h:51
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
struct ParameterList parameter
parameters of the content-type
Definition: body.h:38
#define WithCrypto
Definition: ncrypt.h:154
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:612
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:42
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:509

+ 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 *  file,
const char *  fromcode,
int  ncodes,
const char **  tocodes,
int *  tocode,
struct Content info 
)
static

Change the encoding of a file.

Parameters
[in]fileFile 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(file);
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, file);
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:529
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:625
#define FREE(x)
Definition: memory.h:46

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static size_t convert_file_from_to ( FILE *  file,
const char *  fromcodes,
const char *  tocodes,
char **  fromcode,
char **  tocode,
struct Content info 
)
static

Convert a file between encodings.

Parameters
[in]fileFile 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(file, 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(file, 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 }
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:99
static size_t convert_file_to(FILE *file, const char *fromcode, int ncodes, const char **tocodes, int *tocode, struct Content *info)
Change the encoding of a file.
Definition: sendlib.c:747
#define FREE(x)
Definition: memory.h:46
char * mutt_str_substr_dup(const char *begin, const char *end)
Duplicate a sub-string.
Definition: string.c:576

+ 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(1, "%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  Charset;
1021  if (Charset && (chs || SendCharset) &&
1022  convert_file_from_to(fp, fchs, chs ? chs : SendCharset, &fromcode,
1023  &tocode, info) != (size_t)(-1))
1024  {
1025  if (!chs)
1026  {
1027  char chsbuf[STRING];
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 ? "us-ascii" :
1050  Charset && !mutt_ch_is_us_ascii(Charset) ? Charset : "unknown-8bit"));
1051  }
1052 
1053  return info;
1054 }
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:47
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:51
char * Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:52
bool noconv
don&#39;t do character set conversion
Definition: body.h:77
#define _(a)
Definition: message.h:28
long hibin
8-bit characters
Definition: content.h:35
bool force_charset
send mode: don&#39;t adjust the character set when in send-mode.
Definition: body.h:78
void mutt_ch_canonical_charset(char *buf, size_t buflen, const char *name)
Canonicalise the charset of a string.
Definition: charset.c:312
static char * chs
Definition: gnupgparse.c:72
Info about an attachment.
Definition: content.h:33
static size_t convert_file_from_to(FILE *file, const char *fromcodes, const char *tocodes, char **fromcode, char **tocode, struct Content *info)
Convert a file between encodings.
Definition: sendlib.c:900
#define mutt_ch_is_us_ascii(a)
Definition: charset.h:107
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
char * charset
charset of attached file
Definition: body.h:52
unsigned int type
content-type primary type
Definition: body.h:67
char * AttachCharset
Config: When attaching files, use one of these character sets.
Definition: sendlib.c:77
char * mutt_param_get(const struct ParameterList *p, const char *s)
Find a matching Parameter.
Definition: parameter.c:81
#define STRING
Definition: string2.h:35
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:70
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
#define mutt_error(...)
Definition: logging.h:88
#define FREE(x)
Definition: memory.h:46
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
struct ParameterList parameter
parameters of the content-type
Definition: body.h:38
char * SendCharset
Config: Character sets for outgoing mail ///< Config: List of character sets for outgoing messages...
Definition: email_globals.c:36

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

1069 {
1070  FILE *f = NULL;
1071  char *p = NULL, *q = NULL, *ct = NULL;
1072  char buf[PATH_MAX];
1073  char subtype[STRING], xtype[STRING];
1074  int szf, sze, cur_sze;
1075  int type;
1076  bool found_mimetypes = false;
1077 
1078  *subtype = '\0';
1079  *xtype = '\0';
1080  type = TYPE_OTHER;
1081  cur_sze = 0;
1082 
1083  szf = mutt_str_strlen(path);
1084 
1085  for (int count = 0; count < 4; count++)
1086  {
1087  /* can't use strtok() because we use it in an inner loop below, so use
1088  * a switch statement here instead.
1089  */
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(1, "Internal error, count = %d.\n", count);
1108  goto bye; /* shouldn't happen */
1109  }
1110 
1111  f = fopen(buf, "r");
1112  if (f)
1113  {
1114  found_mimetypes = true;
1115 
1116  while (fgets(buf, sizeof(buf) - 1, f))
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(&f);
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:39
#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:554
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:663
#define ISSPACE(c)
Definition: string2.h:40
WHERE char * HomeDir
User&#39;s home directory.
Definition: globals.h:47
char * subtype
content-type subtype
Definition: body.h:36
#define PATH_MAX
Definition: mutt.h:46
char * xtype
content-type if x-unknown
Definition: body.h: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:742
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:460
unsigned int type
content-type primary type
Definition: body.h:67
#define STRING
Definition: string2.h:35
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
#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:625
int mutt_check_mime_type(const char *s)
Check a MIME type string.
Definition: parse.c:255
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
#define SKIPWS(c)
Definition: string2.h:49

+ 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 *  fpin 
)
static

Convert MIME parts to 7-bit.

Parameters
aBody of the email
fpinFile 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, fpin);
1208  }
1209  else if (mutt_is_message_type(a->type, a->subtype))
1210  {
1211  mutt_message_to_7bit(a, fpin);
1212  }
1213  else
1214  {
1215  a->noconv = true;
1216  a->force_charset = true;
1217 
1218  mutt_mktemp(buf, sizeof(buf));
1219  s.fpout = mutt_file_fopen(buf, "w");
1220  if (!s.fpout)
1221  {
1222  mutt_perror("fopen");
1223  return;
1224  }
1225  s.fpin = fpin;
1226  mutt_decode_attachment(a, &s);
1227  mutt_file_fclose(&s.fpout);
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:1728
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:47
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1214
#define mutt_perror(...)
Definition: logging.h:89
7-bit text
Definition: mime.h:49
static void transform_to_7bit(struct Body *a, FILE *fpin)
Convert MIME parts to 7-bit.
Definition: sendlib.c:1194
bool noconv
don&#39;t do character set conversion
Definition: body.h:77
struct Body * next
next attachment in the list
Definition: body.h:57
8-bit text
Definition: mime.h:50
FILE * fpout
Definition: state.h:34
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:78
unsigned int encoding
content-transfer-encoding
Definition: body.h:68
Base-64 encoded text.
Definition: mime.h:52
char * subtype
content-type subtype
Definition: body.h:36
#define mutt_mktemp(a, b)
Definition: muttlib.h:71
LOFF_T length
length (in bytes) of attachment
Definition: body.h:46
#define PATH_MAX
Definition: mutt.h:46
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:58
FILE * fpin
Definition: state.h:33
unsigned int type
content-type primary type
Definition: body.h:67
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:548
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
bool unlink
flag to indicate the file named by "filename" should be unlink()ed before free()ing this structure ...
Definition: body.h:71
Binary.
Definition: mime.h:53
Quoted-printable text.
Definition: mime.h:51
#define FREE(x)
Definition: memory.h:46
Keep track when processing files.
Definition: state.h:31
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:49

+ 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 *fpin = NULL;
1258  FILE *fpout = NULL;
1259  struct stat sb;
1260 
1261  if (!a->filename && fp)
1262  fpin = fp;
1263  else if (!a->filename || !(fpin = 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(&fpin);
1275  }
1276  a->length = sb.st_size;
1277  }
1278 
1279  mutt_mktemp(temp, sizeof(temp));
1280  fpout = mutt_file_fopen(temp, "w+");
1281  if (!fpout)
1282  {
1283  mutt_perror("fopen");
1284  goto cleanup;
1285  }
1286 
1287  if (!fpin)
1288  goto cleanup;
1289 
1290  fseeko(fpin, a->offset, SEEK_SET);
1291  a->parts = mutt_rfc822_parse_message(fpin, a);
1292 
1293  transform_to_7bit(a->parts, fpin);
1294 
1295  mutt_copy_hdr(fpin, fpout, a->offset, a->offset + a->length,
1296  CH_MIME | CH_NONEWLINE | CH_XMIT, NULL);
1297 
1298  fputs("MIME-Version: 1.0\n", fpout);
1299  mutt_write_mime_header(a->parts, fpout);
1300  fputc('\n', fpout);
1301  mutt_write_mime_body(a->parts, fpout);
1302 
1303 cleanup:
1304  FREE(&line);
1305 
1306  if (fpin && fpin != fp)
1307  mutt_file_fclose(&fpin);
1308  if (fpout)
1309  mutt_file_fclose(&fpout);
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:56
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:47
#define mutt_perror(...)
Definition: logging.h:89
7-bit text
Definition: mime.h:49
static void transform_to_7bit(struct Body *a, FILE *fpin)
Convert MIME parts to 7-bit.
Definition: sendlib.c:1194
struct Body * content
list of MIME parts
Definition: email.h:92
LOFF_T offset
offset where the actual data begins
Definition: body.h:45
#define _(a)
Definition: message.h:28
int mutt_write_mime_header(struct Body *a, FILE *f)
Create a MIME header.
Definition: sendlib.c:359
int mutt_copy_hdr(FILE *in, FILE *out, LOFF_T off_start, LOFF_T off_end, int flags, const char *prefix)
Copy header from one file to another.
Definition: copy.c:72
int mutt_write_mime_body(struct Body *a, FILE *f)
Write a MIME part.
Definition: sendlib.c:488
struct Body * mutt_rfc822_parse_message(FILE *fp, struct Body *parent)
parse a Message/RFC822 body
Definition: parse.c:1384
unsigned int encoding
content-transfer-encoding
Definition: body.h:68
const char * line
Definition: common.c:35
#define mutt_mktemp(a, b)
Definition: muttlib.h:71
LOFF_T length
length (in bytes) of attachment
Definition: body.h:46
#define PATH_MAX
Definition: mutt.h:46
#define CH_XMIT
transmitting this message?
Definition: copy.h:50
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:58
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:548
void mutt_body_free(struct Body **p)
Free a Body.
Definition: body.c:56
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
#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:71
#define FREE(x)
Definition: memory.h:46
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:49
struct Email * email
header information for message/rfc822
Definition: body.h:59
#define CH_NONEWLINE
don&#39;t output terminating newline
Definition: copy.h:55

+ 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[SHORT_STRING];
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 && 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 (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
#define SHORT_STRING
Definition: string2.h:34
bool EncodeFrom
Config: Encode &#39;From &#39; as &#39;quote-printable&#39; at the beginning of lines.
Definition: sendlib.c:79
long linemax
length of the longest line in the file
Definition: content.h:40
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:68
Base-64 encoded text.
Definition: mime.h:52
char * subtype
content-type subtype
Definition: body.h:36
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:70
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:67
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:166
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:625
Quoted-printable text.
Definition: mime.h:51
bool 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:65

+ 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:312
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:742
unsigned int type
content-type primary type
Definition: body.h:67
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:38

+ 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[STRING];
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:47
struct Content * content
structure used to store detailed info about the content of the attachment.
Definition: body.h:53
bool noconv
don&#39;t do character set conversion
Definition: body.h:77
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:78
Info about an attachment.
Definition: content.h:33
#define mutt_ch_is_us_ascii(a)
Definition: charset.h:107
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 STRING
Definition: string2.h:35
#define FREE(x)
Definition: memory.h:46
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:38

+ 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[LONG_STRING];
1462  struct Body *body = NULL;
1463  FILE *fp = NULL;
1464  int cmflags, chflags;
1465  int pgp = WithCrypto ? e->security : 0;
1466 
1467  if (WithCrypto)
1468  {
1469  if ((MimeForwardDecode || ForwardDecrypt) && (e->security & ENCRYPT))
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  chflags = CH_XMIT;
1493  cmflags = 0;
1494 
1495  /* If we are attaching a message, ignore MimeForwardDecode */
1496  if (!attach_msg && 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) && ForwardDecrypt && (e->security & 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:56
int mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:403
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:47
unsigned int security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:37
int mutt_copy_message_ctx(FILE *fpout, struct Mailbox *src, struct Email *e, int flags, int chflags)
Copy a message from a Context.
Definition: copy.c:792
struct Body * content
list of MIME parts
Definition: email.h:92
bool noconv
don&#39;t do character set conversion
Definition: body.h:77
struct Email * mutt_email_new(void)
Create a new Email.
Definition: email.c:63
#define LONG_STRING
Definition: string2.h:36
The body of an email.
Definition: body.h:33
unsigned int disposition
content-disposition
Definition: body.h:69
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:42
void mutt_update_encoding(struct Body *a)
Update the encoding type.
Definition: sendlib.c:1428
struct Envelope * env
envelope information
Definition: email.h:91
void mutt_parse_mime_message(struct Mailbox *m, struct Email *cur)
Parse a MIME email.
Definition: mutt_parse.c:50
bool MimeForwardDecode
Config: Decode the forwarded message before attaching it.
Definition: sendlib.c:83
char * subtype
content-type subtype
Definition: body.h:36
#define CH_TXTPLAIN
generate text/plain MIME headers
Definition: copy.h:58
#define ENCRYPT
Definition: ncrypt.h:119
#define mutt_mktemp(a, b)
Definition: muttlib.h:71
#define MUTT_CM_DECODE
decode the message body into text/plain
Definition: copy.h:34
#define MUTT_CM_CHARCONV
perform character set conversions
Definition: copy.h:38
#define CH_XMIT
transmitting this message?
Definition: copy.h:50
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:58
int mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:510
unsigned int type
content-type primary type
Definition: body.h:67
LOFF_T offset
where in the stream does this message begin?
Definition: email.h:85
#define APPLICATION_PGP
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:548
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:70
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
#define SMIME_ENCRYPT
Definition: ncrypt.h:140
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
bool unlink
flag to indicate the file named by "filename" should be unlink()ed before free()ing this structure ...
Definition: body.h:71
#define MUTT_CM_DECODE_PGP
used for decoding PGP messages
Definition: copy.h:41
bool ForwardDecrypt
Config: Decrypt the message when forwarding it.
Definition: sendlib.c:80
int crypt_valid_passphrase(int flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:144
struct Envelope * mutt_rfc822_read_header(FILE *f, struct Email *e, bool user_hdrs, bool weed)
parses an RFC822 header
Definition: parse.c:971
int mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
Definition: crypt.c:569
Content is inline.
Definition: mime.h:62
struct Email * email
header information for message/rfc822
Definition: body.h:59
#define WithCrypto
Definition: ncrypt.h:154
#define PGP_ENCRYPT
Definition: ncrypt.h:134
#define CH_NONEWLINE
don&#39;t output terminating newline
Definition: copy.h:55
#define APPLICATION_SMIME
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, *fperr;
1557  char cmd[HUGE_STRING];
1558  char *buf = NULL;
1559  size_t buflen;
1560  int dummy = 0;
1561  pid_t thepid;
1562 
1563  mutt_file_expand_fmt_quote(cmd, sizeof(cmd), MimeTypeQueryCommand, att->filename);
1564 
1565  thepid = mutt_create_filter(cmd, NULL, &fp, &fperr);
1566  if (thepid < 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(&fperr);
1582  mutt_wait_filter(thepid);
1583 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:47
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:632
#define _(a)
Definition: message.h:28
void mutt_parse_content_type(char *s, struct Body *ct)
Parse a content type.
Definition: parse.c:393
char * MimeTypeQueryCommand
Config: External command to determine the MIME type of an attachment.
Definition: sendlib.c:85
#define HUGE_STRING
Definition: string2.h:37
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
#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:1323
#define FREE(x)
Definition: memory.h:46
pid_t mutt_create_filter(const char *s, FILE **in, FILE **out, FILE **err)
Set up filter program.
Definition: filter.c:216
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  */
1602  if (!att->subtype)
1603  mutt_lookup_mime_type(att, path);
1604 
1606  {
1607  run_mime_type_query(att);
1608  }
1609 
1610  struct Content *info = mutt_get_content_info(path, att);
1611  if (!info)
1612  {
1613  mutt_body_free(&att);
1614  return NULL;
1615  }
1616 
1617  if (!att->subtype)
1618  {
1619  if ((info->nulbin == 0) &&
1620  (info->lobin == 0 || (info->lobin + info->hibin + info->ascii) / info->lobin >= 10))
1621  {
1622  /* Statistically speaking, there should be more than 10% "lobin"
1623  * chars if this is really a binary file...
1624  */
1625  att->type = TYPE_TEXT;
1626  att->subtype = mutt_str_strdup("plain");
1627  }
1628  else
1629  {
1630  att->type = TYPE_APPLICATION;
1631  att->subtype = mutt_str_strdup("octet-stream");
1632  }
1633  }
1634 
1635  FREE(&info);
1636  mutt_update_encoding(att);
1637  return att;
1638 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:47
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:33
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:42
void mutt_update_encoding(struct Body *a)
Update the encoding type.
Definition: sendlib.c:1428
bool MimeTypeQueryFirst
Config: Run the MimeTypeQueryCommand before the mime.types lookup.
Definition: sendlib.c:86
char * MimeTypeQueryCommand
Config: External command to determine the MIME type of an attachment.
Definition: sendlib.c:85
char * subtype
content-type subtype
Definition: body.h:36
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:1068
unsigned int type
content-type primary type
Definition: body.h:67
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:56
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
#define FREE(x)
Definition: memory.h:46
long nulbin
null characters (0x0)
Definition: content.h:37
Type: &#39;application/*&#39;.
Definition: mime.h:33

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

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

1667 {
1668  char *p = NULL;
1669 
1670  if (b->parts && check_boundary(boundary, b->parts))
1671  return true;
1672 
1673  if (b->next && check_boundary(boundary, b->next))
1674  return true;
1675 
1676  p = mutt_param_get(&b->parameter, "boundary");
1677  if (p && (mutt_str_strcmp(p, boundary) == 0))
1678  {
1679  return true;
1680  }
1681  return false;
1682 }
struct Body * next
next attachment in the list
Definition: body.h:57
static bool check_boundary(const char *boundary, struct Body *b)
check for duplicate boundary
Definition: sendlib.c:1666
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:58
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:38
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:612

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

1690 {
1691  struct Body *new = mutt_body_new();
1692  new->type = TYPE_MULTIPART;
1693  new->subtype = mutt_str_strdup("mixed");
1694  new->encoding = get_toplevel_encoding(b);
1695  do
1696  {
1697  mutt_generate_boundary(&new->parameter);
1698  if (check_boundary(mutt_param_get(&new->parameter, "boundary"), b))
1699  mutt_param_delete(&new->parameter, "boundary");
1700  } while (!mutt_param_get(&new->parameter, "boundary"));
1701  new->use_disp = false;
1702  new->disposition = DISP_INLINE;
1703  new->parts = b;
1704 
1705  return new;
1706 }
static int get_toplevel_encoding(struct Body *a)
Find the most restrictive encoding type.
Definition: sendlib.c:1645
The body of an email.
Definition: body.h:33
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:42
static bool check_boundary(const char *boundary, struct Body *b)
check for duplicate boundary
Definition: sendlib.c:1666
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:384
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 1715 of file sendlib.c.

1716 {
1717  struct Body *t = NULL;
1718 
1719  if (b->parts)
1720  {
1721  t = b;
1722  b = b->parts;
1723  t->parts = NULL;
1724  mutt_body_free(&t);
1725  }
1726  return b;
1727 }
The body of an email.
Definition: body.h:33
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:58
void mutt_body_free(struct Body **p)
Free a Body.
Definition: body.c:56

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

1740 {
1741  struct Address *tmp = NULL;
1742  char buf[LONG_STRING];
1743  int count = 0;
1744 
1745  while (addr)
1746  {
1747  tmp = addr->next;
1748  addr->next = NULL;
1749  buf[0] = 0;
1750  mutt_addr_write(buf, sizeof(buf), addr, display);
1751  size_t len = mutt_str_strlen(buf);
1752  if (count && linelen + len > 74)
1753  {
1754  fputs("\n\t", fp);
1755  linelen = len + 8; /* tab is usually about 8 spaces... */
1756  }
1757  else
1758  {
1759  if (count && addr->mailbox)
1760  {
1761  fputc(' ', fp);
1762  linelen++;
1763  }
1764  linelen += len;
1765  }
1766  fputs(buf, fp);
1767  addr->next = tmp;
1768  if (!addr->group && addr->next && addr->next->mailbox)
1769  {
1770  linelen++;
1771  fputc(',', fp);
1772  }
1773  addr = addr->next;
1774  count++;
1775  }
1776  fputc('\n', fp);
1777 }
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:663
#define LONG_STRING
Definition: string2.h:36
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 *  f,
size_t  trim 
)

Add the message references to a list.

Parameters
rString List of references
fFile 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 1788 of file sendlib.c.

1789 {
1790  struct ListNode *np = NULL;
1791  size_t length = 0;
1792 
1793  STAILQ_FOREACH(np, r, entries)
1794  {
1795  if (++length == trim)
1796  break;
1797  }
1798 
1799  struct ListNode **ref = mutt_mem_calloc(length, sizeof(struct ListNode *));
1800 
1801  // store in reverse order
1802  size_t tmp = length;
1803  STAILQ_FOREACH(np, r, entries)
1804  {
1805  ref[--tmp] = np;
1806  if (tmp == 0)
1807  break;
1808  }
1809 
1810  for (size_t i = 0; i < length; ++i)
1811  {
1812  fputc(' ', f);
1813  fputs(ref[i]->data, f);
1814  if (i != length - 1)
1815  fputc('\n', f);
1816  }
1817 
1818  FREE(&ref);
1819 }
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:46
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,
int  flags,
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
flagsFlags, e.g. CH_DISPLAY
colColumn that this text starts at
Return values
0Success
-1Failure

Definition at line 1831 of file sendlib.c.

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

+ 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,
int  flags 
)
static

Fold one header line.

Parameters
fpFile to write to
tagHeader key, e.g. "From"
valueHeader value
pfxPrefix for header
wraplenColumn to wrap at
flagsFlags, e.g. CH_DISPLAY
Return values
0Success
-1Failure

Definition at line 1876 of file sendlib.c.

1878 {
1879  const char *p = value;
1880  char buf[HUGE_STRING] = "";
1881  int first = 1, col = 0, l = 0;
1882  const bool display = (flags & CH_DISPLAY);
1883 
1884  mutt_debug(4, "pfx=[%s], tag=[%s], flags=%d value=[%s]\n", pfx, tag, flags, 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, flags, col) < 0)
1932  return -1;
1933  col += 8;
1934  }
1935  else if (print_val(fp, pfx, buf, flags, 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 }
static int print_val(FILE *fp, const char *pfx, const char *value, int flags, size_t col)
Add pieces to an email header, wrapping where necessary.
Definition: sendlib.c:1831
#define NONULL(x)
Definition: string2.h:39
#define MIN(a, b)
Definition: memory.h:31
Match case when comparing strings.
Definition: string2.h:69
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:663
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 HUGE_STRING
Definition: string2.h:37
#define CH_DISPLAY
display result to user
Definition: copy.h:65
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:166
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
const char * mutt_str_find_word(const char *src)
Find the next word (non-space)
Definition: string.c:998

+ 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,
int  flags 
)
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
flagsFlags, e.g. CH_DISPLAY
Return values
0Success
-1Failure

Definition at line 2016 of file sendlib.c.

2018 {
2019  char *tagbuf = NULL, *valbuf = NULL, *t = NULL;
2020  int 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 (!(flags & CH_DISPLAY) && (pfxw + max <= wraplen || is_from))
2025  {
2026  valbuf = mutt_str_substr_dup(start, end);
2027  mutt_debug(4, "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(1, "#1 warning: header not in 'key: value' format!\n");
2042  FREE(&valbuf);
2043  return 0;
2044  }
2045  if (print_val(fp, pfx, valbuf, flags, 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(1, "#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(4, "buf[%s%s] too long, max width = %d > %d\n", NONULL(pfx),
2080  NONULL(valbuf), max, wraplen);
2081  if (fold_one_header(fp, tagbuf, valbuf, pfx, wraplen, flags) < 0)
2082  {
2083  FREE(&valbuf);
2084  FREE(&tagbuf);
2085  return -1;
2086  }
2087  FREE(&tagbuf);
2088  FREE(&valbuf);
2089  }
2090  return 0;
2091 }
static int print_val(FILE *fp, const char *pfx, const char *value, int flags, size_t col)
Add pieces to an email header, wrapping where necessary.
Definition: sendlib.c:1831
#define NONULL(x)
Definition: string2.h:39
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:663
static int fold_one_header(FILE *fp, const char *tag, const char *value, const char *pfx, int wraplen, int flags)
Fold one header line.
Definition: sendlib.c:1876
#define CH_DISPLAY
display result to user
Definition: copy.h:65
Ignore case when comparing strings.
Definition: string2.h:70
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:166
#define FREE(x)
Definition: memory.h:46
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
char * mutt_str_substr_dup(const char *begin, const char *end)
Duplicate a sub-string.
Definition: string.c:576

+ 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,
int  flags 
)

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
flagsFlags, e.g. CH_DISPLAY
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 = (flags & CH_DISPLAY);
2115 
2116  if (!display || Weed)
2117  v = unfold_header(v);
2118 
2119  /* when not displaying, use sane wrap value */
2120  if (!display)
2121  {
2122  if (WrapHeaders < 78 || WrapHeaders > 998)
2123  wraplen = 78;
2124  else
2125  wraplen = 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(4, "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, flags);
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, flags) < 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, flags) < 0)
2179  goto out;
2180 
2181  rc = 0;
2182 
2183 out:
2184  FREE(&v);
2185  return rc;
2186 }
#define NONULL(x)
Definition: string2.h:39
short WrapHeaders
Config: Width to wrap headers in outgoing messages.
Definition: sendlib.c:92
static char * unfold_header(char *s)
Unfold a wrapped email header.
Definition: sendlib.c:1974
static int fold_one_header(FILE *fp, const char *tag, const char *value, const char *pfx, int wraplen, int flags)
Fold one header line.
Definition: sendlib.c:1876
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
bool Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: email_globals.c:38
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:65
static int write_one_header(FILE *fp, int pfxw, int max, int wraplen, const char *pfx, const char *start, const char *end, int flags)
Write out one header line.
Definition: sendlib.c:2016
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
#define FREE(x)
Definition: memory.h:46
#define mutt_debug(LEVEL,...)
Definition: logging.h:85

+ 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,
int  mode,
bool  privacy 
)

Write out one RFC822 header line.

Parameters
fpFile to write to
envEnvelope of email
attachAttachment
modeMode, see notes below
privacyIf true, remove headers that might identify the user
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.

mode == 1 => "light" mode (used for edit_headers) mode == 0 => normal mode. write full header + MIME headers mode == -1 => write just the envelope info (used for postponing messages)

privacy true => will omit any headers which may identify the user. Output generated is suitable for being sent through anonymous remailer chains.

Definition at line 2212 of file sendlib.c.

2214 {
2215  char buf[LONG_STRING];
2216  char *p = NULL, *q = NULL;
2217  bool has_agent = false; /* user defined user-agent header field exists */
2218 
2219  if (mode == 0 && !privacy)
2220  fputs(mutt_date_make_date(buf, sizeof(buf)), fp);
2221 
2222  /* UseFrom is not consulted here so that we can still write a From:
2223  * field if the user sets it with the `my_hdr' command
2224  */
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 > 0)
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 > 0)
2256 #ifdef USE_NNTP
2257  if (!OptNewsSend)
2258 #endif
2259  fputs("Cc:\n", fp);
2260 
2261  if (env->bcc)
2262  {
2263  if (mode != 0 || WriteBcc)
2264  {
2265  fputs("Bcc: ", fp);
2266  mutt_write_address_list(env->bcc, fp, 5, 0);
2267  }
2268  }
2269  else if (mode > 0)
2270 #ifdef USE_NNTP
2271  if (!OptNewsSend)
2272 #endif
2273  fputs("Bcc:\n", fp);
2274 
2275 #ifdef USE_NNTP
2276  if (env->newsgroups)
2277  fprintf(fp, "Newsgroups: %s\n", env->newsgroups);
2278  else if (mode == 1 && OptNewsSend)
2279  fputs("Newsgroups:\n", fp);
2280 
2281  if (env->followup_to)
2282  fprintf(fp, "Followup-To: %s\n", env->followup_to);
2283  else if (mode == 1 && OptNewsSend)
2284  fputs("Followup-To:\n", fp);
2285 
2286  if (env->x_comment_to)
2287  fprintf(fp, "X-Comment-To: %s\n", env->x_comment_to);
2288  else if (mode == 1 && OptNewsSend && XCommentTo)
2289  fputs("X-Comment-To:\n", fp);
2290 #endif
2291 
2292  if (env->subject)
2293  mutt_write_one_header(fp, "Subject", env->subject, NULL, 0, 0);
2294  else if (mode == 1)
2295  fputs("Subject:\n", fp);
2296 
2297  /* save message id if the user has set it */
2298  if (env->message_id && !privacy)
2299  fprintf(fp, "Message-ID: %s\n", env->message_id);
2300 
2301  if (env->reply_to)
2302  {
2303  fputs("Reply-To: ", fp);
2304  mutt_write_address_list(env->reply_to, fp, 10, 0);
2305  }
2306  else if (mode > 0)
2307  fputs("Reply-To:\n", fp);
2308 
2309  if (env->mail_followup_to)
2310 #ifdef USE_NNTP
2311  if (!OptNewsSend)
2312 #endif
2313  {
2314  fputs("Mail-Followup-To: ", fp);
2315  mutt_write_address_list(env->mail_followup_to, fp, 18, 0);
2316  }
2317 
2318  if (mode <= 0)
2319  {
2320  if (!STAILQ_EMPTY(&env->references))
2321  {
2322  fputs("References:", fp);
2323  mutt_write_references(&env->references, fp, 10);
2324  fputc('\n', fp);
2325  }
2326 
2327  /* Add the MIME headers */
2328  fputs("MIME-Version: 1.0\n", fp);
2329  mutt_write_mime_header(attach, fp);
2330  }
2331 
2332  if (!STAILQ_EMPTY(&env->in_reply_to))
2333  {
2334  fputs("In-Reply-To:", fp);
2335  mutt_write_references(&env->in_reply_to, fp, 0);
2336  fputc('\n', fp);
2337  }
2338 
2339  /* Add any user defined headers */
2340  struct ListNode *tmp = NULL;
2341  STAILQ_FOREACH(tmp, &env->userhdrs, entries)
2342  {
2343  p = strchr(tmp->data, ':');
2344  if (p)
2345  {
2346  q = p;
2347 
2348  *p = '\0';
2349 
2350  p = mutt_str_skip_email_wsp(p + 1);
2351  if (!*p)
2352  {
2353  *q = ':';
2354  continue; /* don't emit empty fields. */
2355  }
2356 
2357  /* check to see if the user has overridden the user-agent field */
2358  if (mutt_str_startswith(tmp->data, "user-agent", CASE_IGNORE))
2359  {
2360  has_agent = true;
2361  if (privacy)
2362  {
2363  *q = ':';
2364  continue;
2365  }
2366  }
2367 
2368  mutt_write_one_header(fp, tmp->data, p, NULL, 0, 0);
2369  *q = ':';
2370  }
2371  }
2372 
2373  if (mode == 0 && !privacy && UserAgent && !has_agent)
2374  {
2375  /* Add a vanity header */
2376  fprintf(fp, "User-Agent: NeoMutt/%s%s\n", PACKAGE_VERSION, GitVer);
2377  }
2378 
2379  return ferror(fp) == 0 ? 0 : -1;
2380 }
WHERE bool XCommentTo
Config: (nntp) Add &#39;X-Comment-To&#39; header that contains article author.
Definition: globals.h:282
bool UserAgent
Config: Add a &#39;User-Agent&#39; head to outgoing mail.
Definition: sendlib.c:91
struct Address * to
Definition: envelope.h:36
struct ListHead userhdrs
user defined headers
Definition: envelope.h:61
int mutt_write_one_header(FILE *fp, const char *tag, const char *value, const char *pfx, int wraplen, int flags)
Write one header line to a file.
Definition: sendlib.c:2107
#define LONG_STRING
Definition: string2.h:36
int mutt_write_mime_header(struct Body *a, FILE *f)
Create a MIME header.
Definition: sendlib.c:359
struct Address * sender
Definition: envelope.h:39
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:40
void mutt_write_address_list(struct Address *addr, FILE *fp, int linelen, bool display)
wrapper around mutt_write_address()
Definition: sendlib.c:1739
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:60
char * message_id
Definition: envelope.h:47
struct Address * mail_followup_to
Definition: envelope.h:41
WHERE bool WriteBcc
Config: Write out the &#39;Bcc&#39; field when preparing to send a mail.
Definition: globals.h:264
struct Address * from
Definition: envelope.h:35
char * x_comment_to
Definition: envelope.h:56
struct Address * bcc
Definition: envelope.h:38
const char * GitVer
void mutt_write_references(const struct ListHead *r, FILE *f, size_t trim)
Add the message references to a list.
Definition: sendlib.c:1788
Ignore case when comparing strings.
Definition: string2.h:70
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:768
#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:166
char * data
Definition: list.h:35
char * subject
Definition: envelope.h:44
char * newsgroups
Definition: envelope.h:53
char * followup_to
Definition: envelope.h:55
#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:59
A List node for strings.
Definition: list.h:33
struct Address * cc
Definition: envelope.h:37

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

2389 {
2390  char *tmp = NULL;
2391  char *p = NULL;
2392  int i;
2393 
2394  struct ListNode *np = NULL;
2395  STAILQ_FOREACH(np, h, entries)
2396  {
2397  p = strchr(np->data, ':');
2398  if (!p)
2399  continue;
2400 
2401  i = p - np->data;
2402  p = mutt_str_skip_email_wsp(p + 1);
2403  tmp = mutt_str_strdup(p);
2404 
2405  if (!tmp)
2406  continue;
2407 
2408  rfc2047_encode(&tmp, NULL, i + 2, SendCharset);
2409  mutt_mem_realloc(&np->data, i + 2 + mutt_str_strlen(tmp) + 1);
2410 
2411  sprintf(np->data + i + 2, "%s", tmp);
2412 
2413  FREE(&tmp);
2414  }
2415 }
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:663
void rfc2047_encode(char **pd, const char *specials, int col, const char *charsets)
RFC-2047-encode a string.
Definition: rfc2047.c:625
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:768
#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:384
#define FREE(x)
Definition: memory.h:46
A List node for strings.
Definition: list.h:33
char * SendCharset
Config: Character sets for outgoing mail ///< Config: List of character sets for outgoing messages...
Definition: email_globals.c:36

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

2426 {
2427  if (!Hostname || (Hostname[0] == '@'))
2428  return NULL;
2429 
2430  char *p = Hostname;
2431 
2432  if (may_hide_host && HiddenHost)
2433  {
2434  p = strchr(Hostname, '.');
2435  if (p)
2436  p++;
2437 
2438  /* sanity check: don't hide the host if
2439  * the fqdn is something like detebe.org.
2440  */
2441 
2442  if (!p || !strchr(p, '.'))
2443  p = Hostname;
2444  }
2445 
2446  return p;
2447 }
bool HiddenHost
Config: Don&#39;t use the hostname, just the domain, when generating the message id.
Definition: sendlib.c:81
WHERE char * Hostname
Config: Fully-qualified domain name of this machine.
Definition: globals.h:111

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

2456 {
2457  char buf[SHORT_STRING];
2458  time_t now;
2459  unsigned char rndid[MUTT_RANDTAG_LEN + 1];
2460 
2461  mutt_rand_base32(rndid, sizeof(rndid) - 1);
2462  rndid[MUTT_RANDTAG_LEN] = 0;
2463  now = time(NULL);
2464  struct tm *tm = gmtime(&now);
2465  const char *fqdn = mutt_fqdn(false);
2466  if (!fqdn)
2467  fqdn = NONULL(ShortHostname);
2468 
2469  snprintf(buf, sizeof(buf), "<%d%02d%02d%02d%02d%02d.%s@%s>", tm->tm_year + 1900,
2470  tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, rndid, fqdn);
2471  return mutt_str_strdup(buf);
2472 }
#define NONULL(x)
Definition: string2.h:39
#define SHORT_STRING
Definition: string2.h:34
#define MUTT_RANDTAG_LEN
Definition: muttlib.h:42
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2425
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
WHERE char * ShortHostname
Short version of the hostname.
Definition: globals.h:48
void mutt_rand_base32(void *buf, size_t buflen)
Fill a buffer with a base32-encoded random string.
Definition: muttlib.c:509

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

2479 {
2480  SigAlrm = 1;
2481 }
WHERE SIG_ATOMIC_VOLATILE_T SigAlrm
true after SIGALRM is received
Definition: globals.h:89

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

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

Definition at line 2663 of file sendlib.c.

2664 {
2665  for (; addr; addr = addr->next)
2666  {
2667  /* weed out group mailboxes, since those are for display only */
2668  if (addr->mailbox && !addr->group)
2669  {
2670  if (*argslen == *argsmax)
2671  mutt_mem_realloc(&args, (*argsmax += 5) * sizeof(char *));
2672  args[(*argslen)++] = addr->mailbox;
2673  }
2674  }
2675  return args;
2676 }
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
argsArray to add to
argslenNumber of entries in array
argsmaxAllocated size of the array
sstring to add
Return values
ptrUpdated array
Note
The array may be realloc()'d

Definition at line 2688 of file sendlib.c.

2689 {
2690  if (*argslen == *argsmax)
2691  mutt_mem_realloc(&args, (*argsmax += 5) * sizeof(char *));
2692  args[(*argslen)++] = s;
2693  return args;
2694 }
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 2707 of file sendlib.c.

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

2884 {
2885  if (final)
2886  {
2887  if (env->bcc && !(env->to || env->cc))
2888  {
2889  /* some MTA's will put an Apparently-To: header field showing the Bcc:
2890  * recipients if there is no To: or Cc: field, so attempt to suppress
2891  * it by using an empty To: field.
2892  */
2893  env->to = mutt_addr_new();
2894  env->to->group = 1;
2895  env->to->next = mutt_addr_new();
2896 
2897  char buf[LONG_STRING];
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. */
2911  rfc2047_encode_addrlist(env->to, "To");
2912  rfc2047_encode_addrlist(env->cc, "Cc");
2913  rfc2047_encode_addrlist(env->bcc, "Bcc");
2914  rfc2047_encode_addrlist(env->from, "From");
2915  rfc2047_encode_addrlist(env->mail_followup_to, "Mail-Followup-To");
2916  rfc2047_encode_addrlist(env->reply_to, "Reply-To");
2917 
2918  if (env->subject)
2919 #ifdef USE_NNTP
2920  if (!OptNewsSend || MimeSubject)
2921 #endif
2922  {
2923  rfc2047_encode(&env->subject, NULL, sizeof("Subject:"), SendCharset);
2924  }
2925  encode_headers(&env->userhdrs);
2926 }
void rfc2047_encode_addrlist(struct Address *addr, const char *tag)
Encode any RFC2047 headers, where required, in an Address list.
Definition: rfc2047.c:749
static char * gen_msgid(void)
Generate a unique Message ID.
Definition: sendlib.c:2455
struct Address * to
Definition: envelope.h:36
struct ListHead userhdrs
user defined headers
Definition: envelope.h:61
char * mailbox
mailbox and host address
Definition: address.h:35
#define LONG_STRING
Definition: string2.h:36
struct Address * reply_to
Definition: envelope.h:40
const char AddressSpecials[]
Characters with special meaning for email addresses.
Definition: address.c:41
char * message_id
Definition: envelope.h:47
struct Address * mail_followup_to
Definition: envelope.h:41
bool MimeSubject
Config: (nntp) Encode the article subject in base64.
Definition: sendlib.c:84
struct Address * from
Definition: envelope.h:35
void rfc2047_encode(char **pd, const char *specials, int col, const char *charsets)
RFC-2047-encode a string.
Definition: rfc2047.c:625
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:1156
struct Address * bcc
Definition: envelope.h:38
char * subject
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:384
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:43
struct Address * mutt_addr_new(void)
Create a new Address.
Definition: address.c:401
struct Address * cc
Definition: envelope.h:37
static void encode_headers(struct ListHead *h)
RFC2047-encode a list of headers.
Definition: sendlib.c:2388
struct Address * next
Definition: address.h:39
char * SendCharset
Config: Character sets for outgoing mail ///< Config: List of character sets for outgoing messages...
Definition: email_globals.c:36

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

2936 {
2937  struct ListNode *item = NULL;
2938  STAILQ_FOREACH(item, &env->userhdrs, entries)
2939  {
2940  rfc2047_decode(&item->data);
2941  }
2942 
2944 
2945  /* back conversions */
2951  rfc2047_decode(&env->subject);
2952 }
void rfc2047_decode(char **pd)
Decode any RFC2047-encoded header fields.
Definition: rfc2047.c:649
struct Address * to
Definition: envelope.h:36
struct ListHead userhdrs
user defined headers
Definition: envelope.h:61
struct Address * reply_to
Definition: envelope.h:40
struct Address * mail_followup_to
Definition: envelope.h:41
struct Address * from
Definition: envelope.h:35
struct Address * bcc
Definition: envelope.h:38
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
void rfc2047_decode_addrlist(struct Address *a)
Decode any RFC2047 headers in an Address list.
Definition: rfc2047.c:768
char * data
Definition: list.h:35
char * subject
Definition: envelope.h:44
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
struct Address * cc
Definition: envelope.h:37

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

2966 {
2967  int rc = 0;
2968  FILE *f = NULL;
2969  char tempfile[PATH_MAX];
2970  struct Message *msg = NULL;
2971 
2972  if (!e)
2973  {
2974  /* Try to bounce each message out, aborting if we get any failures. */
2975  for (int i = 0; i < Context->mailbox->msg_count; i++)
2976  if (message_is_tagged(Context, i))
2977  rc |= bounce_message(fp, Context->mailbox->hdrs[i], to, resent_from, env_from);
2978  return rc;
2979  }
2980 
2981  /* If we failed to open a message, return with error */
2982  if (!fp && !(msg = mx_msg_open(Context->mailbox, e->msgno)))
2983  return -1;
2984 
2985  if (!fp)
2986  fp = msg->fp;
2987 
2988  mutt_mktemp(tempfile, sizeof(tempfile));
2989  f = mutt_file_fopen(tempfile, "w");
2990  if (f)
2991  {
2992  char date[SHORT_STRING];
2993  int ch_flags = CH_XMIT | CH_NONEWLINE | CH_NOQFROM;
2994  char *msgid_str = NULL;
2995 
2996  if (!BounceDelivered)
2997  ch_flags |= CH_WEED_DELIVERED;
2998 
2999  fseeko(fp, e->offset, SEEK_SET);
3000  fprintf(f, "Resent-From: %s", resent_from);
3001  fprintf(f, "\nResent-%s", mutt_date_make_date(date, sizeof(date)));
3002  msgid_str = gen_msgid();
3003  fprintf(f, "Resent-Message-ID: %s\n", msgid_str);
3004  fputs("Resent-To: ", f);
3005  mutt_write_address_list(to, f, 11, 0);
3006  mutt_copy_header(fp, e, f, ch_flags, NULL);
3007  fputc('\n', f);
3009  FREE(&msgid_str);
3010  if (mutt_file_fclose(&f) != 0)
3011  {
3012  mutt_perror(tempfile);
3013  unlink(tempfile);
3014  return -1;
3015  }
3016 #ifdef USE_SMTP
3017  if (SmtpUrl)
3018  rc = mutt_smtp_send(env_from, to, NULL, NULL, tempfile, e->content->encoding == ENC_8BIT);
3019  else
3020 #endif /* USE_SMTP */
3021  rc = mutt_invoke_sendmail(env_from, to, NULL, NULL, tempfile,
3022  e->content->encoding == ENC_8BIT);
3023  }
3024 
3025  if (msg)
3026  mx_msg_close(Context->mailbox, &msg);
3027 
3028  return rc;
3029 }
The "current" mailbox.
Definition: context.h:36
int msg_count
total number of messages
Definition: mailbox.h:86
#define SHORT_STRING
Definition: string2.h:34
#define mutt_perror(...)
Definition: logging.h:89
int mutt_copy_header(FILE *in, struct Email *e, FILE *out, int flags, const char *prefix)
Copy Email header.
Definition: copy.c:406
static char * gen_msgid(void)
Generate a unique Message ID.
Definition: sendlib.c:2455
struct Body * content
list of MIME parts
Definition: email.h:92
8-bit text
Definition: mime.h:50
struct Email ** hdrs
Definition: mailbox.h:93
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:2707
char * mutt_date_make_date(char *buf, size_t buflen)
Write a date in RFC822 format to a buffer.
Definition: date.c:380
void mutt_write_address_list(struct Address *addr, FILE *fp, int linelen, bool display)
wrapper around mutt_write_address()
Definition: sendlib.c:1739
#define CH_WEED_DELIVERED
weed eventual Delivered-To headers
Definition: copy.h:60
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1187
struct Mailbox * mailbox
Definition: context.h:50
unsigned int encoding
content-transfer-encoding
Definition: body.h:68
#define mutt_mktemp(a, b)
Definition: muttlib.h:71
A local copy of an email.
Definition: mx.h:81
LOFF_T length
length (in bytes) of attachment
Definition: body.h:46
#define PATH_MAX
Definition: mutt.h:46
#define CH_XMIT
transmitting this message?
Definition: copy.h:50
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:2964
bool message_is_tagged(struct Context *ctx, int index)
Is a message in the index tagged (and within limit)
Definition: curs_lib.c:1236
LOFF_T offset
where in the stream does this message begin?
Definition: email.h:85
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:548
#define CH_NOQFROM
ignore ">From " line
Definition: copy.h:62
WHERE char * SmtpUrl
Config: (smtp) Url of the SMTP server.
Definition: globals.h:145
bool BounceDelivered
Config: Add &#39;Delivered-To&#39; to bounced messages.
Definition: sendlib.c:78
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
FILE * fp
pointer to the message data
Definition: mx.h:83
#define FREE(x)
Definition: memory.h:46
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:739
int mutt_file_copy_bytes(FILE *in, FILE *out, size_t size)
Copy some content from one file to another.
Definition: file.c:237
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
return a stream pointer for a message
Definition: mx.c:1139
#define CH_NONEWLINE
don&#39;t output terminating newline
Definition: copy.h:55
int msgno
number displayed to the user
Definition: email.h:88

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

3040 {
3041  const char *fqdn = mutt_fqdn(true);
3042  char resent_from[STRING];
3043  char *err = NULL;
3044 
3045  resent_from[0] = '\0';
3046  struct Address *from = mutt_default_from();
3047 
3048  /* mutt_default_from() does not use $realname if the real name is not set
3049  * in $from, so we add it here. The reason it is not added in
3050  * mutt_default_from() is that during normal sending, we execute
3051  * send-hooks and set the realname last so that it can be changed based
3052  * upon message criteria.
3053  */
3054  if (!from->personal)
3056 
3057  if (fqdn)
3058  mutt_addr_qualify(from, fqdn);
3059 
3060  rfc2047_encode_addrlist(from, "Resent-From");
3061  if (mutt_addrlist_to_intl(from, &err))
3062  {
3063  mutt_error(_("Bad IDN %s while preparing resent-from"), err);
3064  FREE(&err);
3065  mutt_addr_free(&from);
3066  return -1;
3067  }
3068  mutt_addr_write(resent_from, sizeof(resent_from), from, false);
3069 
3070 #ifdef USE_NNTP
3071  OptNewsSend = false;
3072 #endif
3073 
3074  /* prepare recipient list. idna conversion appears to happen before this
3075  * function is called, since the user receives confirmation of the address
3076  * list being bounced to.
3077  */
3078  struct Address *resent_to = mutt_addr_copy_list(to, false);
3079  rfc2047_encode_addrlist(resent_to, "Resent-To");
3080 
3081  int rc = bounce_message(fp, e, resent_to, resent_from, from);
3082 
3083  mutt_addr_free(&resent_to);
3084  mutt_addr_free(&from);
3085 
3086  return rc;
3087 }
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:1266
WHERE char * Realname
Config: Real name of the user.
Definition: globals.h:141
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:2964
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:2425
char * personal
real name of address
Definition: address.h:34
#define STRING
Definition: string2.h:35
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
#define mutt_error(...)
Definition: logging.h:88
#define FREE(x)
Definition: memory.h:46
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 3094 of file sendlib.c.

3095 {
3096  for (; b; b = b->next)
3097  {
3098  if (b->type == TYPE_MESSAGE || b->type == TYPE_MULTIPART)
3099  set_noconv_flags(b->parts, flag);
3100  else if (b->type == TYPE_TEXT && b->noconv)
3101  {
3102  if (flag)
3103  mutt_param_set(&b->parameter, "x-mutt-noconv", "yes");
3104  else
3105  mutt_param_delete(&b->parameter, "x-mutt-noconv");
3106  }
3107  }
3108 }
bool noconv
don&#39;t do character set conversion
Definition: body.h:77
struct Body * next
next attachment in the list
Definition: body.h:57
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:58
unsigned int type
content-type primary type
Definition: body.h:67
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:3094
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:38

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

3123 {
3124  char fcc_tok[PATH_MAX];
3125  char fcc_expanded[PATH_MAX];
3126 
3127  mutt_str_strfcpy(fcc_tok, path, sizeof(fcc_tok));
3128 
3129  char *tok = strtok(fcc_tok, ",");
3130  if (!tok)
3131  return -1;
3132 
3133  mutt_debug(1, "Fcc: initial mailbox = '%s'\n", tok);
3134  /* mutt_expand_path already called above for the first token */
3135  int status = mutt_write_fcc(tok, e, msgid, post, fcc, finalpath);
3136  if (status != 0)
3137  return status;
3138 
3139  while ((tok = strtok(NULL, ",")))
3140  {
3141  if (!*tok)
3142  continue;
3143 
3144  /* Only call mutt_expand_path iff tok has some data */
3145  mutt_debug(1, "Fcc: additional mailbox token = '%s'\n", tok);
3146  mutt_str_strfcpy(fcc_expanded, tok, sizeof(fcc_expanded));
3147  mutt_expand_path(fcc_expanded, sizeof(fcc_expanded));
3148  mutt_debug(1, " Additional mailbox expanded = '%s'\n", fcc_expanded);
3149  status = mutt_write_fcc(fcc_expanded, e, msgid, post, fcc, finalpath);
3150  if (status != 0)
3151  return status;
3152  }
3153 
3154  return 0;
3155 }
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:157
#define PATH_MAX
Definition: mutt.h:46
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:742
#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:3168

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

3170 {
3171  struct Message *msg = NULL;
3172  char tempfile[PATH_MAX];
3173  FILE *tempfp = NULL;
3174  int rc = -1;
3175  bool need_mailbox_cleanup = false;
3176  struct stat st;
3177  char buf[SHORT_STRING];
3178  int onm_flags;
3179 
3180  if (post)
3181  set_noconv_flags(e->content, true);
3182 
3183 #ifdef RECORD_FOLDER_HOOK
3184  mutt_folder_hook(path);
3185 #endif
3186  struct Context *f = mx_mbox_open(NULL, path, MUTT_APPEND | MUTT_QUIET);
3187  if (!f)
3188  {
3189  mutt_debug(1, "unable to open mailbox %s in append-mode, aborting.\n", path);
3190  goto done;
3191  }
3192 
3193  /* We need to add a Content-Length field to avoid problems where a line in
3194  * the message body begins with "From "
3195  */
3196  if ((f->mailbox->magic == MUTT_MMDF) || (f->mailbox->magic == MUTT_MBOX))
3197  {
3198  mutt_mktemp(tempfile, sizeof(tempfile));
3199  tempfp = mutt_file_fopen(tempfile, "w+");
3200  if (!tempfp)
3201  {
3202  mutt_perror(tempfile);
3203  mx_mbox_close(&f, NULL);
3204  goto done;
3205  }
3206  /* remember new mail status before appending message */
3207  need_mailbox_cleanup = true;
3208  stat(path, &st);
3209  }
3210 
3211  e->read = !post; /* make sure to put it in the `cur' directory (maildir) */
3212  onm_flags = MUTT_ADD_FROM;
3213  if (post)
3214  onm_flags |= MUTT_SET_DRAFT;
3215  msg = mx_msg_open_new(f->mailbox, e, onm_flags);
3216  if (!msg)
3217  {
3218  mutt_file_fclose(&tempfp);
3219  mx_mbox_close(&f, NULL);
3220  goto done;
3221  }
3222 
3223  /* post == 1 => postpone message. Set mode = -1 in mutt_rfc822_write_header()
3224  * post == 0 => Normal mode. Set mode = 0 in mutt_rfc822_write_header()
3225  */
3226  mutt_rfc822_write_header(msg->fp, e->env, e->content, post ? -1 : 0, false);
3227 
3228  /* (postponement) if this was a reply of some sort, <msgid> contains the
3229  * Message-ID: of message replied to. Save it using a special X-Mutt-
3230  * header so it can be picked up if the message is recalled at a later
3231  * point in time. This will allow the message to be marked as replied if
3232  * the same mailbox is still open.
3233  */
3234  if (post && msgid)
3235  fprintf(msg->fp, "X-Mutt-References: %s\n", msgid);
3236 
3237  /* (postponement) save the Fcc: using a special X-Mutt- header so that
3238  * it can be picked up when the message is recalled
3239  */
3240  if (post && fcc)
3241  fprintf(msg->fp, "X-Mutt-Fcc: %s\n", fcc);
3242 
3243  if ((f->mailbox->magic == MUTT_MMDF) || (f->mailbox->magic == MUTT_MBOX))
3244  fprintf(msg->fp, "Status: RO\n");
3245 
3246  /* mutt_rfc822_write_header() only writes out a Date: header with
3247  * mode == 0, i.e. _not_ postponement; so write out one ourself */
3248  if (post)
3249  fprintf(msg->fp, "%s", mutt_date_make_date(buf, sizeof(buf)));
3250 
3251  /* (postponement) if the mail is to be signed or encrypted, save this info */
3252  if (((WithCrypto & APPLICATION_PGP) != 0) && post && (e->security & APPLICATION_PGP))
3253  {
3254  fputs("X-Mutt-PGP: ", msg->fp);
3255  if (e->security & ENCRYPT)
3256  fputc('E', msg->fp);
3257  if (e->security & OPPENCRYPT)
3258  fputc('O', msg->fp);
3259  if (e->security & SIGN)
3260  {
3261  fputc('S', msg->fp);
3262  if (PgpSignAs && *PgpSignAs)
3263  fprintf(msg->fp, "<%s>", PgpSignAs);
3264  }
3265  if (e->security & INLINE)
3266  fputc('I', msg->fp);
3267  fputc('\n', msg->fp);
3268  }
3269 
3270  /* (postponement) if the mail is to be signed or encrypted, save this info */
3271  if (((WithCrypto & APPLICATION_SMIME) != 0) && post && (e->security & APPLICATION_SMIME))
3272  {
3273  fputs("X-Mutt-SMIME: ", msg->fp);
3274  if (e->security & ENCRYPT)
3275  {
3276  fputc('E', msg->fp);
3278  fprintf(msg->fp, "C<%s>", SmimeEncryptWith);
3279  }
3280  if (e->security & OPPENCRYPT)
3281  fputc('O', msg->fp);
3282  if (e->security & SIGN)
3283  {
3284  fputc('S', msg->fp);
3285  if (SmimeSignAs && *SmimeSignAs)
3286  fprintf(msg->fp, "<%s>", SmimeSignAs);
3287  }
3288  if (e->security & INLINE)
3289  fputc('I', msg->fp);
3290  fputc('\n', msg->fp);
3291  }
3292 
3293 #ifdef MIXMASTER
3294  /* (postponement) if the mail is to be sent through a mixmaster
3295  * chain, save that information
3296  */
3297 
3298  if (post && !STAILQ_EMPTY(&e->chain))
3299  {
3300  fputs("X-Mutt-Mix:", msg->fp);
3301  struct ListNode *p = NULL;
3302  STAILQ_FOREACH(p, &e->chain, entries)
3303  {
3304  fprintf(msg->fp, " %s", (char *) p->data);
3305  }
3306 
3307  fputc('\n', msg->fp);
3308  }
3309 #endif
3310 
3311  if (tempfp)
3312  {
3313  char sasha[LONG_STRING];
3314  int lines = 0;
3315 
3316  mutt_write_mime_body(e->content, tempfp);
3317 
3318  /* make sure the last line ends with a newline. Emacs doesn't ensure
3319  * this will happen, and it can cause problems parsing the mailbox
3320  * later.
3321  */
3322  fseek(tempfp, -1, SEEK_END);
3323  if (fgetc(tempfp) != '\n')
3324  {
3325  fseek(tempfp, 0, SEEK_END);
3326  fputc('\n', tempfp);
3327  }
3328 
3329  fflush(tempfp);
3330  if (ferror(tempfp))
3331  {
3332  mutt_debug(1, "%s: write failed.\n", tempfile);
3333  mutt_file_fclose(&tempfp);
3334  unlink(tempfile);
3335  mx_msg_commit(f->mailbox, msg); /* XXX really? */
3336  mx_msg_close(f->mailbox, &msg);
3337  mx_mbox_close(&f, NULL);
3338  goto done;
3339  }
3340 
3341  /* count the number of lines */
3342  rewind(tempfp);
3343  while (fgets(sasha, sizeof(sasha), tempfp))
3344  lines++;
3345  fprintf(msg->fp, "Content-Length: " OFF_T_FMT "\n", (LOFF_T) ftello(tempfp));
3346  fprintf(msg->fp, "Lines: %d\n\n", lines);
3347 
3348  /* copy the body and clean up */
3349  rewind(tempfp);
3350  rc = mutt_file_copy_stream(tempfp, msg->fp);
3351  if (fclose(tempfp) != 0)
3352  rc = -1;
3353  /* if there was an error, leave the temp version */
3354  if (!rc)
3355  unlink(tempfile);
3356  }
3357  else
3358  {
3359  fputc('\n', msg->fp); /* finish off the header */
3360  rc = mutt_write_mime_body(e->content, msg->fp);
3361  }
3362 
3363  if (mx_msg_commit(f->mailbox, msg) != 0)
3364  rc = -1;
3365  else if (finalpath)
3366  *finalpath = mutt_str_strdup(msg->committed_path);
3367  mx_msg_close(f->mailbox, &msg);
3368  mx_mbox_close(&f, NULL);
3369 
3370  if (!post && need_mailbox_cleanup)
3371  mutt_mailbox_cleanup(path, &st);
3372 
3373  if (post)
3374  set_noconv_flags(e->content, false);
3375 
3376 done:
3377 #ifdef RECORD_FOLDER_HOOK
3378  /* We ran a folder hook for the destination mailbox,
3379  * now we run it for the user's current mailbox */
3380  if (Context && Context->mailbox->path)
3382 #endif
3383 
3384  return rc;
3385 }
#define MUTT_APPEND
open mailbox for appending messages
Definition: mx.h:50
The "current" mailbox.
Definition: context.h:36
#define SIGN
Definition: ncrypt.h:120
#define SHORT_STRING
Definition: string2.h:34
void mutt_folder_hook(const char *path)
Perform a folder hook.
Definition: hook.c:371
#define mutt_perror(...)
Definition: logging.h:89
unsigned int security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:37
struct Body * content
list of MIME parts
Definition: email.h:92
&#39;mmdf&#39; Mailbox type
Definition: magic.h:38
void mutt_mailbox_cleanup(const char *path, struct stat *st)
Restore the timestamp of a mailbox.
Definition: mailbox.c:217
#define LONG_STRING
Definition: string2.h:36
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_write_mime_body(struct Body *a, FILE *f)
Write a MIME part.
Definition: sendlib.c:488
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1187
bool read
Definition: email.h:49
int mutt_rfc822_write_header(FILE *fp, struct Envelope *env, struct Body *attach, int mode, bool privacy)
Write out one RFC822 header line.
Definition: sendlib.c:2212
struct Context * mx_mbox_open(struct Mailbox *m, const char *path, int flags)
Open a mailbox and parse it.
Definition: mx.c:254
struct Mailbox * mailbox
Definition: context.h:50
#define INLINE
Definition: ncrypt.h:126
enum MailboxType magic
mailbox type
Definition: mailbox.h:99
struct Envelope * env
envelope information
Definition: email.h:91
WHERE char * SmimeEncryptWith
Config: Algorithm for encryption.
Definition: globals.h:173
struct Message * mx_msg_open_new(struct Mailbox *m, struct Email *e, int flags)
Open a new message.
Definition: mx.c:1053
#define OPPENCRYPT
Definition: ncrypt.h:127
WHERE char * PgpSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:168
int mx_mbox_close(struct Context **pctx, int *index_hint)
Save changes and close mailbox.
Definition: mx.c:568
WHERE char * SmimeSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:172
#define ENCRYPT
Definition: ncrypt.h:119
&#39;mbox&#39; Mailbox type
Definition: magic.h:37
#define mutt_mktemp(a, b)
Definition: muttlib.h:71
A local copy of an email.
Definition: mx.h:81
int mutt_file_copy_stream(FILE *fin, FILE *fout)
Copy the contents of one file into another.
Definition: file.c:264
#define PATH_MAX
Definition: mutt.h:46
#define MUTT_QUIET
do not print any messages
Definition: mx.h:52
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
#define APPLICATION_PGP
Definition: ncrypt.h:129
char path[PATH_MAX]
Definition: mailbox.h:78
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:548
char * data
Definition: list.h:35
static const char * lines[]
Definition: file.c:8
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
int mx_msg_commit(struct Mailbox *m, struct Message *msg)
Commit a message to a folder - Wrapper for MxOps::msg_commit()
Definition: mx.c:1166
FILE * fp
pointer to the message data
Definition: mx.h:83
static void set_noconv_flags(struct Body *b, bool flag)
Set/reset the "x-mutt-noconv" flag.
Definition: sendlib.c:3094
#define STAILQ_EMPTY(head)
Definition: queue.h:346
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
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:154
#define APPLICATION_SMIME
Definition: ncrypt.h:130

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Variable Documentation

bool Allow8bit

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

Definition at line 76 of file sendlib.c.

char* AttachCharset

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

Definition at line 77 of file sendlib.c.

bool BounceDelivered

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

Definition at line 78 of file sendlib.c.

bool EncodeFrom

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

Definition at line 79 of file sendlib.c.

bool ForwardDecrypt

Config: Decrypt the message when forwarding it.

Definition at line 80 of file sendlib.c.

bool HiddenHost

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

Definition at line 81 of file sendlib.c.

char* Inews

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

Definition at line 82 of file sendlib.c.

bool MimeForwardDecode

Config: Decode the forwarded message before attaching it.

Definition at line 83 of file sendlib.c.

bool MimeSubject

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

encode subject line with RFC2047

Definition at line 84 of file sendlib.c.

char* MimeTypeQueryCommand

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

Definition at line 85 of file sendlib.c.

bool MimeTypeQueryFirst

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

Definition at line 86 of file sendlib.c.

char* Sendmail

Config: External command to send email.

Definition at line 87 of file sendlib.c.

short SendmailWait

Config: Time to wait for sendmail to finish.

Definition at line 88 of file sendlib.c.

bool Use8bitmime

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

Definition at line 89 of file sendlib.c.

bool UseEnvelopeFrom

Config: Set the envelope sender of the message.

Definition at line 90 of file sendlib.c.

bool UserAgent

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

Definition at line 91 of file sendlib.c.

short WrapHeaders

Config: Width to wrap headers in outgoing messages.

Definition at line 92 of file sendlib.c.