NeoMutt  2018-07-16 +2481-68dcde
Teaching an old dog new tricks
DOXYGEN
sendlib.h File Reference

Miscellaneous functions for sending an email. More...

#include <stdbool.h>
#include <stdio.h>
#include "email/lib.h"
#include "copy.h"
+ Include dependency graph for sendlib.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Enumerations

enum  MuttWriteHeaderMode { MUTT_WRITE_HEADER_NORMAL, MUTT_WRITE_HEADER_POSTPONE, MUTT_WRITE_HEADER_EDITHDRS, MUTT_WRITE_HEADER_MIME }
 Modes for mutt_rfc822_write_header() More...
 

Functions

char * mutt_body_get_charset (struct Body *b, char *buf, size_t buflen)
 Get a body's character set. More...
 
int mutt_bounce_message (FILE *fp, struct Email *e, struct AddressList *to)
 Bounce an email message. More...
 
const char * mutt_fqdn (bool may_hide_host)
 Get the Fully-Qualified Domain Name. More...
 
void mutt_generate_boundary (struct ParameterList *pl)
 Create a unique boundary id for a MIME part. More...
 
struct Contentmutt_get_content_info (const char *fname, struct Body *b)
 Analyze file to determine MIME encoding to use. More...
 
int mutt_invoke_sendmail (struct AddressList *from, struct AddressList *to, struct AddressList *cc, struct AddressList *bcc, const char *msg, int eightbit)
 Run sendmail. More...
 
enum ContentType mutt_lookup_mime_type (struct Body *att, const char *path)
 Find the MIME type for an attachment. More...
 
struct Bodymutt_make_file_attach (const char *path)
 Create a file attachment. More...
 
struct Bodymutt_make_message_attach (struct Mailbox *m, struct Email *e, bool attach_msg)
 Create a message attachment. More...
 
struct Bodymutt_make_multipart (struct Body *b)
 Create a multipart email. More...
 
void mutt_message_to_7bit (struct Body *a, FILE *fp)
 Convert an email's MIME parts to 7-bit. More...
 
void mutt_prepare_envelope (struct Envelope *env, bool final)
 Prepare an email header. More...
 
struct Bodymutt_remove_multipart (struct Body *b)
 Extract the multipart body if it exists. More...
 
int mutt_rfc822_write_header (FILE *fp, struct Envelope *env, struct Body *attach, enum MuttWriteHeaderMode mode, bool privacy, bool hide_protected_subject)
 Write out one RFC822 header line. More...
 
void mutt_stamp_attachment (struct Body *a)
 Timestamp an Attachment. More...
 
void mutt_unprepare_envelope (struct Envelope *env)
 Undo the encodings of mutt_prepare_envelope() More...
 
void mutt_update_encoding (struct Body *a)
 Update the encoding type. More...
 
void mutt_write_addrlist (struct AddressList *addr, FILE *fp, int linelen, bool display)
 wrapper around mutt_write_address() 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...
 
int mutt_write_mime_body (struct Body *a, FILE *fp)
 Write a MIME part. More...
 
int mutt_write_mime_header (struct Body *a, FILE *fp)
 Create a MIME header. 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_one_header (FILE *fp, const char *tag, const char *value, const char *pfx, int wraplen, CopyHeaderFlags chflags)
 Write one header line to a file. More...
 
void mutt_write_references (const struct ListHead *r, FILE *fp, size_t trim)
 Add the message references to a list. More...
 

Variables

bool C_Allow8bit
 Config: Allow 8-bit messages, don't use quoted-printable or base64. More...
 
char * C_AttachCharset
 Config: When attaching files, use one of these character sets. More...
 
bool C_BounceDelivered
 Config: Add 'Delivered-To' to bounced messages. More...
 
bool C_EncodeFrom
 Config: Encode 'From ' as 'quote-printable' at the beginning of lines. More...
 
bool C_ForwardDecrypt
 Config: Decrypt the message when forwarding it. More...
 
bool C_HiddenHost
 Config: Don't use the hostname, just the domain, when generating the message id. More...
 
char * C_Inews
 Config: (nntp) External command to post news articles. More...
 
bool C_MimeForwardDecode
 Config: Decode the forwarded message before attaching it. More...
 
bool C_MimeSubject
 encode subject line with RFC2047 More...
 
char * C_MimeTypeQueryCommand
 Config: External command to determine the MIME type of an attachment. More...
 
bool C_MimeTypeQueryFirst
 Config: Run the C_MimeTypeQueryCommand before the mime.types lookup. More...
 
char * C_Sendmail
 Config: External command to send email. More...
 
short C_SendmailWait
 Config: Time to wait for sendmail to finish. More...
 
bool C_Use8bitmime
 Config: Use 8-bit messages and ESMTP to send messages. More...
 
bool C_UseEnvelopeFrom
 Config: Set the envelope sender of the message. More...
 
bool C_UserAgent
 Config: Add a 'User-Agent' head to outgoing mail. More...
 
short C_WrapHeaders
 Config: Width to wrap headers in outgoing messages. More...
 

Detailed Description

Miscellaneous functions for sending an email.

Authors
  • Richard Russon
  • Pietro Cerutti

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file sendlib.h.

Enumeration Type Documentation

◆ MuttWriteHeaderMode

Modes for mutt_rfc822_write_header()

Enumerator
MUTT_WRITE_HEADER_NORMAL 

A normal Email, write full header + MIME headers.

MUTT_WRITE_HEADER_POSTPONE 

A postponed Email, just the envelope info.

MUTT_WRITE_HEADER_EDITHDRS 

"light" mode (used for edit_hdrs)

MUTT_WRITE_HEADER_MIME 

Write protected headers.

Definition at line 58 of file sendlib.h.

59 {
64 };
A normal Email, write full header + MIME headers.
Definition: sendlib.h:60
A postponed Email, just the envelope info.
Definition: sendlib.h:61
"light" mode (used for edit_hdrs)
Definition: sendlib.h:62
Write protected headers.
Definition: sendlib.h:63

Function Documentation

◆ mutt_body_get_charset()

char* mutt_body_get_charset ( struct Body b,
char *  buf,
size_t  buflen 
)

Get a body's character set.

Parameters
bBody to examine
bufBuffer for the result
buflenLength of the buffer
Return values
ptrBuffer containing character set
NULLOn error, or if not a text type

Definition at line 1431 of file sendlib.c.

1432 {
1433  char *p = NULL;
1434 
1435  if (b && (b->type != TYPE_TEXT))
1436  return NULL;
1437 
1438  if (b)
1439  p = mutt_param_get(&b->parameter, "charset");
1440 
1441  if (p)
1442  mutt_ch_canonical_charset(buf, buflen, p);
1443  else
1444  mutt_str_strfcpy(buf, "us-ascii", buflen);
1445 
1446  return buf;
1447 }
void mutt_ch_canonical_charset(char *buf, size_t buflen, const char *name)
Canonicalise the charset of a string.
Definition: charset.c:345
Type: &#39;text/*&#39;.
Definition: mime.h:38
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
unsigned int type
content-type primary type
Definition: body.h:65
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_bounce_message()

int mutt_bounce_message ( FILE *  fp,
struct Email e,
struct AddressList *  to 
)

Bounce an email message.

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

Definition at line 3116 of file sendlib.c.

3117 {
3118  if (!fp || !e || !to || TAILQ_EMPTY(to))
3119  return -1;
3120 
3121  const char *fqdn = mutt_fqdn(true);
3122  char resent_from[256];
3123  char *err = NULL;
3124 
3125  resent_from[0] = '\0';
3126  struct Address *from = mutt_default_from();
3127  struct AddressList from_list = TAILQ_HEAD_INITIALIZER(from_list);
3128  mutt_addrlist_append(&from_list, from);
3129 
3130  /* mutt_default_from() does not use $realname if the real name is not set
3131  * in $from, so we add it here. The reason it is not added in
3132  * mutt_default_from() is that during normal sending, we execute
3133  * send-hooks and set the realname last so that it can be changed based
3134  * upon message criteria. */
3135  if (!from->personal)
3137 
3138  mutt_addrlist_qualify(&from_list, fqdn);
3139 
3140  rfc2047_encode_addrlist(&from_list, "Resent-From");
3141  if (mutt_addrlist_to_intl(&from_list, &err))
3142  {
3143  mutt_error(_("Bad IDN %s while preparing resent-from"), err);
3144  FREE(&err);
3145  mutt_addrlist_clear(&from_list);
3146  return -1;
3147  }
3148  mutt_addrlist_write(resent_from, sizeof(resent_from), &from_list, false);
3149 
3150 #ifdef USE_NNTP
3151  OptNewsSend = false;
3152 #endif
3153 
3154  /* prepare recipient list. idna conversion appears to happen before this
3155  * function is called, since the user receives confirmation of the address
3156  * list being bounced to. */
3157  struct AddressList resent_to = TAILQ_HEAD_INITIALIZER(resent_to);
3158  mutt_addrlist_copy(&resent_to, to, false);
3159  rfc2047_encode_addrlist(&resent_to, "Resent-To");
3160  int rc = bounce_message(fp, e, &resent_to, resent_from, &from_list);
3161  mutt_addrlist_clear(&resent_to);
3162  mutt_addrlist_clear(&from_list);
3163 
3164  return rc;
3165 }
static int bounce_message(FILE *fp, struct Email *e, struct AddressList *to, const char *resent_from, struct AddressList *env_from)
Bounce an email message.
Definition: sendlib.c:3060
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1381
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:727
#define _(a)
Definition: message.h:28
An email address.
Definition: address.h:34
size_t mutt_addrlist_write(char *buf, size_t buflen, const struct AddressList *al, bool display)
Write an Address to a buffer.
Definition: address.c:1137
void rfc2047_encode_addrlist(struct AddressList *al, const char *tag)
Encode any RFC2047 headers, where required, in an Address list.
Definition: rfc2047.c:748
struct Address * mutt_default_from(void)
Get a default &#39;from&#39; Address.
Definition: send.c:1307
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2527
char * personal
Real name of address.
Definition: address.h:36
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:640
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1216
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define mutt_error(...)
Definition: logging.h:84
#define FREE(x)
Definition: memory.h:40
WHERE char * C_Realname
Config: Real name of the user.
Definition: globals.h:143
#define TAILQ_EMPTY(head)
Definition: queue.h:715
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:44
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:631
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1401
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_fqdn()

const char* mutt_fqdn ( bool  may_hide_host)

Get the Fully-Qualified Domain Name.

Parameters
may_hide_hostIf true, hide the hostname (leaving just the domain)
Return values
ptrstring pointer into Hostname
NULLError, e.g no Hostname
Warning
Do not free the returned pointer

Definition at line 2527 of file sendlib.c.

2528 {
2529  if (!C_Hostname || (C_Hostname[0] == '@'))
2530  return NULL;
2531 
2532  char *p = C_Hostname;
2533 
2534  if (may_hide_host && C_HiddenHost)
2535  {
2536  p = strchr(C_Hostname, '.');
2537  if (p)
2538  p++;
2539 
2540  // sanity check: don't hide the host if the fqdn is something like example.com
2541  if (!p || !strchr(p, '.'))
2542  p = C_Hostname;
2543  }
2544 
2545  return p;
2546 }
bool C_HiddenHost
Config: Don&#39;t use the hostname, just the domain, when generating the message id.
Definition: sendlib.c:87
WHERE char * C_Hostname
Config: Fully-qualified domain name of this machine.
Definition: globals.h:116
+ Here is the caller graph for this function:

◆ mutt_generate_boundary()

void mutt_generate_boundary ( struct ParameterList *  pl)

Create a unique boundary id for a MIME part.

Parameters
plMIME part

Definition at line 604 of file sendlib.c.

