NeoMutt  2025-12-11-435-g4ac674
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
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
 Length of random tag for message boundaries.
 

Functions

int mutt_bounce_message (FILE *fp, struct Mailbox *m, struct Email *e, struct AddressList *to, struct ConfigSubset *sub)
 Bounce an email message.
 
const char * mutt_fqdn (bool may_hide_host, const struct ConfigSubset *sub)
 Get the Fully-Qualified Domain Name.
 
enum ContentType mutt_lookup_mime_type (struct Body *b, const char *path)
 Find the MIME type for an attachment.
 
struct Bodymutt_make_file_attach (const char *path, struct ConfigSubset *sub)
 Create a file attachment.
 
struct Bodymutt_make_message_attach (struct Mailbox *m, struct Email *e, bool attach_msg, struct ConfigSubset *sub)
 Create a message attachment.
 
void mutt_message_to_7bit (struct Body *b, FILE *fp, struct ConfigSubset *sub)
 Convert an email's MIME parts to 7-bit.
 
void mutt_prepare_envelope (struct Envelope *env, bool final, struct ConfigSubset *sub)
 Prepare an email header.
 
void mutt_stamp_attachment (struct Body *b)
 Timestamp an Attachment.
 
void mutt_unprepare_envelope (struct Envelope *env)
 Undo the encodings of mutt_prepare_envelope()
 
void mutt_update_encoding (struct Body *b, struct ConfigSubset *sub)
 Update the encoding type.
 
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.
 
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.
 

Detailed Description

Miscellaneous functions for sending an email.

Authors
  • Pietro Cerutti
  • Richard Russon

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

Length of random tag for message boundaries.

Definition at line 36 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 876 of file sendlib.c.

878{
879 if (!fp || !e || !to || TAILQ_EMPTY(to))
880 return -1;
881
882 const char *fqdn = mutt_fqdn(true, sub);
883 char *err = NULL;
884
885 struct Address *from = mutt_default_from(sub);
886 struct AddressList from_list = TAILQ_HEAD_INITIALIZER(from_list);
887 mutt_addrlist_append(&from_list, from);
888
889 /* mutt_default_from() does not use $real_name if the real name is not set
890 * in $from, so we add it here. The reason it is not added in
891 * mutt_default_from() is that during normal sending, we execute
892 * send-hooks and set the real_name last so that it can be changed based
893 * upon message criteria. */
894 if (!from->personal)
895 {
896 const char *const c_real_name = cs_subset_string(sub, "real_name");
897 if (c_real_name)
898 from->personal = buf_new(c_real_name);
899 }
900
901 mutt_addrlist_qualify(&from_list, fqdn);
902
903 rfc2047_encode_addrlist(&from_list, "Resent-From");
904 if (mutt_addrlist_to_intl(&from_list, &err))
905 {
906 mutt_error(_("Bad IDN %s while preparing resent-from"), err);
907 FREE(&err);
908 mutt_addrlist_clear(&from_list);
909 return -1;
910 }
911 struct Buffer *resent_from = buf_pool_get();
912 mutt_addrlist_write(&from_list, resent_from, false);
913
914 OptNewsSend = false;
915
916 /* prepare recipient list. idna conversion appears to happen before this
917 * function is called, since the user receives confirmation of the address
918 * list being bounced to. */
919 struct AddressList resent_to = TAILQ_HEAD_INITIALIZER(resent_to);
920 mutt_addrlist_copy(&resent_to, to, false);
921 rfc2047_encode_addrlist(&resent_to, "Resent-To");
922 int rc = bounce_message(fp, m, e, &resent_to, buf_string(resent_from), &from_list, sub);
923 mutt_addrlist_clear(&resent_to);
924 mutt_addrlist_clear(&from_list);
925 buf_pool_release(&resent_from);
926 return rc;
927}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition address.c:769
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition address.c:680
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition address.c:1464
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition address.c:1484
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition address.c:1210
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition address.c:1297
struct Buffer * buf_new(const char *str)
Allocate a new Buffer.
Definition buffer.c:304
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
bool OptNewsSend
(pseudo) used to change behavior when posting
Definition globals.c:54
#define mutt_error(...)
Definition logging2.h:94
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
#define _(a)
Definition message.h:28
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
#define TAILQ_HEAD_INITIALIZER(head)
Definition queue.h:694
#define TAILQ_EMPTY(head)
Definition queue.h:778
void rfc2047_encode_addrlist(struct AddressList *al, const char *tag)
Encode any RFC2047 headers, where required, in an Address list.
Definition rfc2047.c:770
struct Address * mutt_default_from(struct ConfigSubset *sub)
Get a default 'from' Address.
Definition send.c:1396
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition sendlib.c:706
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:804
An email address.
Definition address.h:35
struct Buffer * personal
Real name of address.
Definition address.h:36
String manipulation buffer.
Definition buffer.h:36
+ 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 706 of file sendlib.c.

