NeoMutt  2025-12-11-58-g09398d
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
 

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

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

879{
880 if (!fp || !e || !to || TAILQ_EMPTY(to))
881 return -1;
882
883 const char *fqdn = mutt_fqdn(true, sub);
884 char *err = NULL;
885
886 struct Address *from = mutt_default_from(sub);
887 struct AddressList from_list = TAILQ_HEAD_INITIALIZER(from_list);
888 mutt_addrlist_append(&from_list, from);
889
890 /* mutt_default_from() does not use $real_name if the real name is not set
891 * in $from, so we add it here. The reason it is not added in
892 * mutt_default_from() is that during normal sending, we execute
893 * send-hooks and set the real_name last so that it can be changed based
894 * upon message criteria. */
895 if (!from->personal)
896 {
897 const char *const c_real_name = cs_subset_string(sub, "real_name");
898 if (c_real_name)
899 from->personal = buf_new(c_real_name);
900 }
901
902 mutt_addrlist_qualify(&from_list, fqdn);
903
904 rfc2047_encode_addrlist(&from_list, "Resent-From");
905 if (mutt_addrlist_to_intl(&from_list, &err))
906 {
907 mutt_error(_("Bad IDN %s while preparing resent-from"), err);
908 FREE(&err);
909 mutt_addrlist_clear(&from_list);
910 return -1;
911 }
912 struct Buffer *resent_from = buf_pool_get();
913 mutt_addrlist_write(&from_list, resent_from, false);
914
915 OptNewsSend = false;
916
917 /* prepare recipient list. idna conversion appears to happen before this
918 * function is called, since the user receives confirmation of the address
919 * list being bounced to. */
920 struct AddressList resent_to = TAILQ_HEAD_INITIALIZER(resent_to);
921 mutt_addrlist_copy(&resent_to, to, false);
922 rfc2047_encode_addrlist(&resent_to, "Resent-To");
923 int rc = bounce_message(fp, m, e, &resent_to, buf_string(resent_from), &from_list, sub);
924 mutt_addrlist_clear(&resent_to);
925 mutt_addrlist_clear(&from_list);
926 buf_pool_release(&resent_from);
927 return rc;
928}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition address.c:765
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:1460
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition address.c:1480
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition address.c:1206
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition address.c:1293
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:65
#define mutt_error(...)
Definition logging2.h:93
#define FREE(x)
Definition memory.h:62
#define _(a)
Definition message.h:28
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:96
#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:766
struct Address * mutt_default_from(struct ConfigSubset *sub)
Get a default 'from' Address.
Definition send.c:1394
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition sendlib.c:707
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:805
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 707 of file sendlib.c.

708{
709 const char *const c_hostname = cs_subset_string(sub, "hostname");
710 if (!c_hostname || (c_hostname[0] == '@'))
711 return NULL;
712
713 const char *p = c_hostname;
714
715 const bool c_hidden_host = cs_subset_bool(sub, "hidden_host");
716 if (may_hide_host && c_hidden_host)
717 {
718 p = strchr(c_hostname, '.');
719 if (p)
720 p++;
721
722 // sanity check: don't hide the host if the fqdn is something like example.com
723 if (!p || !strchr(p, '.'))
724 p = c_hostname;
725 }
726
727 return p;
728}
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 76 of file sendlib.c.

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

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