605 {
606  char rs[MUTT_RANDTAG_LEN + 1];
607 
608  mutt_rand_base32(rs, sizeof(rs) - 1);
609  rs[MUTT_RANDTAG_LEN] = 0;
610  mutt_param_set(pl, "boundary", rs);
611 }
#define MUTT_RANDTAG_LEN
Definition: muttlib.h:43
void mutt_rand_base32(void *buf, size_t buflen)
Fill a buffer with a base32-encoded random string.
Definition: muttlib.c:513
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_get_content_info()

struct Content* mutt_get_content_info ( const char *  fname,
struct Body b 
)

Analyze file to determine MIME encoding to use.

Parameters
fnameFile to examine
bBody to update
Return values
ptrNewly allocated Content

Also set the body charset, sometimes, or not.

Definition at line 1013 of file sendlib.c.

1014 {
1015  struct Content *info = NULL;
1016  struct ContentState state = { 0 };
1017  FILE *fp = NULL;
1018  char *fromcode = NULL;
1019  char *tocode = NULL;
1020  char buf[100];
1021  size_t r;
1022 
1023  struct stat sb;
1024 
1025  if (b && !fname)
1026  fname = b->filename;
1027 
1028  if (stat(fname, &sb) == -1)
1029  {
1030  mutt_error(_("Can't stat %s: %s"), fname, strerror(errno));
1031  return NULL;
1032  }
1033 
1034  if (!S_ISREG(sb.st_mode))
1035  {
1036  mutt_error(_("%s isn't a regular file"), fname);
1037  return NULL;
1038  }
1039 
1040  fp = fopen(fname, "r");
1041  if (!fp)
1042  {
1043  mutt_debug(LL_DEBUG1, "%s: %s (errno %d)\n", fname, strerror(errno), errno);
1044  return NULL;
1045  }
1046 
1047  info = mutt_mem_calloc(1, sizeof(struct Content));
1048 
1049  if (b && (b->type == TYPE_TEXT) && (!b->noconv && !b->force_charset))
1050  {
1051  char *chs = mutt_param_get(&b->parameter, "charset");
1052  char *fchs = b->use_disp ? (C_AttachCharset ? C_AttachCharset : C_Charset) : C_Charset;
1053  if (C_Charset && (chs || C_SendCharset) &&
1054  (convert_file_from_to(fp, fchs, chs ? chs : C_SendCharset, &fromcode,
1055  &tocode, info) != (size_t)(-1)))
1056  {
1057  if (!chs)
1058  {
1059  char chsbuf[256];
1060  mutt_ch_canonical_charset(chsbuf, sizeof(chsbuf), tocode);
1061  mutt_param_set(&b->parameter, "charset", chsbuf);
1062  }
1063  FREE(&b->charset);
1064  b->charset = fromcode;
1065  FREE(&tocode);
1066  mutt_file_fclose(&fp);
1067  return info;
1068  }
1069  }
1070 
1071  rewind(fp);
1072  while ((r = fread(buf, 1, sizeof(buf), fp)))
1073  update_content_info(info, &state, buf, r);
1074  update_content_info(info, &state, 0, 0);
1075 
1076  mutt_file_fclose(&fp);
1077 
1078  if (b && (b->type == TYPE_TEXT) && (!b->noconv && !b->force_charset))
1079  {
1080  mutt_param_set(&b->parameter, "charset",
1081  (!info->hibin ?
1082  "us-ascii" :
1083  C_Charset && !mutt_ch_is_us_ascii(C_Charset) ? C_Charset : "unknown-8bit"));
1084  }
1085 
1086  return info;
1087 }
Info about the body of an email.
Definition: sendlib.c:616
static void update_content_info(struct Content *info, struct ContentState *s, char *buf, size_t buflen)
Cache some info about an email.
Definition: sendlib.c:632
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
bool noconv
Don&#39;t do character set conversion.
Definition: body.h:73
#define _(a)
Definition: message.h:28
long hibin
8-bit characters
Definition: content.h:35
char * C_SendCharset
Config: Character sets for outgoing mail.
Definition: email_globals.c:38
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:150
bool force_charset
Send mode: don&#39;t adjust the character set when in send-mode.
Definition: body.h:74
void mutt_ch_canonical_charset(char *buf, size_t buflen, const char *name)
Canonicalise the charset of a string.
Definition: charset.c:345
#define mutt_ch_is_us_ascii(str)
Definition: charset.h:107
static char * chs
Definition: gnupgparse.c:72
Info about an attachment.
Definition: content.h:33
Type: &#39;text/*&#39;.
Definition: mime.h:38
char * C_AttachCharset
Config: When attaching files, use one of these character sets.
Definition: sendlib.c:83
char * charset
Send mode: charset of attached file as stored on disk.
Definition: body.h:49
unsigned int type
content-type primary type
Definition: body.h:65
Log at debug level 1.
Definition: logging.h:56
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
#define mutt_error(...)
Definition: logging.h:84
#define FREE(x)
Definition: memory.h:40
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:54
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
static size_t convert_file_from_to(FILE *fp, const char *fromcodes, const char *tocodes, char **fromcode, char **tocode, struct Content *info)
Convert a file between encodings.
Definition: sendlib.c:934
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_invoke_sendmail()

int mutt_invoke_sendmail ( struct AddressList *  from,
struct AddressList *  to,
struct AddressList *  cc,
struct AddressList *  bcc,
const char *  msg,
int  eightbit 
)

Run sendmail.

Parameters
fromThe sender
toRecipients
ccRecipients
bccRecipients
msgFile containing message
eightbitMessage contains 8bit chars
Return values
0Success
-1Failure

Definition at line 2819 of file sendlib.c.

2822 {
2823  char *ps = NULL, *path = NULL, *s = NULL, *childout = NULL;
2824  char **args = NULL;
2825  size_t argslen = 0, argsmax = 0;
2826  char **extra_args = NULL;
2827  int i;
2828 
2829 #ifdef USE_NNTP
2830  if (OptNewsSend)
2831  {
2832  char cmd[1024];
2833 
2834  mutt_expando_format(cmd, sizeof(cmd), 0, sizeof(cmd), NONULL(C_Inews),
2836  if (!*cmd)
2837  {
2838  i = nntp_post(Context->mailbox, msg);
2839  unlink(msg);
2840  return i;
2841  }
2842 
2843  s = mutt_str_strdup(cmd);
2844  }
2845  else
2846 #endif
2848 
2849  /* ensure that $sendmail is set to avoid a crash. http://dev.mutt.org/trac/ticket/3548 */
2850  if (!s)
2851  {
2852  mutt_error(_("$sendmail must be set in order to send mail"));
2853  return -1;
2854  }
2855 
2856  ps = s;
2857  i = 0;
2858  while ((ps = strtok(ps, " ")))
2859  {
2860  if (argslen == argsmax)
2861  mutt_mem_realloc(&args, sizeof(char *) * (argsmax += 5));
2862 
2863  if (i)
2864  {
2865  if (mutt_str_strcmp(ps, "--") == 0)
2866  break;
2867  args[argslen++] = ps;
2868  }
2869  else
2870  {
2871  path = mutt_str_strdup(ps);
2872  ps = strrchr(ps, '/');
2873  if (ps)
2874  ps++;
2875  else
2876  ps = path;
2877  args[argslen++] = ps;
2878  }
2879  ps = NULL;
2880  i++;
2881  }
2882 
2883 #ifdef USE_NNTP
2884  if (!OptNewsSend)
2885  {
2886 #endif
2887  size_t extra_argslen = 0;
2888  /* If C_Sendmail contained a "--", we save the recipients to append to
2889  * args after other possible options added below. */
2890  if (ps)
2891  {
2892  ps = NULL;
2893  size_t extra_argsmax = 0;
2894  while ((ps = strtok(ps, " ")))
2895  {
2896  if (extra_argslen == extra_argsmax)
2897  mutt_mem_realloc(&extra_args, sizeof(char *) * (extra_argsmax += 5));
2898 
2899  extra_args[extra_argslen++] = ps;
2900  ps = NULL;
2901  }
2902  }
2903 
2904  if (eightbit && C_Use8bitmime)
2905  args = add_option(args, &argslen, &argsmax, "-B8BITMIME");
2906 
2907  if (C_UseEnvelopeFrom)
2908  {
2910  {
2911  args = add_option(args, &argslen, &argsmax, "-f");
2912  args = add_args_one(args, &argslen, &argsmax, C_EnvelopeFromAddress);
2913  }
2914  else if (!TAILQ_EMPTY(from) && !TAILQ_NEXT(TAILQ_FIRST(from), entries))
2915  {
2916  args = add_option(args, &argslen, &argsmax, "-f");
2917  args = add_args(args, &argslen, &argsmax, from);
2918  }
2919  }
2920 
2921  if (C_DsnNotify)
2922  {
2923  args = add_option(args, &argslen, &argsmax, "-N");
2924  args = add_option(args, &argslen, &argsmax, C_DsnNotify);
2925  }
2926  if (C_DsnReturn)
2927  {
2928  args = add_option(args, &argslen, &argsmax, "-R");
2929  args = add_option(args, &argslen, &argsmax, C_DsnReturn);
2930  }
2931  args = add_option(args, &argslen, &argsmax, "--");
2932  for (i = 0; i < extra_argslen; i++)
2933  args = add_option(args, &argslen, &argsmax, extra_args[i]);
2934  args = add_args(args, &argslen, &argsmax, to);
2935  args = add_args(args, &argslen, &argsmax, cc);
2936  args = add_args(args, &argslen, &argsmax, bcc);
2937 #ifdef USE_NNTP
2938  }
2939 #endif
2940 
2941  if (argslen == argsmax)
2942  mutt_mem_realloc(&args, sizeof(char *) * (++argsmax));
2943 
2944  args[argslen++] = NULL;
2945 
2946  /* Some user's $sendmail command uses gpg for password decryption,
2947  * and is set up to prompt using ncurses pinentry. If we
2948  * mutt_endwin() it leaves other users staring at a blank screen.
2949  * So instead, just force a hard redraw on the next refresh. */
2950  if (!OptNoCurses)
2952 
2953  i = send_msg(path, args, msg, OptNoCurses ? NULL : &childout);
2954  if (i != (EX_OK & 0xff))
2955  {
2956  if (i != S_BKG)
2957  {
2958  const char *e = mutt_str_sysexit(i);
2959  mutt_error(_("Error sending message, child exited %d (%s)"), i, NONULL(e));
2960  if (childout)
2961  {
2962  struct stat st;
2963 
2964  if ((stat(childout, &st) == 0) && (st.st_size > 0))
2965  mutt_do_pager(_("Output of the delivery process"), childout,
2966  MUTT_PAGER_NO_FLAGS, NULL);
2967  }
2968  }
2969  }
2970  else if (childout)
2971  unlink(childout);
2972 
2973  FREE(&childout);
2974  FREE(&path);
2975  FREE(&s);
2976  FREE(&args);
2977  FREE(&extra_args);
2978 
2979  if (i == (EX_OK & 0xff))
2980  i = 0;
2981  else if (i == S_BKG)
2982  i = 1;
2983  else
2984  i = -1;
2985  return i;
2986 }
The "current" mailbox.
Definition: context.h:36
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t *callback, unsigned long data, MuttFormatFlags flags)
Expand expandos (x) in a string.
Definition: muttlib.c:844
char * C_Sendmail
Config: External command to send email.
Definition: sendlib.c:93
#define NONULL(x)
Definition: string2.h:37
static int send_msg(const char *path, char **args, const char *msg, char **tempfile)
invoke sendmail in a subshell
Definition: sendlib.c:2592
#define TAILQ_FIRST(head)
Definition: queue.h:717
int nntp_post(struct Mailbox *m, const char *msg)
Post article.
Definition: nntp.c:1971
static char ** add_args(char **args, size_t *argslen, size_t *argsmax, struct AddressList *al)
Add a list of Addresses to a dynamic array.
Definition: sendlib.c:2777
#define _(a)
Definition: message.h:28
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:46
#define S_BKG
Definition: string2.h:43
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
bool C_Use8bitmime
Config: Use 8-bit messages and ESMTP to send messages.
Definition: sendlib.c:95
struct Mailbox * mailbox
Definition: context.h:50
char * C_Inews
Config: (nntp) External command to post news articles.
Definition: sendlib.c:88
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
const char * mutt_str_sysexit(int err_num)
Return a string matching an error code.
Definition: string.c:112
static char ** add_option(char **args, size_t *argslen, size_t *argsmax, char *s)
Add a string to a dynamic array.
Definition: sendlib.c:2800
bool C_UseEnvelopeFrom
Config: Set the envelope sender of the message.
Definition: sendlib.c:96
WHERE char * C_DsnReturn
Config: What to send as a notification of message delivery or delay.
Definition: globals.h:113
int mutt_do_pager(const char *banner, const char *tempfile, PagerFlags do_color, struct Pager *info)
Display some page-able text to the user.
Definition: curs_lib.c:586
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define mutt_error(...)
Definition: logging.h:84
WHERE struct Address * C_EnvelopeFromAddress
Config: Manually set the sender for outgoing messages.
Definition: globals.h:98
#define FREE(x)
Definition: memory.h:40
#define TAILQ_NEXT(elm, field)
Definition: queue.h:816
#define TAILQ_EMPTY(head)
Definition: queue.h:715
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:44
const char * nntp_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, unsigned long data, MuttFormatFlags flags)
Expand the newsrc filename - Implements format_t.
Definition: newsrc.c:909
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition: curs_lib.c:116
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
WHERE char * C_DsnNotify
Config: Request notification for message delivery or delay.
Definition: globals.h:112
static char ** add_args_one(char **args, size_t *argslen, size_t *argsmax, struct Address *addr)
Add an Address to a dynamic array.
Definition: sendlib.c:2757
#define EX_OK
Definition: sendlib.c:75
#define MUTT_PAGER_NO_FLAGS
No flags are set.
Definition: pager.h:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_lookup_mime_type()

