Send an email.
2117{
2119 FILE *fp_tmp = NULL;
2120 struct Body *pbody = NULL;
2121 int i;
2122 bool free_clear_content = false;
2123
2124 struct Body *clear_content = NULL;
2125 char *pgpkeylist = NULL;
2126
2127 char *pgp_sign_as = NULL;
2128 char *smime_sign_as = NULL;
2129 const char *tag = NULL;
2130 char *err = NULL;
2131 const char *ctype = NULL;
2132 char *finalpath = NULL;
2133 struct Email *e_cur = NULL;
2134
2137
2138 int rc = -1;
2139
2142 else
2144
2146
2148 {
2149
2150
2153 return rc;
2154
2157 }
2158
2159
2160
2162
2164 {
2166 {
2169 }
2171 {
2172 const char *
const c_smime_sign_as =
cs_subset_string(sub,
"smime_sign_as");
2174 }
2175 }
2176
2177
2178
2179
2180
2181 if (!e_templ)
2182 {
2184
2186 {
2188 if (rc < 0)
2189 {
2191 goto cleanup;
2192 }
2193 flags = rc;
2194
2195
2197 {
2200 }
2201 else
2202 {
2203 flags &= ~SEND_NEWS;
2205 }
2206 }
2207
2209 {
2214 if (!fp_tmp)
2215 {
2217 goto cleanup;
2218 }
2219 }
2220
2223 }
2224
2225
2227 {
2228
2230
2232 }
2233
2235 {
2236
2237
2239 {
2242 e_templ->
body = pbody;
2243
2245 ctype = c_content_type;
2246 if (!ctype)
2247 ctype = "text/plain";
2252
2253 if (tempfile)
2254 {
2259 }
2260 else
2261 {
2267 }
2268 }
2269 else
2270 {
2275 }
2276
2277 if (!fp_tmp)
2278 {
2282 goto cleanup;
2283 }
2284 }
2285
2287
2289 {
2290
2291
2292
2293
2294
2295
2297 {
2301 }
2303 }
2304
2305 const bool c_reply_with_xorig =
cs_subset_bool(sub,
"reply_with_xorig");
2307 {
2308
2309
2310
2311
2312
2313
2314
2315
2317 {
2321 }
2322 }
2323
2324 const bool c_resume_draft_files =
cs_subset_bool(sub,
"resume_draft_files");
2327 {
2330 {
2331 goto cleanup;
2332 }
2333
2335 if (c_hdrs)
2337
2338
2340
2343
2345 {
2347 }
2348
2352 if (!(flags &
SEND_BATCH) && !(c_auto_edit && c_edit_headers) &&
2354 {
2356 goto cleanup;
2357 }
2358
2359
2360
2361
2362
2363
2365 if (killfrom)
2366 {
2368 }
2369
2371 {
2372
2374
2375
2376
2377
2379 }
2380
2381
2382
2384
2385
2386
2387
2388
2390
2391
2392 if (killfrom)
2393 {
2395
2399 }
2400
2401 if (c_hdrs)
2403
2405 {
2407 {
2409 goto cleanup;
2410 }
2411 }
2412
2415
2419 {
2421 }
2422
2423
2426 {
2427 goto cleanup;
2428 }
2429
2431 {
2433 }
2434 }
2435
2436
2437
2438
2439
2441 {
2444 {
2446 }
2447 }
2448
2449
2450
2452
2453
2454
2455 {
2458 {
2460 if (c_real_name)
2462 }
2463 }
2464
2467
2469 {
2470 struct stat st = { 0 };
2471 time_t mtime;
2476 if (mtime == (time_t) -1)
2477 {
2479 goto cleanup;
2480 }
2481
2483
2486
2487
2488
2489
2490
2491
2492
2493
2494
2496 (((flags &
SEND_FORWARD) == 0) || (c_edit_headers && c_auto_edit) ||
2498 {
2499
2505 {
2507 goto cleanup;
2508 }
2509 else if (c_edit_headers)
2510 {
2514 }
2515 else
2516 {
2519 {
2520 if (mtime != st.st_mtime)
2522 }
2523 else
2524 {
2526 }
2527 }
2528
2530 }
2531
2533 {
2535 {
2536
2537 if ((mtime == st.st_mtime) && !e_templ->
body->
next &&
2539 {
2541 goto cleanup;
2542 }
2543 }
2544 else
2545 {
2547 }
2548 }
2549 }
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2563 {
2564 bool c_autocrypt = false;
2565 bool c_autocrypt_reply = false;
2566
2567#ifdef USE_AUTOCRYPT
2570#endif
2571
2573 {
2575 }
2576 else
2577 {
2578 const bool c_crypt_auto_sign =
cs_subset_bool(sub,
"crypt_auto_sign");
2579 const bool c_crypt_auto_encrypt =
cs_subset_bool(sub,
"crypt_auto_encrypt");
2580 const bool c_crypt_reply_encrypt =
cs_subset_bool(sub,
"crypt_reply_encrypt");
2581 const bool c_crypt_reply_sign =
cs_subset_bool(sub,
"crypt_reply_sign");
2582 const bool c_crypt_reply_sign_encrypted =
cs_subset_bool(sub,
"crypt_reply_sign_encrypted");
2583
2584 if (c_crypt_auto_sign)
2586 if (c_crypt_auto_encrypt)
2594
2595 const bool c_crypt_opportunistic_encrypt =
cs_subset_bool(sub,
"crypt_opportunistic_encrypt");
2596
2599 {
2600 const bool c_pgp_auto_inline =
cs_subset_bool(sub,
"pgp_auto_inline");
2601 const bool c_pgp_reply_inline =
cs_subset_bool(sub,
"pgp_reply_inline");
2602
2603 if (c_pgp_auto_inline)
2607 }
2608 }
2609
2610 const bool c_crypt_opportunistic_encrypt =
cs_subset_bool(sub,
"crypt_opportunistic_encrypt");
2611
2612 if (e_templ->
security || c_crypt_opportunistic_encrypt)
2613 {
2614 const bool c_crypt_auto_pgp =
cs_subset_bool(sub,
"crypt_auto_pgp");
2615 const bool c_crypt_auto_smime =
cs_subset_bool(sub,
"crypt_auto_smime");
2616
2617
2618
2619
2620
2621
2622
2623
2624 if (e_cur)
2625 {
2628 {
2630 }
2633 {
2635 }
2636 }
2637
2638 const bool c_smime_is_default =
cs_subset_bool(sub,
"smime_is_default");
2639
2640
2641
2643 {
2645 {
2647 }
2649 {
2651 }
2653 {
2655 }
2656 }
2657 }
2658
2659
2660 if (c_crypt_opportunistic_encrypt)
2661 {
2662
2663
2664
2666 {
2669 }
2670 }
2671
2672
2675 }
2676
2677
2678
2679
2681 {
2682 mutt_error(
_(
"No crypto backend configured. Disabling message security setting."));
2684 }
2685
2686
2687
2688
2690
2693 {
2694
2696 if (killfrom)
2697 {
2699 }
2701 if (killfrom)
2702 {
2704 }
2705 }
2706
2708
2710
2712 {
2713 main_loop:
2714
2718 if (i == -1)
2719 {
2720
2723 else
2725 goto cleanup;
2726 }
2727 else if (i == 1)
2728 {
2730 goto main_loop;
2732 rc = 1;
2733 goto cleanup;
2734 }
2735 }
2736
2738 {
2742 {
2744 {
2745 puts(
_(
"No recipients specified"));
2746 goto cleanup;
2747 }
2748
2750 goto main_loop;
2751 }
2752 }
2753
2755 {
2759 goto cleanup;
2760 goto main_loop;
2761 }
2762
2764
2767 {
2768
2771 goto main_loop;
2772 }
2773
2775 {
2777 goto main_loop;
2778 }
2779
2781 {
2783 goto main_loop;
2784 }
2785
2787 {
2788 goto main_loop;
2789 }
2790
2793
2794
2795
2796
2797
2799
2800
2801
2802
2803
2804
2805 clear_content = NULL;
2806 free_clear_content = false;
2807
2809 {
2811 {
2812
2813 clear_content = e_templ->
body;
2814
2817 {
2820
2822
2824
2826 {
2828 rc = -1;
2829 goto cleanup;
2830 }
2831
2832 goto main_loop;
2833 }
2835 }
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845 if (clear_content && (e_templ->
body != clear_content) &&
2846 (e_templ->
body->
parts != clear_content))
2847 free_clear_content = true;
2848 }
2849
2852
2854
2855 const bool c_fcc_before_send =
cs_subset_bool(sub,
"fcc_before_send");
2856 if (c_fcc_before_send)
2857 save_fcc(m, e_templ, &fcc, clear_content, pgpkeylist, flags, &finalpath, sub);
2858
2860 if (i < 0)
2861 {
2863 {
2865 ;
2868 {
2869 if (e_templ->
body != clear_content)
2870 {
2872 e_templ->
body = clear_content;
2873 }
2874 }
2876 {
2880 {
2882 }
2883 }
2884
2893 goto main_loop;
2894 }
2895 else
2896 {
2897 puts(
_(
"Could not send the message"));
2898 goto cleanup;
2899 }
2900 }
2901
2902 if (!c_fcc_before_send)
2903 save_fcc(m, e_templ, &fcc, clear_content, pgpkeylist, flags, &finalpath, sub);
2904
2906 {
2910#ifdef USE_NOTMUCH
2912 if (c_nm_record)
2914#endif
2916 }
2917
2920
2923
2924
2925
2927 {
2929 {
2930 struct Email **ep = NULL;
2932 {
2933 struct Email *e = *ep;
2935 }
2936 }
2937 }
2938
2939 rc = 0;
2940
2941cleanup:
2943
2945 {
2947 {
2950 }
2952 {
2954 FREE(&smime_sign_as);
2955 }
2956 }
2957
2961
2963 return rc;
2964}
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.
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
struct Buffer buf_make(size_t size)
Make a new buffer on the stack.
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-Orig-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.