NeoMutt  2022-04-29-215-gc12b98
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 dependency graph for sendlib.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define MUTT_RANDTAG_LEN   16
 

Functions

int mutt_bounce_message (FILE *fp, struct Mailbox *m, struct Email *e, struct AddressList *to, struct ConfigSubset *sub)
 Bounce an email message. More...
 
const char * mutt_fqdn (bool may_hide_host, const struct ConfigSubset *sub)
 Get the Fully-Qualified Domain Name. 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, struct ConfigSubset *sub)
 Create a file attachment. More...
 
struct Bodymutt_make_message_attach (struct Mailbox *m, struct Email *e, bool attach_msg, struct ConfigSubset *sub)
 Create a message attachment. More...
 
void mutt_message_to_7bit (struct Body *a, FILE *fp, struct ConfigSubset *sub)
 Convert an email's MIME parts to 7-bit. More...
 
void mutt_prepare_envelope (struct Envelope *env, bool final, struct ConfigSubset *sub)
 Prepare an email header. 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, struct ConfigSubset *sub)
 Update the encoding type. More...
 
int mutt_write_fcc (const char *path, struct Email *e, const char *msgid, bool post, const char *fcc, char **finalpath, struct ConfigSubset *sub)
 Write email to FCC mailbox. More...
 
int mutt_write_multiple_fcc (const char *path, struct Email *e, const char *msgid, bool post, char *fcc, char **finalpath, struct ConfigSubset *sub)
 Handle FCC with multiple, comma separated entries. 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.

Macro Definition Documentation

◆ MUTT_RANDTAG_LEN

#define MUTT_RANDTAG_LEN   16

Definition at line 35 of file sendlib.h.

Function Documentation

◆ mutt_bounce_message()

int mutt_bounce_message ( FILE *  fp,
struct Mailbox m,
struct Email e,
struct AddressList *  to,
struct ConfigSubset sub 
)

Bounce an email message.

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

Definition at line 894 of file sendlib.c.

896{
897 if (!fp || !e || !to || TAILQ_EMPTY(to))
898 return -1;
899
900 const char *fqdn = mutt_fqdn(true, sub);
901 char resent_from[256] = { 0 };
902 char *err = NULL;
903
904 resent_from[0] = '\0';
905 struct Address *from = mutt_default_from(sub);
906 struct AddressList from_list = TAILQ_HEAD_INITIALIZER(from_list);
907 mutt_addrlist_append(&from_list, from);
908
909 /* mutt_default_from() does not use $real_name if the real name is not set
910 * in $from, so we add it here. The reason it is not added in
911 * mutt_default_from() is that during normal sending, we execute
912 * send-hooks and set the real_name last so that it can be changed based
913 * upon message criteria. */
914 if (!from->personal)
915 {
916 const char *const c_real_name = cs_subset_string(sub, "real_name");
917 from->personal = mutt_str_dup(c_real_name);
918 }
919
920 mutt_addrlist_qualify(&from_list, fqdn);
921
922 rfc2047_encode_addrlist(&from_list, "Resent-From");
923 if (mutt_addrlist_to_intl(&from_list, &err))
924 {
925 mutt_error(_("Bad IDN %s while preparing resent-from"), err);
926 FREE(&err);
927 mutt_addrlist_clear(&from_list);
928 return -1;
929 }
930 mutt_addrlist_write(&from_list, resent_from, sizeof(resent_from), false);
931
932#ifdef USE_NNTP
933 OptNewsSend = false;
934#endif
935
936 /* prepare recipient list. idna conversion appears to happen before this
937 * function is called, since the user receives confirmation of the address
938 * list being bounced to. */
939 struct AddressList resent_to = TAILQ_HEAD_INITIALIZER(resent_to);
940 mutt_addrlist_copy(&resent_to, to, false);
941 rfc2047_encode_addrlist(&resent_to, "Resent-To");
942 int rc = bounce_message(fp, m, e, &resent_to, resent_from, &from_list, sub);
943 mutt_addrlist_clear(&resent_to);
944 mutt_addrlist_clear(&from_list);
945
946 return rc;
947}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:737
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:650
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1470
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1490
size_t mutt_addrlist_write(const struct AddressList *al, char *buf, size_t buflen, bool display)
Write an Address to a buffer.
Definition: address.c:1150
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1305
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
#define mutt_error(...)
Definition: logging.h:87
#define FREE(x)
Definition: memory.h:43
#define _(a)
Definition: message.h:28
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:51
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
#define TAILQ_EMPTY(head)
Definition: queue.h:721
void rfc2047_encode_addrlist(struct AddressList *al, const char *tag)
Encode any RFC2047 headers, where required, in an Address list.
Definition: rfc2047.c:750
struct Address * mutt_default_from(struct ConfigSubset *sub)
Get a default 'from' Address.
Definition: send.c:1459
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:698
static int bounce_message(FILE *fp, struct Mailbox *m, struct Email *e, struct AddressList *to, const char *resent_from, struct AddressList *env_from, struct ConfigSubset *sub)
Bounce an email message.
Definition: sendlib.c:819
An email address.
Definition: address.h:36
char * personal
Real name of address.
Definition: address.h:37
+ 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,
const struct ConfigSubset sub 
)

Get the Fully-Qualified Domain Name.

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

Definition at line 698 of file sendlib.c.

