Send an email.
2037{
2039 FILE *fp_tmp = NULL;
2040 struct Body *pbody = NULL;
2041 int i;
2042 bool free_clear_content = false;
2043
2044 struct Body *clear_content = NULL;
2045 char *pgpkeylist = NULL;
2046
2047 char *pgp_sign_as = NULL;
2048 char *smime_sign_as = NULL;
2049 const char *tag = NULL;
2050 char *err = NULL;
2051 char *finalpath = NULL;
2052 struct Email *e_cur = NULL;
2053
2056
2057 int rc = -1;
2058
2061 else
2063
2065
2067 {
2068
2069
2072 return rc;
2073
2076 }
2077
2079 {
2081 {
2084 }
2086 {
2087 const char *
const c_smime_sign_as =
cs_subset_string(sub,
"smime_sign_as");
2089 }
2090 }
2091
2092
2093
2094
2095
2096 if (!e_templ)
2097 {
2099
2101 {
2103 if (rc < 0)
2104 {
2106 goto cleanup;
2107 }
2108 flags = rc;
2109
2110
2112 {
2115 }
2116 else
2117 {
2120 }
2121 }
2122
2124 {
2129 if (!fp_tmp)
2130 {
2132 goto cleanup;
2133 }
2134 }
2135
2138 }
2139
2140
2142 {
2143
2145
2147 }
2148
2150 {
2151
2152
2154 {
2157 e_templ->
body = pbody;
2158
2160 const char *ctype =
mutt_str_dup(c_content_type ? c_content_type :
"text/plain");
2166
2167 if (tempfile)
2168 {
2173 }
2174 else
2175 {
2181 }
2182 }
2183 else
2184 {
2189 }
2190
2191 if (!fp_tmp)
2192 {
2196 goto cleanup;
2197 }
2198 }
2199
2201
2203 {
2204
2205
2206
2207
2208
2209
2211 {
2215 }
2217 }
2218
2219 const bool c_reply_with_xorig =
cs_subset_bool(sub,
"reply_with_xorig");
2221 {
2222
2223
2224
2225
2226
2227
2228
2229
2231 {
2235 }
2236 }
2237
2240
2241 const bool c_resume_draft_files =
cs_subset_bool(sub,
"resume_draft_files");
2244 {
2247 {
2248 goto cleanup;
2249 }
2250
2252 if (c_hdrs)
2254
2255
2257
2260
2262 {
2264 }
2265
2269 if (!(flags &
SEND_BATCH) && !(c_auto_edit && c_edit_headers) &&
2271 {
2273 goto cleanup;
2274 }
2275
2276
2277
2278
2279
2280
2282 if (killfrom)
2283 {
2285 }
2286
2288 {
2289
2291
2292
2293
2294
2296 }
2297
2298
2299
2301
2302
2303
2304
2305
2307
2308
2309 if (killfrom)
2310 {
2312
2316 }
2317
2318 if (c_hdrs)
2320
2322 {
2324 {
2326 goto cleanup;
2327 }
2328 }
2329
2332
2336 {
2338 }
2339
2340
2343 {
2344 goto cleanup;
2345 }
2346
2348 {
2350 }
2351 }
2352
2353
2354
2355
2356
2358 {
2361 {
2363 }
2364 }
2365
2366
2367
2369
2370
2371
2372 {
2375 {
2377 if (c_real_name)
2379 }
2380 }
2381
2384
2386 {
2387 struct stat st = { 0 };
2388 time_t mtime;
2393 if (mtime == (time_t) -1)
2394 {
2396 goto cleanup;
2397 }
2398
2400
2403
2404
2405
2406
2407
2408
2409
2410
2411
2413 (((flags &
SEND_FORWARD) == 0) || (c_edit_headers && c_auto_edit) ||
2415 {
2416
2422 {
2424 goto cleanup;
2425 }
2426 else if (c_edit_headers)
2427 {
2431 }
2432 else
2433 {
2436 {
2437 if (mtime != st.st_mtime)
2439 }
2440 else
2441 {
2443 }
2444 }
2445
2447 }
2448
2450 {
2452 {
2453
2454 if ((mtime == st.st_mtime) && !e_templ->
body->
next &&
2456 {
2458 goto cleanup;
2459 }
2460 }
2461 else
2462 {
2464 }
2465 }
2466 }
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2480 {
2481 bool c_autocrypt = false;
2482 bool c_autocrypt_reply = false;
2483
2484#ifdef USE_AUTOCRYPT
2487#endif
2488
2490 {
2492 }
2493 else
2494 {
2495 const bool c_crypt_auto_sign =
cs_subset_bool(sub,
"crypt_auto_sign");
2496 const bool c_crypt_auto_encrypt =
cs_subset_bool(sub,
"crypt_auto_encrypt");
2497 const bool c_crypt_reply_encrypt =
cs_subset_bool(sub,
"crypt_reply_encrypt");
2498 const bool c_crypt_reply_sign =
cs_subset_bool(sub,
"crypt_reply_sign");
2499 const bool c_crypt_reply_sign_encrypted =
cs_subset_bool(sub,
"crypt_reply_sign_encrypted");
2500
2501 if (c_crypt_auto_sign)
2503 if (c_crypt_auto_encrypt)
2511
2512 const bool c_crypt_opportunistic_encrypt =
cs_subset_bool(sub,
"crypt_opportunistic_encrypt");
2513
2516 {
2517 const bool c_pgp_auto_inline =
cs_subset_bool(sub,
"pgp_auto_inline");
2518 const bool c_pgp_reply_inline =
cs_subset_bool(sub,
"pgp_reply_inline");
2519
2520 if (c_pgp_auto_inline)
2524 }
2525 }
2526
2527 const bool c_crypt_opportunistic_encrypt =
cs_subset_bool(sub,
"crypt_opportunistic_encrypt");
2528
2529 if (e_templ->
security || c_crypt_opportunistic_encrypt)
2530 {
2531 const bool c_crypt_auto_pgp =
cs_subset_bool(sub,
"crypt_auto_pgp");
2532 const bool c_crypt_auto_smime =
cs_subset_bool(sub,
"crypt_auto_smime");
2533
2534
2535
2536
2537
2538
2539
2540
2541 if (e_cur)
2542 {
2545 {
2547 }
2550 {
2552 }
2553 }
2554
2555 const bool c_smime_is_default =
cs_subset_bool(sub,
"smime_is_default");
2556
2557
2558
2560 {
2562 {
2564 }
2566 {
2568 }
2570 {
2572 }
2573 }
2574 }
2575
2576
2577 if (c_crypt_opportunistic_encrypt)
2578 {
2579
2580
2581
2583 {
2586 }
2587 }
2588
2589
2592 }
2593
2594
2595
2596
2598 {
2599 mutt_error(
_(
"No crypto backend configured. Disabling message security setting."));
2601 }
2602
2603
2604
2605
2607
2610 {
2611
2613 if (killfrom)
2614 {
2616 }
2618 if (killfrom)
2619 {
2621 }
2622 }
2623
2625
2627
2629 {
2630 main_loop:
2631
2635 if (i == -1)
2636 {
2637
2640 else
2642 goto cleanup;
2643 }
2644 else if (i == 1)
2645 {
2647 goto main_loop;
2649 rc = 1;
2650 goto cleanup;
2651 }
2652 }
2653
2655 {
2659 {
2661 {
2662 puts(
_(
"No recipients specified"));
2663 goto cleanup;
2664 }
2665
2667 goto main_loop;
2668 }
2669 }
2670
2672 {
2676 goto cleanup;
2677 goto main_loop;
2678 }
2679
2681
2684 {
2685
2688 goto main_loop;
2689 }
2690
2692 {
2694 goto main_loop;
2695 }
2696
2698 {
2700 goto main_loop;
2701 }
2702
2704 {
2705 goto main_loop;
2706 }
2707
2708 const bool c_confirm_empty_to =
cs_subset_bool(sub,
"confirm_empty_to");
2711 {
2712 goto main_loop;
2713 }
2714
2717
2718
2719
2720
2721
2723
2724
2725
2726
2727
2728
2729 clear_content = NULL;
2730 free_clear_content = false;
2731
2733 {
2735 {
2736
2737 clear_content = e_templ->
body;
2738
2741 {
2744
2746
2748
2750 {
2752 rc = -1;
2753 goto cleanup;
2754 }
2755
2756 goto main_loop;
2757 }
2759 }
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769 if (clear_content && (e_templ->
body != clear_content) &&
2770 (e_templ->
body->
parts != clear_content))
2771 free_clear_content = true;
2772 }
2773
2776
2778
2779 const bool c_fcc_before_send =
cs_subset_bool(sub,
"fcc_before_send");
2780 if (c_fcc_before_send)
2781 {
2782 if (
save_fcc(m, e_templ, fcc, clear_content, pgpkeylist, flags, &finalpath, sub) &&
2784 {
2785
2786 puts(
_(
"Fcc failed. Aborting sending."));
2787 goto cleanup;
2788 }
2789 }
2790
2792 if (i < 0)
2793 {
2795 {
2797 ;
2800 {
2801 if (e_templ->
body != clear_content)
2802 {
2804 e_templ->
body = clear_content;
2805 }
2806 }
2808 {
2812 {
2814 }
2815 }
2816
2825 goto main_loop;
2826 }
2827 else
2828 {
2829 puts(
_(
"Could not send the message"));
2830 goto cleanup;
2831 }
2832 }
2833
2834 if (!c_fcc_before_send)
2835 save_fcc(m, e_templ, fcc, clear_content, pgpkeylist, flags, &finalpath, sub);
2836
2838 {
2842#ifdef USE_NOTMUCH
2844 if (c_nm_record)
2846#endif
2848 }
2849
2852
2855
2856
2857
2859 {
2861 {
2862 struct Email **ep = NULL;
2864 {
2865 struct Email *e = *ep;
2867 }
2868 }
2869 }
2870
2871 rc = 0;
2872
2873cleanup:
2875
2877 {
2879 {
2882 }
2884 {
2886 FREE(&smime_sign_as);
2887 }
2888 }
2889
2893
2895 return rc;
2896}
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
Don't free the header when closing compose dialog.
@ 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,...)
void mutt_select_fcc(struct Buffer *path, struct Email *e)
Select the FCC path for an email.
@ 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 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.
@ SEC_NONE
No flags are set.
@ SEC_INLINE
Email has an inline signature.
@ 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.
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.
@ SEND_CONSUMED_STDIN
stdin has been read; don't read it twice
@ SEND_NO_FREE_HEADER
Used by the -E flag.
@ SEND_CLI_CRYPTO
Enable message security in modes that by default don't enable it.
@ SEND_DRAFT_FILE
Used by the -H flag.
@ SEND_POSTPONED_FCC
Used by mutt_get_postponed() to signal that the Mutt-Fcc header field was present.
@ SEND_POSTPONED
Recall a postponed email.
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.
#define buf_mktemp_draft(buf)