707{
708 const char *const c_hostname = cs_subset_string(sub, "hostname");
709 if (!c_hostname || (c_hostname[0] == '@'))
710 return NULL;
711
712 const char *p = c_hostname;
713
714 const bool c_hidden_host = cs_subset_bool(sub, "hidden_host");
715 if (may_hide_host && c_hidden_host)
716 {
717 p = strchr(c_hostname, '.');
718 if (p)
719 p++;
720
721 // sanity check: don't hide the host if the fqdn is something like example.com
722 if (!p || !strchr(p, '.'))
723 p = c_hostname;
724 }
725
726 return p;
727}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
+ 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 * b,
const char * path )

Find the MIME type for an attachment.

Parameters
bEmail with attachment
pathPath to attachment
Return values
enumContentType, 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 75 of file sendlib.c.

76{
77 FILE *fp = NULL;
78 char *p = NULL, *q = NULL, *ct = NULL;
79 char buf[PATH_MAX] = { 0 };
80 char subtype[256] = { 0 };
81 char xtype[256] = { 0 };
82 int sze, cur_sze = 0;
83 bool found_mimetypes = false;
84 enum ContentType type = TYPE_OTHER;
85
86 int szf = mutt_str_len(path);
87
88 for (int count = 0; count < 4; count++)
89 {
90 /* can't use strtok() because we use it in an inner loop below, so use
91 * a switch statement here instead. */
92 switch (count)
93 {
94 /* last file with last entry to match wins type/xtype */
95 case 0:
96 /* check default unix mimetypes location first */
97 mutt_str_copy(buf, "/etc/mime.types", sizeof(buf));
98 break;
99 case 1:
100 mutt_str_copy(buf, SYSCONFDIR "/mime.types", sizeof(buf));
101 break;
102 case 2:
103 mutt_str_copy(buf, PKGDATADIR "/mime.types", sizeof(buf));
104 break;
105 case 3:
106 snprintf(buf, sizeof(buf), "%s/.mime.types", NONULL(NeoMutt->home_dir));
107 break;
108 default:
109 mutt_debug(LL_DEBUG1, "Internal error, count = %d\n", count);
110 goto bye; /* shouldn't happen */
111 }
112
113 fp = mutt_file_fopen(buf, "r");
114 if (fp)
115 {
116 found_mimetypes = true;
117
118 while (fgets(buf, sizeof(buf) - 1, fp))
119 {
120 /* weed out any comments */
121 p = strchr(buf, '#');
122 if (p)
123 *p = '\0';
124
125 /* remove any leading space. */
126 ct = buf;
127 SKIPWS(ct);
128
129 /* position on the next field in this line */
130 p = strpbrk(ct, " \t");
131 if (!p)
132 continue;
133 *p++ = 0;
134 SKIPWS(p);
135
136 /* cycle through the file extensions */
137 while ((p = strtok(p, " \t\n")))
138 {
139 sze = mutt_str_len(p);
140 if ((sze > cur_sze) && (szf >= sze) && mutt_istr_equal(path + szf - sze, p) &&
141 ((szf == sze) || (path[szf - sze - 1] == '.')))
142 {
143 /* get the content-type */
144
145 p = strchr(ct, '/');
146 if (!p)
147 {
148 /* malformed line, just skip it. */
149 break;
150 }
151 *p++ = 0;
152
153 for (q = p; *q && !mutt_isspace(*q); q++)
154 ; // do nothing
155
156 mutt_strn_copy(subtype, p, q - p, sizeof(subtype));
157
158 type = mutt_check_mime_type(ct);
159 if (type == TYPE_OTHER)
160 mutt_str_copy(xtype, ct, sizeof(xtype));
161
162 cur_sze = sze;
163 }
164 p = NULL;
165 }
166 }
167 mutt_file_fclose(&fp);
168 }
169 }
170
171bye:
172
173 /* no mime.types file found */
174 if (!found_mimetypes)
175 {
176 mutt_error(_("Could not find any mime.types file"));
177 }
178
179 if ((type != TYPE_OTHER) || (*xtype != '\0'))
180 {
181 b->type = type;
182 mutt_str_replace(&b->subtype, subtype);
183 mutt_str_replace(&b->xtype, xtype);
184 }
185
186 return type;
187}
bool mutt_isspace(int arg)
Wrapper for isspace(3)
Definition ctype.c:96
enum ContentType mutt_check_mime_type(const char *s)
Check a MIME type string.
Definition parse.c:371
#define mutt_file_fclose(FP)
Definition file.h:139
#define mutt_file_fopen(PATH, MODE)
Definition file.h:138
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
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:674
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:364
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:500
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:583
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition string.c:284
#define PATH_MAX
Definition mutt.h:49
#define NONULL(x)
Definition string2.h:44
#define SKIPWS(ch)
Definition string2.h:52
char * xtype
content-type if x-unknown
Definition body.h:62
char * subtype
content-type subtype
Definition body.h:61
unsigned int type
content-type primary type, ContentType
Definition body.h:40
Container for Accounts, Notifications.
Definition neomutt.h:41
char * home_dir
User's home directory.
Definition neomutt.h:56
+ 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 606 of file sendlib.c.