enum ContentType mutt_lookup_mime_type ( struct Body att,
const char *  path 
)

Find the MIME type for an attachment.

Parameters
attEmail with attachment
pathPath to attachment
Return values
numMIME type, e.g. TYPE_IMAGE

Given a file at 'path', see if there is a registered MIME type. Returns the major MIME type, and copies the subtype to "d". First look in a system mime.types if we can find one, then look for ~/.mime.types. The longest match is used so that we can match 'ps.gz' when 'gz' also exists.

Definition at line 1101 of file sendlib.c.

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

◆ mutt_make_file_attach()

struct Body* mutt_make_file_attach ( const char *  path)

Create a file attachment.

Parameters
pathFile to attach
Return values
ptrNewly allocated Body
NULLError

Definition at line 1620 of file sendlib.c.

1621 {
1622  struct Body *att = mutt_body_new();
1623  att->filename = mutt_str_strdup(path);
1624 
1626  run_mime_type_query(att);
1627 
1628  /* Attempt to determine the appropriate content-type based on the filename
1629  * suffix. */
1630  if (!att->subtype)
1631  mutt_lookup_mime_type(att, path);
1632 
1634  {
1635  run_mime_type_query(att);
1636  }
1637 
1638  struct Content *info = mutt_get_content_info(path, att);
1639  if (!info)
1640  {
1641  mutt_body_free(&att);
1642  return NULL;
1643  }
1644 
1645  if (!att->subtype)
1646  {
1647  if ((info->nulbin == 0) &&
1648  ((info->lobin == 0) || ((info->lobin + info->hibin + info->ascii) / info->lobin >= 10)))
1649  {
1650  /* Statistically speaking, there should be more than 10% "lobin"
1651  * chars if this is really a binary file... */
1652  att->type = TYPE_TEXT;
1653  att->subtype = mutt_str_strdup("plain");
1654  }
1655  else
1656  {
1657  att->type = TYPE_APPLICATION;
1658  att->subtype = mutt_str_strdup("octet-stream");
1659  }
1660  }
1661 
1662  FREE(&info);
1663  mutt_update_encoding(att);
1664  return att;
1665 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
static void run_mime_type_query(struct Body *att)
Run an external command to determine the MIME type.
Definition: sendlib.c:1581
long hibin
8-bit characters
Definition: content.h:35
The body of an email.
Definition: body.h:34
struct Content * mutt_get_content_info(const char *fname, struct Body *b)
Analyze file to determine MIME encoding to use.
Definition: sendlib.c:1013
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
void mutt_update_encoding(struct Body *a)
Update the encoding type.
Definition: sendlib.c:1455
char * subtype
content-type subtype
Definition: body.h:37
Info about an attachment.
Definition: content.h:33
long ascii
Number of ascii chars.
Definition: content.h:39
Type: &#39;text/*&#39;.
Definition: mime.h:38
unsigned int type
content-type primary type
Definition: body.h:65
long lobin
Unprintable 7-bit chars (eg., control chars)
Definition: content.h:36
enum ContentType mutt_lookup_mime_type(struct Body *att, const char *path)
Find the MIME type for an attachment.
Definition: sendlib.c:1101
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
char * C_MimeTypeQueryCommand
Config: External command to determine the MIME type of an attachment.
Definition: sendlib.c:91
#define FREE(x)
Definition: memory.h:40
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
long nulbin
Null characters (0x0)
Definition: content.h:37
Type: &#39;application/*&#39;.
Definition: mime.h:33
bool C_MimeTypeQueryFirst
Config: Run the C_MimeTypeQueryCommand before the mime.types lookup.
Definition: sendlib.c:92
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_make_message_attach()

struct Body* mutt_make_message_attach ( struct Mailbox m,
struct Email e,
bool  attach_msg 
)

Create a message attachment.

Parameters
mMailbox
eEmail
attach_msgtrue if attaching a message
Return values
ptrNewly allocated Body
NULLError

Definition at line 1486 of file sendlib.c.

1487 {
1488  char buf[1024];
1489  struct Body *body = NULL;
1490  FILE *fp = NULL;
1491  CopyMessageFlags cmflags;
1493 
1494  if (WithCrypto)
1495  {
1497  {
1499  return NULL;
1500  }
1501  }
1502 
1503  mutt_mktemp(buf, sizeof(buf));
1504  fp = mutt_file_fopen(buf, "w+");
1505  if (!fp)
1506  return NULL;
1507 
1508  body = mutt_body_new();
1509  body->type = TYPE_MESSAGE;
1510  body->subtype = mutt_str_strdup("rfc822");
1511  body->filename = mutt_str_strdup(buf);
1512  body->unlink = true;
1513  body->use_disp = false;
1514  body->disposition = DISP_INLINE;
1515  body->noconv = true;
1516 
1518 
1519  CopyHeaderFlags chflags = CH_XMIT;
1520  cmflags = MUTT_CM_NO_FLAGS;
1521 
1522  /* If we are attaching a message, ignore C_MimeForwardDecode */
1523  if (!attach_msg && C_MimeForwardDecode)
1524  {
1525  chflags |= CH_MIME | CH_TXTPLAIN;
1526  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1528  pgp &= ~PGP_ENCRYPT;
1530  pgp &= ~SMIME_ENCRYPT;
1531  }
1532  else if ((WithCrypto != 0) && C_ForwardDecrypt && (e->security & SEC_ENCRYPT))
1533  {
1534  if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_multipart_encrypted(e->content))
1535  {
1536  chflags |= CH_MIME | CH_NONEWLINE;
1537  cmflags = MUTT_CM_DECODE_PGP;
1538  pgp &= ~PGP_ENCRYPT;
1539  }
1540  else if (((WithCrypto & APPLICATION_PGP) != 0) &&
1542  {
1543  chflags |= CH_MIME | CH_TXTPLAIN;
1544  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1545  pgp &= ~PGP_ENCRYPT;
1546  }
1547  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
1549  {
1550  chflags |= CH_MIME | CH_TXTPLAIN;
1551  cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1552  pgp &= ~SMIME_ENCRYPT;
1553  }
1554  }
1555 
1556  mutt_copy_message(fp, m, e, cmflags, chflags);
1557 
1558  fflush(fp);
1559  rewind(fp);
1560 
1561  body->email = email_new();
1562  body->email->offset = 0;
1563  /* we don't need the user headers here */
1564  body->email->env = mutt_rfc822_read_header(fp, body->email, false, false);
1565  if (WithCrypto)
1566  body->email->security = pgp;
1567  mutt_update_encoding(body);
1568  body->parts = body->email->content;
1569 
1570  mutt_file_fclose(&fp);
1571 
1572  return body;
1573 }
#define CH_MIME
Ignore MIME fields.
Definition: copy.h:60
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
bool C_MimeForwardDecode
Config: Decode the forwarded message before attaching it.
Definition: sendlib.c:89
#define SEC_NO_FLAGS
No flags are set.
Definition: ncrypt.h:121
struct Body * content
List of MIME parts.
Definition: email.h:92
bool noconv
Don&#39;t do character set conversion.
Definition: body.h:73
void mutt_parse_mime_message(struct Mailbox *m, struct Email *e)
Parse a MIME email.
Definition: mutt_parse.c:48
int mutt_copy_message(FILE *fp_out, struct Mailbox *m, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags)
Copy a message from a Mailbox.
Definition: copy.c:806
uint16_t CopyMessageFlags
Flags for mutt_copy_message(), e.g. MUTT_CM_NOHEADER.
Definition: copy.h:31
#define SEC_ENCRYPT
Email is encrypted.
Definition: ncrypt.h:122
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:34
The body of an email.
Definition: body.h:34
unsigned int disposition
content-disposition
Definition: body.h:67
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:147
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:453
void mutt_update_encoding(struct Body *a)
Update the encoding type.
Definition: sendlib.c:1455
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:150
struct Envelope * env
Envelope information.
Definition: email.h:91
char * subtype
content-type subtype
Definition: body.h:37
#define CH_TXTPLAIN
Generate text/plain MIME headers.
Definition: copy.h:62
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:560
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:76
#define MUTT_CM_DECODE
Decode the message body into text/plain.
Definition: copy.h:37
bool C_ForwardDecrypt
Config: Decrypt the message when forwarding it.
Definition: sendlib.c:86
#define MUTT_CM_CHARCONV
Perform character set conversions.
Definition: copy.h:41
#define CH_XMIT
Transmitting this message? (Ignore Lines: and Content-Length:)
Definition: copy.h:54
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
SecurityFlags mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
Definition: crypt.c:619
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/ncrypt.h pgplib.h, smime.h
Definition: email.h:41
unsigned int type
content-type primary type
Definition: body.h:65
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:85
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:134
Type: &#39;message/*&#39;.
Definition: mime.h:35
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:49
#define SMIME_ENCRYPT
Definition: ncrypt.h:146
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
#define MUTT_CM_DECODE_PGP
Used for decoding PGP messages.
Definition: copy.h:44
struct Email * email_new(void)
Create a new Email.
Definition: email.c:68
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: ncrypt.h:120
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:583
Content is inline.
Definition: mime.h:62
struct Envelope * mutt_rfc822_read_header(FILE *fp, struct Email *e, bool user_hdrs, bool weed)
parses an RFC822 header
Definition: parse.c:1128
struct Email * email
header information for message/rfc822
Definition: body.h:55
#define WithCrypto
Definition: ncrypt.h:160
#define PGP_ENCRYPT
Definition: ncrypt.h:140
#define CH_NONEWLINE
Don&#39;t output terminating newline after the header.
Definition: copy.h:59
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: ncrypt.h:135
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_make_multipart()

struct Body* mutt_make_multipart ( struct Body b)

Create a multipart email.

Parameters
bBody of email to start
Return values
ptrNewly allocated Body

Definition at line 1716 of file sendlib.c.

1717 {
1718  struct Body *new_body = mutt_body_new();
1719  new_body->type = TYPE_MULTIPART;
1720  new_body->subtype = mutt_str_strdup("mixed");
1721  new_body->encoding = get_toplevel_encoding(b);
1722  do
1723  {
1724  mutt_generate_boundary(&new_body->parameter);
1725  if (check_boundary(mutt_param_get(&new_body->parameter, "boundary"), b))
1726  mutt_param_delete(&new_body->parameter, "boundary");
1727  } while (!mutt_param_get(&new_body->parameter, "boundary"));
1728  new_body->use_disp = false;
1729  new_body->disposition = DISP_INLINE;
1730  new_body->parts = b;
1731 
1732  return new_body;
1733 }
static int get_toplevel_encoding(struct Body *a)
Find the most restrictive encoding type.
Definition: sendlib.c:1672
The body of an email.
Definition: body.h:34
unsigned int disposition
content-disposition
Definition: body.h:67
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
void mutt_generate_boundary(struct ParameterList *pl)
Create a unique boundary id for a MIME part.
Definition: sendlib.c:604
static bool check_boundary(const char *boundary, struct Body *b)
check for duplicate boundary
Definition: sendlib.c:1693
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
char * subtype
content-type subtype
Definition: body.h:37
void mutt_param_delete(struct ParameterList *pl, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:142
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
unsigned int type
content-type primary type
Definition: body.h:65
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
Content is inline.
Definition: mime.h:62
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_message_to_7bit()

void mutt_message_to_7bit ( struct Body a,
FILE *  fp 
)

Convert an email's MIME parts to 7-bit.

Parameters
aBody of the email
fpFile to read (OPTIONAL)

Definition at line 1280 of file sendlib.c.

1281 {
1282  char temp[PATH_MAX];
1283  char *line = NULL;
1284  FILE *fp_in = NULL;
1285  FILE *fp_out = NULL;
1286  struct stat sb;
1287 
1288  if (!a->filename && fp)
1289  fp_in = fp;
1290  else if (!a->filename || !(fp_in = fopen(a->filename, "r")))
1291  {
1292  mutt_error(_("Could not open %s"), a->filename ? a->filename : "(null)");
1293  return;
1294  }
1295  else
1296  {
1297  a->offset = 0;
1298  if (stat(a->filename, &sb) == -1)
1299  {
1300  mutt_perror("stat");
1301  mutt_file_fclose(&fp_in);
1302  }
1303  a->length = sb.st_size;
1304  }
1305 
1306  mutt_mktemp(temp, sizeof(temp));
1307  fp_out = mutt_file_fopen(temp, "w+");
1308  if (!fp_out)
1309  {
1310  mutt_perror("fopen");
1311  goto cleanup;
1312  }
1313 
1314  if (!fp_in)
1315  goto cleanup;
1316 
1317  fseeko(fp_in, a->offset, SEEK_SET);
1318  a->parts = mutt_rfc822_parse_message(fp_in, a);
1319 
1320  transform_to_7bit(a->parts, fp_in);
1321 
1322  mutt_copy_hdr(fp_in, fp_out, a->offset, a->offset + a->length,
1323  CH_MIME | CH_NONEWLINE | CH_XMIT, NULL);
1324 
1325  fputs("MIME-Version: 1.0\n", fp_out);
1326  mutt_write_mime_header(a->parts, fp_out);
1327  fputc('\n', fp_out);
1328  mutt_write_mime_body(a->parts, fp_out);
1329 
1330 cleanup:
1331  FREE(&line);
1332 
1333  if (fp_in && (fp_in != fp))
1334  mutt_file_fclose(&fp_in);
1335  if (fp_out)
1336  mutt_file_fclose(&fp_out);
1337  else
1338  return;
1339 
1340  a->encoding = ENC_7BIT;
1341  FREE(&a->d_filename);
1342  a->d_filename = a->filename;
1343  if (a->filename && a->unlink)
1344  unlink(a->filename);
1345  a->filename = mutt_str_strdup(temp);
1346  a->unlink = true;
1347  if (stat(a->filename, &sb) == -1)
1348  {
1349  mutt_perror("stat");
1350  return;
1351  }
1352  a->length = sb.st_size;
1353  mutt_body_free(&a->parts);
1354  a->email->content = NULL;
1355 }
#define CH_MIME
Ignore MIME fields.
Definition: copy.h:60
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
#define mutt_perror(...)
Definition: logging.h:85
7-bit text
Definition: mime.h:49
struct Body * content
List of MIME parts.
Definition: email.h:92
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
static void transform_to_7bit(struct Body *a, FILE *fp_in)
Convert MIME parts to 7-bit.
Definition: sendlib.c:1221
struct Body * mutt_rfc822_parse_message(FILE *fp, struct Body *parent)
parse a Message/RFC822 body
Definition: parse.c:1556
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:150
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
const char * line
Definition: common.c:36
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:76
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
#define PATH_MAX
Definition: mutt.h:52
int mutt_write_mime_body(struct Body *a, FILE *fp)
Write a MIME part.
Definition: sendlib.c:521
#define CH_XMIT
Transmitting this message? (Ignore Lines: and Content-Length:)
Definition: copy.h:54
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define mutt_error(...)
Definition: logging.h:84
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
#define FREE(x)
Definition: memory.h:40
int mutt_write_mime_header(struct Body *a, FILE *fp)
Create a MIME header.
Definition: sendlib.c:362
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:583
struct Email * email
header information for message/rfc822
Definition: body.h:55
int mutt_copy_hdr(FILE *fp_in, FILE *fp_out, LOFF_T off_start, LOFF_T off_end, CopyHeaderFlags chflags, const char *prefix)
Copy header from one file to another.
Definition: copy.c:76
#define CH_NONEWLINE
Don&#39;t output terminating newline after the header.
Definition: copy.h:59
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_prepare_envelope()

void mutt_prepare_envelope ( struct Envelope env,
bool  final 
)

Prepare an email header.

Parameters
envEnvelope to prepare
finaltrue if this email is going to be sent (not postponed)

Encode all the headers prior to sending the email.

For postponing (!final) do the necessary encodings only

Definition at line 2997 of file sendlib.c.

2998 {
2999  if (final)
3000  {
3001  if (!TAILQ_EMPTY(&env->bcc) && TAILQ_EMPTY(&env->to) && TAILQ_EMPTY(&env->cc))
3002  {
3003  /* some MTA's will put an Apparently-To: header field showing the Bcc:
3004  * recipients if there is no To: or Cc: field, so attempt to suppress
3005  * it by using an empty To: field. */
3006  struct Address *to = mutt_addr_new();
3007  to->group = true;
3008  mutt_addrlist_append(&env->to, to);
3010 
3011  char buf[1024];
3012  buf[0] = '\0';
3013  mutt_addr_cat(buf, sizeof(buf), "undisclosed-recipients", AddressSpecials);
3014 
3015  to->mailbox = mutt_str_strdup(buf);
3016  }
3017 
3018  mutt_set_followup_to(env);
3019 
3020  if (!env->message_id)
3021  env->message_id = gen_msgid();
3022  }
3023 
3024  /* Take care of 8-bit => 7-bit conversion. */
3026  encode_headers(&env->userhdrs);
3027 }
void rfc2047_encode_envelope(struct Envelope *env)
Encode the fields of an Envelope.
Definition: rfc2047.c:809
static char * gen_msgid(void)
Generate a unique Message ID.
Definition: sendlib.c:2554
const char AddressSpecials[]
Characters with special meaning for email addresses.
Definition: address.c:42
struct AddressList bcc
Email&#39;s &#39;Bcc&#39; list.
Definition: envelope.h:60
struct ListHead userhdrs
user defined headers
Definition: envelope.h:83
struct Address * mutt_addr_new(void)
Create a new Address.
Definition: address.c:384
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
char * message_id
Message ID.
Definition: envelope.h:69
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
void mutt_set_followup_to(struct Envelope *env)
Set followup-to field.
Definition: send.c:1187
bool group
Group mailbox?
Definition: address.h:38
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
#define TAILQ_EMPTY(head)
Definition: queue.h:715
void mutt_addr_cat(char *buf, size_t buflen, const char *value, const char *specials)
Copy a string and wrap it in quotes if it contains special characters.
Definition: address.c:671
static void encode_headers(struct ListHead *h)
RFC2047-encode a list of headers.
Definition: sendlib.c:2490
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1401
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_remove_multipart()

struct Body* mutt_remove_multipart ( struct Body b)

Extract the multipart body if it exists.

Parameters
bBody to alter
Return values
ptrThe parts of the Body
Note
The original Body is freed

Definition at line 1742 of file sendlib.c.

1743 {
1744  struct Body *t = NULL;
1745 
1746  if (b->parts)
1747  {
1748  t = b;
1749  b = b->parts;
1750  t->parts = NULL;
1751  mutt_body_free(&t);
1752  }
1753  return b;
1754 }
The body of an email.
Definition: body.h:34
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_rfc822_write_header()

int mutt_rfc822_write_header ( FILE *  fp,
struct Envelope env,
struct Body attach,
enum MuttWriteHeaderMode  mode,
bool  privacy,
bool  hide_protected_subject 
)

Write out one RFC822 header line.

Parameters
fpFile to write to
envEnvelope of email
attachAttachment
modeMode, see MuttWriteHeaderMode
privacyIf true, remove headers that might identify the user
hide_protected_subjectIf true, replace subject header
Return values
0Success
-1Failure

Note: all RFC2047 encoding should be done outside of this routine, except for the "real name." This will allow this routine to be used more than once, if necessary.

Likewise, all IDN processing should happen outside of this routine.

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

hide_protected_subject: replaces the Subject header with $crypt_protected_headers_subject in NORMAL or POSTPONE mode.

Definition at line 2324 of file sendlib.c.

2327 {
2328  char buf[1024];
2329 
2330  if ((mode == MUTT_WRITE_HEADER_NORMAL) && !privacy)
2331  fputs(mutt_date_make_date(buf, sizeof(buf)), fp);
2332 
2333  /* UseFrom is not consulted here so that we can still write a From:
2334  * field if the user sets it with the 'my_hdr' command */
2335  if (!TAILQ_EMPTY(&env->from) && !privacy)
2336  {
2337  buf[0] = '\0';
2338  mutt_addrlist_write(buf, sizeof(buf), &env->from, false);
2339  fprintf(fp, "From: %s\n", buf);
2340  }
2341 
2342  if (!TAILQ_EMPTY(&env->sender) && !privacy)
2343  {
2344  buf[0] = '\0';
2345  mutt_addrlist_write(buf, sizeof(buf), &env->sender, false);
2346  fprintf(fp, "Sender: %s\n", buf);
2347  }
2348 
2349  if (!TAILQ_EMPTY(&env->to))
2350  {
2351  fputs("To: ", fp);
2352  mutt_write_addrlist(&env->to, fp, 4, 0);
2353  }
2354  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2355 #ifdef USE_NNTP
2356  if (!OptNewsSend)
2357 #endif
2358  fputs("To:\n", fp);
2359 
2360  if (!TAILQ_EMPTY(&env->cc))
2361  {
2362  fputs("Cc: ", fp);
2363  mutt_write_addrlist(&env->cc, fp, 4, 0);
2364  }
2365  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2366 #ifdef USE_NNTP
2367  if (!OptNewsSend)
2368 #endif
2369  fputs("Cc:\n", fp);
2370 
2371  if (!TAILQ_EMPTY(&env->bcc))
2372  {
2373  if ((mode == MUTT_WRITE_HEADER_POSTPONE) || (mode == MUTT_WRITE_HEADER_EDITHDRS) ||
2374  ((mode == MUTT_WRITE_HEADER_NORMAL) && C_WriteBcc))
2375  {
2376  fputs("Bcc: ", fp);
2377  mutt_write_addrlist(&env->bcc, fp, 5, 0);
2378  }
2379  }
2380  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2381 #ifdef USE_NNTP
2382  if (!OptNewsSend)
2383 #endif
2384  fputs("Bcc:\n", fp);
2385 
2386 #ifdef USE_NNTP
2387  if (env->newsgroups)
2388  fprintf(fp, "Newsgroups: %s\n", env->newsgroups);
2389  else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend)
2390  fputs("Newsgroups:\n", fp);
2391 
2392  if (env->followup_to)
2393  fprintf(fp, "Followup-To: %s\n", env->followup_to);
2394  else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend)
2395  fputs("Followup-To:\n", fp);
2396 
2397  if (env->x_comment_to)
2398  fprintf(fp, "X-Comment-To: %s\n", env->x_comment_to);
2399  else if ((mode == MUTT_WRITE_HEADER_EDITHDRS) && OptNewsSend && C_XCommentTo)
2400  fputs("X-Comment-To:\n", fp);
2401 #endif
2402 
2403  if (env->subject)
2404  {
2405  if (hide_protected_subject &&
2406  ((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_POSTPONE)))
2408  else
2409  mutt_write_one_header(fp, "Subject", env->subject, NULL, 0, CH_NO_FLAGS);
2410  }
2411  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2412  fputs("Subject:\n", fp);
2413 
2414  /* save message id if the user has set it */
2415  if (env->message_id && !privacy)
2416  fprintf(fp, "Message-ID: %s\n", env->message_id);
2417 
2418  if (!TAILQ_EMPTY(&env->reply_to))
2419  {
2420  fputs("Reply-To: ", fp);
2421  mutt_write_addrlist(&env->reply_to, fp, 10, 0);
2422  }
2423  else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
2424  fputs("Reply-To:\n", fp);
2425 
2426  if (!TAILQ_EMPTY(&env->mail_followup_to))
2427  {
2428 #ifdef USE_NNTP
2429  if (!OptNewsSend)
2430 #endif
2431  {
2432  fputs("Mail-Followup-To: ", fp);
2433  mutt_write_addrlist(&env->mail_followup_to, fp, 18, 0);
2434  }
2435  }
2436 
2437  /* Add any user defined headers */
2438  struct UserHdrsOverride userhdrs_overrides = write_userhdrs(fp, &env->userhdrs, privacy);
2439 
2440  if ((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_POSTPONE))
2441  {
2442  if (!STAILQ_EMPTY(&env->references))
2443  {
2444  fputs("References:", fp);
2445  mutt_write_references(&env->references, fp, 10);
2446  fputc('\n', fp);
2447  }
2448 
2449  /* Add the MIME headers */
2450  if (!userhdrs_overrides.is_overridden[USERHDRS_OVERRIDE_CONTENT_TYPE])
2451  {
2452  fputs("MIME-Version: 1.0\n", fp);
2453  mutt_write_mime_header(attach, fp);
2454  }
2455  }
2456 
2457  if (!STAILQ_EMPTY(&env->in_reply_to))
2458  {
2459  fputs("In-Reply-To:", fp);
2460  mutt_write_references(&env->in_reply_to, fp, 0);
2461  fputc('\n', fp);
2462  }
2463 
2464 #ifdef USE_AUTOCRYPT
2465  if (C_Autocrypt)
2466  {
2467  if (mode == MUTT_WRITE_HEADER_NORMAL)
2469  if (mode == MUTT_WRITE_HEADER_MIME)
2471  }
2472 #endif
2473 
2474  if ((mode == MUTT_WRITE_HEADER_NORMAL) && !privacy && C_UserAgent &&
2475  !userhdrs_overrides.is_overridden[USERHDRS_OVERRIDE_USER_AGENT])
2476  {
2477  /* Add a vanity header */
2478  fprintf(fp, "User-Agent: NeoMutt/%s%s\n", PACKAGE_VERSION, GitVer);
2479  }
2480 
2481  return (ferror(fp) == 0) ? 0 : -1;
2482 }
WHERE bool C_Autocrypt
Config: Enables the Autocrypt feature.
Definition: globals.h:205
WHERE bool C_WriteBcc
Config: Write out the &#39;Bcc&#39; field when preparing to send a mail.
Definition: globals.h:273
struct AddressList mail_followup_to
Email&#39;s &#39;mail-followup-to&#39;.
Definition: envelope.h:63
struct AddressList reply_to
Email&#39;s &#39;reply-to&#39;.
Definition: envelope.h:62
struct AddressList bcc
Email&#39;s &#39;Bcc&#39; list.
Definition: envelope.h:60
WHERE char * C_CryptProtectedHeadersSubject
Config: Use this as the subject for encrypted emails.
Definition: globals.h:110
bool C_UserAgent
Config: Add a &#39;User-Agent&#39; head to outgoing mail.
Definition: sendlib.c:97
A normal Email, write full header + MIME headers.
Definition: sendlib.h:60
A postponed Email, just the envelope info.
Definition: sendlib.h:61
struct ListHead userhdrs
user defined headers
Definition: envelope.h:83
size_t mutt_addrlist_write(char *buf, size_t buflen, const struct AddressList *al, bool display)
Write an Address to a buffer.
Definition: address.c:1137
char * mutt_date_make_date(char *buf, size_t buflen)
Write a date in RFC822 format to a buffer.
Definition: date.c:371
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:82
char * message_id
Message ID.
Definition: envelope.h:69
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
static struct UserHdrsOverride write_userhdrs(FILE *fp, const struct ListHead *userhdrs, bool privacy)
Write user-defined headers and keep track of the interesting ones.
Definition: sendlib.c:2257
char * x_comment_to
List of &#39;X-comment-to&#39; fields.
Definition: envelope.h:78
void mutt_write_references(const struct ListHead *r, FILE *fp, size_t trim)
Add the message references to a list.
Definition: sendlib.c:1812
const char * GitVer
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:50
"light" mode (used for edit_hdrs)
Definition: sendlib.h:62
void mutt_write_addrlist(struct AddressList *al, FILE *fp, int linelen, bool display)
wrapper around mutt_write_address()
Definition: sendlib.c:1766
bool is_overridden[mutt_array_size(userhdrs_override_headers)]
Definition: sendlib.c:2232
char * subject
Email&#39;s subject.
Definition: envelope.h:66
char * newsgroups
List of newsgroups.
Definition: envelope.h:75
WHERE bool C_XCommentTo
Config: (nntp) Add &#39;X-Comment-To&#39; header that contains article author.
Definition: globals.h:294
char * followup_to
List of &#39;followup-to&#39; fields.
Definition: envelope.h:77
int mutt_write_mime_header(struct Body *a, FILE *fp)
Create a MIME header.
Definition: sendlib.c:362
#define STAILQ_EMPTY(head)
Definition: queue.h:346
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
struct AddressList sender
Email&#39;s sender.
Definition: envelope.h:61
Write protected headers.
Definition: sendlib.h:63
#define TAILQ_EMPTY(head)
Definition: queue.h:715
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:44
struct ListHead references
message references (in reverse order)
Definition: envelope.h:81
int mutt_autocrypt_write_gossip_headers(struct Envelope *env, FILE *fp)
Write the Autocrypt gossip headers to a file.
Definition: autocrypt.c:777
int mutt_write_one_header(FILE *fp, const char *tag, const char *value, const char *pfx, int wraplen, CopyHeaderFlags chflags)
Write one header line to a file.
Definition: sendlib.c:2133
int mutt_autocrypt_write_autocrypt_header(struct Envelope *env, FILE *fp)
Write the Autocrypt header to a file.
Definition: autocrypt.c:740
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_stamp_attachment()