699{
700 const char *const c_hostname = cs_subset_string(sub, "hostname");
701 if (!c_hostname || (c_hostname[0] == '@'))
702 return NULL;
703
704 const char *p = c_hostname;
705
706 const bool c_hidden_host = cs_subset_bool(sub, "hidden_host");
707 if (may_hide_host && c_hidden_host)
708 {
709 p = strchr(c_hostname, '.');
710 if (p)
711 p++;
712
713 // sanity check: don't hide the host if the fqdn is something like example.com
714 if (!p || !strchr(p, '.'))
715 p = c_hostname;
716 }
717
718 return p;
719}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
+ 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 71 of file sendlib.c.

72{
73 FILE *fp = NULL;
74 char *p = NULL, *q = NULL, *ct = NULL;
75 char buf[PATH_MAX] = { 0 };
76 char subtype[256] = { 0 };
77 char xtype[256] = { 0 };
78 int sze, cur_sze = 0;
79 bool found_mimetypes = false;
80 enum ContentType type = TYPE_OTHER;
81
82 int szf = mutt_str_len(path);
83
84 for (int count = 0; count < 4; count++)
85 {
86 /* can't use strtok() because we use it in an inner loop below, so use
87 * a switch statement here instead. */
88 switch (count)
89 {
90 /* last file with last entry to match wins type/xtype */
91 case 0:
92 /* check default unix mimetypes location first */
93 mutt_str_copy(buf, "/etc/mime.types", sizeof(buf));
94 break;
95 case 1:
96 mutt_str_copy(buf, SYSCONFDIR "/mime.types", sizeof(buf));
97 break;
98 case 2:
99 mutt_str_copy(buf, PKGDATADIR "/mime.types", sizeof(buf));
100 break;
101 case 3:
102 snprintf(buf, sizeof(buf), "%s/.mime.types", NONULL(HomeDir));
103 break;
104 default:
105 mutt_debug(LL_DEBUG1, "Internal error, count = %d\n", count);
106 goto bye; /* shouldn't happen */
107 }
108
109 fp = fopen(buf, "r");
110 if (fp)
111 {
112 found_mimetypes = true;
113
114 while (fgets(buf, sizeof(buf) - 1, fp))
115 {
116 /* weed out any comments */
117 p = strchr(buf, '#');
118 if (p)
119 *p = '\0';
120
121 /* remove any leading space. */
122 ct = buf;
123 SKIPWS(ct);
124
125 /* position on the next field in this line */
126 p = strpbrk(ct, " \t");
127 if (!p)
128 continue;
129 *p++ = 0;
130 SKIPWS(p);
131
132 /* cycle through the file extensions */
133 while ((p = strtok(p, " \t\n")))
134 {
135 sze = mutt_str_len(p);
136 if ((sze > cur_sze) && (szf >= sze) && mutt_istr_equal(path + szf - sze, p) &&
137 ((szf == sze) || (path[szf - sze - 1] == '.')))
138 {
139 /* get the content-type */
140
141 p = strchr(ct, '/');
142 if (!p)
143 {
144 /* malformed line, just skip it. */
145 break;
146 }
147 *p++ = 0;
148
149 for (q = p; *q && !IS_SPACE(*q); q++)
150 ; // do nothing
151
152 mutt_strn_copy(subtype, p, q - p, sizeof(subtype));
153
154 type = mutt_check_mime_type(ct);
155 if (type == TYPE_OTHER)
156 mutt_str_copy(xtype, ct, sizeof(xtype));
157
158 cur_sze = sze;
159 }
160 p = NULL;
161 }
162 }
163 mutt_file_fclose(&fp);
164 }
165 }
166
167bye:
168
169 /* no mime.types file found */
170 if (!found_mimetypes)
171 {
172 mutt_error(_("Could not find any mime.types file"));
173 }
174
175 if ((type != TYPE_OTHER) || (*xtype != '\0'))
176 {
177 att->type = type;
178 mutt_str_replace(&att->subtype, subtype);
179 mutt_str_replace(&att->xtype, xtype);
180 }
181
182 return type;
183}
char * HomeDir
User's home directory.
Definition: mutt_globals.h:49
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
ContentType
Content-Type.
Definition: mime.h:30
@ TYPE_OTHER
Unknown Content-Type.
Definition: mime.h:31
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:819
char * mutt_strn_copy(char *dest, const char *src, size_t len, size_t dsize)
Copy a sub-string into a buffer.
Definition: string.c:431
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:652
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:326
#define PATH_MAX
Definition: mutt.h:40
enum ContentType mutt_check_mime_type(const char *s)
Check a MIME type string.
Definition: parse.c:323
#define NONULL(x)
Definition: string2.h:37
#define IS_SPACE(ch)
Definition: string2.h:38
#define SKIPWS(ch)
Definition: string2.h:46
char * xtype
content-type if x-unknown
Definition: body.h:61
char * subtype
content-type subtype
Definition: body.h:60
unsigned int type
content-type primary type, ContentType
Definition: body.h:40
+ 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,
struct ConfigSubset sub 
)

Create a file attachment.

Parameters
pathFile to attach
subConfig Subset
Return values
ptrNewly allocated Body
NULLError

Definition at line 598 of file sendlib.c.