456{
457 struct Body *body = NULL;
458 FILE *fp = NULL;
459 CopyMessageFlags cmflags;
461
462 const bool c_mime_forward_decode = cs_subset_bool(sub, "mime_forward_decode");
463 const bool c_forward_decrypt = cs_subset_bool(sub, "forward_decrypt");
464 if (WithCrypto)
465 {
466 if ((c_mime_forward_decode || c_forward_decrypt) && (e->security & SEC_ENCRYPT))
467 {
469 return NULL;
470 }
471 }
472
473 struct Buffer *tempfile = buf_pool_get();
474 buf_mktemp(tempfile);
475 fp = mutt_file_fopen_masked(buf_string(tempfile), "w+");
476 if (!fp)
477 {
478 buf_pool_release(&tempfile);
479 return NULL;
480 }
481
482 body = mutt_body_new();
483 body->type = TYPE_MESSAGE;
484 body->subtype = mutt_str_dup("rfc822");
485 body->filename = mutt_str_dup(buf_string(tempfile));
486 body->unlink = true;
487 body->use_disp = false;
488 body->disposition = DISP_INLINE;
489 body->noconv = true;
490
491 buf_pool_release(&tempfile);
492
493 struct Message *msg = mx_msg_open(m, e);
494 if (!msg)
495 {
496 mutt_body_free(&body);
498 return NULL;
499 }
501
502 CopyHeaderFlags chflags = CH_XMIT;
503 cmflags = MUTT_CM_NO_FLAGS;
504
505 /* If we are attaching a message, ignore `$mime_forward_decode` */
506 if (!attach_msg && c_mime_forward_decode)
507 {
508 chflags |= CH_MIME | CH_TXTPLAIN;
511 pgp &= ~PGP_ENCRYPT;
513 pgp &= ~SMIME_ENCRYPT;
514 }
515 else if ((WithCrypto != 0) && c_forward_decrypt && (e->security & SEC_ENCRYPT))
516 {
518 {
519 chflags |= CH_MIME | CH_NONEWLINE;
520 cmflags = MUTT_CM_DECODE_PGP;
521 pgp &= ~PGP_ENCRYPT;
522 }
523 else if (((WithCrypto & APPLICATION_PGP) != 0) &&
525 {
526 chflags |= CH_MIME | CH_TXTPLAIN;
528 pgp &= ~PGP_ENCRYPT;
529 }
530 else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
532 {
533 chflags |= CH_MIME | CH_NONEWLINE;
534 cmflags = MUTT_CM_DECODE_SMIME;
535 pgp &= ~SMIME_ENCRYPT;
536 }
537 }
538
539 mutt_copy_message(fp, e, msg, cmflags, chflags, 0);
540 mx_msg_close(m, &msg);
541
542 fflush(fp);
543 rewind(fp);
544
545 body->email = email_new();
546 body->email->offset = 0;
547 /* we don't need the user headers here */
548 body->email->env = mutt_rfc822_read_header(fp, body->email, false, false);
549 if (WithCrypto)
550 body->email->security = pgp;
551 mutt_update_encoding(body, sub);
552 body->parts = body->email->body;
553
555
556 return body;
557}
void mutt_parse_mime_message(struct Email *e, FILE *fp)
Parse a MIME email.
Definition commands.c:629
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:908
#define CH_XMIT
Transmitting this message? (Ignore Lines: and Content-Length:)
Definition copy.h:57
#define MUTT_CM_DECODE_PGP
Used for decoding PGP messages.
Definition copy.h:47
#define MUTT_CM_DECODE
Decode the message body into text/plain.
Definition copy.h:40
#define CH_NONEWLINE
Don't output terminating newline after the header.
Definition copy.h:62
#define MUTT_CM_CHARCONV
Perform character set conversions.
Definition copy.h:44
#define MUTT_CM_DECODE_SMIME
Used for decoding S/MIME messages.
Definition copy.h:48
#define CH_MIME
Ignore MIME fields.
Definition copy.h:63
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition copy.h:52
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition copy.h:37
#define CH_TXTPLAIN
Generate text/plain MIME headers.
Definition copy.h:65
uint16_t CopyMessageFlags
Flags for mutt_copy_message(), e.g. MUTT_CM_NOHEADER.
Definition copy.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:1204
@ 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:1185
struct Message * mx_msg_open(struct Mailbox *m, struct Email *e)
Return a stream pointer for a message.
Definition mx.c:1139
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition lib.h:82
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition lib.h:96
#define PGP_ENCRYPT
Definition lib.h:102
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition lib.h:97
#define SEC_NO_FLAGS
No flags are set.
Definition lib.h:83
#define SEC_ENCRYPT
Email is encrypted.
Definition lib.h:84
#define SMIME_ENCRYPT
Definition lib.h:108
#define WithCrypto
Definition lib.h:122
#define mutt_file_fopen_masked(PATH, MODE)
Definition neomutt.h:82
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 259 of file sendlib.c.

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

741{
742 if (final)
743 {
744 if (!TAILQ_EMPTY(&env->bcc) && TAILQ_EMPTY(&env->to) && TAILQ_EMPTY(&env->cc))
745 {
746 /* some MTA's will put an Apparently-To: header field showing the Bcc:
747 * recipients if there is no To: or Cc: field, so attempt to suppress
748 * it by using an empty To: field. */
749 struct Address *to = mutt_addr_new();
750 to->group = true;
751 mutt_addrlist_append(&env->to, to);
753
754 char buf[1024] = { 0 };
755 buf[0] = '\0';
756 mutt_addr_cat(buf, sizeof(buf), "undisclosed-recipients", AddressSpecials);
757
758 buf_strcpy(to->mailbox, buf);
759 }
760
761 mutt_set_followup_to(env, sub);
762
763 if (!env->message_id)
764 env->message_id = msgid_generate();
765 }
766
767 /* Take care of 8-bit => 7-bit conversion. */
769 encode_headers(&env->userhdrs, sub);
770}
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:857
void mutt_set_followup_to(struct Envelope *env, struct ConfigSubset *sub)
Set followup-to field.
Definition send.c:1270
static void encode_headers(struct ListHead *h, struct ConfigSubset *sub)
RFC2047-encode a list of headers.
Definition sendlib.c:667
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 410 of file sendlib.c.

411{
412 b->stamp = mutt_date_now();
413}
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition date.c:455
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 779 of file sendlib.c.

780{
781 struct ListNode *item = NULL;
782 STAILQ_FOREACH(item, &env->userhdrs, entries)
783 {
784 rfc2047_decode(&item->data);
785 }
786
788
789 /* back conversions */
791}
#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:832
void rfc2047_decode(char **pd)
Decode any RFC2047-encoded header fields.
Definition rfc2047.c:661
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 422 of file sendlib.c.

423{
424 struct Content *info = NULL;
425 char chsbuf[256] = { 0 };
426
427 /* override noconv when it's us-ascii */
428 if (mutt_ch_is_us_ascii(mutt_body_get_charset(b, chsbuf, sizeof(chsbuf))))
429 b->noconv = false;
430
431 if (!b->force_charset && !b->noconv)
432 mutt_param_delete(&b->parameter, "charset");
433
434 info = mutt_get_content_info(b->filename, b, sub);
435 if (!info)
436 return;
437
438 set_encoding(b, info, sub);
440
441 FREE(&b->content);
442 b->content = info;
443}
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:90
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:351
void mutt_stamp_attachment(struct Body *b)
Timestamp an Attachment.
Definition sendlib.c:410
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 1018 of file sendlib.c.

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

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