void mutt_stamp_attachment ( struct Body a)

Timestamp an Attachment.

Parameters
aAttachment

Definition at line 1418 of file sendlib.c.

1419 {
1420  a->stamp = mutt_date_epoch();
1421 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:410
time_t stamp
Time stamp of last encoding update.
Definition: body.h:61
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_unprepare_envelope()

void mutt_unprepare_envelope ( struct Envelope env)

Undo the encodings of mutt_prepare_envelope()

Parameters
envEnvelope to unprepare

Decode all the headers of an email, e.g. when the sending failed or was aborted.

Definition at line 3036 of file sendlib.c.

3037 {
3038  struct ListNode *item = NULL;
3039  STAILQ_FOREACH(item, &env->userhdrs, entries)
3040  {
3041  rfc2047_decode(&item->data);
3042  }
3043 
3045 
3046  /* back conversions */
3048 }
struct AddressList mail_followup_to
Email&#39;s &#39;mail-followup-to&#39;.
Definition: envelope.h:63
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1381
struct ListHead userhdrs
user defined headers
Definition: envelope.h:83
void rfc2047_decode_envelope(struct Envelope *env)
Decode the fields of an Envelope.
Definition: rfc2047.c:789
void rfc2047_decode(char **pd)
Decode any RFC2047-encoded header fields.
Definition: rfc2047.c:649
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
char * data
String.
Definition: list.h:35
A List node for strings.
Definition: list.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_update_encoding()

void mutt_update_encoding ( struct Body a)

Update the encoding type.

Parameters
aBody to update

Assumes called from send mode where Body->filename points to actual file

Definition at line 1455 of file sendlib.c.

1456 {
1457  struct Content *info = NULL;
1458  char chsbuf[256];
1459 
1460  /* override noconv when it's us-ascii */
1461  if (mutt_ch_is_us_ascii(mutt_body_get_charset(a, chsbuf, sizeof(chsbuf))))
1462  a->noconv = false;
1463 
1464  if (!a->force_charset && !a->noconv)
1465  mutt_param_delete(&a->parameter, "charset");
1466 
1467  info = mutt_get_content_info(a->filename, a);
1468  if (!info)
1469  return;
1470 
1471  set_encoding(a, info);
1473 
1474  FREE(&a->content);
1475  a->content = info;
1476 }
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:1418
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
struct Content * content
Detailed info about the content of the attachment.
Definition: body.h:51
bool noconv
Don&#39;t do character set conversion.
Definition: body.h:73
struct Content * mutt_get_content_info(const char *fname, struct Body *b)
Analyze file to determine MIME encoding to use.
Definition: sendlib.c:1013
bool force_charset
Send mode: don&#39;t adjust the character set when in send-mode.
Definition: body.h:74
#define mutt_ch_is_us_ascii(str)
Definition: charset.h:107
Info about an attachment.
Definition: content.h:33
void mutt_param_delete(struct ParameterList *pl, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:142
static void set_encoding(struct Body *b, struct Content *info)
determine which Content-Transfer-Encoding to use
Definition: sendlib.c:1362
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body&#39;s character set.
Definition: sendlib.c:1431
#define FREE(x)
Definition: memory.h:40
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_write_addrlist()

void mutt_write_addrlist ( struct AddressList *  al,
FILE *  fp,
int  linelen,
bool  display 
)

wrapper around mutt_write_address()

Parameters
alAddress list
fpFile to write to
linelenLine length to use
displayTrue if these addresses will be displayed to the user

So we can handle very large recipient lists without needing a huge temporary buffer in memory

Definition at line 1766 of file sendlib.c.

1767 {
1768  char buf[1024];
1769  int count = 0;
1770 
1771  struct Address *a = NULL;
1772  TAILQ_FOREACH(a, al, entries)
1773  {
1774  buf[0] = '\0';
1775  mutt_addr_write(buf, sizeof(buf), a, display);
1776  size_t len = mutt_str_strlen(buf);
1777  if (count && (linelen + len > 74))
1778  {
1779  fputs("\n\t", fp);
1780  linelen = len + 8; /* tab is usually about 8 spaces... */
1781  }
1782  else
1783  {
1784  if (count && a->mailbox)
1785  {
1786  fputc(' ', fp);
1787  linelen++;
1788  }
1789  linelen += len;
1790  }
1791  fputs(buf, fp);
1792  struct Address *next = TAILQ_NEXT(a, entries);
1793  if (!a->group && next && next->mailbox)
1794  {
1795  linelen++;
1796  fputc(',', fp);
1797  }
1798  count++;
1799  }
1800  fputc('\n', fp);
1801 }
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
size_t mutt_addr_write(char *buf, size_t buflen, struct Address *addr, bool display)
Write a single Address to a buffer.
Definition: address.c:1015
bool group
Group mailbox?
Definition: address.h:38
#define TAILQ_NEXT(elm, field)
Definition: queue.h:816
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_write_fcc()

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

3248 {
3249  struct Message *msg = NULL;
3250  char tempfile[PATH_MAX];
3251  FILE *fp_tmp = NULL;
3252  int rc = -1;
3253  bool need_mailbox_cleanup = false;
3254  struct stat st;
3255  char buf[128];
3256  MsgOpenFlags onm_flags;
3257 
3258  if (post)
3259  set_noconv_flags(e->content, true);
3260 
3261 #ifdef RECORD_FOLDER_HOOK
3262  mutt_folder_hook(path, NULL);
3263 #endif
3264  struct Mailbox *m_fcc = mx_path_resolve(path);
3265  bool old_append = m_fcc->append;
3266  struct Context *ctx_fcc = mx_mbox_open(m_fcc, MUTT_APPEND | MUTT_QUIET);
3267  if (!ctx_fcc)
3268  {
3269  mutt_debug(LL_DEBUG1, "unable to open mailbox %s in append-mode, aborting\n", path);
3270  mailbox_free(&m_fcc);
3271  goto done;
3272  }
3273 
3274  /* We need to add a Content-Length field to avoid problems where a line in
3275  * the message body begins with "From " */
3276  if ((ctx_fcc->mailbox->magic == MUTT_MMDF) || (ctx_fcc->mailbox->magic == MUTT_MBOX))
3277  {
3278  mutt_mktemp(tempfile, sizeof(tempfile));
3279  fp_tmp = mutt_file_fopen(tempfile, "w+");
3280  if (!fp_tmp)
3281  {
3282  mutt_perror(tempfile);
3283  mx_mbox_close(&ctx_fcc);
3284  goto done;
3285  }
3286  /* remember new mail status before appending message */
3287  need_mailbox_cleanup = true;
3288  stat(path, &st);
3289  }
3290 
3291  e->read = !post; /* make sure to put it in the 'cur' directory (maildir) */
3292  onm_flags = MUTT_ADD_FROM;
3293  if (post)
3294  onm_flags |= MUTT_SET_DRAFT;
3295  msg = mx_msg_open_new(ctx_fcc->mailbox, e, onm_flags);
3296  if (!msg)
3297  {
3298  mutt_file_fclose(&fp_tmp);
3299  mx_mbox_close(&ctx_fcc);
3300  goto done;
3301  }
3302 
3303  /* post == 1 => postpone message.
3304  * post == 0 => Normal mode. */
3308 
3309  /* (postponement) if this was a reply of some sort, <msgid> contains the
3310  * Message-ID: of message replied to. Save it using a special X-Mutt-
3311  * header so it can be picked up if the message is recalled at a later
3312  * point in time. This will allow the message to be marked as replied if
3313  * the same mailbox is still open. */
3314  if (post && msgid)
3315  fprintf(msg->fp, "X-Mutt-References: %s\n", msgid);
3316 
3317  /* (postponement) save the Fcc: using a special X-Mutt- header so that
3318  * it can be picked up when the message is recalled */
3319  if (post && fcc)
3320  fprintf(msg->fp, "X-Mutt-Fcc: %s\n", fcc);
3321 
3322  if ((ctx_fcc->mailbox->magic == MUTT_MMDF) || (ctx_fcc->mailbox->magic == MUTT_MBOX))
3323  fprintf(msg->fp, "Status: RO\n");
3324 
3325  /* mutt_rfc822_write_header() only writes out a Date: header with
3326  * mode == 0, i.e. _not_ postponement; so write out one ourself */
3327  if (post)
3328  fprintf(msg->fp, "%s", mutt_date_make_date(buf, sizeof(buf)));
3329 
3330  /* (postponement) if the mail is to be signed or encrypted, save this info */
3331  if (((WithCrypto & APPLICATION_PGP) != 0) && post && (e->security & APPLICATION_PGP))
3332  {
3333  fputs("X-Mutt-PGP: ", msg->fp);
3334  if (e->security & SEC_ENCRYPT)
3335  fputc('E', msg->fp);
3336  if (e->security & SEC_OPPENCRYPT)
3337  fputc('O', msg->fp);
3338  if (e->security & SEC_SIGN)
3339  {
3340  fputc('S', msg->fp);
3341  if (C_PgpSignAs)
3342  fprintf(msg->fp, "<%s>", C_PgpSignAs);
3343  }
3344  if (e->security & SEC_INLINE)
3345  fputc('I', msg->fp);
3346 #ifdef USE_AUTOCRYPT
3347  if (e->security & SEC_AUTOCRYPT)
3348  fputc('A', msg->fp);
3350  fputc('Z', msg->fp);
3351 #endif
3352  fputc('\n', msg->fp);
3353  }
3354 
3355  /* (postponement) if the mail is to be signed or encrypted, save this info */
3356  if (((WithCrypto & APPLICATION_SMIME) != 0) && post && (e->security & APPLICATION_SMIME))
3357  {
3358  fputs("X-Mutt-SMIME: ", msg->fp);
3359  if (e->security & SEC_ENCRYPT)
3360  {
3361  fputc('E', msg->fp);
3362  if (C_SmimeEncryptWith)
3363  fprintf(msg->fp, "C<%s>", C_SmimeEncryptWith);
3364  }
3365  if (e->security & SEC_OPPENCRYPT)
3366  fputc('O', msg->fp);
3367  if (e->security & SEC_SIGN)
3368  {
3369  fputc('S', msg->fp);
3370  if (C_SmimeSignAs)
3371  fprintf(msg->fp, "<%s>", C_SmimeSignAs);
3372  }
3373  if (e->security & SEC_INLINE)
3374  fputc('I', msg->fp);
3375  fputc('\n', msg->fp);
3376  }
3377 
3378 #ifdef MIXMASTER
3379  /* (postponement) if the mail is to be sent through a mixmaster
3380  * chain, save that information */
3381 
3382  if (post && !STAILQ_EMPTY(&e->chain))
3383  {
3384  fputs("X-Mutt-Mix:", msg->fp);
3385  struct ListNode *p = NULL;
3386  STAILQ_FOREACH(p, &e->chain, entries)
3387  {
3388  fprintf(msg->fp, " %s", (char *) p->data);
3389  }
3390 
3391  fputc('\n', msg->fp);
3392  }
3393 #endif
3394 
3395  if (fp_tmp)
3396  {
3397  mutt_write_mime_body(e->content, fp_tmp);
3398 
3399  /* make sure the last line ends with a newline. Emacs doesn't ensure this
3400  * will happen, and it can cause problems parsing the mailbox later. */
3401  fseek(fp_tmp, -1, SEEK_END);
3402  if (fgetc(fp_tmp) != '\n')
3403  {
3404  fseek(fp_tmp, 0, SEEK_END);
3405  fputc('\n', fp_tmp);
3406  }
3407 
3408  fflush(fp_tmp);
3409  if (ferror(fp_tmp))
3410  {
3411  mutt_debug(LL_DEBUG1, "%s: write failed\n", tempfile);
3412  mutt_file_fclose(&fp_tmp);
3413  unlink(tempfile);
3414  mx_msg_commit(ctx_fcc->mailbox, msg); /* XXX really? */
3415  mx_msg_close(ctx_fcc->mailbox, &msg);
3416  mx_mbox_close(&ctx_fcc);
3417  goto done;
3418  }
3419 
3420  /* count the number of lines */
3421  int lines = 0;
3422  char line_buf[1024];
3423  rewind(fp_tmp);
3424  while (fgets(line_buf, sizeof(line_buf), fp_tmp))
3425  lines++;
3426  fprintf(msg->fp, "Content-Length: " OFF_T_FMT "\n", (LOFF_T) ftello(fp_tmp));
3427  fprintf(msg->fp, "Lines: %d\n\n", lines);
3428 
3429  /* copy the body and clean up */
3430  rewind(fp_tmp);
3431  rc = mutt_file_copy_stream(fp_tmp, msg->fp);
3432  if (fclose(fp_tmp) != 0)
3433  rc = -1;
3434  /* if there was an error, leave the temp version */
3435  if (rc == 0)
3436  unlink(tempfile);
3437  }
3438  else
3439  {
3440  fputc('\n', msg->fp); /* finish off the header */
3441  rc = mutt_write_mime_body(e->content, msg->fp);
3442  }
3443 
3444  if (mx_msg_commit(ctx_fcc->mailbox, msg) != 0)
3445  rc = -1;
3446  else if (finalpath)
3447  *finalpath = mutt_str_strdup(msg->committed_path);
3448  mx_msg_close(ctx_fcc->mailbox, &msg);
3449  mx_mbox_close(&ctx_fcc);
3450 
3451  if (!post && need_mailbox_cleanup)
3452  mutt_mailbox_cleanup(path, &st);
3453 
3454  if (post)
3455  set_noconv_flags(e->content, false);
3456 
3457 done:
3458  m_fcc->append = old_append;
3459 #ifdef RECORD_FOLDER_HOOK
3460  /* We ran a folder hook for the destination mailbox,
3461  * now we run it for the user's current mailbox */
3462  if (Context && Context->mailbox->path)
3464 #endif
3465 
3466  return rc;
3467 }
#define MUTT_APPEND
Open mailbox for appending messages.
Definition: mx.h:52
The "current" mailbox.
Definition: context.h:36
#define SEC_AUTOCRYPT
Message will be, or was Autocrypt encrypt+signed.
Definition: ncrypt.h:131
#define mutt_perror(...)
Definition: logging.h:85
int mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:558
void mutt_mailbox_cleanup(const char *path, struct stat *st)
Restore the timestamp of a mailbox.
Definition: mutt_mailbox.c:353
#define SEC_AUTOCRYPT_OVERRIDE
Indicates manual set/unset of encryption.
Definition: ncrypt.h:132
A normal Email, write full header + MIME headers.
Definition: sendlib.h:60
bool mutt_should_hide_protected_subject(struct Email *e)
Should NeoMutt hide the protected subject?
Definition: crypt.c:1082
struct Body * content
List of MIME parts.
Definition: email.h:92
A postponed Email, just the envelope info.
Definition: sendlib.h:61
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:254
#define SEC_INLINE
Email has an inline signature.
Definition: ncrypt.h:129
#define SEC_ENCRYPT
Email is encrypted.
Definition: ncrypt.h:122
char * mutt_date_make_date(char *buf, size_t buflen)
Write a date in RFC822 format to a buffer.
Definition: date.c:371
#define MUTT_SET_DRAFT
set the message draft flag
Definition: mx.h:65
int mutt_rfc822_write_header(FILE *fp, struct Envelope *env, struct Body *attach, enum MuttWriteHeaderMode mode, bool privacy, bool hide_protected_subject)
Write out one RFC822 header line.
Definition: sendlib.c:2324
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1087
void mutt_folder_hook(const char *path, const char *desc)
Perform a folder hook.
Definition: hook.c:516
bool read
Email is read.
Definition: email.h:53
struct Mailbox * mailbox
Definition: context.h:50
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:55
enum MailboxType magic
Mailbox type.
Definition: mailbox.h:116
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:150
struct Envelope * env
Envelope information.
Definition: email.h:91
struct Message * mx_msg_open_new(struct Mailbox *m, struct Email *e, MsgOpenFlags flags)
Open a new message.
Definition: mx.c:956
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:76
#define SEC_SIGN
Email is signed.
Definition: ncrypt.h:123
A local copy of an email.
Definition: mx.h:81
A mailbox.
Definition: mailbox.h:92
#define PATH_MAX
Definition: mutt.h:52
int mutt_write_mime_body(struct Body *a, FILE *fp)
Write a MIME part.
Definition: sendlib.c:521
WHERE char * C_SmimeEncryptWith
Config: Algorithm for encryption.
Definition: globals.h:173
&#39;mmdf&#39; Mailbox type
Definition: mailbox.h:48
bool append
Mailbox is opened in append mode.
Definition: mailbox.h:124
#define MUTT_QUIET
Do not print any messages.
Definition: mx.h:54
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/ncrypt.h pgplib.h, smime.h
Definition: email.h:41
WHERE bool C_CryptProtectedHeadersRead
Config: Display protected headers (Memory Hole) in the pager.
Definition: globals.h:281
uint8_t MsgOpenFlags
Flags for mx_msg_open_new(), e.g. MUTT_ADD_FROM.
Definition: mx.h:62
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: ncrypt.h:130
&#39;mbox&#39; Mailbox type
Definition: mailbox.h:47
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:134
char * committed_path
the final path generated by mx_msg_commit()
Definition: mx.h:85
char * data
String.
Definition: list.h:35
Log at debug level 1.
Definition: logging.h:56
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:268
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
int mx_msg_commit(struct Mailbox *m, struct Message *msg)
Commit a message to a folder - Wrapper for MxOps::msg_commit()
Definition: mx.c:1066
FILE * fp
pointer to the message data
Definition: mx.h:83
struct Mailbox * mx_path_resolve(const char *path)
XXX.
Definition: mx.c:1539
static void set_noconv_flags(struct Body *b, bool flag)
Set/reset the "x-mutt-noconv" flag.
Definition: sendlib.c:3172
#define STAILQ_EMPTY(head)
Definition: queue.h:346
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
WHERE char * C_PgpSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:168
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:583
WHERE char * C_SmimeSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:172
A List node for strings.
Definition: list.h:33
#define MUTT_ADD_FROM
add a From_ line
Definition: mx.h:64
#define WithCrypto
Definition: ncrypt.h:160
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: ncrypt.h:135
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_write_mime_body()

int mutt_write_mime_body ( struct Body a,
FILE *  fp 
)

Write a MIME part.

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

Definition at line 521 of file sendlib.c.

522 {
523  FILE *fp_in = NULL;
524  struct FgetConv *fc = NULL;
525 
526  if (a->type == TYPE_MULTIPART)
527  {
528  /* First, find the boundary to use */
529  const char *p = mutt_param_get(&a->parameter, "boundary");
530  if (!p)
531  {
532  mutt_debug(LL_DEBUG1, "no boundary parameter found\n");
533  mutt_error(_("No boundary parameter found [report this error]"));
534  return -1;
535  }
536  char boundary[128];
537  mutt_str_strfcpy(boundary, p, sizeof(boundary));
538 
539  for (struct Body *t = a->parts; t; t = t->next)
540  {
541  fprintf(fp, "\n--%s\n", boundary);
542  if (mutt_write_mime_header(t, fp) == -1)
543  return -1;
544  fputc('\n', fp);
545  if (mutt_write_mime_body(t, fp) == -1)
546  return -1;
547  }
548  fprintf(fp, "\n--%s--\n", boundary);
549  return ferror(fp) ? -1 : 0;
550  }
551 
552  /* This is pretty gross, but it's the best solution for now... */
553  if (((WithCrypto & APPLICATION_PGP) != 0) && (a->type == TYPE_APPLICATION) &&
554  (mutt_str_strcmp(a->subtype, "pgp-encrypted") == 0))
555  {
556  fputs("Version: 1\n", fp);
557  return 0;
558  }
559 
560  fp_in = fopen(a->filename, "r");
561  if (!fp_in)
562  {
563  mutt_debug(LL_DEBUG1, "%s no longer exists\n", a->filename);
564  mutt_error(_("%s no longer exists"), a->filename);
565  return -1;
566  }
567 
568  if ((a->type == TYPE_TEXT) && (!a->noconv))
569  {
570  char send_charset[128];
572  fp_in, a->charset,
573  mutt_body_get_charset(a, send_charset, sizeof(send_charset)), 0);
574  }
575  else
576  fc = mutt_ch_fgetconv_open(fp_in, 0, 0, 0);
577 
579  if (a->encoding == ENC_QUOTED_PRINTABLE)
581  else if (a->encoding == ENC_BASE64)
583  else if ((a->type == TYPE_TEXT) && (!a->noconv))
584  encode_8bit(fc, fp);
585  else
586  mutt_file_copy_stream(fp_in, fp);
588 
590  mutt_file_fclose(&fp_in);
591 
592  if (SigInt == 1)
593  {
594  SigInt = 0;
595  return -1;
596  }
597  return ferror(fp) ? -1 : 0;
598 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
WHERE SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: globals.h:84
static void encode_base64(struct FgetConv *fc, FILE *fp_out, int istext)
Base64-encode some data.
Definition: sendlib.c:312
bool noconv
Don&#39;t do character set conversion.
Definition: body.h:73
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:53
static bool write_as_text_part(struct Body *b)
Should the Body be written as a text MIME part.
Definition: sendlib.c:508
void mutt_sig_allow_interrupt(bool allow)
Allow/disallow Ctrl-C (SIGINT)
Definition: signal.c:238
The body of an email.
Definition: body.h:34
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:150
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
static void encode_quoted(struct FgetConv *fc, FILE *fp_out, bool istext)
Encode text as quoted printable.
Definition: sendlib.c:106
char * subtype
content-type subtype
Definition: body.h:37
FILE * fp
Definition: charset.h:43
Type: &#39;text/*&#39;.
Definition: mime.h:38
int mutt_write_mime_body(struct Body *a, FILE *fp)
Write a MIME part.
Definition: sendlib.c:521
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
char * charset
Send mode: charset of attached file as stored on disk.
Definition: body.h:49
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body&#39;s character set.
Definition: sendlib.c:1431
char * p
Definition: charset.h:47
static void encode_8bit(struct FgetConv *fc, FILE *fp_out)
Write the data as raw 8-bit data.
Definition: sendlib.c:340
unsigned int type
content-type primary type
Definition: body.h:65
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:134
void mutt_ch_fgetconv_close(struct FgetConv **fc)
Close an fgetconv handle.
Definition: charset.c:882
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
Log at debug level 1.
Definition: logging.h:56
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:268
#define mutt_error(...)
Definition: logging.h:84
Quoted-printable text.
Definition: mime.h:51
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
int mutt_write_mime_header(struct Body *a, FILE *fp)
Create a MIME header.
Definition: sendlib.c:362
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct FgetConv * mutt_ch_fgetconv_open(FILE *fp, const char *from, const char *to, int flags)
Prepare a file for charset conversion.
Definition: charset.c:852
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
#define WithCrypto
Definition: ncrypt.h:160
Cursor for converting a file&#39;s encoding.
Definition: charset.h:41
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
Type: &#39;application/*&#39;.
Definition: mime.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_write_mime_header()

int mutt_write_mime_header ( struct Body a,
FILE *  fp 
)

Create a MIME header.

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

Definition at line 362 of file sendlib.c.

363 {
364  if (!a || !fp)
365  return -1;
366 
367  int len;
368  int tmplen;
369  char buf[256] = { 0 };
370 
371  fprintf(fp, "Content-Type: %s/%s", TYPE(a), a->subtype);
372 
373  if (!TAILQ_EMPTY(&a->parameter))
374  {
375  len = 25 + mutt_str_strlen(a->subtype); /* approximate len. of content-type */
376 
377  struct Parameter *np = NULL;
378  TAILQ_FOREACH(np, &a->parameter, entries)
379  {
380  if (!np->attribute || !np->value)
381  continue;
382 
383  struct ParameterList pl_conts = rfc2231_encode_string(np->attribute, np->value);
384  struct Parameter *cont = NULL;
385  TAILQ_FOREACH(cont, &pl_conts, entries)
386  {
387  fputc(';', fp);
388 
389  buf[0] = 0;
390  mutt_addr_cat(buf, sizeof(buf), cont->value, MimeSpecials);
391 
392  /* Dirty hack to make messages readable by Outlook Express
393  * for the Mac: force quotes around the boundary parameter
394  * even when they aren't needed.
395  */
396  if (!mutt_str_strcasecmp(cont->attribute, "boundary") &&
397  !mutt_str_strcmp(buf, cont->value))
398  snprintf(buf, sizeof(buf), "\"%s\"", cont->value);
399 
400  tmplen = mutt_str_strlen(buf) + mutt_str_strlen(cont->attribute) + 1;
401  if (len + tmplen + 2 > 76)
402  {
403  fputs("\n\t", fp);
404  len = tmplen + 1;
405  }
406  else
407  {
408  fputc(' ', fp);
409  len += tmplen + 1;
410  }
411 
412  fprintf(fp, "%s=%s", cont->attribute, buf);
413  }
414 
415  mutt_param_free(&pl_conts);
416  }
417  }
418 
419  fputc('\n', fp);
420 
421  if (a->language)
422  fprintf(fp, "Content-Language: %s\n", a->language);
423 
424  if (a->description)
425  fprintf(fp, "Content-Description: %s\n", a->description);
426 
427  if (a->disposition != DISP_NONE)
428  {
429  const char *dispstr[] = { "inline", "attachment", "form-data" };
430 
431  if (a->disposition < sizeof(dispstr) / sizeof(char *))
432  {
433  fprintf(fp, "Content-Disposition: %s", dispstr[a->disposition]);
434  len = 21 + mutt_str_strlen(dispstr[a->disposition]);
435 
436  if (a->use_disp && (a->disposition != DISP_INLINE))
437  {
438  char *fn = a->d_filename;
439  if (!fn)
440  fn = a->filename;
441 
442  if (fn)
443  {
444  /* Strip off the leading path... */
445  char *t = strrchr(fn, '/');
446  if (t)
447  t++;
448  else
449  t = fn;
450 
451  struct ParameterList pl_conts = rfc2231_encode_string("filename", t);
452  struct Parameter *cont = NULL;
453  TAILQ_FOREACH(cont, &pl_conts, entries)
454  {
455  fputc(';', fp);
456  buf[0] = 0;
457  mutt_addr_cat(buf, sizeof(buf), cont->value, MimeSpecials);
458 
459  tmplen = mutt_str_strlen(buf) + mutt_str_strlen(cont->attribute) + 1;
460  if (len + tmplen + 2 > 76)
461  {
462  fputs("\n\t", fp);
463  len = tmplen + 1;
464  }
465  else
466  {
467  fputc(' ', fp);
468  len += tmplen + 1;
469  }
470 
471  fprintf(fp, "%s=%s", cont->attribute, buf);
472  }
473 
474  mutt_param_free(&pl_conts);
475  }
476  }
477 
478  fputc('\n', fp);
479  }
480  else
481  {
482  mutt_debug(LL_DEBUG1, "ERROR: invalid content-disposition %d\n", a->disposition);
483  }
484  }
485 
486  if (a->encoding != ENC_7BIT)
487  fprintf(fp, "Content-Transfer-Encoding: %s\n", ENCODING(a->encoding));
488 
490 #ifdef USE_AUTOCRYPT
491  || C_Autocrypt
492 #endif
493  ) &&
494  a->mime_headers)
495  {
496  mutt_rfc822_write_header(fp, a->mime_headers, NULL, MUTT_WRITE_HEADER_MIME, false, false);
497  }
498 
499  /* Do NOT add the terminator here!!! */
500  return ferror(fp) ? -1 : 0;
501 }
char * attribute
Parameter name.
Definition: parameter.h:34
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
WHERE bool C_Autocrypt
Config: Enables the Autocrypt feature.
Definition: globals.h:205
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
7-bit text
Definition: mime.h:49
WHERE bool C_CryptProtectedHeadersWrite
Config: Generate protected header (Memory Hole) for signed and encrypted emails.
Definition: globals.h:283
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
unsigned int disposition
content-disposition
Definition: body.h:67
int mutt_rfc822_write_header(FILE *fp, struct Envelope *env, struct Body *attach, enum MuttWriteHeaderMode mode, bool privacy, bool hide_protected_subject)
Write out one RFC822 header line.
Definition: sendlib.c:2324
#define ENCODING(x)
Definition: mime.h:85
void mutt_param_free(struct ParameterList *pl)
Free a ParameterList.
Definition: parameter.c:61
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
char * subtype
content-type subtype
Definition: body.h:37
FILE * fp
Definition: charset.h:43
const char MimeSpecials[]
Characters that need special treatment in MIME.
Definition: mime.c:67
char * description
content-description
Definition: body.h:40
#define TYPE(body)
Definition: mime.h:83
char * value
Parameter value.
Definition: parameter.h:35
Log at debug level 1.
Definition: logging.h:56
No preferred disposition.
Definition: mime.h:65
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
struct ParameterList rfc2231_encode_string(const char *attribute, char *value)
Encode a string to be suitable for an RFC2231 header.
Definition: rfc2231.c:329
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
Attribute associated with a MIME part.
Definition: parameter.h:32
char * language
content-language (RFC8255)
Definition: body.h:38
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Write protected headers.
Definition: sendlib.h:63
#define TAILQ_EMPTY(head)
Definition: queue.h:715
Content is inline.
Definition: mime.h:62
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
void mutt_addr_cat(char *buf, size_t buflen, const char *value, const char *specials)
Copy a string and wrap it in quotes if it contains special characters.
Definition: address.c:671
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_write_multiple_fcc()