607{
608 if (!path || (path[0] == '\0'))
609 return NULL;
610
611 struct Body *b = mutt_body_new();
612 b->filename = mutt_str_dup(path);
613
614 const char *const c_mime_type_query_command = cs_subset_string(sub, "mime_type_query_command");
615 const bool c_mime_type_query_first = cs_subset_bool(sub, "mime_type_query_first");
616
617 if (c_mime_type_query_command && c_mime_type_query_first)
618 run_mime_type_query(b, sub);
619
620 /* Attempt to determine the appropriate content-type based on the filename
621 * suffix. */
622 if (!b->subtype)
623 mutt_lookup_mime_type(b, path);
624
625 if (!b->subtype && c_mime_type_query_command && !c_mime_type_query_first)
626 {
627 run_mime_type_query(b, sub);
628 }
629
630 struct Content *info = mutt_get_content_info(path, b, sub);
631 if (!info)
632 {
633 mutt_body_free(&b);
634 return NULL;
635 }
636
637 if (!b->subtype)
638 {
639 if ((info->nulbin == 0) &&
640 ((info->lobin == 0) || ((info->lobin + info->hibin + info->ascii) / info->lobin >= 10)))
641 {
642 /* Statistically speaking, there should be more than 10% "lobin"
643 * chars if this is really a binary file... */
644 b->type = TYPE_TEXT;
645 b->subtype = mutt_str_dup("plain");
646 }
647 else
648 {
650 b->subtype = mutt_str_dup("octet-stream");
651 }
652 }
653
654 FREE(&info);
655 mutt_update_encoding(b, sub);
656 return b;
657}
struct Content * mutt_get_content_info(const char *fname, struct Body *b, struct ConfigSubset *sub)
Analyze file to determine MIME encoding to use.
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition body.c:58
struct Body * mutt_body_new(void)
Create a new Body.
Definition body.c:44
@ TYPE_APPLICATION
Type: 'application/*'.
Definition mime.h:33
@ TYPE_TEXT
Type: 'text/*'.
Definition mime.h:38
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
void mutt_update_encoding(struct Body *b, struct ConfigSubset *sub)
Update the encoding type.
Definition sendlib.c:421
enum ContentType mutt_lookup_mime_type(struct Body *b, const char *path)
Find the MIME type for an attachment.
Definition sendlib.c:75
static void run_mime_type_query(struct Body *b, struct ConfigSubset *sub)
Run an external command to determine the MIME type.
Definition sendlib.c:565
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:59
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 453 of file sendlib.c.