599{
600 if (!path || (path[0] == '\0'))
601 return NULL;
602
603 struct Body *att = mutt_body_new();
604 att->filename = mutt_str_dup(path);
605
606 const char *const c_mime_type_query_command = cs_subset_string(sub, "mime_type_query_command");
607 const bool c_mime_type_query_first = cs_subset_bool(sub, "mime_type_query_first");
608
609 if (c_mime_type_query_command && c_mime_type_query_first)
610 run_mime_type_query(att, sub);
611
612 /* Attempt to determine the appropriate content-type based on the filename
613 * suffix. */
614 if (!att->subtype)
615 mutt_lookup_mime_type(att, path);
616
617 if (!att->subtype && c_mime_type_query_command && !c_mime_type_query_first)
618 {
619 run_mime_type_query(att, sub);
620 }
621
622 struct Content *info = mutt_get_content_info(path, att, sub);
623 if (!info)
624 {
625 mutt_body_free(&att);
626 return NULL;
627 }
628
629 if (!att->subtype)
630 {
631 if ((info->nulbin == 0) &&
632 ((info->lobin == 0) || ((info->lobin + info->hibin + info->ascii) / info->lobin >= 10)))
633 {
634 /* Statistically speaking, there should be more than 10% "lobin"
635 * chars if this is really a binary file... */
636 att->type = TYPE_TEXT;
637 att->subtype = mutt_str_dup("plain");
638 }
639 else
640 {
641 att->type = TYPE_APPLICATION;
642 att->subtype = mutt_str_dup("octet-stream");
643 }
644 }
645
646 FREE(&info);
647 mutt_update_encoding(att, sub);
648 return att;
649}
struct Content * mutt_get_content_info(const char *fname, struct Body *b, struct ConfigSubset *sub)
Analyze file to determine MIME encoding to use.
Definition: content_info.c:180
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
@ TYPE_APPLICATION
Type: 'application/*'.
Definition: mime.h:33
@ TYPE_TEXT
Type: 'text/*'.
Definition: mime.h:38
enum ContentType mutt_lookup_mime_type(struct Body *att, const char *path)
Find the MIME type for an attachment.
Definition: sendlib.c:71
void mutt_update_encoding(struct Body *a, struct ConfigSubset *sub)
Update the encoding type.
Definition: sendlib.c:413
static void run_mime_type_query(struct Body *att, struct ConfigSubset *sub)
Run an external command to determine the MIME type.
Definition: sendlib.c:557
The body of an email.
Definition: body.h:36
char * filename
When sending a message, this is the file to which this structure refers.
Definition: body.h:58
Info about an attachment.
Definition: content.h:35
long hibin
8-bit characters
Definition: content.h:36
long ascii
Number of ascii chars.
Definition: content.h:40
long nulbin
Null characters (0x0)
Definition: content.h:38
long lobin
Unprintable 7-bit chars (eg., control chars)
Definition: content.h:37
+ 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,
struct ConfigSubset sub 
)

Create a message attachment.

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

Definition at line 445 of file sendlib.c.