int mutt_write_multiple_fcc ( const char *  path,
struct Email e,
const char *  msgid,
bool  post,
char *  fcc,
char **  finalpath 
)

Handle FCC with multiple, comma separated entries.

Parameters
[in]pathPath to mailboxes (comma separated)
[in]eEmail
[in]msgidMessage id
[in]postIf true, postpone message
[in]fccfcc setting to save (postpone only)
[out]finalpathFinal path of email
Return values
0Success
-1Failure

Definition at line 3199 of file sendlib.c.

3201 {
3202  char fcc_tok[PATH_MAX];
3203  char fcc_expanded[PATH_MAX];
3204 
3205  mutt_str_strfcpy(fcc_tok, path, sizeof(fcc_tok));
3206 
3207  char *tok = strtok(fcc_tok, ",");
3208  if (!tok)
3209  return -1;
3210 
3211  mutt_debug(LL_DEBUG1, "Fcc: initial mailbox = '%s'\n", tok);
3212  /* mutt_expand_path already called above for the first token */
3213  int status = mutt_write_fcc(tok, e, msgid, post, fcc, finalpath);
3214  if (status != 0)
3215  return status;
3216 
3217  while ((tok = strtok(NULL, ",")))
3218  {
3219  if (!*tok)
3220  continue;
3221 
3222  /* Only call mutt_expand_path if tok has some data */
3223  mutt_debug(LL_DEBUG1, "Fcc: additional mailbox token = '%s'\n", tok);
3224  mutt_str_strfcpy(fcc_expanded, tok, sizeof(fcc_expanded));
3225  mutt_expand_path(fcc_expanded, sizeof(fcc_expanded));
3226  mutt_debug(LL_DEBUG1, " Additional mailbox expanded = '%s'\n", fcc_expanded);
3227  status = mutt_write_fcc(fcc_expanded, e, msgid, post, fcc, finalpath);
3228  if (status != 0)
3229  return status;
3230  }
3231 
3232  return 0;
3233 }
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:128
#define PATH_MAX
Definition: mutt.h:52
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
Log at debug level 1.
Definition: logging.h:56
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
int mutt_write_fcc(const char *path, struct Email *e, const char *msgid, bool post, char *fcc, char **finalpath)
Write email to FCC mailbox.
Definition: sendlib.c:3246
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_write_one_header()