455{
456 struct Body *body = NULL;
457 FILE *fp = NULL;
458 CopyMessageFlags cmflags;
460
461 const bool c_mime_forward_decode = cs_subset_bool(sub, "mime_forward_decode");
462 const bool c_forward_decrypt = cs_subset_bool(sub, "forward_decrypt");
463 if (WithCrypto)
464 {
465 if ((c_mime_forward_decode || c_forward_decrypt) && (e->security & SEC_ENCRYPT))
466 {
468 return NULL;
469 }
470 }
471
472 struct Buffer *tempfile = buf_pool_get();
473 buf_mktemp(tempfile);
474 fp = mutt_file_fopen_masked(buf_string(tempfile), "w+");
475 if (!fp)
476 {
477 buf_pool_release(&tempfile);
478 return NULL;
479 }
480
481 body = mutt_body_new();
482 body->type = TYPE_MESSAGE;
483 body->subtype = mutt_str_dup("rfc822");
484 body->filename = mutt_str_dup(buf_string(tempfile));
485 body->unlink = true;
486 body->use_disp = false;
487 body->disposition = DISP_INLINE;
488 body->noconv = true;
489
490 buf_pool_release(&tempfile);
491
492 struct Message *msg = mx_msg_open(m, e);
493 if (!msg)
494 {
495 mutt_body_free(&body);
497 return NULL;
498 }
500
501 CopyHeaderFlags chflags = CH_XMIT;
502 cmflags = MUTT_CM_NO_FLAGS;
503
504 /* If we are attaching a message, ignore `$mime_forward_decode` */
505 if (!attach_msg && c_mime_forward_decode)
506 {
507 chflags |= CH_MIME | CH_TXTPLAIN;
510 pgp &= ~PGP_ENCRYPT;
512 pgp &= ~SMIME_ENCRYPT;
513 }
514 else if ((WithCrypto != 0) && c_forward_decrypt && (e->security & SEC_ENCRYPT))
515 {
517 {
518 chflags |= CH_MIME | CH_NONEWLINE;
519 cmflags = MUTT_CM_DECODE_PGP;
520 pgp &= ~PGP_ENCRYPT;
521 }
522 else if (((WithCrypto & APPLICATION_PGP) != 0) &&
524 {
525 chflags |= CH_MIME | CH_TXTPLAIN;
527 pgp &= ~PGP_ENCRYPT;
528 }
529 else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
531 {
532 chflags |= CH_MIME | CH_NONEWLINE;
533 cmflags = MUTT_CM_DECODE_SMIME;
534 pgp &= ~SMIME_ENCRYPT;
535 }
536 }
537
538 mutt_copy_message(fp, e, msg, cmflags, chflags, 0);
539 mx_msg_close(m, &msg);
540
541 fflush(fp);
542 rewind(fp);
543
544 body->email = email_new();
545 body->email->offset = 0;
546 /* we don't need the user headers here */
547 body->email->env = mutt_rfc822_read_header(fp, body->email, false, false);
548 if (WithCrypto)
549 body->email->security = pgp;
550 mutt_update_encoding(body, sub);
551 body->parts = body->email->body;
552
554
555 return body;
556}
void mutt_parse_mime_message(struct Email *e, FILE *fp)
Parse a MIME email.
Definition commands.c:627
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_email.c:917
#define CH_XMIT
Transmitting this message? (Ignore Lines: and Content-Length:)
Definition copy_email.h:59
#define MUTT_CM_DECODE_PGP
Used for decoding PGP messages.
Definition copy_email.h:47
#define MUTT_CM_DECODE
Decode the message body into text/plain.
Definition copy_email.h:40
#define CH_NONEWLINE
Don't output terminating newline after the header.
Definition copy_email.h:64
#define MUTT_CM_CHARCONV
Perform character set conversions.
Definition copy_email.h:44
#define MUTT_CM_DECODE_SMIME
Used for decoding S/MIME messages.
Definition copy_email.h:48
#define CH_MIME
Ignore MIME fields.
Definition copy_email.h:65
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition copy_email.h:54
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition copy_email.h:37
#define CH_TXTPLAIN
Generate text/plain MIME headers.
Definition copy_email.h:67
uint16_t CopyMessageFlags
Flags for mutt_copy_message(), e.g. MUTT_CM_NOHEADER.
Definition copy_email.h:36
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition crypt.c:609
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition crypt.c:131
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition crypt.c:443
SecurityFlags mutt_is_application_pgp(const struct Body *b)
Does the message use PGP?
Definition crypt.c:548
struct Email * email_new(void)
Create a new Email.
Definition email.c:77
struct Envelope * mutt_rfc822_read_header(FILE *fp, struct Email *e, bool user_hdrs, bool weed)
Parses an RFC822 header.
Definition parse.c:1210
@ TYPE_MESSAGE
Type: 'message/*'.
Definition mime.h:35
@ DISP_INLINE
Content is inline.
Definition mime.h:62
int mx_msg_close(struct Mailbox *m, struct Message **ptr)
Close a message.
Definition mx.c:1182
struct Message * mx_msg_open(struct Mailbox *m, struct Email *e)
Return a stream pointer for a message.
Definition mx.c:1136
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition lib.h:84
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition lib.h:98
#define PGP_ENCRYPT
Email is PGP encrypted.
Definition lib.h:104
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition lib.h:99
#define SEC_NO_FLAGS
No flags are set.
Definition lib.h:85
#define SEC_ENCRYPT
Email is encrypted.
Definition lib.h:86
#define SMIME_ENCRYPT
Email is S/MIME encrypted.
Definition lib.h:110
#define WithCrypto
Definition lib.h:124
#define mutt_file_fopen_masked(PATH, MODE)
Open a file with proper permissions, tracked for debugging.
Definition neomutt.h:90
struct Body * parts
parts of a multipart or message/rfc822
Definition body.h:73
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:68
bool use_disp
Content-Disposition uses filename= ?
Definition body.h:47
struct Email * email
header information for message/rfc822
Definition body.h:74
unsigned int disposition
content-disposition, ContentDisposition
Definition body.h:42
struct Envelope * env
Envelope information.
Definition email.h:68
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition email.h:43
struct Body * body
List of MIME parts.
Definition email.h:69
LOFF_T offset
Where in the stream does this message begin?
Definition email.h:71
A local copy of an email.
Definition message.h:34
FILE * fp
pointer to the message data
Definition message.h:35
#define buf_mktemp(buf)
Definition tmp.h:33
+ 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 * b,
FILE * fp,
struct ConfigSubset * sub )

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

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

