Send an email.
2122{
2124 FILE *fp_tmp = NULL;
2125 struct Body *pbody = NULL;
2126 int i;
2127 bool free_clear_content = false;
2128
2129 struct Body *clear_content = NULL;
2130 char *pgpkeylist = NULL;
2131
2132 char *pgp_sign_as = NULL;
2133 char *smime_sign_as = NULL;
2134 const char *tag = NULL;
2135 char *err = NULL;
2136 const char *ctype = NULL;
2137 char *finalpath = NULL;
2138 struct Email *e_cur = NULL;
2139
2142
2143 int rc = -1;
2144
2147 else
2149
2151
2153 {
2154
2155
2158 return rc;
2159
2162 }
2163
2165 {
2167 {
2170 }
2172 {
2173 const char *
const c_smime_sign_as =
cs_subset_string(sub,
"smime_sign_as");
2175 }
2176 }
2177
2178
2179
2180
2181
2182 if (!e_templ)
2183 {
2185
2187 {
2189 if (rc < 0)
2190 {
2192 goto cleanup;
2193 }
2194 flags = rc;
2195
2196
2198 {
2201 }
2202 else
2203 {
2204 flags &= ~SEND_NEWS;
2206 }
2207 }
2208
2210 {
2215 if (!fp_tmp)
2216 {
2218 goto cleanup;
2219 }
2220 }
2221
2224 }
2225
2226
2228 {
2229
2231
2233 }
2234
2236 {
2237
2238
2240 {
2243 e_templ->
body = pbody;
2244
2246 ctype = c_content_type;
2247 if (!ctype)
2248 ctype = "text/plain";
2253
2254 if (tempfile)
2255 {
2260 }
2261 else
2262 {
2268 }
2269 }
2270 else
2271 {
2276 }
2277
2278 if (!fp_tmp)
2279 {
2283 goto cleanup;
2284 }
2285 }
2286
2288
2290 {
2291
2292
2293
2294
2295
2296
2298 {
2302 }
2304 }
2305
2306 const bool c_reply_with_xorig =
cs_subset_bool(sub,
"reply_with_xorig");
2308 {
2309
2310
2311
2312
2313
2314
2315
2316
2318 {
2322 }
2323 }
2324
2325 const bool c_resume_draft_files =
cs_subset_bool(sub,
"resume_draft_files");
2328 {
2331 {
2332 goto cleanup;
2333 }
2334
2336 if (c_hdrs)
2338
2339
2341
2344
2346 {
2348 }
2349
2353 if (!(flags &
SEND_BATCH) && !(c_auto_edit && c_edit_headers) &&
2355 {
2357 goto cleanup;
2358 }
2359
2360
2361
2362
2363
2364
2366 if (killfrom)
2367 {
2369 }
2370
2372 {
2373
2375
2376
2377
2378
2380 }
2381
2382
2383
2385
2386
2387
2388
2389
2391
2392
2393 if (killfrom)
2394 {
2396
2400 }
2401
2402 if (c_hdrs)
2404
2406 {
2408 {
2410 goto cleanup;
2411 }
2412 }
2413
2416
2420 {
2422 }
2423
2424
2427 {
2428 goto cleanup;
2429 }
2430
2432 {
2434 }
2435 }
2436
2437
2438
2439
2440
2442 {
2445 {
2447 }
2448 }
2449
2450
2451
2453
2454
2455
2456 {
2459 {
2461 if (c_real_name)
2463 }
2464 }
2465
2468
2470 {
2471 struct stat st = { 0 };
2472 time_t mtime;
2477 if (mtime == (time_t) -1)
2478 {
2480 goto cleanup;
2481 }
2482
2484
2487
2488
2489
2490
2491
2492
2493
2494
2495
2497 (((flags &
SEND_FORWARD) == 0) || (c_edit_headers && c_auto_edit) ||
2499 {
2500
2506 {
2508 goto cleanup;
2509 }
2510 else if (c_edit_headers)
2511 {
2515 }
2516 else
2517 {
2520 {
2521 if (mtime != st.st_mtime)
2523 }
2524 else
2525 {
2527 }
2528 }
2529
2531 }
2532
2534 {
2536 {
2537
2538 if ((mtime == st.st_mtime) && !e_templ->
body->
next &&
2540 {
2542 goto cleanup;
2543 }
2544 }
2545 else
2546 {
2548 }
2549 }
2550 }
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2564 {
2565 bool c_autocrypt = false;
2566 bool c_autocrypt_reply = false;
2567
2568#ifdef USE_AUTOCRYPT
2571#endif
2572
2574 {
2576 }
2577 else
2578 {
2579 const bool c_crypt_auto_sign =
cs_subset_bool(sub,
"crypt_auto_sign");
2580 const bool c_crypt_auto_encrypt =
cs_subset_bool(sub,
"crypt_auto_encrypt");
2581 const bool c_crypt_reply_encrypt =
cs_subset_bool(sub,
"crypt_reply_encrypt");
2582 const bool c_crypt_reply_sign =
cs_subset_bool(sub,
"crypt_reply_sign");
2583 const bool c_crypt_reply_sign_encrypted =
cs_subset_bool(sub,
"crypt_reply_sign_encrypted");
2584
2585 if (c_crypt_auto_sign)
2587 if (c_crypt_auto_encrypt)
2595
2596 const bool c_crypt_opportunistic_encrypt =
cs_subset_bool(sub,
"crypt_opportunistic_encrypt");
2597
2600 {
2601 const bool c_pgp_auto_inline =
cs_subset_bool(sub,
"pgp_auto_inline");
2602 const bool c_pgp_reply_inline =
cs_subset_bool(sub,
"pgp_reply_inline");
2603
2604 if (c_pgp_auto_inline)
2608 }
2609 }
2610
2611 const bool c_crypt_opportunistic_encrypt =
cs_subset_bool(sub,
"crypt_opportunistic_encrypt");
2612
2613 if (e_templ->
security || c_crypt_opportunistic_encrypt)
2614 {
2615 const bool c_crypt_auto_pgp =
cs_subset_bool(sub,
"crypt_auto_pgp");
2616 const bool c_crypt_auto_smime =
cs_subset_bool(sub,
"crypt_auto_smime");
2617
2618
2619
2620
2621
2622
2623
2624
2625 if (e_cur)
2626 {
2629 {
2631 }
2634 {
2636 }
2637 }
2638
2639 const bool c_smime_is_default =
cs_subset_bool(sub,
"smime_is_default");
2640
2641
2642
2644 {
2646 {
2648 }
2650 {
2652 }
2654 {
2656 }
2657 }
2658 }
2659
2660
2661 if (c_crypt_opportunistic_encrypt)
2662 {
2663
2664
2665
2667 {
2670 }
2671 }
2672
2673
2676 }
2677
2678
2679
2680
2682 {
2683 mutt_error(
_(
"No crypto backend configured. Disabling message security setting."));
2685 }
2686
2687
2688
2689
2691
2694 {
2695
2697 if (killfrom)
2698 {
2700 }
2702 if (killfrom)
2703 {
2705 }
2706 }
2707
2709
2711
2713 {
2714 main_loop:
2715
2719 if (i == -1)
2720 {
2721
2724 else
2726 goto cleanup;
2727 }
2728 else if (i == 1)
2729 {
2731 goto main_loop;
2733 rc = 1;
2734 goto cleanup;
2735 }
2736 }
2737
2739 {
2743 {
2745 {
2746 puts(
_(
"No recipients specified"));
2747 goto cleanup;
2748 }
2749
2751 goto main_loop;
2752 }
2753 }
2754
2756 {
2760 goto cleanup;
2761 goto main_loop;
2762 }
2763
2765
2768 {
2769
2772 goto main_loop;
2773 }
2774
2776 {
2778 goto main_loop;
2779 }
2780
2782 {
2784 goto main_loop;
2785 }
2786
2788 {
2789 goto main_loop;
2790 }
2791
2794
2795
2796
2797
2798
2800
2801
2802
2803
2804
2805
2806 clear_content = NULL;
2807 free_clear_content = false;
2808
2810 {
2812 {
2813
2814 clear_content = e_templ->
body;
2815
2818 {
2821
2823
2825
2827 {
2829 rc = -1;
2830 goto cleanup;
2831 }
2832
2833 goto main_loop;
2834 }
2836 }
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846 if (clear_content && (e_templ->
body != clear_content) &&
2847 (e_templ->
body->
parts != clear_content))
2848 free_clear_content = true;
2849 }
2850
2853
2855
2856 const bool c_fcc_before_send =
cs_subset_bool(sub,
"fcc_before_send");
2857 if (c_fcc_before_send)
2858 save_fcc(m, e_templ, fcc, clear_content, pgpkeylist, flags, &finalpath, sub);
2859
2861 if (i < 0)
2862 {
2864 {
2866 ;
2869 {
2870 if (e_templ->
body != clear_content)
2871 {
2873 e_templ->
body = clear_content;
2874 }
2875 }
2877 {
2881 {
2883 }
2884 }
2885
2894 goto main_loop;
2895 }
2896 else
2897 {
2898 puts(
_(
"Could not send the message"));
2899 goto cleanup;
2900 }
2901 }
2902
2903 if (!c_fcc_before_send)
2904 save_fcc(m, e_templ, fcc, clear_content, pgpkeylist, flags, &finalpath, sub);
2905
2907 {
2911#ifdef USE_NOTMUCH
2913 if (c_nm_record)
2915#endif
2917 }
2918
2921
2924
2925
2926
2928 {
2930 {
2931 struct Email **ep = NULL;
2933 {
2934 struct Email *e = *ep;
2936 }
2937 }
2938 }
2939
2940 rc = 0;
2941
2942cleanup:
2944
2946 {
2948 {
2951 }
2953 {
2955 FREE(&smime_sign_as);
2956 }
2957 }
2958
2962
2964 return rc;
2965}
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.