Send an email.
2128{
2130 FILE *fp_tmp = NULL;
2131 struct Body *pbody = NULL;
2132 int i;
2133 bool free_clear_content = false;
2134
2135 struct Body *clear_content = NULL;
2136 char *pgpkeylist = NULL;
2137
2138 char *pgp_sign_as = NULL;
2139 char *smime_sign_as = NULL;
2140 const char *tag = NULL;
2141 char *err = NULL;
2142 const char *ctype = NULL;
2143 char *finalpath = NULL;
2145 struct Email *e_cur = NULL;
2146
2147 if (el)
2149 if (en)
2151
2152 int rc = -1;
2153
2154#ifdef USE_NNTP
2157 else
2159#endif
2160
2162
2164 {
2165
2166
2169 return rc;
2170
2173 }
2174
2175
2176
2178
2180 {
2182 {
2185 }
2187 {
2188 const char *
const c_smime_sign_as =
cs_subset_string(sub,
"smime_sign_as");
2190 }
2191 }
2192
2193
2194
2195
2196
2197 if (!e_templ)
2198 {
2200
2202 {
2204 if (rc < 0)
2205 {
2207 goto cleanup;
2208 }
2209 flags = rc;
2210#ifdef USE_NNTP
2211
2212
2214 {
2217 }
2218 else
2219 {
2220 flags &= ~SEND_NEWS;
2222 }
2223#endif
2224 }
2225
2227 {
2232 if (!fp_tmp)
2233 {
2235 goto cleanup;
2236 }
2237 }
2238
2241 }
2242
2243
2245 {
2246
2248
2250 }
2251
2253 {
2254
2255
2257 {
2260 e_templ->
body = pbody;
2261
2263 ctype = c_content_type;
2264 if (!ctype)
2265 ctype = "text/plain";
2270
2271 if (tempfile)
2272 {
2277 }
2278 else
2279 {
2280 char buf[1024] = { 0 };
2284 }
2285 }
2286 else
2287 {
2292 }
2293
2294 if (!fp_tmp)
2295 {
2299 goto cleanup;
2300 }
2301 }
2302
2304
2306 {
2307
2308
2309
2310
2311
2312
2314 {
2318 }
2320 }
2321
2322 const bool c_reply_with_xorig =
cs_subset_bool(sub,
"reply_with_xorig");
2324 {
2325
2326
2327
2328
2329
2330
2331
2332
2334 {
2338 }
2339 }
2340
2341 const bool c_resume_draft_files =
cs_subset_bool(sub,
"resume_draft_files");
2344 {
2347 {
2348 goto cleanup;
2349 }
2350
2352 if (c_hdrs)
2354
2355
2357
2360
2361#ifdef USE_NNTP
2363 {
2365 }
2366#endif
2367
2371 if (!(flags &
SEND_BATCH) && !(c_auto_edit && c_edit_headers) &&
2373 {
2375 goto cleanup;
2376 }
2377
2378
2379
2380
2381
2382
2384 if (killfrom)
2385 {
2387 }
2388
2390 {
2391
2393
2394
2395
2396
2398 }
2399
2400
2401
2403
2404
2405
2406
2407
2409
2410
2411 if (killfrom)
2412 {
2414
2418 }
2419
2420 if (c_hdrs)
2422
2424 {
2426 {
2428 mutt_message(
_(
"Try: echo | neomutt -s 'subject' user@example.com"));
2429 goto cleanup;
2430 }
2431 }
2432
2435
2439 {
2441 }
2442
2443
2446 {
2447 goto cleanup;
2448 }
2449
2451 {
2453 }
2454 }
2455
2456
2457
2458
2459
2461 {
2464 {
2466 }
2467 }
2468
2469
2470
2472
2473
2474
2475 {
2478 {
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
2506
2507
2508
2509
2510
2511
2512
2513
2514
2516 (((flags &
SEND_FORWARD) == 0) || (c_edit_headers && c_auto_edit) ||
2518 {
2519
2525 {
2527 goto cleanup;
2528 }
2529 else if (c_edit_headers)
2530 {
2534 }
2535 else
2536 {
2539 {
2540 if (mtime != st.st_mtime)
2542 }
2543 else
2544 {
2546 }
2547 }
2548
2550 }
2551
2553 {
2555 {
2557
2558
2559 if ((mtime == st.st_mtime) && !e_templ->
body->
next &&
2561 {
2563 goto cleanup;
2564 }
2565 }
2566 else
2568 }
2569 }
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2582 {
2583 bool c_autocrypt = false;
2584 bool c_autocrypt_reply = false;
2585
2586#ifdef USE_AUTOCRYPT
2589#endif
2590
2592 {
2594 }
2595 else
2596 {
2597 const bool c_crypt_auto_sign =
cs_subset_bool(sub,
"crypt_auto_sign");
2598 const bool c_crypt_auto_encrypt =
cs_subset_bool(sub,
"crypt_auto_encrypt");
2599 const bool c_crypt_reply_encrypt =
cs_subset_bool(sub,
"crypt_reply_encrypt");
2600 const bool c_crypt_reply_sign =
cs_subset_bool(sub,
"crypt_reply_sign");
2601 const bool c_crypt_reply_sign_encrypted =
cs_subset_bool(sub,
"crypt_reply_sign_encrypted");
2602
2603 if (c_crypt_auto_sign)
2605 if (c_crypt_auto_encrypt)
2613
2614 const bool c_crypt_opportunistic_encrypt =
cs_subset_bool(sub,
"crypt_opportunistic_encrypt");
2615
2618 {
2619 const bool c_pgp_auto_inline =
cs_subset_bool(sub,
"pgp_auto_inline");
2620 const bool c_pgp_reply_inline =
cs_subset_bool(sub,
"pgp_reply_inline");
2621
2622 if (c_pgp_auto_inline)
2626 }
2627 }
2628
2629 const bool c_crypt_opportunistic_encrypt =
cs_subset_bool(sub,
"crypt_opportunistic_encrypt");
2630
2631 if (e_templ->
security || c_crypt_opportunistic_encrypt)
2632 {
2633 const bool c_crypt_auto_pgp =
cs_subset_bool(sub,
"crypt_auto_pgp");
2634 const bool c_crypt_auto_smime =
cs_subset_bool(sub,
"crypt_auto_smime");
2635
2636
2637
2638
2639
2640
2641
2642
2643 if (e_cur)
2644 {
2647 {
2649 }
2652 {
2654 }
2655 }
2656
2657 const bool c_smime_is_default =
cs_subset_bool(sub,
"smime_is_default");
2658
2659
2660
2662 {
2664 {
2666 }
2668 {
2670 }
2672 {
2674 }
2675 }
2676 }
2677
2678
2679 if (c_crypt_opportunistic_encrypt)
2680 {
2681
2682
2683
2685 {
2688 }
2689 }
2690
2691
2694 }
2695
2696
2697
2698
2700 {
2701 mutt_error(
_(
"No crypto backend configured. Disabling message security setting."));
2703 }
2704
2705
2706
2707
2709
2712 {
2713
2715 if (killfrom)
2716 {
2718 }
2720 if (killfrom)
2721 {
2723 }
2724 }
2725
2727
2729
2731 {
2732 main_loop:
2733
2737 sub);
2738 if (i == -1)
2739 {
2740
2741#ifdef USE_NNTP
2744 else
2745#endif
2747 goto cleanup;
2748 }
2749 else if (i == 1)
2750 {
2752 goto main_loop;
2754 rc = 1;
2755 goto cleanup;
2756 }
2757 }
2758
2759#ifdef USE_NNTP
2761#endif
2765 {
2767 {
2768 puts(
_(
"No recipients specified"));
2769 goto cleanup;
2770 }
2771
2773 goto main_loop;
2774 }
2775
2777 {
2781 goto cleanup;
2782 goto main_loop;
2783 }
2784
2786
2789 {
2790
2793 goto main_loop;
2794 }
2795#ifdef USE_NNTP
2797 {
2799 goto main_loop;
2800 }
2801
2803 {
2805 goto main_loop;
2806 }
2807#endif
2808
2810 {
2811 goto main_loop;
2812 }
2813
2816
2817
2818
2819
2820
2822
2823
2824
2825
2826
2827
2828 clear_content = NULL;
2829 free_clear_content = false;
2830
2832 {
2834 {
2835
2836 clear_content = e_templ->
body;
2837
2840 {
2843
2845
2847 goto main_loop;
2848 }
2850 }
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860 if (clear_content && (e_templ->
body != clear_content) &&
2861 (e_templ->
body->
parts != clear_content))
2862 free_clear_content = true;
2863 }
2864
2867
2869
2870 const bool c_fcc_before_send =
cs_subset_bool(sub,
"fcc_before_send");
2871 if (c_fcc_before_send)
2872 save_fcc(m, e_templ, &fcc, clear_content, pgpkeylist, flags, &finalpath, sub);
2873
2875 if (i < 0)
2876 {
2878 {
2880 ;
2883 {
2884 if (e_templ->
body != clear_content)
2885 {
2887 e_templ->
body = clear_content;
2888 }
2889 }
2891 {
2895 }
2896
2905 goto main_loop;
2906 }
2907 else
2908 {
2909 puts(
_(
"Could not send the message"));
2910 goto cleanup;
2911 }
2912 }
2913
2914 if (!c_fcc_before_send)
2915 save_fcc(m, e_templ, &fcc, clear_content, pgpkeylist, flags, &finalpath, sub);
2916
2918 {
2922#ifdef USE_NOTMUCH
2924 if (c_nm_record)
2926#endif
2928 }
2929
2932
2935
2936
2937
2939 {
2941 {
2943 {
2945 }
2946 }
2947 }
2948
2949 rc = 0;
2950
2951cleanup:
2953
2955 {
2957 {
2960 }
2962 {
2964 FREE(&smime_sign_as);
2965 }
2966 }
2967
2971
2973 return rc;
2974}
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.
#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.
int 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 mutt_mktemp(buf, buflen)
#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.
bool OptNoCurses
(pseudo) when sending in batch mode
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 x-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.