447{
448 struct Body *body = NULL;
449 FILE *fp = NULL;
450 CopyMessageFlags cmflags;
452
453 const bool c_mime_forward_decode = cs_subset_bool(sub, "mime_forward_decode");
454 const bool c_forward_decrypt = cs_subset_bool(sub, "forward_decrypt");
455 if (WithCrypto)
456 {
457 if ((c_mime_forward_decode || c_forward_decrypt) && (e->security & SEC_ENCRYPT))
458 {
460 return NULL;
461 }
462 }
463
464 struct Buffer *buf = mutt_buffer_pool_get();
466 fp = mutt_file_fopen(mutt_buffer_string(buf), "w+");
467 if (!fp)
468 {
470 return NULL;
471 }
472
473 body = mutt_body_new();
474 body->type = TYPE_MESSAGE;
475 body->subtype = mutt_str_dup("rfc822");
477 body->unlink = true;
478 body->use_disp = false;
479 body->disposition = DISP_INLINE;
480 body->noconv = true;
481
483
484 struct Message *msg = mx_msg_open(m, e->msgno);
485 if (!msg)
486 {
487 mutt_body_free(&body);
489 return NULL;
490 }
492
493 CopyHeaderFlags chflags = CH_XMIT;
494 cmflags = MUTT_CM_NO_FLAGS;
495
496 /* If we are attaching a message, ignore `$mime_forward_decode` */
497 if (!attach_msg && c_mime_forward_decode)
498 {
499 chflags |= CH_MIME | CH_TXTPLAIN;
502 pgp &= ~PGP_ENCRYPT;
504 pgp &= ~SMIME_ENCRYPT;
505 }
506 else if ((WithCrypto != 0) && c_forward_decrypt && (e->security & SEC_ENCRYPT))
507 {
509 {
510 chflags |= CH_MIME | CH_NONEWLINE;
511 cmflags = MUTT_CM_DECODE_PGP;
512 pgp &= ~PGP_ENCRYPT;
513 }
514 else if (((WithCrypto & APPLICATION_PGP) != 0) &&
516 {
517 chflags |= CH_MIME | CH_TXTPLAIN;
519 pgp &= ~PGP_ENCRYPT;
520 }
521 else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
523 {
524 chflags |= CH_MIME | CH_TXTPLAIN;
526 pgp &= ~SMIME_ENCRYPT;
527 }
528 }
529
530 mutt_copy_message(fp, e, msg, cmflags, chflags, 0);
531 mx_msg_close(m, &msg);
532
533 fflush(fp);
534 rewind(fp);
535
536 body->email = email_new();
537 body->email->offset = 0;
538 /* we don't need the user headers here */
539 body->email->env = mutt_rfc822_read_header(fp, body->email, false, false);
540 if (WithCrypto)
541 body->email->security = pgp;
542 mutt_update_encoding(body, sub);
543 body->parts = body->email->body;
544
546
547 return body;
548}
void mutt_parse_mime_message(struct Email *e, FILE *fp)
Parse a MIME email.
Definition: attachments.c:591
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
int mutt_copy_message(FILE *fp_out, struct Email *e, struct Message *msg, CopyMessageFlags cmflags, CopyHeaderFlags chflags, int wraplen)
Copy a message from a Mailbox.
Definition: copy.c:864
#define CH_XMIT
Transmitting this message? (Ignore Lines: and Content-Length:)
Definition: copy.h:55
#define MUTT_CM_DECODE_PGP
Used for decoding PGP messages.
Definition: copy.h:45
#define MUTT_CM_DECODE
Decode the message body into text/plain.
Definition: copy.h:38
#define CH_NONEWLINE
Don't output terminating newline after the header.
Definition: copy.h:60
#define MUTT_CM_CHARCONV
Perform character set conversions.
Definition: copy.h:42
#define CH_MIME
Ignore MIME fields.
Definition: copy.h:61
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:50
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:35
#define CH_TXTPLAIN
Generate text/plain MIME headers.
Definition: copy.h:63
uint16_t CopyMessageFlags
Flags for mutt_copy_message(), e.g. MUTT_CM_NOHEADER.
Definition: copy.h:34
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
Definition: crypt.c:544
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:601
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:134
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:439
struct Email * email_new(void)
Create a new Email.
Definition: email.c:78
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:618
@ TYPE_MESSAGE
Type: 'message/*'.
Definition: mime.h:35
@ DISP_INLINE
Content is inline.
Definition: mime.h:62
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1193
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
Return a stream pointer for a message.
Definition: mx.c:1147
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:76
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:90
#define PGP_ENCRYPT
Definition: lib.h:96
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:91
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:77
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:78
#define SMIME_ENCRYPT
Definition: lib.h:102
#define WithCrypto
Definition: lib.h:116
struct Envelope * mutt_rfc822_read_header(FILE *fp, struct Email *e, bool user_hdrs, bool weed)
Parses an RFC822 header.
Definition: parse.c:1158
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:72
bool noconv
Don't do character set conversion.
Definition: body.h:46
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:67
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:47
struct Email * email
header information for message/rfc822
Definition: body.h:73
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:42
String manipulation buffer.
Definition: buffer.h:34
struct Envelope * env
Envelope information.
Definition: email.h:66
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition: email.h:41
struct Body * body
List of MIME parts.
Definition: email.h:67
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:69
int msgno
Number displayed to the user.
Definition: email.h:111
A local copy of an email.
Definition: mxapi.h:43
FILE * fp
pointer to the message data
Definition: mxapi.h:44
+ 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,
struct ConfigSubset sub 
)

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

Parameters
aBody of the email
fpFile to read (OPTIONAL)
subConfig Subset

Definition at line 254 of file sendlib.c.