int mutt_write_one_header ( FILE *  fp,
const char *  tag,
const char *  value,
const char *  pfx,
int  wraplen,
CopyHeaderFlags  chflags 
)

Write one header line to a file.

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

split several headers into individual ones and call write_one_header for each one

Definition at line 2133 of file sendlib.c.

2135 {
2136  char *last = NULL, *line = NULL;
2137  int max = 0, w, rc = -1;
2138  int pfxw = mutt_strwidth(pfx);
2139  char *v = mutt_str_strdup(value);
2140  bool display = (chflags & CH_DISPLAY);
2141 
2142  if (!display || C_Weed)
2143  v = unfold_header(v);
2144 
2145  /* when not displaying, use sane wrap value */
2146  if (!display)
2147  {
2148  if ((C_WrapHeaders < 78) || (C_WrapHeaders > 998))
2149  wraplen = 78;
2150  else
2151  wraplen = C_WrapHeaders;
2152  }
2153  else if ((wraplen <= 0) || (wraplen > MuttIndexWindow->cols))
2154  wraplen = MuttIndexWindow->cols;
2155 
2156  if (tag)
2157  {
2158  /* if header is short enough, simply print it */
2159  if (!display && (mutt_strwidth(tag) + 2 + pfxw + mutt_strwidth(v) <= wraplen))
2160  {
2161  mutt_debug(LL_DEBUG5, "buf[%s%s: %s] is short enough\n", NONULL(pfx), tag, v);
2162  if (fprintf(fp, "%s%s: %s\n", NONULL(pfx), tag, v) <= 0)
2163  goto out;
2164  rc = 0;
2165  goto out;
2166  }
2167  else
2168  {
2169  rc = fold_one_header(fp, tag, v, pfx, wraplen, chflags);
2170  goto out;
2171  }
2172  }
2173 
2174  char *p = v;
2175  last = v;
2176  line = v;
2177  while (p && *p)
2178  {
2179  p = strchr(p, '\n');
2180 
2181  /* find maximum line width in current header */
2182  if (p)
2183  *p = '\0';
2184  w = mutt_mb_width(line, 0, display);
2185  if (w > max)
2186  max = w;
2187  if (p)
2188  *p = '\n';
2189 
2190  if (!p)
2191  break;
2192 
2193  line = ++p;
2194  if ((*p != ' ') && (*p != '\t'))
2195  {
2196  if (write_one_header(fp, pfxw, max, wraplen, pfx, last, p, chflags) < 0)
2197  goto out;
2198  last = p;
2199  max = 0;
2200  }
2201  }
2202 
2203  if (last && *last)
2204  if (write_one_header(fp, pfxw, max, wraplen, pfx, last, p, chflags) < 0)
2205  goto out;
2206 
2207  rc = 0;
2208 
2209 out:
2210  FREE(&v);
2211  return rc;
2212 }
short C_WrapHeaders
Config: Width to wrap headers in outgoing messages.
Definition: sendlib.c:98
#define NONULL(x)
Definition: string2.h:37
static char * unfold_header(char *s)
Unfold a wrapped email header.
Definition: sendlib.c:2000
int mutt_mb_width(const char *str, int col, bool display)
Measure a string&#39;s display width (in screen columns)
Definition: mbyte.c:139
const char * line
Definition: common.c:36
int mutt_strwidth(const char *s)
Measure a string&#39;s width in screen cells.
Definition: curs_lib.c:1266
struct MuttWindow * MuttIndexWindow
Index Window.
Definition: mutt_window.c:40
#define CH_DISPLAY
Display result to user.
Definition: copy.h:69
static int write_one_header(FILE *fp, int pfxw, int max, int wraplen, const char *pfx, const char *start, const char *end, CopyHeaderFlags chflags)
Write out one header line.
Definition: sendlib.c:2042
char * value
Parameter value.
Definition: parameter.h:35
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
static int fold_one_header(FILE *fp, const char *tag, const char *value, const char *pfx, int wraplen, CopyHeaderFlags chflags)
Fold one header line.
Definition: sendlib.c:1901
#define FREE(x)
Definition: memory.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Log at debug level 5.
Definition: logging.h:60
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: email_globals.c:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_write_references()