Definition at line 258 of file sendlib.c.

259{
260 struct Buffer *tempfile = buf_pool_get();
261 FILE *fp_in = NULL;
262 FILE *fp_out = NULL;
263 struct stat st = { 0 };
264
265 if (!b->filename && fp)
266 {
267 fp_in = fp;
268 }
269 else if (!b->filename || !(fp_in = mutt_file_fopen(b->filename, "r")))
270 {
271 mutt_error(_("Could not open %s"), b->filename ? b->filename : "(null)");
272 return;
273 }
274 else
275 {
276 b->offset = 0;
277 if (stat(b->filename, &st) == -1)
278 {
279 mutt_perror("stat");
280 mutt_file_fclose(&fp_in);
281 goto cleanup;
282 }
283 b->length = st.st_size;
284 }
285
286 /* Avoid buffer pool due to recursion */
287 buf_mktemp(tempfile);
288 fp_out = mutt_file_fopen(buf_string(tempfile), "w+");
289 if (!fp_out)
290 {
291 mutt_perror("fopen");
292 goto cleanup;
293 }
294
295 if (!mutt_file_seek(fp_in, b->offset, SEEK_SET))
296 {
297 goto cleanup;
298 }
299 b->parts = mutt_rfc822_parse_message(fp_in, b);
300
301 transform_to_7bit(b->parts, fp_in, sub);
302
303 mutt_copy_hdr(fp_in, fp_out, b->offset, b->offset + b->length,
304 CH_MIME | CH_NONEWLINE | CH_XMIT, NULL, 0);
305
306 fputs("MIME-Version: 1.0\n", fp_out);
307 mutt_write_mime_header(b->parts, fp_out, sub);
308 fputc('\n', fp_out);
309 mutt_write_mime_body(b->parts, fp_out, sub);
310
311 if (fp_in != fp)
312 mutt_file_fclose(&fp_in);
313 mutt_file_fclose(&fp_out);
314
315 b->encoding = ENC_7BIT;
316 FREE(&b->d_filename);
317 b->d_filename = b->filename;
318 if (b->filename && b->unlink)
319 unlink(b->filename);
320 b->filename = buf_strdup(tempfile);
321 b->unlink = true;
322 if (stat(b->filename, &st) == -1)
323 {
324 mutt_perror("stat");
325 goto cleanup;
326 }
327 b->length = st.st_size;
329 b->email->body = NULL;
330
331cleanup:
332 if (fp_in && (fp_in != fp))
333 mutt_file_fclose(&fp_in);
334
335 if (fp_out)
336 {
337 mutt_file_fclose(&fp_out);
338 mutt_file_unlink(buf_string(tempfile));
339 }
340
341 buf_pool_release(&tempfile);
342}
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:571
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_email.c:112
struct Body * mutt_rfc822_parse_message(FILE *fp, struct Body *b)
Parse a Message/RFC822 body.
Definition parse.c:1848
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition file.c:652
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition file.c:156
#define mutt_perror(...)
Definition logging2.h:95
@ ENC_7BIT
7-bit text
Definition mime.h:49
int mutt_write_mime_body(struct Body *b, FILE *fp, struct ConfigSubset *sub)
Write a MIME part.
Definition body.c:300
int mutt_write_mime_header(struct Body *b, FILE *fp, struct ConfigSubset *sub)
Create a MIME header.
Definition header.c:757
static void transform_to_7bit(struct Body *b, FILE *fp_in, struct ConfigSubset *sub)
Convert MIME parts to 7-bit.
Definition sendlib.c:195
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 739 of file sendlib.c.