255{
256 struct Buffer temp = mutt_buffer_make(0);
257 FILE *fp_in = NULL;
258 FILE *fp_out = NULL;
259 struct stat st = { 0 };
260
261 if (!a->filename && fp)
262 fp_in = fp;
263 else if (!a->filename || !(fp_in = fopen(a->filename, "r")))
264 {
265 mutt_error(_("Could not open %s"), a->filename ? a->filename : "(null)");
266 return;
267 }
268 else
269 {
270 a->offset = 0;
271 if (stat(a->filename, &st) == -1)
272 {
273 mutt_perror("stat");
274 mutt_file_fclose(&fp_in);
275 goto cleanup;
276 }
277 a->length = st.st_size;
278 }
279
280 /* Avoid buffer pool due to recursion */
281 mutt_buffer_mktemp(&temp);
282 fp_out = mutt_file_fopen(mutt_buffer_string(&temp), "w+");
283 if (!fp_out)
284 {
285 mutt_perror("fopen");
286 goto cleanup;
287 }
288
289 if (!mutt_file_seek(fp_in, a->offset, SEEK_SET))
290 {
291 goto cleanup;
292 }
293 a->parts = mutt_rfc822_parse_message(fp_in, a);
294
295 transform_to_7bit(a->parts, fp_in, sub);
296
297 mutt_copy_hdr(fp_in, fp_out, a->offset, a->offset + a->length,
298 CH_MIME | CH_NONEWLINE | CH_XMIT, NULL, 0);
299
300 fputs("MIME-Version: 1.0\n", fp_out);
301 mutt_write_mime_header(a->parts, fp_out, sub);
302 fputc('\n', fp_out);
303 mutt_write_mime_body(a->parts, fp_out, sub);
304
305 if (fp_in != fp)
306 mutt_file_fclose(&fp_in);
307 mutt_file_fclose(&fp_out);
308
309 a->encoding = ENC_7BIT;
310 FREE(&a->d_filename);
311 a->d_filename = a->filename;
312 if (a->filename && a->unlink)
313 unlink(a->filename);
314 a->filename = mutt_buffer_strdup(&temp);
315 a->unlink = true;
316 if (stat(a->filename, &st) == -1)
317 {
318 mutt_perror("stat");
319 goto cleanup;
320 }
321 a->length = st.st_size;
323 a->email->body = NULL;
324
325cleanup:
326 if (fp_in && (fp_in != fp))
327 mutt_file_fclose(&fp_in);
328
329 if (fp_out)
330 {
331 mutt_file_fclose(&fp_out);
333 }
334
335 mutt_buffer_dealloc(&temp);
336}
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:67
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:309
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:447
int mutt_copy_hdr(FILE *fp_in, FILE *fp_out, LOFF_T off_start, LOFF_T off_end, CopyHeaderFlags chflags, const char *prefix, int wraplen)
Copy header from one file to another.
Definition: copy.c:104
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:690
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:194
#define mutt_perror(...)
Definition: logging.h:88
int mutt_write_mime_header(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Create a MIME header.
Definition: header.c:760
@ ENC_7BIT
7-bit text
Definition: mime.h:49
struct Body * mutt_rfc822_parse_message(FILE *fp, struct Body *parent)
Parse a Message/RFC822 body.
Definition: parse.c:1752
int mutt_write_mime_body(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Write a MIME part.
Definition: body.c:314
static void transform_to_7bit(struct Body *a, FILE *fp_in, struct ConfigSubset *sub)
Convert MIME parts to 7-bit.
Definition: sendlib.c:191
char * d_filename
filename to be used for the content-disposition header If NULL, filename is used instead.
Definition: body.h:56
LOFF_T offset
offset where the actual data begins
Definition: body.h:52
LOFF_T length
length (in bytes) of attachment
Definition: body.h:53
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:41
+ 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,
struct ConfigSubset sub 
)

Prepare an email header.

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

Encode all the headers prior to sending the email.

For postponing (!final) do the necessary encodings only

Definition at line 754 of file sendlib.c.

755{
756 if (final)
757 {
758 if (!TAILQ_EMPTY(&env->bcc) && TAILQ_EMPTY(&env->to) && TAILQ_EMPTY(&env->cc))
759 {
760 /* some MTA's will put an Apparently-To: header field showing the Bcc:
761 * recipients if there is no To: or Cc: field, so attempt to suppress
762 * it by using an empty To: field. */
763 struct Address *to = mutt_addr_new();
764 to->group = true;
765 mutt_addrlist_append(&env->to, to);
767
768 char buf[1024] = { 0 };
769 buf[0] = '\0';
770 mutt_addr_cat(buf, sizeof(buf), "undisclosed-recipients", AddressSpecials);
771
772 to->mailbox = mutt_str_dup(buf);
773 }
774
775 mutt_set_followup_to(env, sub);
776
777 if (!env->message_id)
778 env->message_id = gen_msgid(sub);
779 }
780
781 /* Take care of 8-bit => 7-bit conversion. */
783 encode_headers(&env->userhdrs, sub);
784}
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:681
struct Address * mutt_addr_new(void)
Create a new Address.
Definition: address.c:385
const char AddressSpecials[]
Characters with special meaning for email addresses.
Definition: address.c:42
void rfc2047_encode_envelope(struct Envelope *env)
Encode the fields of an Envelope.
Definition: rfc2047.c:813
void mutt_set_followup_to(struct Envelope *env, struct ConfigSubset *sub)
Set followup-to field.
Definition: send.c:1334
static char * gen_msgid(struct ConfigSubset *sub)
Generate a unique Message ID.
Definition: sendlib.c:727
static void encode_headers(struct ListHead *h, struct ConfigSubset *sub)
RFC2047-encode a list of headers.
Definition: sendlib.c:658
bool group
Group mailbox?
Definition: address.h:39
char * mailbox
Mailbox and host address.
Definition: address.h:38
struct ListHead userhdrs
user defined headers
Definition: envelope.h:87
struct AddressList to
Email's 'To' list.
Definition: envelope.h:60
char * message_id
Message ID.
Definition: envelope.h:73
struct AddressList cc
Email's 'Cc' list.
Definition: envelope.h:61
struct AddressList bcc
Email's 'Bcc' list.
Definition: envelope.h:62
+ 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 401 of file sendlib.c.

402{
403 a->stamp = mutt_date_epoch();
404}
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:428
time_t stamp
Time stamp of last encoding update.
Definition: body.h:76
+ 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 793 of file sendlib.c.

794{
795 struct ListNode *item = NULL;
796 STAILQ_FOREACH(item, &env->userhdrs, entries)
797 {
798 rfc2047_decode(&item->data);
799 }
800
802
803 /* back conversions */
805}
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
void rfc2047_decode_envelope(struct Envelope *env)
Decode the fields of an Envelope.
Definition: rfc2047.c:793
void rfc2047_decode(char **pd)
Decode any RFC2047-encoded header fields.
Definition: rfc2047.c:649
struct AddressList mail_followup_to
Email's 'mail-followup-to'.
Definition: envelope.h:65
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
+ 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,
struct ConfigSubset sub 
)

Update the encoding type.

Parameters
aBody to update
subConfig Subset

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

Definition at line 413 of file sendlib.c.