void mutt_write_references ( const struct ListHead *  r,
FILE *  fp,
size_t  trim 
)

Add the message references to a list.

Parameters
rString List of references
fpFile to write to
trimTrim the list to at most this many items

Write the list in reverse because they are stored in reverse order when parsed to speed up threading.

Definition at line 1812 of file sendlib.c.

1813 {
1814  struct ListNode *np = NULL;
1815  size_t length = 0;
1816 
1817  STAILQ_FOREACH(np, r, entries)
1818  {
1819  if (++length == trim)
1820  break;
1821  }
1822 
1823  struct ListNode **ref = mutt_mem_calloc(length, sizeof(struct ListNode *));
1824 
1825  // store in reverse order
1826  size_t tmp = length;
1827  STAILQ_FOREACH(np, r, entries)
1828  {
1829  ref[--tmp] = np;
1830  if (tmp == 0)
1831  break;
1832  }
1833 
1834  for (size_t i = 0; i < length; i++)
1835  {
1836  fputc(' ', fp);
1837  fputs(ref[i]->data, fp);
1838  if (i != length - 1)
1839  fputc('\n', fp);
1840  }
1841 
1842  FREE(&ref);
1843 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
char * data
String.
Definition: list.h:35
#define FREE(x)
Definition: memory.h:40
A List node for strings.
Definition: list.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ C_Allow8bit

bool C_Allow8bit

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

Definition at line 82 of file sendlib.c.

◆ C_AttachCharset

char* C_AttachCharset

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

Definition at line 83 of file sendlib.c.

◆ C_BounceDelivered

bool C_BounceDelivered

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

Definition at line 84 of file sendlib.c.

◆ C_EncodeFrom

bool C_EncodeFrom

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

Definition at line 85 of file sendlib.c.

◆ C_ForwardDecrypt

bool C_ForwardDecrypt

Config: Decrypt the message when forwarding it.

Definition at line 86 of file sendlib.c.

◆ C_HiddenHost

bool C_HiddenHost

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

Definition at line 87 of file sendlib.c.

◆ C_Inews

char* C_Inews

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

Definition at line 88 of file sendlib.c.

◆ C_MimeForwardDecode

bool C_MimeForwardDecode

Config: Decode the forwarded message before attaching it.

Definition at line 89 of file sendlib.c.

◆ C_MimeSubject

bool C_MimeSubject

encode subject line with RFC2047

encode subject line with RFC2047

Definition at line 90 of file sendlib.c.

◆ C_MimeTypeQueryCommand

char* C_MimeTypeQueryCommand

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

Definition at line 91 of file sendlib.c.

◆ C_MimeTypeQueryFirst

bool C_MimeTypeQueryFirst

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

Definition at line 92 of file sendlib.c.

◆ C_Sendmail

char* C_Sendmail

Config: External command to send email.

Definition at line 93 of file sendlib.c.

◆ C_SendmailWait

short C_SendmailWait

Config: Time to wait for sendmail to finish.

Definition at line 94 of file sendlib.c.

◆ C_Use8bitmime

bool C_Use8bitmime

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

Definition at line 95 of file sendlib.c.

◆ C_UseEnvelopeFrom

bool C_UseEnvelopeFrom

Config: Set the envelope sender of the message.

Definition at line 96 of file sendlib.c.

◆ C_UserAgent

bool C_UserAgent

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

Definition at line 97 of file sendlib.c.

◆ C_WrapHeaders

short C_WrapHeaders

Config: Width to wrap headers in outgoing messages.

Definition at line 98 of file sendlib.c.