Send an email.
2033{
2035 FILE *fp_tmp = NULL;
2036 struct Body *pbody = NULL;
2037 int i;
2038 bool free_clear_content = false;
2039
2040 struct Body *clear_content = NULL;
2041 char *pgpkeylist = NULL;
2042
2043 char *pgp_sign_as = NULL;
2044 char *smime_sign_as = NULL;
2045 const char *tag = NULL;
2046 char *err = NULL;
2047 char *finalpath = NULL;
2048 struct Email *e_cur = NULL;
2049
2052
2053 int rc = -1;
2054
2057 else
2059
2061
2063 {
2064
2065
2068 return rc;
2069
2072 }
2073
2075 {
2077 {
2080 }
2082 {
2083 const char *
const c_smime_sign_as =
cs_subset_string(sub,
"smime_sign_as");
2085 }
2086 }
2087
2088
2089
2090
2091
2092 if (!e_templ)
2093 {
2095
2097 {
2099 if (rc < 0)
2100 {
2102 goto cleanup;
2103 }
2104 flags = rc;
2105
2106
2108 {
2111 }
2112 else
2113 {
2116 }
2117 }
2118
2120 {
2125 if (!fp_tmp)
2126 {
2128 goto cleanup;
2129 }
2130 }
2131
2134 }
2135
2136
2138 {
2139
2141
2143 }
2144
2146 {
2147
2148
2150 {
2153 e_templ->
body = pbody;
2154
2156 const char *ctype =
mutt_str_dup(c_content_type ? c_content_type :
"text/plain");
2162
2163 if (tempfile)
2164 {
2169 }
2170 else
2171 {
2177 }
2178 }
2179 else
2180 {
2185 }
2186
2187 if (!fp_tmp)
2188 {
2192 goto cleanup;
2193 }
2194 }
2195
2197
2199 {
2200
2201
2202
2203
2204
2205
2207 {
2211 }
2213 }
2214
2215 const bool c_reply_with_xorig =
cs_subset_bool(sub,
"reply_with_xorig");
2217 {
2218
2219
2220
2221
2222
2223
2224
2225
2227 {
2231 }
2232 }
2233
2236
2237 const bool c_resume_draft_files =
cs_subset_bool(sub,
"resume_draft_files");
2240 {
2243 {
2244 goto cleanup;
2245 }
2246
2248 if (c_hdrs)
2250
2251
2253
2256
2258 {
2260 }
2261
2265 if (!(flags &
SEND_BATCH) && !(c_auto_edit && c_edit_headers) &&
2267 {
2269 goto cleanup;
2270 }
2271
2272
2273
2274
2275
2276
2278 if (killfrom)
2279 {
2281 }
2282
2284 {
2285
2287
2288
2289
2290
2292 }
2293
2294
2295
2297
2298
2299
2300
2301
2303
2304
2305 if (killfrom)
2306 {
2308
2312 }
2313
2314 if (c_hdrs)
2316
2318 {
2320 {
2322 goto cleanup;
2323 }
2324 }
2325
2328
2332 {
2334 }
2335
2336
2339 {
2340 goto cleanup;
2341 }
2342
2344 {
2346 }
2347 }
2348
2349
2350
2351
2352
2354 {
2357 {
2359 }
2360 }
2361
2362
2363
2365
2366
2367
2368 {
2371 {
2373 if (c_real_name)
2375 }
2376 }
2377
2380
2382 {
2383 struct stat st = { 0 };
2384 time_t mtime;
2389 if (mtime == (time_t) -1)
2390 {
2392 goto cleanup;
2393 }
2394
2396
2399
2400
2401
2402
2403
2404
2405
2406
2407
2409 (((flags &
SEND_FORWARD) == 0) || (c_edit_headers && c_auto_edit) ||
2411 {
2412
2418 {
2420 goto cleanup;
2421 }
2422 else if (c_edit_headers)
2423 {
2427 }
2428 else
2429 {
2432 {
2433 if (mtime != st.st_mtime)
2435 }
2436 else
2437 {
2439 }
2440 }
2441
2443 }
2444
2446 {
2448 {
2449
2450 if ((mtime == st.st_mtime) && !e_templ->
body->
next &&
2452 {
2454 goto cleanup;
2455 }
2456 }
2457 else
2458 {
2460 }
2461 }
2462 }
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2476 {
2477 bool c_autocrypt = false;
2478 bool c_autocrypt_reply = false;
2479
2480#ifdef USE_AUTOCRYPT
2483#endif
2484
2486 {
2488 }
2489 else
2490 {
2491 const bool c_crypt_auto_sign =
cs_subset_bool(sub,
"crypt_auto_sign");
2492 const bool c_crypt_auto_encrypt =
cs_subset_bool(sub,
"crypt_auto_encrypt");
2493 const bool c_crypt_reply_encrypt =
cs_subset_bool(sub,
"crypt_reply_encrypt");
2494 const bool c_crypt_reply_sign =
cs_subset_bool(sub,
"crypt_reply_sign");
2495 const bool c_crypt_reply_sign_encrypted =
cs_subset_bool(sub,
"crypt_reply_sign_encrypted");
2496
2497 if (c_crypt_auto_sign)
2499 if (c_crypt_auto_encrypt)
2507
2508 const bool c_crypt_opportunistic_encrypt =
cs_subset_bool(sub,
"crypt_opportunistic_encrypt");
2509
2512 {
2513 const bool c_pgp_auto_inline =
cs_subset_bool(sub,
"pgp_auto_inline");
2514 const bool c_pgp_reply_inline =
cs_subset_bool(sub,
"pgp_reply_inline");
2515
2516 if (c_pgp_auto_inline)
2520 }
2521 }
2522
2523 const bool c_crypt_opportunistic_encrypt =
cs_subset_bool(sub,
"crypt_opportunistic_encrypt");
2524
2525 if (e_templ->
security || c_crypt_opportunistic_encrypt)
2526 {
2527 const bool c_crypt_auto_pgp =
cs_subset_bool(sub,
"crypt_auto_pgp");
2528 const bool c_crypt_auto_smime =
cs_subset_bool(sub,
"crypt_auto_smime");
2529
2530
2531
2532
2533
2534
2535
2536
2537 if (e_cur)
2538 {
2541 {
2543 }
2546 {
2548 }
2549 }
2550
2551 const bool c_smime_is_default =
cs_subset_bool(sub,
"smime_is_default");
2552
2553
2554
2556 {
2558 {
2560 }
2562 {
2564 }
2566 {
2568 }
2569 }
2570 }
2571
2572
2573 if (c_crypt_opportunistic_encrypt)
2574 {
2575
2576
2577
2579 {
2582 }
2583 }
2584
2585
2588 }
2589
2590
2591
2592
2594 {
2595 mutt_error(
_(
"No crypto backend configured. Disabling message security setting."));
2597 }
2598
2599
2600
2601
2603
2606 {
2607
2609 if (killfrom)
2610 {
2612 }
2614 if (killfrom)
2615 {
2617 }
2618 }
2619
2621
2623
2625 {
2626 main_loop:
2627
2631 if (i == -1)
2632 {
2633
2636 else
2638 goto cleanup;
2639 }
2640 else if (i == 1)
2641 {
2643 goto main_loop;
2645 rc = 1;
2646 goto cleanup;
2647 }
2648 }
2649
2651 {
2655 {
2657 {
2658 puts(
_(
"No recipients specified"));
2659 goto cleanup;
2660 }
2661
2663 goto main_loop;
2664 }
2665 }
2666
2668 {
2672 goto cleanup;
2673 goto main_loop;
2674 }
2675
2677
2680 {
2681
2684 goto main_loop;
2685 }
2686
2688 {
2690 goto main_loop;
2691 }
2692
2694 {
2696 goto main_loop;
2697 }
2698
2700 {
2701 goto main_loop;
2702 }
2703
2704 const bool c_confirm_empty_to =
cs_subset_bool(sub,
"confirm_empty_to");
2707 {
2708 goto main_loop;
2709 }
2710
2713
2714
2715
2716
2717
2719
2720
2721
2722
2723
2724
2725 clear_content = NULL;
2726 free_clear_content = false;
2727
2729 {
2731 {
2732
2733 clear_content = e_templ->
body;
2734
2737 {
2740
2742
2744
2746 {
2748 rc = -1;
2749 goto cleanup;
2750 }
2751
2752 goto main_loop;
2753 }
2755 }
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765 if (clear_content && (e_templ->
body != clear_content) &&
2766 (e_templ->
body->
parts != clear_content))
2767 free_clear_content = true;
2768 }
2769
2772
2774
2775 const bool c_fcc_before_send =
cs_subset_bool(sub,
"fcc_before_send");
2776 if (c_fcc_before_send)
2777 {
2778 if (
save_fcc(m, e_templ, fcc, clear_content, pgpkeylist, flags, &finalpath, sub) &&
2780 {
2781
2782 puts(
_(
"Fcc failed. Aborting sending."));
2783 goto cleanup;
2784 }
2785 }
2786
2788 if (i < 0)
2789 {
2791 {
2793 ;
2796 {
2797 if (e_templ->
body != clear_content)
2798 {
2800 e_templ->
body = clear_content;
2801 }
2802 }
2804 {
2808 {
2810 }
2811 }
2812
2821 goto main_loop;
2822 }
2823 else
2824 {
2825 puts(
_(
"Could not send the message"));
2826 goto cleanup;
2827 }
2828 }
2829
2830 if (!c_fcc_before_send)
2831 save_fcc(m, e_templ, fcc, clear_content, pgpkeylist, flags, &finalpath, sub);
2832
2834 {
2838#ifdef USE_NOTMUCH
2840 if (c_nm_record)
2842#endif
2844 }
2845
2848
2851
2852
2853
2855 {
2857 {
2858 struct Email **ep = NULL;
2860 {
2861 struct Email *e = *ep;
2863 }
2864 }
2865 }
2866
2867 rc = 0;
2868
2869cleanup:
2871
2873 {
2875 {
2878 }
2880 {
2882 FREE(&smime_sign_as);
2883 }
2884 }
2885
2889
2891 return rc;
2892}
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)