414{
415 struct Content *info = NULL;
416 char chsbuf[256] = { 0 };
417
418 /* override noconv when it's us-ascii */
419 if (mutt_ch_is_us_ascii(mutt_body_get_charset(a, chsbuf, sizeof(chsbuf))))
420 a->noconv = false;
421
422 if (!a->force_charset && !a->noconv)
423 mutt_param_delete(&a->parameter, "charset");
424
425 info = mutt_get_content_info(a->filename, a, sub);
426 if (!info)
427 return;
428
429 set_encoding(a, info, sub);
431
432 FREE(&a->content);
433 a->content = info;
434}
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body's character set.
Definition: body.c:131
#define mutt_ch_is_us_ascii(str)
Definition: charset.h:96
void mutt_param_delete(struct ParameterList *pl, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:142
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:401
static void set_encoding(struct Body *b, struct Content *info, struct ConfigSubset *sub)
Determine which Content-Transfer-Encoding to use.
Definition: sendlib.c:344
struct ParameterList parameter
Parameters of the content-type.
Definition: body.h:62
struct Content * content
Detailed info about the content of the attachment.
Definition: body.h:69
bool force_charset
Send mode: don't adjust the character set when in send-mode.
Definition: body.h:44
+ 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,
const char *  fcc,
char **  finalpath,
struct ConfigSubset sub 
)

Write email to FCC mailbox.

Parameters
[in]pathPath to mailbox
[in]eEmail
[in]msgidMessage id
[in]postIf true, postpone message, else fcc mode
[in]fccfcc setting to save (postpone only)
[out]finalpathFinal path of email
[in]subConfig Subset
Return values
0Success
-1Failure

Definition at line 1030 of file sendlib.c.

