Send an email.
2129{
2131 FILE *fp_tmp = NULL;
2132 struct Body *pbody = NULL;
2133 int i;
2134 bool free_clear_content = false;
2135
2136 struct Body *clear_content = NULL;
2137 char *pgpkeylist = NULL;
2138
2139 char *pgp_sign_as = NULL;
2140 char *smime_sign_as = NULL;
2141 const char *tag = NULL;
2142 char *err = NULL;
2143 const char *ctype = NULL;
2144 char *finalpath = NULL;
2145 struct Email *e_cur = NULL;
2146
2149
2150 int rc = -1;
2151
2152#ifdef USE_NNTP
2155 else
2157#endif
2158
2160
2162 {
2163
2164
2167 return rc;
2168
2171 }
2172
2173
2174
2176
2178 {
2180 {
2183 }
2185 {
2186 const char *
const c_smime_sign_as =
cs_subset_string(sub,
"smime_sign_as");
2188 }
2189 }
2190
2191
2192
2193
2194
2195 if (!e_templ)
2196 {
2198
2200 {
2202 if (rc < 0)
2203 {
2205 goto cleanup;
2206 }
2207 flags = rc;
2208#ifdef USE_NNTP
2209
2210
2212 {
2215 }
2216 else
2217 {
2218 flags &= ~SEND_NEWS;
2220 }
2221#endif
2222 }
2223
2225 {
2230 if (!fp_tmp)
2231 {
2233 goto cleanup;
2234 }
2235 }
2236
2239 }
2240
2241
2243 {
2244
2246
2248 }
2249
2251 {
2252
2253
2255 {
2258 e_templ->
body = pbody;
2259
2261 ctype = c_content_type;
2262 if (!ctype)
2263 ctype = "text/plain";
2268
2269 if (tempfile)
2270 {
2275 }
2276 else
2277 {
2283 }
2284 }
2285 else
2286 {
2291 }
2292
2293 if (!fp_tmp)
2294 {
2298 goto cleanup;
2299 }
2300 }
2301
2303
2305 {
2306
2307
2308
2309
2310
2311
2313 {
2317 }
2319 }
2320
2321 const bool c_reply_with_xorig =
cs_subset_bool(sub,
"reply_with_xorig");
2323 {
2324
2325
2326
2327
2328
2329
2330
2331
2333 {
2337 }
2338 }
2339
2340 const bool c_resume_draft_files =
cs_subset_bool(sub,
"resume_draft_files");
2343 {
2346 {
2347 goto cleanup;
2348 }
2349
2351 if (c_hdrs)
2353
2354
2356
2359
2360#ifdef USE_NNTP
2362 {
2364 }
2365#endif
2366
2370 if (!(flags &
SEND_BATCH) && !(c_auto_edit && c_edit_headers) &&
2372 {
2374 goto cleanup;
2375 }
2376
2377
2378
2379
2380
2381
2383 if (killfrom)
2384 {
2386 }
2387
2389 {
2390
2392
2393
2394
2395
2397 }
2398
2399
2400
2402
2403
2404
2405
2406
2408
2409
2410 if (killfrom)
2411 {
2413
2417 }
2418
2419 if (c_hdrs)
2421
2423 {
2425 {
2427 mutt_message(
_(
"Try: echo | neomutt -s 'subject' user@example.com"));
2428 goto cleanup;
2429 }
2430 }
2431
2434
2438 {
2440 }
2441
2442
2445 {
2446 goto cleanup;
2447 }
2448
2450 {
2452 }
2453 }
2454
2455
2456
2457
2458
2460 {
2463 {
2465 }
2466 }
2467
2468
2469
2471
2472
2473
2474 {
2477 {
2479 if (c_real_name)
2481 }
2482 }
2483
2486
2488 {
2489 struct stat st = { 0 };
2490 time_t mtime;
2495 if (mtime == (time_t) -1)
2496 {
2498 goto cleanup;
2499 }
2500
2502
2505
2506
2507
2508
2509
2510
2511
2512
2513
2515 (((flags &
SEND_FORWARD) == 0) || (c_edit_headers && c_auto_edit) ||
2517 {
2518
2524 {
2526 goto cleanup;
2527 }
2528 else if (c_edit_headers)
2529 {
2533 }
2534 else
2535 {
2538 {
2539 if (mtime != st.st_mtime)
2541 }
2542 else
2543 {
2545 }
2546 }
2547
2549 }
2550
2552 {
2554 {
2555
2556 if ((mtime == st.st_mtime) && !e_templ->
body->
next &&
2558 {
2560 goto cleanup;
2561 }
2562 }
2563 else
2564 {
2566 }
2567 }
2568 }
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2581 {
2582 bool c_autocrypt = false;
2583 bool c_autocrypt_reply = false;
2584
2585#ifdef USE_AUTOCRYPT
2588#endif
2589
2591 {
2593 }
2594 else
2595 {
2596 const bool c_crypt_auto_sign =
cs_subset_bool(sub,
"crypt_auto_sign");
2597 const bool c_crypt_auto_encrypt =
cs_subset_bool(sub,
"crypt_auto_encrypt");
2598 const bool c_crypt_reply_encrypt =
cs_subset_bool(sub,
"crypt_reply_encrypt");
2599 const bool c_crypt_reply_sign =
cs_subset_bool(sub,
"crypt_reply_sign");
2600 const bool c_crypt_reply_sign_encrypted =
cs_subset_bool(sub,
"crypt_reply_sign_encrypted");
2601
2602 if (c_crypt_auto_sign)
2604 if (c_crypt_auto_encrypt)
2612
2613 const bool c_crypt_opportunistic_encrypt =
cs_subset_bool(sub,
"crypt_opportunistic_encrypt");
2614
2617 {
2618 const bool c_pgp_auto_inline =
cs_subset_bool(sub,
"pgp_auto_inline");
2619 const bool c_pgp_reply_inline =
cs_subset_bool(sub,
"pgp_reply_inline");
2620
2621 if (c_pgp_auto_inline)
2625 }
2626 }
2627
2628 const bool c_crypt_opportunistic_encrypt =
cs_subset_bool(sub,
"crypt_opportunistic_encrypt");
2629
2630 if (e_templ->
security || c_crypt_opportunistic_encrypt)
2631 {
2632 const bool c_crypt_auto_pgp =
cs_subset_bool(sub,
"crypt_auto_pgp");
2633 const bool c_crypt_auto_smime =
cs_subset_bool(sub,
"crypt_auto_smime");
2634
2635
2636
2637
2638
2639
2640
2641
2642 if (e_cur)
2643 {
2646 {
2648 }
2651 {
2653 }
2654 }
2655
2656 const bool c_smime_is_default =
cs_subset_bool(sub,
"smime_is_default");
2657
2658
2659
2661 {
2663 {
2665 }
2667 {
2669 }
2671 {
2673 }
2674 }
2675 }
2676
2677
2678 if (c_crypt_opportunistic_encrypt)
2679 {
2680
2681
2682
2684 {
2687 }
2688 }
2689
2690
2693 }
2694
2695
2696
2697
2699 {
2700 mutt_error(
_(
"No crypto backend configured. Disabling message security setting."));
2702 }
2703
2704
2705
2706
2708
2711 {
2712
2714 if (killfrom)
2715 {
2717 }
2719 if (killfrom)
2720 {
2722 }
2723 }
2724
2726
2728
2730 {
2731 main_loop:
2732
2736 if (i == -1)
2737 {
2738
2739#ifdef USE_NNTP
2742 else
2743#endif
2745 goto cleanup;
2746 }
2747 else if (i == 1)
2748 {
2750 goto main_loop;
2752 rc = 1;
2753 goto cleanup;
2754 }
2755 }
2756
2757#ifdef USE_NNTP
2759#endif
2763 {
2765 {
2766 puts(
_(
"No recipients specified"));
2767 goto cleanup;
2768 }
2769
2771 goto main_loop;
2772 }
2773
2775 {
2779 goto cleanup;
2780 goto main_loop;
2781 }
2782
2784
2787 {
2788
2791 goto main_loop;
2792 }
2793#ifdef USE_NNTP
2795 {
2797 goto main_loop;
2798 }
2799
2801 {
2803 goto main_loop;
2804 }
2805#endif
2806
2808 {
2809 goto main_loop;
2810 }
2811
2814
2815
2816
2817
2818
2820
2821
2822
2823
2824
2825
2826 clear_content = NULL;
2827 free_clear_content = false;
2828
2830 {
2832 {
2833
2834 clear_content = e_templ->
body;
2835
2838 {
2841
2843
2845 goto main_loop;
2846 }
2848 }
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858 if (clear_content && (e_templ->
body != clear_content) &&
2859 (e_templ->
body->
parts != clear_content))
2860 free_clear_content = true;
2861 }
2862
2865
2867
2868 const bool c_fcc_before_send =
cs_subset_bool(sub,
"fcc_before_send");
2869 if (c_fcc_before_send)
2870 save_fcc(m, e_templ, &fcc, clear_content, pgpkeylist, flags, &finalpath, sub);
2871
2873 if (i < 0)
2874 {
2876 {
2878 ;
2881 {
2882 if (e_templ->
body != clear_content)
2883 {
2885 e_templ->
body = clear_content;
2886 }
2887 }
2889 {
2893 {
2895 }
2896 }
2897
2906 goto main_loop;
2907 }
2908 else
2909 {
2910 puts(
_(
"Could not send the message"));
2911 goto cleanup;
2912 }
2913 }
2914
2915 if (!c_fcc_before_send)
2916 save_fcc(m, e_templ, &fcc, clear_content, pgpkeylist, flags, &finalpath, sub);
2917
2919 {
2923#ifdef USE_NOTMUCH
2925 if (c_nm_record)
2927#endif
2929 }
2930
2933
2936
2937
2938
2940 {
2942 {
2943 struct Email **ep = NULL;
2945 {
2946 struct Email *e = *ep;
2948 }
2949 }
2950 }
2951
2952 rc = 0;
2953
2954cleanup:
2956
2958 {
2960 {
2963 }
2965 {
2967 FREE(&smime_sign_as);
2968 }
2969 }
2970
2974
2976 return rc;
2977}
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
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 *ct)
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.
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
@ DISP_INLINE
Content is inline.
@ MUTT_REPLIED
Messages that have been replied to.
bool mutt_edit_attachment(struct Body *a)
Edit an attachment.
bool mutt_needs_mailcap(struct Body *m)
Does this type need a mailcap entry do display.
void mutt_sleep(short s)
Sleep for a while.
void buf_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
#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.
void mutt_update_encoding(struct Body *a, 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.