740{
741 if (final)
742 {
743 if (!TAILQ_EMPTY(&env->bcc) && TAILQ_EMPTY(&env->to) && TAILQ_EMPTY(&env->cc))
744 {
745 /* some MTA's will put an Apparently-To: header field showing the Bcc:
746 * recipients if there is no To: or Cc: field, so attempt to suppress
747 * it by using an empty To: field. */
748 struct Address *to = mutt_addr_new();
749 to->group = true;
750 mutt_addrlist_append(&env->to, to);
752
753 char buf[1024] = { 0 };
754 buf[0] = '\0';
755 mutt_addr_cat(buf, sizeof(buf), "undisclosed-recipients", AddressSpecials);
756
757 buf_strcpy(to->mailbox, buf);
758 }
759
760 mutt_set_followup_to(env, sub);
761
762 if (!env->message_id)
763 env->message_id = msgid_generate();
764 }
765
766 /* Take care of 8-bit => 7-bit conversion. */
768 encode_headers(&env->userhdrs, sub);
769}
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:708
struct Address * mutt_addr_new(void)
Create a new Address.
Definition address.c:401
const char AddressSpecials[]
Characters with special meaning for email addresses.
Definition address.c:45
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
char * msgid_generate(void)
Generate a Message-Id.
void rfc2047_encode_envelope(struct Envelope *env)
Encode the fields of an Envelope.
Definition rfc2047.c:861
void mutt_set_followup_to(struct Envelope *env, struct ConfigSubset *sub)
Set followup-to field.
Definition send.c:1272
static void encode_headers(struct ListHead *h, struct ConfigSubset *sub)
RFC2047-encode a list of headers.
Definition sendlib.c:666
bool group
Group mailbox?
Definition address.h:38
struct Buffer * mailbox
Mailbox and host address.
Definition address.h:37
struct ListHead userhdrs
user defined headers
Definition envelope.h:85
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 * b)

Timestamp an Attachment.

Parameters
bAttachment

Definition at line 409 of file sendlib.c.