1032{
1033 struct Message *msg = NULL;
1034 struct Buffer *tempfile = NULL;
1035 FILE *fp_tmp = NULL;
1036 int rc = -1;
1037 bool need_mailbox_cleanup = false;
1038 struct stat st = { 0 };
1039 MsgOpenFlags onm_flags;
1040
1041 if (post)
1042 set_noconv_flags(e->body, true);
1043
1044#ifdef RECORD_FOLDER_HOOK
1045 mutt_folder_hook(path, NULL);
1046#endif
1047 struct Mailbox *m_fcc = mx_path_resolve(path);
1048 bool old_append = m_fcc->append;
1049 if (!mx_mbox_open(m_fcc, MUTT_APPEND | MUTT_QUIET))
1050 {
1051 mutt_debug(LL_DEBUG1, "unable to open mailbox %s in append-mode, aborting\n", path);
1052 goto done;
1053 }
1054
1055 /* We need to add a Content-Length field to avoid problems where a line in
1056 * the message body begins with "From " */
1057 if ((m_fcc->type == MUTT_MMDF) || (m_fcc->type == MUTT_MBOX))
1058 {
1059 tempfile = mutt_buffer_pool_get();
1060 mutt_buffer_mktemp(tempfile);
1061 fp_tmp = mutt_file_fopen(mutt_buffer_string(tempfile), "w+");
1062 if (!fp_tmp)
1063 {
1065 mx_mbox_close(m_fcc);
1066 goto done;
1067 }
1068 /* remember new mail status before appending message */
1069 need_mailbox_cleanup = true;
1070 stat(path, &st);
1071 }
1072
1073 e->read = !post; /* make sure to put it in the 'cur' directory (maildir) */
1074 onm_flags = MUTT_ADD_FROM;
1075 if (post)
1076 onm_flags |= MUTT_SET_DRAFT;
1077 msg = mx_msg_open_new(m_fcc, e, onm_flags);
1078 if (!msg)
1079 {
1080 mutt_file_fclose(&fp_tmp);
1081 mx_mbox_close(m_fcc);
1082 goto done;
1083 }
1084
1085 const bool c_crypt_protected_headers_read = cs_subset_bool(sub, "crypt_protected_headers_read");
1086
1087 /* post == 1 => postpone message.
1088 * post == 0 => Normal mode. */
1089 mutt_rfc822_write_header(msg->fp, e->env, e->body,
1091 c_crypt_protected_headers_read &&
1093 sub);
1094
1095 /* (postponement) if this was a reply of some sort, <msgid> contains the
1096 * Message-ID: of message replied to. Save it using a special X-Mutt-
1097 * header so it can be picked up if the message is recalled at a later
1098 * point in time. This will allow the message to be marked as replied if
1099 * the same mailbox is still open. */
1100 if (post && msgid)
1101 fprintf(msg->fp, "X-Mutt-References: %s\n", msgid);
1102
1103 /* (postponement) save the Fcc: using a special X-Mutt- header so that
1104 * it can be picked up when the message is recalled */
1105 if (post && fcc)
1106 fprintf(msg->fp, "X-Mutt-Fcc: %s\n", fcc);
1107
1108 if ((m_fcc->type == MUTT_MMDF) || (m_fcc->type == MUTT_MBOX))
1109 fprintf(msg->fp, "Status: RO\n");
1110
1111 /* (postponement) if the mail is to be signed or encrypted, save this info */
1112 if (((WithCrypto & APPLICATION_PGP) != 0) && post && (e->security & APPLICATION_PGP))
1113 {
1114 fputs("X-Mutt-PGP: ", msg->fp);
1115 if (e->security & SEC_ENCRYPT)
1116 fputc('E', msg->fp);
1117 if (e->security & SEC_OPPENCRYPT)
1118 fputc('O', msg->fp);
1119 if (e->security & SEC_SIGN)
1120 {
1121 fputc('S', msg->fp);
1122
1123 const char *const c_pgp_sign_as = cs_subset_string(sub, "pgp_sign_as");
1124 if (c_pgp_sign_as)
1125 fprintf(msg->fp, "<%s>", c_pgp_sign_as);
1126 }
1127 if (e->security & SEC_INLINE)
1128 fputc('I', msg->fp);
1129#ifdef USE_AUTOCRYPT
1130 if (e->security & SEC_AUTOCRYPT)
1131 fputc('A', msg->fp);
1133 fputc('Z', msg->fp);
1134#endif
1135 fputc('\n', msg->fp);
1136 }
1137
1138 /* (postponement) if the mail is to be signed or encrypted, save this info */
1139 if (((WithCrypto & APPLICATION_SMIME) != 0) && post && (e->security & APPLICATION_SMIME))
1140 {
1141 fputs("X-Mutt-SMIME: ", msg->fp);
1142 if (e->security & SEC_ENCRYPT)
1143 {
1144 fputc('E', msg->fp);
1145
1146 const char *const c_smime_encrypt_with = cs_subset_string(sub, "smime_encrypt_with");
1147 if (c_smime_encrypt_with)
1148 fprintf(msg->fp, "C<%s>", c_smime_encrypt_with);
1149 }
1150 if (e->security & SEC_OPPENCRYPT)
1151 fputc('O', msg->fp);
1152 if (e->security & SEC_SIGN)
1153 {
1154 fputc('S', msg->fp);
1155
1156 const char *const c_smime_sign_as = cs_subset_string(sub, "smime_sign_as");
1157 if (c_smime_sign_as)
1158 fprintf(msg->fp, "<%s>", c_smime_sign_as);
1159 }
1160 if (e->security & SEC_INLINE)
1161 fputc('I', msg->fp);
1162 fputc('\n', msg->fp);
1163 }
1164
1165#ifdef MIXMASTER
1166 /* (postponement) if the mail is to be sent through a mixmaster
1167 * chain, save that information */
1168
1169 if (post && !STAILQ_EMPTY(&e->chain))
1170 {
1171 fputs("X-Mutt-Mix:", msg->fp);
1172 struct ListNode *p = NULL;
1173 STAILQ_FOREACH(p, &e->chain, entries)
1174 {
1175 fprintf(msg->fp, " %s", (char *) p->data);
1176 }
1177
1178 fputc('\n', msg->fp);
1179 }
1180#endif
1181
1182 if (fp_tmp)
1183 {
1184 mutt_write_mime_body(e->body, fp_tmp, sub);
1185
1186 /* make sure the last line ends with a newline. Emacs doesn't ensure this
1187 * will happen, and it can cause problems parsing the mailbox later. */
1188 if (mutt_file_seek(fp_tmp, -1, SEEK_END) && (fgetc(fp_tmp) != '\n') &&
1189 mutt_file_seek(fp_tmp, 0, SEEK_END))
1190 {
1191 fputc('\n', fp_tmp);
1192 }
1193
1194 fflush(fp_tmp);
1195 if (ferror(fp_tmp))
1196 {
1197 mutt_debug(LL_DEBUG1, "%s: write failed\n", mutt_buffer_string(tempfile));
1198 mutt_file_fclose(&fp_tmp);
1199 unlink(mutt_buffer_string(tempfile));
1200 mx_msg_commit(m_fcc, msg); /* XXX really? */
1201 mx_msg_close(m_fcc, &msg);
1202 mx_mbox_close(m_fcc);
1203 goto done;
1204 }
1205
1206 /* count the number of lines */
1207 int lines = 0;
1208 char line_buf[1024] = { 0 };
1209 rewind(fp_tmp);
1210 while (fgets(line_buf, sizeof(line_buf), fp_tmp))
1211 lines++;
1212 fprintf(msg->fp, "Content-Length: " OFF_T_FMT "\n", (LOFF_T) ftello(fp_tmp));
1213 fprintf(msg->fp, "Lines: %d\n\n", lines);
1214
1215 /* copy the body and clean up */
1216 rewind(fp_tmp);
1217 rc = mutt_file_copy_stream(fp_tmp, msg->fp);
1218 if (mutt_file_fclose(&fp_tmp) != 0)
1219 rc = -1;
1220 /* if there was an error, leave the temp version */
1221 if (rc >= 0)
1222 {
1223 unlink(mutt_buffer_string(tempfile));
1224 rc = 0;
1225 }
1226 }
1227 else
1228 {
1229 fputc('\n', msg->fp); /* finish off the header */
1230 rc = mutt_write_mime_body(e->body, msg->fp, sub);
1231 }
1232
1233 if (mx_msg_commit(m_fcc, msg) != 0)
1234 rc = -1;
1235 else if (finalpath)
1236 *finalpath = mutt_str_dup(msg->committed_path);
1237 mx_msg_close(m_fcc, &msg);
1238 mx_mbox_close(m_fcc);
1239
1240 if (!post && need_mailbox_cleanup)
1241 mutt_mailbox_cleanup(path, &st);
1242
1243 if (post)
1244 set_noconv_flags(e->body, false);
1245
1246done:
1247 m_fcc->append = old_append;
1248 mailbox_free(&m_fcc);
1249
1250#ifdef RECORD_FOLDER_HOOK
1251 /* We ran a folder hook for the destination mailbox,
1252 * now we run it for the user's current mailbox */
1253 const struct Mailbox *m_cur = get_current_mailbox();
1254 if (m_cur)
1255 mutt_folder_hook(m_cur->path, m_cur->desc);
1256#endif
1257
1258 if (fp_tmp)
1259 {
1260 mutt_file_fclose(&fp_tmp);
1261 unlink(mutt_buffer_string(tempfile));
1262 }
1263 mutt_buffer_pool_release(&tempfile);
1264
1265 return rc;
1266}
bool mutt_should_hide_protected_subject(struct Email *e)
Should NeoMutt hide the protected subject?
Definition: crypt.c:1078
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:260
int mutt_rfc822_write_header(FILE *fp, struct Envelope *env, struct Body *attach, enum MuttWriteHeaderMode mode, bool privacy, bool hide_protected_subject, struct ConfigSubset *sub)
Write out one RFC822 header line.
Definition: header.c:572
@ MUTT_WRITE_HEADER_FCC
fcc mode, like normal mode but for Bcc header
Definition: header.h:41
@ MUTT_WRITE_HEADER_POSTPONE
A postponed Email, just the envelope info.
Definition: header.h:42
void mutt_folder_hook(const char *path, const char *desc)
Perform a folder hook.
Definition: hook.c:589
struct Mailbox * get_current_mailbox(void)
Get the current Mailbox.
Definition: index.c:624
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:87
@ MUTT_MMDF
'mmdf' Mailbox type
Definition: mailbox.h:46
@ MUTT_MBOX
'mbox' Mailbox type
Definition: mailbox.h:45
void mutt_mailbox_cleanup(const char *path, struct stat *st)
Restore the timestamp of a mailbox.
Definition: mutt_mailbox.c:424
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:304
struct Message * mx_msg_open_new(struct Mailbox *m, const struct Email *e, MsgOpenFlags flags)
Open a new message.
Definition: mx.c:1057
int mx_msg_commit(struct Mailbox *m, struct Message *msg)
Commit a message to a folder - Wrapper for MxOps::msg_commit()
Definition: mx.c:1172
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1677
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
Definition: mx.c:615
uint8_t MsgOpenFlags
Flags for mx_msg_open_new(), e.g. MUTT_ADD_FROM.
Definition: mx.h:41
#define MUTT_ADD_FROM
add a From_ line
Definition: mx.h:43
#define MUTT_SET_DRAFT
set the message draft flag
Definition: mx.h:44
#define MUTT_APPEND
Open mailbox for appending messages.
Definition: mxapi.h:63
#define MUTT_QUIET
Do not print any messages.
Definition: mxapi.h:65
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:85
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:87
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:86
#define SEC_AUTOCRYPT_OVERRIDE
(Autocrypt) Indicates manual set/unset of encryption
Definition: lib.h:88
#define SEC_SIGN
Email is signed.
Definition: lib.h:79
#define STAILQ_EMPTY(head)
Definition: queue.h:348
static void set_noconv_flags(struct Body *b, bool flag)
Set/reset the "x-mutt-noconv" flag.
Definition: sendlib.c:954
bool read
Email is read.
Definition: email.h:48
struct ListHead chain
Mixmaster chain.
Definition: email.h:90
A mailbox.
Definition: mailbox.h:79
bool append
Mailbox is opened in append mode.
Definition: mailbox.h:109
enum MailboxType type
Mailbox type.
Definition: mailbox.h:102
struct ConfigSubset * sub
Inherited config items.
Definition: mailbox.h:83
char * committed_path
the final path generated by mx_msg_commit()
Definition: mxapi.h:46
+ 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,
struct ConfigSubset sub 
)

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
[in]subConfig Subset
Return values
0Success
-1Failure

