Send an email.
2101{
2103 FILE *fp_tmp = NULL;
2104 struct Body *pbody = NULL;
2105 int i;
2106 bool free_clear_content = false;
2107
2108 struct Body *clear_content = NULL;
2109 char *pgpkeylist = NULL;
2110
2111 char *pgp_sign_as = NULL;
2112 char *smime_sign_as = NULL;
2113 const char *tag = NULL;
2114 char *err = NULL;
2115 const char *ctype = NULL;
2116 char *finalpath = NULL;
2117 struct Email *e_cur = NULL;
2118
2121
2122 int rc = -1;
2123
2126 else
2128
2130
2132 {
2133
2134
2137 return rc;
2138
2141 }
2142
2144 {
2146 {
2149 }
2151 {
2152 const char *
const c_smime_sign_as =
cs_subset_string(sub,
"smime_sign_as");
2154 }
2155 }
2156
2157
2158
2159
2160
2161 if (!e_templ)
2162 {
2164
2166 {
2168 if (rc < 0)
2169 {
2171 goto cleanup;
2172 }
2173 flags = rc;
2174
2175
2177 {
2180 }
2181 else
2182 {
2183 flags &= ~SEND_NEWS;
2185 }
2186 }
2187
2189 {
2194 if (!fp_tmp)
2195 {
2197 goto cleanup;
2198 }
2199 }
2200
2203 }
2204
2205
2207 {
2208
2210
2212 }
2213
2215 {
2216
2217
2219 {
2222 e_templ->
body = pbody;
2223
2225 ctype = c_content_type;
2226 if (!ctype)
2227 ctype = "text/plain";
2232
2233 if (tempfile)
2234 {
2239 }
2240 else
2241 {
2247 }
2248 }
2249 else
2250 {
2255 }
2256
2257 if (!fp_tmp)
2258 {
2262 goto cleanup;
2263 }
2264 }
2265
2267
2269 {
2270
2271
2272
2273
2274
2275
2277 {
2281 }
2283 }
2284
2285 const bool c_reply_with_xorig =
cs_subset_bool(sub,
"reply_with_xorig");
2287 {
2288
2289
2290
2291
2292
2293
2294
2295
2297 {
2301 }
2302 }
2303
2304 const bool c_resume_draft_files =
cs_subset_bool(sub,
"resume_draft_files");
2307 {
2310 {
2311 goto cleanup;
2312 }
2313
2315 if (c_hdrs)
2317
2318
2320
2323
2325 {
2327 }
2328
2332 if (!(flags &
SEND_BATCH) && !(c_auto_edit && c_edit_headers) &&
2334 {
2336 goto cleanup;
2337 }
2338
2339
2340
2341
2342
2343
2345 if (killfrom)
2346 {
2348 }
2349
2351 {
2352
2354
2355
2356
2357
2359 }
2360
2361
2362
2364
2365
2366
2367
2368
2370
2371
2372 if (killfrom)
2373 {
2375
2379 }
2380
2381 if (c_hdrs)
2383
2385 {
2387 {
2389 goto cleanup;
2390 }
2391 }
2392
2395
2399 {
2401 }
2402
2403
2406 {
2407 goto cleanup;
2408 }
2409
2411 {
2413 }
2414 }
2415
2416
2417
2418
2419
2421 {
2424 {
2426 }
2427 }
2428
2429
2430
2432
2433
2434
2435 {
2438 {
2440 if (c_real_name)
2442 }
2443 }
2444
2447
2449 {
2450 struct stat st = { 0 };
2451 time_t mtime;
2456 if (mtime == (time_t) -1)
2457 {
2459 goto cleanup;
2460 }
2461
2463
2466
2467
2468
2469
2470
2471
2472
2473
2474
2476 (((flags &
SEND_FORWARD) == 0) || (c_edit_headers && c_auto_edit) ||
2478 {
2479
2485 {
2487 goto cleanup;
2488 }
2489 else if (c_edit_headers)
2490 {
2494 }
2495 else
2496 {
2499 {
2500 if (mtime != st.st_mtime)
2502 }
2503 else
2504 {
2506 }
2507 }
2508
2510 }
2511
2513 {
2515 {
2516
2517 if ((mtime == st.st_mtime) && !e_templ->
body->
next &&
2519 {
2521 goto cleanup;
2522 }
2523 }
2524 else
2525 {
2527 }
2528 }
2529 }
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2543 {
2544 bool c_autocrypt = false;
2545 bool c_autocrypt_reply = false;
2546
2547#ifdef USE_AUTOCRYPT
2550#endif
2551
2553 {
2555 }
2556 else
2557 {
2558 const bool c_crypt_auto_sign =
cs_subset_bool(sub,
"crypt_auto_sign");
2559 const bool c_crypt_auto_encrypt =
cs_subset_bool(sub,
"crypt_auto_encrypt");
2560 const bool c_crypt_reply_encrypt =
cs_subset_bool(sub,
"crypt_reply_encrypt");
2561 const bool c_crypt_reply_sign =
cs_subset_bool(sub,
"crypt_reply_sign");
2562 const bool c_crypt_reply_sign_encrypted =
cs_subset_bool(sub,
"crypt_reply_sign_encrypted");
2563
2564 if (c_crypt_auto_sign)
2566 if (c_crypt_auto_encrypt)
2574
2575 const bool c_crypt_opportunistic_encrypt =
cs_subset_bool(sub,
"crypt_opportunistic_encrypt");
2576
2579 {
2580 const bool c_pgp_auto_inline =
cs_subset_bool(sub,
"pgp_auto_inline");
2581 const bool c_pgp_reply_inline =
cs_subset_bool(sub,
"pgp_reply_inline");
2582
2583 if (c_pgp_auto_inline)
2587 }
2588 }
2589
2590 const bool c_crypt_opportunistic_encrypt =
cs_subset_bool(sub,
"crypt_opportunistic_encrypt");
2591
2592 if (e_templ->
security || c_crypt_opportunistic_encrypt)
2593 {
2594 const bool c_crypt_auto_pgp =
cs_subset_bool(sub,
"crypt_auto_pgp");
2595 const bool c_crypt_auto_smime =
cs_subset_bool(sub,
"crypt_auto_smime");
2596
2597
2598
2599
2600
2601
2602
2603
2604 if (e_cur)
2605 {
2608 {
2610 }
2613 {
2615 }
2616 }
2617
2618 const bool c_smime_is_default =
cs_subset_bool(sub,
"smime_is_default");
2619
2620
2621
2623 {
2625 {
2627 }
2629 {
2631 }
2633 {
2635 }
2636 }
2637 }
2638
2639
2640 if (c_crypt_opportunistic_encrypt)
2641 {
2642
2643
2644
2646 {
2649 }
2650 }
2651
2652
2655 }
2656
2657
2658
2659
2661 {
2662 mutt_error(
_(
"No crypto backend configured. Disabling message security setting."));
2664 }
2665
2666
2667
2668
2670
2673 {
2674
2676 if (killfrom)
2677 {
2679 }
2681 if (killfrom)
2682 {
2684 }
2685 }
2686
2688
2690
2692 {
2693 main_loop:
2694
2698 if (i == -1)
2699 {
2700
2703 else
2705 goto cleanup;
2706 }
2707 else if (i == 1)
2708 {
2710 goto main_loop;
2712 rc = 1;
2713 goto cleanup;
2714 }
2715 }
2716
2718 {
2722 {
2724 {
2725 puts(
_(
"No recipients specified"));
2726 goto cleanup;
2727 }
2728
2730 goto main_loop;
2731 }
2732 }
2733
2735 {
2739 goto cleanup;
2740 goto main_loop;
2741 }
2742
2744
2747 {
2748
2751 goto main_loop;
2752 }
2753
2755 {
2757 goto main_loop;
2758 }
2759
2761 {
2763 goto main_loop;
2764 }
2765
2767 {
2768 goto main_loop;
2769 }
2770
2773
2774
2775
2776
2777
2779
2780
2781
2782
2783
2784
2785 clear_content = NULL;
2786 free_clear_content = false;
2787
2789 {
2791 {
2792
2793 clear_content = e_templ->
body;
2794
2797 {
2800
2802
2804
2806 {
2808 rc = -1;
2809 goto cleanup;
2810 }
2811
2812 goto main_loop;
2813 }
2815 }
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825 if (clear_content && (e_templ->
body != clear_content) &&
2826 (e_templ->
body->
parts != clear_content))
2827 free_clear_content = true;
2828 }
2829
2832
2834
2835 const bool c_fcc_before_send =
cs_subset_bool(sub,
"fcc_before_send");
2836 if (c_fcc_before_send)
2837 save_fcc(m, e_templ, fcc, clear_content, pgpkeylist, flags, &finalpath, sub);
2838
2840 if (i < 0)
2841 {
2843 {
2845 ;
2848 {
2849 if (e_templ->
body != clear_content)
2850 {
2852 e_templ->
body = clear_content;
2853 }
2854 }
2856 {
2860 {
2862 }
2863 }
2864
2873 goto main_loop;
2874 }
2875 else
2876 {
2877 puts(
_(
"Could not send the message"));
2878 goto cleanup;
2879 }
2880 }
2881
2882 if (!c_fcc_before_send)
2883 save_fcc(m, e_templ, fcc, clear_content, pgpkeylist, flags, &finalpath, sub);
2884
2886 {
2890#ifdef USE_NOTMUCH
2892 if (c_nm_record)
2894#endif
2896 }
2897
2900
2903
2904
2905
2907 {
2909 {
2910 struct Email **ep = NULL;
2912 {
2913 struct Email *e = *ep;
2915 }
2916 }
2917 }
2918
2919 rc = 0;
2920
2921cleanup:
2923
2925 {
2927 {
2930 }
2932 {
2934 FREE(&smime_sign_as);
2935 }
2936 }
2937
2941
2943 return rc;
2944}
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.
#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.
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 OptNoCurses
(pseudo) when sending in batch mode
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.
#define MUTT_SEND_HOOK
send-hook: when composing a new email
#define MUTT_SEND2_HOOK
send2-hook: when changing fields in the compose menu
#define MUTT_REPLY_HOOK
reply-hook: when replying to 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 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.
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.
#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.