Send an email.
2029{
2031 FILE *fp_tmp = NULL;
2032 struct Body *pbody = NULL;
2033 int i;
2034 bool free_clear_content = false;
2035
2036 struct Body *clear_content = NULL;
2037 char *pgpkeylist = NULL;
2038
2039 char *pgp_sign_as = NULL;
2040 char *smime_sign_as = NULL;
2041 const char *tag = NULL;
2042 char *err = NULL;
2043 const char *ctype = NULL;
2044 char *finalpath = NULL;
2045 struct Email *e_cur = NULL;
2046
2049
2050 int rc = -1;
2051
2054 else
2056
2058
2060 {
2061
2062
2065 return rc;
2066
2069 }
2070
2072 {
2074 {
2077 }
2079 {
2080 const char *
const c_smime_sign_as =
cs_subset_string(sub,
"smime_sign_as");
2082 }
2083 }
2084
2085
2086
2087
2088
2089 if (!e_templ)
2090 {
2092
2094 {
2096 if (rc < 0)
2097 {
2099 goto cleanup;
2100 }
2101 flags = rc;
2102
2103
2105 {
2108 }
2109 else
2110 {
2113 }
2114 }
2115
2117 {
2122 if (!fp_tmp)
2123 {
2125 goto cleanup;
2126 }
2127 }
2128
2131 }
2132
2133
2135 {
2136
2138
2140 }
2141
2143 {
2144
2145
2147 {
2150 e_templ->
body = pbody;
2151
2153 ctype = c_content_type;
2154 if (!ctype)
2155 ctype = "text/plain";
2160
2161 if (tempfile)
2162 {
2167 }
2168 else
2169 {
2175 }
2176 }
2177 else
2178 {
2183 }
2184
2185 if (!fp_tmp)
2186 {
2190 goto cleanup;
2191 }
2192 }
2193
2195
2197 {
2198
2199
2200
2201
2202
2203
2205 {
2209 }
2211 }
2212
2213 const bool c_reply_with_xorig =
cs_subset_bool(sub,
"reply_with_xorig");
2215 {
2216
2217
2218
2219
2220
2221
2222
2223
2225 {
2229 }
2230 }
2231
2234
2235 const bool c_resume_draft_files =
cs_subset_bool(sub,
"resume_draft_files");
2238 {
2241 {
2242 goto cleanup;
2243 }
2244
2246 if (c_hdrs)
2248
2249
2251
2254
2256 {
2258 }
2259
2263 if (!(flags &
SEND_BATCH) && !(c_auto_edit && c_edit_headers) &&
2265 {
2267 goto cleanup;
2268 }
2269
2270
2271
2272
2273
2274
2276 if (killfrom)
2277 {
2279 }
2280
2282 {
2283
2285
2286
2287
2288
2290 }
2291
2292
2293
2295
2296
2297
2298
2299
2301
2302
2303 if (killfrom)
2304 {
2306
2310 }
2311
2312 if (c_hdrs)
2314
2316 {
2318 {
2320 goto cleanup;
2321 }
2322 }
2323
2326
2330 {
2332 }
2333
2334
2337 {
2338 goto cleanup;
2339 }
2340
2342 {
2344 }
2345 }
2346
2347
2348
2349
2350
2352 {
2355 {
2357 }
2358 }
2359
2360
2361
2363
2364
2365
2366 {
2369 {
2371 if (c_real_name)
2373 }
2374 }
2375
2378
2380 {
2381 struct stat st = { 0 };
2382 time_t mtime;
2387 if (mtime == (time_t) -1)
2388 {
2390 goto cleanup;
2391 }
2392
2394
2397
2398
2399
2400
2401
2402
2403
2404
2405
2407 (((flags &
SEND_FORWARD) == 0) || (c_edit_headers && c_auto_edit) ||
2409 {
2410
2416 {
2418 goto cleanup;
2419 }
2420 else if (c_edit_headers)
2421 {
2425 }
2426 else
2427 {
2430 {
2431 if (mtime != st.st_mtime)
2433 }
2434 else
2435 {
2437 }
2438 }
2439
2441 }
2442
2444 {
2446 {
2447
2448 if ((mtime == st.st_mtime) && !e_templ->
body->
next &&
2450 {
2452 goto cleanup;
2453 }
2454 }
2455 else
2456 {
2458 }
2459 }
2460 }
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2474 {
2475 bool c_autocrypt = false;
2476 bool c_autocrypt_reply = false;
2477
2478#ifdef USE_AUTOCRYPT
2481#endif
2482
2484 {
2486 }
2487 else
2488 {
2489 const bool c_crypt_auto_sign =
cs_subset_bool(sub,
"crypt_auto_sign");
2490 const bool c_crypt_auto_encrypt =
cs_subset_bool(sub,
"crypt_auto_encrypt");
2491 const bool c_crypt_reply_encrypt =
cs_subset_bool(sub,
"crypt_reply_encrypt");
2492 const bool c_crypt_reply_sign =
cs_subset_bool(sub,
"crypt_reply_sign");
2493 const bool c_crypt_reply_sign_encrypted =
cs_subset_bool(sub,
"crypt_reply_sign_encrypted");
2494
2495 if (c_crypt_auto_sign)
2497 if (c_crypt_auto_encrypt)
2505
2506 const bool c_crypt_opportunistic_encrypt =
cs_subset_bool(sub,
"crypt_opportunistic_encrypt");
2507
2510 {
2511 const bool c_pgp_auto_inline =
cs_subset_bool(sub,
"pgp_auto_inline");
2512 const bool c_pgp_reply_inline =
cs_subset_bool(sub,
"pgp_reply_inline");
2513
2514 if (c_pgp_auto_inline)
2518 }
2519 }
2520
2521 const bool c_crypt_opportunistic_encrypt =
cs_subset_bool(sub,
"crypt_opportunistic_encrypt");
2522
2523 if (e_templ->
security || c_crypt_opportunistic_encrypt)
2524 {
2525 const bool c_crypt_auto_pgp =
cs_subset_bool(sub,
"crypt_auto_pgp");
2526 const bool c_crypt_auto_smime =
cs_subset_bool(sub,
"crypt_auto_smime");
2527
2528
2529
2530
2531
2532
2533
2534
2535 if (e_cur)
2536 {
2539 {
2541 }
2544 {
2546 }
2547 }
2548
2549 const bool c_smime_is_default =
cs_subset_bool(sub,
"smime_is_default");
2550
2551
2552
2554 {
2556 {
2558 }
2560 {
2562 }
2564 {
2566 }
2567 }
2568 }
2569
2570
2571 if (c_crypt_opportunistic_encrypt)
2572 {
2573
2574
2575
2577 {
2580 }
2581 }
2582
2583
2586 }
2587
2588
2589
2590
2592 {
2593 mutt_error(
_(
"No crypto backend configured. Disabling message security setting."));
2595 }
2596
2597
2598
2599
2601
2604 {
2605
2607 if (killfrom)
2608 {
2610 }
2612 if (killfrom)
2613 {
2615 }
2616 }
2617
2619
2621
2623 {
2624 main_loop:
2625
2629 if (i == -1)
2630 {
2631
2634 else
2636 goto cleanup;
2637 }
2638 else if (i == 1)
2639 {
2641 goto main_loop;
2643 rc = 1;
2644 goto cleanup;
2645 }
2646 }
2647
2649 {
2653 {
2655 {
2656 puts(
_(
"No recipients specified"));
2657 goto cleanup;
2658 }
2659
2661 goto main_loop;
2662 }
2663 }
2664
2666 {
2670 goto cleanup;
2671 goto main_loop;
2672 }
2673
2675
2678 {
2679
2682 goto main_loop;
2683 }
2684
2686 {
2688 goto main_loop;
2689 }
2690
2692 {
2694 goto main_loop;
2695 }
2696
2698 {
2699 goto main_loop;
2700 }
2701
2702 const bool c_confirm_empty_to =
cs_subset_bool(sub,
"confirm_empty_to");
2705 {
2706 goto main_loop;
2707 }
2708
2711
2712
2713
2714
2715
2717
2718
2719
2720
2721
2722
2723 clear_content = NULL;
2724 free_clear_content = false;
2725
2727 {
2729 {
2730
2731 clear_content = e_templ->
body;
2732
2735 {
2738
2740
2742
2744 {
2746 rc = -1;
2747 goto cleanup;
2748 }
2749
2750 goto main_loop;
2751 }
2753 }
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763 if (clear_content && (e_templ->
body != clear_content) &&
2764 (e_templ->
body->
parts != clear_content))
2765 free_clear_content = true;
2766 }
2767
2770
2772
2773 const bool c_fcc_before_send =
cs_subset_bool(sub,
"fcc_before_send");
2774 if (c_fcc_before_send)
2775 save_fcc(m, e_templ, fcc, clear_content, pgpkeylist, flags, &finalpath, sub);
2776
2778 if (i < 0)
2779 {
2781 {
2783 ;
2786 {
2787 if (e_templ->
body != clear_content)
2788 {
2790 e_templ->
body = clear_content;
2791 }
2792 }
2794 {
2798 {
2800 }
2801 }
2802
2811 goto main_loop;
2812 }
2813 else
2814 {
2815 puts(
_(
"Could not send the message"));
2816 goto cleanup;
2817 }
2818 }
2819
2820 if (!c_fcc_before_send)
2821 save_fcc(m, e_templ, fcc, clear_content, pgpkeylist, flags, &finalpath, sub);
2822
2824 {
2828#ifdef USE_NOTMUCH
2830 if (c_nm_record)
2832#endif
2834 }
2835
2838
2841
2842
2843
2845 {
2847 {
2848 struct Email **ep = NULL;
2850 {
2851 struct Email *e = *ep;
2853 }
2854 }
2855 }
2856
2857 rc = 0;
2858
2859cleanup:
2861
2863 {
2865 {
2868 }
2870 {
2872 FREE(&smime_sign_as);
2873 }
2874 }
2875
2879
2881 return rc;
2882}
int mutt_addrlist_count_recips(const struct AddressList *al)
Count the number of Addresses with valid recipients.
void mutt_expand_aliases_env(struct Envelope *env)
Expand aliases in all the fields of an Envelope.
struct Buffer * buf_new(const char *str)
Allocate a new Buffer.
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
@ CMD_SEND_HOOK
:send-hook
@ CMD_SEND2_HOOK
:send2-hook
@ CMD_REPLY_HOOK
:reply-hook
#define MUTT_COMPOSE_NOFREEHEADER
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
int crypt_get_keys(struct Email *e, char **keylist, bool oppenc_mode)
Check we have all the keys we need.
bool crypt_has_module_backend(SecurityFlags type)
Is there a crypto backend for a given type?
void mutt_edit_file(const char *editor, const char *file)
Let the user edit a file.
struct Body * mutt_body_new(void)
Create a new Body.
void mutt_parse_content_type(const char *s, struct Body *b)
Parse a content type.
bool mutt_parse_mailto(struct Envelope *env, char **body, const char *src)
Parse a mailto:// url.
struct Envelope * mutt_env_new(void)
Create a new Envelope.
void mutt_env_to_local(struct Envelope *env)
Convert an Envelope's Address fields to local format.
char * msgid_generate(void)
Generate a Message-Id.
time_t mutt_file_decrease_mtime(const char *fp, struct stat *st)
Decrease a file's modification time by 1 second.
void mutt_set_flag(struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool upd_mbox)
Set a flag on an email.
bool OptGui
(pseudo) when the gui (and curses) are started
int dlg_compose(struct Email *e, struct Buffer *fcc, uint8_t flags, struct ConfigSubset *sub)
Allow the user to edit the message envelope -.
#define mutt_debug(LEVEL,...)
@ LL_DEBUG5
Log at debug level 5.
@ LL_DEBUG1
Log at debug level 1.
@ DISP_INLINE
Content is inline.
@ MUTT_REPLIED
Messages that have been replied to.
bool mutt_edit_attachment(struct Body *b)
Edit an attachment.
void mutt_sleep(short s)
Sleep for a while.
void buf_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
bool mutt_needs_mailcap(struct Body *b)
Does this type need a mailcap entry do display.
#define SEC_INLINE
Email has an inline signature.
#define SEC_NO_FLAGS
No flags are set.
#define SEC_AUTOCRYPT_OVERRIDE
(Autocrypt) Indicates manual set/unset of encryption
int nm_record_message(struct Mailbox *m, char *path, struct Email *e)
Add a message to the Notmuch database.
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
int mutt_num_postponed(struct Mailbox *m, bool force)
Return the number of postponed messages.
int mutt_get_postponed(struct Mailbox *m_cur, struct Email *hdr, struct Email **cur, struct Buffer *fcc)
Recall a postponed message.
enum QuadOption query_yesorno(const char *prompt, enum QuadOption def)
Ask the user a Yes/No question.
void mutt_rfc3676_space_stuff(struct Email *e)
Perform RFC3676 space stuffing on an Email.
void mutt_select_fcc(struct Buffer *path, struct Email *e)
Select the FCC path for an email.
static int postpone_message(struct Email *e_post, struct Email *e_cur, const char *fcc, SendFlags flags, struct ConfigSubset *sub)
Save an Email for another day.
static bool is_reply(struct Email *reply, struct Email *orig)
Is one email a reply to another?
static int save_fcc(struct Mailbox *m, struct Email *e, struct Buffer *fcc, struct Body *clear_content, char *pgpkeylist, SendFlags flags, char **finalpath, struct ConfigSubset *sub)
Save an Email to a 'sent mail' folder.
static int envelope_defaults(struct Envelope *env, struct EmailArray *ea, SendFlags flags, struct ConfigSubset *sub)
Fill in some defaults for a new email.
void mutt_fix_reply_recipients(struct Envelope *env, struct ConfigSubset *sub)
Remove duplicate recipients.
static int generate_body(FILE *fp_tmp, struct Email *e, SendFlags flags, struct Mailbox *m, struct EmailArray *ea, struct ConfigSubset *sub)
Create a new email body.
static void mutt_make_greeting(struct Email *e, FILE *fp_out, struct ConfigSubset *sub)
Add greetings string.
static int invoke_mta(struct Mailbox *m, struct Email *e, struct ConfigSubset *sub)
Send an email.
static void process_user_recips(struct Envelope *env)
Process the user headers.
static void process_user_header(struct Envelope *env)
Process the user headers.
static int edit_envelope(struct Envelope *en, SendFlags flags, struct ConfigSubset *sub)
Edit Envelope fields.
static bool abort_for_missing_attachments(const struct Body *b, struct ConfigSubset *sub)
Should we abort sending because of missing attachments?
static void set_reverse_name(struct AddressList *al, struct Envelope *env, struct ConfigSubset *sub)
Try to set the 'from' field from the recipients.
static void fix_end_of_file(const char *data)
Ensure a file ends with a linefeed.
static void append_signature(FILE *fp, struct ConfigSubset *sub)
Append a signature to an email.
#define SEND_POSTPONED_FCC
Used by mutt_get_postponed() to signal that the Mutt-Fcc header field was present.
#define SEND_NO_FREE_HEADER
Used by the -E flag.
#define SEND_DRAFT_FILE
Used by the -H flag.
#define SEND_POSTPONED
Recall a postponed email.
#define SEND_CONSUMED_STDIN
stdin has been read; don't read it twice
#define SEND_CLI_CRYPTO
Enable message security in modes that by default don't enable it.
void mutt_update_encoding(struct Body *b, struct ConfigSubset *sub)
Update the encoding type.
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
bool use_disp
Content-Disposition uses filename= ?
unsigned int disposition
content-disposition, ContentDisposition
bool replied
Email has been replied to.
struct AddressList x_original_to
Email's 'X-Original-to'.
char * list_post
This stores a mailto URL, or nothing.
enum MailboxType type
Mailbox type.
void * mdata
Driver specific data.
NNTP-specific Mailbox data -.
int cs_subset_str_string_set(const struct ConfigSubset *sub, const char *name, const char *value, struct Buffer *err)
Set a config item by string.