Definition at line 982 of file sendlib.c.

984{
985 char fcc_tok[PATH_MAX] = { 0 };
986 char fcc_expanded[PATH_MAX] = { 0 };
987
988 mutt_str_copy(fcc_tok, path, sizeof(fcc_tok));
989
990 char *tok = strtok(fcc_tok, ",");
991 if (!tok)
992 return -1;
993
994 mutt_debug(LL_DEBUG1, "Fcc: initial mailbox = '%s'\n", tok);
995 /* mutt_expand_path already called above for the first token */
996 int status = mutt_write_fcc(tok, e, msgid, post, fcc, finalpath, sub);
997 if (status != 0)
998 return status;
999
1000 while ((tok = strtok(NULL, ",")))
1001 {
1002 if (*tok == '\0')
1003 continue;
1004
1005 /* Only call mutt_expand_path if tok has some data */
1006 mutt_debug(LL_DEBUG1, "Fcc: additional mailbox token = '%s'\n", tok);
1007 mutt_str_copy(fcc_expanded, tok, sizeof(fcc_expanded));
1008 mutt_expand_path(fcc_expanded, sizeof(fcc_expanded));
1009 mutt_debug(LL_DEBUG1, " Additional mailbox expanded = '%s'\n", fcc_expanded);
1010 status = mutt_write_fcc(fcc_expanded, e, msgid, post, fcc, finalpath, sub);
1011 if (status != 0)
1012 return status;
1013 }
1014
1015 return 0;
1016}
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:123
int mutt_write_fcc(const char *path, struct Email *e, const char *msgid, bool post, const char *fcc, char **finalpath, struct ConfigSubset *sub)
Write email to FCC mailbox.
Definition: sendlib.c:1030
+ Here is the call graph for this function:
+ Here is the caller graph for this function: