Send an email.
2139{
2141 FILE *fp_tmp = NULL;
2142 struct Body *pbody = NULL;
2143 int i;
2144 bool free_clear_content = false;
2145
2146 struct Body *clear_content = NULL;
2147 char *pgpkeylist = NULL;
2148
2149 char *pgp_sign_as = NULL;
2150 char *smime_sign_as = NULL;
2151 const char *tag = NULL;
2152 char *err = NULL;
2153 const char *ctype = NULL;
2154 char *finalpath = NULL;
2156 struct Email *e_cur = NULL;
2157
2158 if (el)
2160 if (en)
2162
2163 int rc = -1;
2164
2165#ifdef USE_NNTP
2168 else
2170#endif
2171
2173
2175 {
2176
2177
2180 return rc;
2181
2184 }
2185
2186
2187
2189
2191 {
2193 {
2196 }
2198 {
2199 const char *
const c_smime_sign_as =
cs_subset_string(sub,
"smime_sign_as");
2201 }
2202 }
2203
2204
2205
2206
2207
2208 if (!e_templ)
2209 {
2211
2213 {
2215 if (rc < 0)
2216 {
2218 goto cleanup;
2219 }
2220 flags = rc;
2221#ifdef USE_NNTP
2222
2223
2225 {
2228 }
2229 else
2230 {
2231 flags &= ~SEND_NEWS;
2233 }
2234#endif
2235 }
2236
2238 {
2243 if (!fp_tmp)
2244 {
2246 goto cleanup;
2247 }
2248 }
2249
2252 }
2253
2254
2256 {
2257
2259
2261 }
2262
2264 {
2265
2266
2268 {
2271 e_templ->
body = pbody;
2272
2274 ctype = c_content_type;
2275 if (!ctype)
2276 ctype = "text/plain";
2281
2282 if (tempfile)
2283 {
2288 }
2289 else
2290 {
2291 char buf[1024] = { 0 };
2295 }
2296 }
2297 else
2298 {
2303 }
2304
2305 if (!fp_tmp)
2306 {
2310 goto cleanup;
2311 }
2312 }
2313
2315
2317 {
2318
2319
2320
2321
2322
2323
2325 {
2329 }
2331 }
2332
2333 const bool c_reply_with_xorig =
cs_subset_bool(sub,
"reply_with_xorig");
2335 {
2336
2337
2338
2339
2340
2341
2342
2343
2345 {
2349 }
2350 }
2351
2352 const bool c_resume_draft_files =
cs_subset_bool(sub,
"resume_draft_files");
2355 {
2358 {
2359 goto cleanup;
2360 }
2361
2363 if (c_hdrs)
2365
2366
2368
2371
2372#ifdef USE_NNTP
2374 {
2376 }
2377#endif
2378
2382 if (!(flags &
SEND_BATCH) && !(c_auto_edit && c_edit_headers) &&
2384 {
2386 goto cleanup;
2387 }
2388
2389
2390
2391
2392
2393
2395 if (killfrom)
2396 {
2398 }
2399
2401 {
2402
2404
2405
2406
2407
2409 }
2410
2411
2412
2414
2415
2416
2417
2418
2420
2421
2422 if (killfrom)
2423 {
2425
2429 }
2430
2431 if (c_hdrs)
2433
2435 {
2437 {
2439 mutt_message(
_(
"Try: echo | neomutt -s 'subject' user@example.com"));
2440 goto cleanup;
2441 }
2442 }
2443
2446
2450 {
2452 }
2453
2454
2457 {
2458 goto cleanup;
2459 }
2460
2462 {
2464 }
2465 }
2466
2467
2468
2469
2470
2472 {
2475 {
2477 }
2478 }
2479
2480
2481
2483
2484
2485
2486 {
2489 {
2492 }
2493 }
2494
2497
2499 {
2500 struct stat st = { 0 };
2501 time_t mtime;
2506 if (mtime == (time_t) -1)
2507 {
2509 goto cleanup;
2510 }
2511
2513
2517
2518
2519
2520
2521
2522
2523
2524
2525
2527 (((flags &
SEND_FORWARD) == 0) || (c_edit_headers && c_auto_edit) ||
2529 {
2530
2536 {
2538 goto cleanup;
2539 }
2540 else if (c_edit_headers)
2541 {
2545 }
2546 else
2547 {
2550 {
2551 if (mtime != st.st_mtime)
2553 }
2554 else
2555 {
2557 }
2558 }
2559
2561 }
2562
2564 {
2566 {
2568
2569
2570 if ((mtime == st.st_mtime) && !e_templ->
body->
next &&
2572 {
2574 goto cleanup;
2575 }
2576 }
2577 else
2578 {
2580 }
2581 }
2582 }
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2595 {
2596 bool c_autocrypt = false;
2597 bool c_autocrypt_reply = false;
2598
2599#ifdef USE_AUTOCRYPT
2602#endif
2603
2605 {
2607 }
2608 else
2609 {
2610 const bool c_crypt_auto_sign =
cs_subset_bool(sub,
"crypt_auto_sign");
2611 const bool c_crypt_auto_encrypt =
cs_subset_bool(sub,
"crypt_auto_encrypt");
2612 const bool c_crypt_reply_encrypt =
cs_subset_bool(sub,
"crypt_reply_encrypt");
2613 const bool c_crypt_reply_sign =
cs_subset_bool(sub,
"crypt_reply_sign");
2614 const bool c_crypt_reply_sign_encrypted =
cs_subset_bool(sub,
"crypt_reply_sign_encrypted");
2615
2616 if (c_crypt_auto_sign)
2618 if (c_crypt_auto_encrypt)
2626
2627 const bool c_crypt_opportunistic_encrypt =
cs_subset_bool(sub,
"crypt_opportunistic_encrypt");
2628
2631 {
2632 const bool c_pgp_auto_inline =
cs_subset_bool(sub,
"pgp_auto_inline");
2633 const bool c_pgp_reply_inline =
cs_subset_bool(sub,
"pgp_reply_inline");
2634
2635 if (c_pgp_auto_inline)
2639 }
2640 }
2641
2642 const bool c_crypt_opportunistic_encrypt =
cs_subset_bool(sub,
"crypt_opportunistic_encrypt");
2643
2644 if (e_templ->
security || c_crypt_opportunistic_encrypt)
2645 {
2646 const bool c_crypt_auto_pgp =
cs_subset_bool(sub,
"crypt_auto_pgp");
2647 const bool c_crypt_auto_smime =
cs_subset_bool(sub,
"crypt_auto_smime");
2648
2649
2650
2651
2652
2653
2654
2655
2656 if (e_cur)
2657 {
2660 {
2662 }
2665 {
2667 }
2668 }
2669
2670 const bool c_smime_is_default =
cs_subset_bool(sub,
"smime_is_default");
2671
2672
2673
2675 {
2677 {
2679 }
2681 {
2683 }
2685 {
2687 }
2688 }
2689 }
2690
2691
2692 if (c_crypt_opportunistic_encrypt)
2693 {
2694
2695
2696
2698 {
2701 }
2702 }
2703
2704
2707 }
2708
2709
2710
2711
2713 {
2714 mutt_error(
_(
"No crypto backend configured. Disabling message security setting."));
2716 }
2717
2718
2719
2720
2722
2725 {
2726
2728 if (killfrom)
2729 {
2731 }
2733 if (killfrom)
2734 {
2736 }
2737 }
2738
2740
2742
2744 {
2745 main_loop:
2746
2750 sub);
2751 if (i == -1)
2752 {
2753
2754#ifdef USE_NNTP
2757 else
2758#endif
2760 goto cleanup;
2761 }
2762 else if (i == 1)
2763 {
2765 goto main_loop;
2767 rc = 1;
2768 goto cleanup;
2769 }
2770 }
2771
2772#ifdef USE_NNTP
2774#endif
2778 {
2780 {
2781 puts(
_(
"No recipients specified"));
2782 goto cleanup;
2783 }
2784
2786 goto main_loop;
2787 }
2788
2790 {
2794 goto cleanup;
2795 goto main_loop;
2796 }
2797
2799
2802 {
2803
2806 goto main_loop;
2807 }
2808#ifdef USE_NNTP
2810 {
2812 goto main_loop;
2813 }
2814
2816 {
2818 goto main_loop;
2819 }
2820#endif
2821
2823 {
2824 goto main_loop;
2825 }
2826
2829
2830
2831
2832
2833
2835
2836
2837
2838
2839
2840
2841 clear_content = NULL;
2842 free_clear_content = false;
2843
2845 {
2847 {
2848
2849 clear_content = e_templ->
body;
2850
2853 {
2856
2858
2860 goto main_loop;
2861 }
2863 }
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873 if (clear_content && (e_templ->
body != clear_content) &&
2874 (e_templ->
body->
parts != clear_content))
2875 free_clear_content = true;
2876 }
2877
2880
2882
2883 const bool c_fcc_before_send =
cs_subset_bool(sub,
"fcc_before_send");
2884 if (c_fcc_before_send)
2885 save_fcc(m, e_templ, &fcc, clear_content, pgpkeylist, flags, &finalpath, sub);
2886
2888 if (i < 0)
2889 {
2891 {
2893 ;
2896 {
2897 if (e_templ->
body != clear_content)
2898 {
2900 e_templ->
body = clear_content;
2901 }
2902 }
2904 {
2908 {
2910 }
2911 }
2912
2921 goto main_loop;
2922 }
2923 else
2924 {
2925 puts(
_(
"Could not send the message"));
2926 goto cleanup;
2927 }
2928 }
2929
2930 if (!c_fcc_before_send)
2931 save_fcc(m, e_templ, &fcc, clear_content, pgpkeylist, flags, &finalpath, sub);
2932
2934 {
2938#ifdef USE_NOTMUCH
2940 if (c_nm_record)
2942#endif
2944 }
2945
2948
2951
2952
2953
2955 {
2957 {
2959 {
2961 }
2962 }
2963 }
2964
2965 rc = 0;
2966
2967cleanup:
2969
2971 {
2973 {
2976 }
2978 {
2980 FREE(&smime_sign_as);
2981 }
2982 }
2983
2987
2989 return rc;
2990}
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 mutt_buffer_make(size_t size)
Make a new buffer on the stack.
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
#define MUTT_COMPOSE_NOFREEHEADER
int mutt_compose_menu(struct Email *e, struct Buffer *fcc, uint8_t flags, struct ConfigSubset *sub)
Allow the user to edit the message envelope.
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.
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.
bool OptNoCurses
(pseudo) when sending in batch mode
#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.
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
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.
#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.
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.
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.
#define mutt_set_flag(m, e, flag, bf)
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 int generate_body(FILE *fp_tmp, struct Email *e, SendFlags flags, struct Mailbox *m, struct EmailList *el, struct ConfigSubset *sub)
Create a new email body.
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.
void mutt_fix_reply_recipients(struct Envelope *env, struct ConfigSubset *sub)
Remove duplicate recipients.
static int envelope_defaults(struct Envelope *env, struct EmailList *el, SendFlags flags, struct ConfigSubset *sub)
Fill in some defaults for a new email.
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.
#define mutt_mktemp(buf, buflen)