410{
411 b->stamp = mutt_date_now();
412}
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition date.c:457
time_t stamp
Time stamp of last encoding update.
Definition body.h:77
+ 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 778 of file sendlib.c.

779{
780 struct ListNode *item = NULL;
781 STAILQ_FOREACH(item, &env->userhdrs, entries)
782 {
783 rfc2047_decode(&item->data);
784 }
785
787
788 /* back conversions */
790}
#define STAILQ_FOREACH(var, head, field)
Definition queue.h:390
void rfc2047_decode_envelope(struct Envelope *env)
Decode the fields of an Envelope.
Definition rfc2047.c:836
void rfc2047_decode(char **pd)
Decode any RFC2047-encoded header fields.
Definition rfc2047.c:665
struct AddressList mail_followup_to
Email's 'mail-followup-to'.
Definition envelope.h:65
A List node for strings.
Definition list.h:37
char * data
String.
Definition list.h:38
+ 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 * b,
struct ConfigSubset * sub )

Update the encoding type.

Parameters
bBody to update
subConfig Subset

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

Definition at line 421 of file sendlib.c.

422{
423 struct Content *info = NULL;
424 char chsbuf[256] = { 0 };
425
426 /* override noconv when it's us-ascii */
427 if (mutt_ch_is_us_ascii(mutt_body_get_charset(b, chsbuf, sizeof(chsbuf))))
428 b->noconv = false;
429
430 if (!b->force_charset && !b->noconv)
431 mutt_param_delete(&b->parameter, "charset");
432
433 info = mutt_get_content_info(b->filename, b, sub);
434 if (!info)
435 return;
436
437 set_encoding(b, info, sub);
439
440 FREE(&b->content);
441 b->content = info;
442}
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body's character set.
Definition body.c:133
#define mutt_ch_is_us_ascii(str)
Definition charset.h:108
void mutt_param_delete(struct ParameterList *pl, const char *attribute)
Delete a matching Parameter.
Definition parameter.c:143
static void set_encoding(struct Body *b, struct Content *info, struct ConfigSubset *sub)
Determine which Content-Transfer-Encoding to use.
Definition sendlib.c:350
void mutt_stamp_attachment(struct Body *b)
Timestamp an Attachment.
Definition sendlib.c:409
struct ParameterList parameter
Parameters of the content-type.
Definition body.h:63
struct Content * content
Detailed info about the content of the attachment.
Definition body.h:70
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 1017 of file sendlib.c.

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

966{
967 char fcc_tok[PATH_MAX] = { 0 };
968
969 mutt_str_copy(fcc_tok, path, sizeof(fcc_tok));
970
971 char *tok = strtok(fcc_tok, ",");
972 if (!tok)
973 return -1;
974
975 mutt_debug(LL_DEBUG1, "Fcc: initial mailbox = '%s'\n", tok);
976 /* expand_path already called above for the first token */
977 int status = mutt_write_fcc(tok, e, msgid, post, fcc, finalpath, sub);
978 if (status != 0)
979 return status;
980
981 struct Buffer *fcc_expanded = buf_pool_get();
982 while ((tok = strtok(NULL, ",")))
983 {
984 if (*tok == '\0')
985 continue;
986
987 /* Only call expand_path if tok has some data */
988 mutt_debug(LL_DEBUG1, "Fcc: additional mailbox token = '%s'\n", tok);
989 buf_strcpy(fcc_expanded, tok);
990 expand_path(fcc_expanded, false);
991 mutt_debug(LL_DEBUG1, " Additional mailbox expanded = '%s'\n",
992 buf_string(fcc_expanded));
993 status = mutt_write_fcc(buf_string(fcc_expanded), e, msgid, post, fcc, finalpath, sub);
994 if (status != 0)
995 {
996 buf_pool_release(&fcc_expanded);
997 return status;
998 }
999 }
1000
1001 buf_pool_release(&fcc_expanded);
1002 return 0;
1003}
void expand_path(struct Buffer *buf, bool regex)
Create the canonical path.
Definition muttlib.c:121
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:1017
+ Here is the call graph for this function:
+ Here is the caller graph for this function: