NeoMutt  2025-12-11-1039-g550ac6
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
external.c
Go to the documentation of this file.
1
25
31
32#include "config.h"
33#include <limits.h>
34#include <stdbool.h>
35#include <stdio.h>
36#include <sys/stat.h>
37#include <sys/types.h>
38#include "mutt/lib.h"
39#include "address/lib.h"
40#include "config/lib.h"
41#include "email/lib.h"
42#include "core/lib.h"
43#include "alias/lib.h"
44#include "gui/lib.h"
45#include "mutt.h"
46#include "external.h"
47#include "attach/lib.h"
48#include "browser/lib.h"
49#include "complete/lib.h"
50#include "editor/lib.h"
51#include "history/lib.h"
52#include "hooks/lib.h"
53#include "imap/lib.h"
54#include "ncrypt/lib.h"
55#include "parse/lib.h"
56#include "progress/lib.h"
57#include "question/lib.h"
58#include "send/lib.h"
59#include "globals.h"
60#include "mutt_logging.h"
61#include "mutt_mailbox.h"
62#include "muttlib.h"
63#include "mx.h"
64#ifdef USE_NOTMUCH
65#include "notmuch/lib.h"
66#endif
67#ifdef ENABLE_NLS
68#include <libintl.h>
69#endif
70
72static struct Buffer LastSaveFolder = { 0 };
73
81
87void index_bounce_message(struct Mailbox *m, struct EmailArray *ea)
88{
89 if (!m || !ea || ARRAY_EMPTY(ea))
90 return;
91
92 struct Buffer *buf = buf_pool_get();
93 struct Buffer *prompt = buf_pool_get();
94 struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
95 char *err = NULL;
96 int rc;
97 int msg_count = 0;
98
99 struct Email **ep = NULL;
100 ARRAY_FOREACH(ep, ea)
101 {
102 struct Email *e = *ep;
103 /* RFC5322 mandates a From: header,
104 * so warn before bouncing messages without one */
105 if (TAILQ_EMPTY(&e->env->from))
106 mutt_error(_("Warning: message contains no From: header"));
107
108 msg_count++;
109 }
110
111 if (msg_count == 1)
112 buf_strcpy(prompt, _("Bounce message to: "));
113 else
114 buf_strcpy(prompt, _("Bounce tagged messages to: "));
115
117 &CompleteAliasOps, NULL);
118 if ((rc != 0) || buf_is_empty(buf))
119 goto done;
120
122 if (TAILQ_EMPTY(&al))
123 {
124 mutt_error(_("Error parsing address"));
125 goto done;
126 }
127
129
130 if (mutt_addrlist_to_intl(&al, &err) < 0)
131 {
132 mutt_error(_("Bad IDN: '%s'"), err);
133 FREE(&err);
134 goto done;
135 }
136
137 buf_reset(buf);
138 mutt_addrlist_write(&al, buf, true);
139
140 buf_printf(prompt, ngettext("Bounce message to %s?", "Bounce messages to %s?", msg_count),
141 buf_string(buf));
142
143 if (query_quadoption(buf_string(prompt), NeoMutt->sub, "bounce") != MUTT_YES)
144 {
145 msgwin_clear_text(NULL);
146 mutt_message(ngettext("Message not bounced", "Messages not bounced", msg_count));
147 goto done;
148 }
149
150 msgwin_clear_text(NULL);
151
152 struct Message *msg = NULL;
153 ARRAY_FOREACH(ep, ea)
154 {
155 struct Email *e = *ep;
156 msg = mx_msg_open(m, e);
157 if (!msg)
158 {
159 rc = -1;
160 break;
161 }
162
163 rc = mutt_bounce_message(msg->fp, m, e, &al, NeoMutt->sub);
164 mx_msg_close(m, &msg);
165
166 if (rc < 0)
167 break;
168 }
169
170 /* If no error, or background, display message. */
171 if ((rc == 0) || (rc == S_BKG))
172 mutt_message(ngettext("Message bounced", "Messages bounced", msg_count));
173
174done:
176 buf_pool_release(&buf);
177 buf_pool_release(&prompt);
178}
179
187static void pipe_set_flags(bool decode, bool print, CopyMessageFlags *cmflags,
188 CopyHeaderFlags *chflags)
189{
190 if (decode)
191 {
192 *chflags |= CH_DECODE | CH_REORDER;
193 *cmflags |= MUTT_CM_DECODE | MUTT_CM_CHARCONV;
194
195 const bool c_print_decode_weed = cs_subset_bool(NeoMutt->sub, "print_decode_weed");
196 const bool c_pipe_decode_weed = cs_subset_bool(NeoMutt->sub, "pipe_decode_weed");
197 if (print ? c_print_decode_weed : c_pipe_decode_weed)
198 {
199 *chflags |= CH_WEED;
200 *cmflags |= MUTT_CM_WEED;
201 }
202
203 /* Just as with copy-decode, we need to update the mime fields to avoid
204 * confusing programs that may process the email. However, we don't want
205 * to force those fields to appear in printouts. */
206 if (!print)
207 *chflags |= CH_MIME | CH_TXTPLAIN;
208 }
209
210 if (print)
211 *cmflags |= MUTT_CM_PRINTING;
212}
213
223static void pipe_msg(struct Mailbox *m, struct Email *e, struct Message *msg,
224 FILE *fp, bool decode, bool print)
225{
227 CopyHeaderFlags chflags = CH_FROM;
228
229 pipe_set_flags(decode, print, &cmflags, &chflags);
230
231 if ((WithCrypto != 0) && decode && e->security & SEC_ENCRYPT)
232 {
234 return;
235 mutt_endwin();
236 }
237
238 const bool own_msg = !msg;
239 if (own_msg)
240 {
241 msg = mx_msg_open(m, e);
242 if (!msg)
243 {
244 return;
245 }
246 }
247
248 if (decode)
249 {
251 }
252
253 mutt_copy_message(fp, e, msg, cmflags, chflags, 0);
254
255 if (own_msg)
256 {
257 mx_msg_close(m, &msg);
258 }
259}
260
275static int pipe_message(struct Mailbox *m, struct EmailArray *ea, const char *cmd,
276 bool decode, bool print, bool split, const char *sep)
277{
278 if (!m || !ea || ARRAY_EMPTY(ea))
279 return 1;
280
281 int rc = 0;
282 pid_t pid;
283 FILE *fp_out = NULL;
284
285 if (ARRAY_SIZE(ea) == 1)
286 {
287 struct Email *e = *ARRAY_GET(ea, 0);
288 /* handle a single message */
290
291 struct Message *msg = mx_msg_open(m, e);
292 if (msg && (WithCrypto != 0) && decode)
293 {
296 {
297 mx_msg_close(m, &msg);
298 return 1;
299 }
300 }
301 mutt_endwin();
302
303 pid = filter_create(cmd, &fp_out, NULL, NULL, NeoMutt->env);
304 if (pid < 0)
305 {
306 mutt_perror(_("Can't create filter process"));
307 mx_msg_close(m, &msg);
308 return 1;
309 }
310
311 OptKeepQuiet = true;
312 pipe_msg(m, e, msg, fp_out, decode, print);
313 mx_msg_close(m, &msg);
314 mutt_file_fclose(&fp_out);
315 rc = filter_wait(pid);
316 OptKeepQuiet = false;
317 }
318 else
319 {
320 /* handle tagged messages */
321 if ((WithCrypto != 0) && decode)
322 {
323 struct Email **ep = NULL;
324 ARRAY_FOREACH(ep, ea)
325 {
326 struct Email *e = *ep;
327 struct Message *msg = mx_msg_open(m, e);
328 if (msg)
329 {
332 mx_msg_close(m, &msg);
333 }
335 {
336 return 1;
337 }
338 }
339 }
340
341 if (split)
342 {
343 struct Email **ep = NULL;
344 ARRAY_FOREACH(ep, ea)
345 {
346 struct Email *e = *ep;
348 mutt_endwin();
349 pid = filter_create(cmd, &fp_out, NULL, NULL, NeoMutt->env);
350 if (pid < 0)
351 {
352 mutt_perror(_("Can't create filter process"));
353 return 1;
354 }
355 OptKeepQuiet = true;
356 pipe_msg(m, e, NULL, fp_out, decode, print);
357 /* add the message separator */
358 if (sep)
359 fputs(sep, fp_out);
360 mutt_file_fclose(&fp_out);
361 if (filter_wait(pid) != 0)
362 rc = 1;
363 OptKeepQuiet = false;
364 }
365 }
366 else
367 {
368 mutt_endwin();
369 pid = filter_create(cmd, &fp_out, NULL, NULL, NeoMutt->env);
370 if (pid < 0)
371 {
372 mutt_perror(_("Can't create filter process"));
373 return 1;
374 }
375 OptKeepQuiet = true;
376 struct Email **ep = NULL;
377 ARRAY_FOREACH(ep, ea)
378 {
379 struct Email *e = *ep;
381 pipe_msg(m, e, NULL, fp_out, decode, print);
382 /* add the message separator */
383 if (sep)
384 fputs(sep, fp_out);
385 }
386 mutt_file_fclose(&fp_out);
387 if (filter_wait(pid) != 0)
388 rc = 1;
389 OptKeepQuiet = false;
390 }
391 }
392
393 const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
394 if ((rc != 0) || c_wait_key)
396 return rc;
397}
398
404void mutt_pipe_message(struct Mailbox *m, struct EmailArray *ea)
405{
406 if (!m || !ea)
407 return;
408
409 struct Buffer *buf = buf_pool_get();
410
411 if (mw_get_field(_("Pipe to command: "), buf, MUTT_COMP_NONE, HC_EXT_COMMAND,
412 &CompleteFileOps, NULL) != 0)
413 {
414 goto cleanup;
415 }
416
417 if (buf_is_empty(buf))
418 goto cleanup;
419
420 expand_path(buf, false);
421 const bool c_pipe_decode = cs_subset_bool(NeoMutt->sub, "pipe_decode");
422 const bool c_pipe_split = cs_subset_bool(NeoMutt->sub, "pipe_split");
423 const char *const c_pipe_sep = cs_subset_string(NeoMutt->sub, "pipe_sep");
424 pipe_message(m, ea, buf_string(buf), c_pipe_decode, false, c_pipe_split, c_pipe_sep);
425
426cleanup:
427 buf_pool_release(&buf);
428}
429
437bool mutt_print_message(struct Mailbox *m, struct EmailArray *ea)
438{
439 if (!m || !ea)
440 return false;
441
442 const enum QuadOption c_print = cs_subset_quad(NeoMutt->sub, "print");
443 const char *const c_print_command = cs_subset_string(NeoMutt->sub, "print_command");
444 if (c_print && !c_print_command)
445 {
446 mutt_message(_("No printing command has been defined"));
447 return false;
448 }
449
450 int msg_count = ARRAY_SIZE(ea);
451 const char *msg = ngettext("Print message?", "Print tagged messages?", msg_count);
452 if (query_quadoption(msg, NeoMutt->sub, "print") != MUTT_YES)
453 {
454 return false;
455 }
456
457 const bool c_print_decode = cs_subset_bool(NeoMutt->sub, "print_decode");
458 const bool c_print_split = cs_subset_bool(NeoMutt->sub, "print_split");
459 if (pipe_message(m, ea, c_print_command, c_print_decode, true, c_print_split, "\f") == 0)
460 {
461 mutt_message(ngettext("Message printed", "Messages printed", msg_count));
462 return true;
463 }
464
465 mutt_message(ngettext("Message could not be printed",
466 "Messages could not be printed", msg_count));
467 return false;
468}
469
475bool mutt_select_sort(bool reverse)
476{
477 enum EmailSortType sort = EMAIL_SORT_DATE;
478
479 switch (mw_multi_choice(reverse ?
480 /* L10N: The highlighted letters must match the "Sort" options */
481 _("Rev-Sort (d)ate,(f)rm,(r)ecv,(s)ubj,t(o),(t)hread,(u)nsort,si(z)e,s(c)ore,s(p)am,(l)abel?") :
482 /* L10N: The highlighted letters must match the "Rev-Sort" options */
483 _("Sort (d)ate,(f)rm,(r)ecv,(s)ubj,t(o),(t)hread,(u)nsort,si(z)e,s(c)ore,s(p)am,(l)abel?"),
484 /* L10N: These must match the highlighted letters from "Sort" and "Rev-Sort" */
485 _("dfrsotuzcpl")))
486 {
487 case -1: /* abort - don't resort */
488 return false;
489
490 case 1: /* (d)ate */
491 sort = EMAIL_SORT_DATE;
492 break;
493
494 case 2: /* (f)rm */
495 sort = EMAIL_SORT_FROM;
496 break;
497
498 case 3: /* (r)ecv */
500 break;
501
502 case 4: /* (s)ubj */
503 sort = EMAIL_SORT_SUBJECT;
504 break;
505
506 case 5: /* t(o) */
507 sort = EMAIL_SORT_TO;
508 break;
509
510 case 6: /* (t)hread */
511 sort = EMAIL_SORT_THREADS;
512 break;
513
514 case 7: /* (u)nsort */
515 sort = EMAIL_SORT_UNSORTED;
516 break;
517
518 case 8: /* si(z)e */
519 sort = EMAIL_SORT_SIZE;
520 break;
521
522 case 9: /* s(c)ore */
523 sort = EMAIL_SORT_SCORE;
524 break;
525
526 case 10: /* s(p)am */
527 sort = EMAIL_SORT_SPAM;
528 break;
529
530 case 11: /* (l)abel */
531 sort = EMAIL_SORT_LABEL;
532 break;
533
534 default:
535 return false;
536 }
537
538 const unsigned char c_use_threads = cs_subset_enum(NeoMutt->sub, "use_threads");
539 const enum EmailSortType c_sort = cs_subset_sort(NeoMutt->sub, "sort");
540 int rc = CSR_ERR_CODE;
541 if ((sort != EMAIL_SORT_THREADS) || (c_use_threads == UT_UNSET))
542 {
543 if ((sort != EMAIL_SORT_THREADS) && (c_sort & SORT_LAST))
544 sort |= SORT_LAST;
545 if (reverse)
546 sort |= SORT_REVERSE;
547
548 rc = cs_subset_str_native_set(NeoMutt->sub, "sort", sort, NULL);
549 }
550 else
551 {
552 ASSERT((c_sort & SORT_MASK) != EMAIL_SORT_THREADS); /* See index_config_observer() */
553 /* Preserve the value of $sort, and toggle whether we are threaded. */
554 switch (c_use_threads)
555 {
556 case UT_FLAT:
557 rc = cs_subset_str_native_set(NeoMutt->sub, "use_threads",
558 reverse ? UT_REVERSE : UT_THREADS, NULL);
559 break;
560 case UT_THREADS:
561 rc = cs_subset_str_native_set(NeoMutt->sub, "use_threads",
562 reverse ? UT_REVERSE : UT_FLAT, NULL);
563 break;
564 case UT_REVERSE:
565 rc = cs_subset_str_native_set(NeoMutt->sub, "use_threads",
566 reverse ? UT_FLAT : UT_THREADS, NULL);
567 break;
568 default:
569 ASSERT(false);
570 }
571 }
572
573 return ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE));
574}
575
582{
583 bool rc = false;
584 struct Buffer *buf = buf_pool_get();
585
586 if (mw_get_field(_("Shell command: "), buf, MUTT_COMP_NONE, HC_EXT_COMMAND,
587 &CompleteFileOps, NULL) != 0)
588 {
589 goto done;
590 }
591
592 if (buf_is_empty(buf))
593 {
594 const char *const c_shell = cs_subset_string(NeoMutt->sub, "shell");
595 buf_strcpy(buf, c_shell);
596 }
597
598 if (buf_is_empty(buf))
599 {
600 goto done;
601 }
602
603 msgwin_clear_text(NULL);
604 mutt_endwin();
605 fflush(stdout);
606 int rc2 = mutt_system(buf_string(buf));
607 if (rc2 == -1)
608 mutt_debug(LL_DEBUG1, "Error running \"%s\"\n", buf_string(buf));
609
610 const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
611 if ((rc2 != 0) || c_wait_key)
613
614 rc = true;
615done:
616 buf_pool_release(&buf);
617 return rc;
618}
619
625{
626 struct Buffer *buf = buf_pool_get();
627 struct ParseContext *pc = parse_context_new();
628 struct ParseError *pe = parse_error_new();
629
630 window_redraw(NULL);
631
632 /* if enter is pressed after : with no command, just return */
633 struct FileCompletionData cdata = { false, NULL, NULL, NULL, win };
634 if ((mw_get_field(":", buf, MUTT_COMP_NONE, HC_NEO_COMMAND, &CompleteCommandOps, &cdata) != 0) ||
635 buf_is_empty(buf))
636 {
637 goto done;
638 }
639
640 enum CommandResult rc = parse_rc_line(buf, pc, pe);
641 if (!buf_is_empty(pe->message))
642 {
643 if (rc == MUTT_CMD_SUCCESS) /* command succeeded with message */
644 mutt_message("%s", buf_string(pe->message));
645 else if (rc == MUTT_CMD_ERROR)
646 mutt_error("%s", buf_string(pe->message));
647 else if (rc == MUTT_CMD_WARNING)
648 mutt_warning("%s", buf_string(pe->message));
649 }
650
651 if (NeoMutt)
652 {
653 // Running commands could cause anything to change, so let others know
655 }
656
657done:
658 buf_pool_release(&buf);
660 parse_error_free(&pe);
661}
662
668{
669 const char *pfx = NULL;
670
671 struct AddressList *al = mutt_get_address(env, &pfx);
672 if (!al)
673 return;
674
675 /* Note: We don't convert IDNA to local representation this time.
676 * That is intentional, so the user has an opportunity to copy &
677 * paste the on-the-wire form of the address to other, IDN-unable
678 * software. */
679 struct Buffer *buf = buf_pool_get();
680 mutt_addrlist_write(al, buf, false);
681 mutt_message("%s: %s", pfx, buf_string(buf));
682 buf_pool_release(&buf);
683}
684
692static void set_copy_flags(struct Email *e, enum MessageTransformOpt transform_opt,
693 CopyMessageFlags *cmflags, CopyHeaderFlags *chflags)
694{
695 *cmflags = MUTT_CM_NONE;
696 *chflags = CH_UPDATE_LEN;
697
698 const bool need_decrypt = (transform_opt == TRANSFORM_DECRYPT) &&
699 (e->security & SEC_ENCRYPT);
700 const bool want_pgp = (WithCrypto & APPLICATION_PGP);
701 const bool want_smime = (WithCrypto & APPLICATION_SMIME);
702 const bool is_pgp = mutt_is_application_pgp(e->body) & SEC_ENCRYPT;
703 const bool is_smime = mutt_is_application_smime(e->body) & SEC_ENCRYPT;
704
705 if (need_decrypt && want_pgp && mutt_is_multipart_encrypted(e->body))
706 {
707 *chflags = CH_NONEWLINE | CH_XMIT | CH_MIME;
708 *cmflags = MUTT_CM_DECODE_PGP;
709 }
710 else if (need_decrypt && want_pgp && is_pgp)
711 {
712 *chflags = CH_XMIT | CH_MIME | CH_TXTPLAIN;
713 *cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
714 }
715 else if (need_decrypt && want_smime && is_smime)
716 {
717 *chflags = CH_NONEWLINE | CH_XMIT | CH_MIME;
718 *cmflags = MUTT_CM_DECODE_SMIME;
719 }
720 else if (transform_opt == TRANSFORM_DECODE)
721 {
722 *chflags = CH_XMIT | CH_MIME | CH_TXTPLAIN | CH_DECODE; // then decode RFC2047
723 *cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
724 const bool c_copy_decode_weed = cs_subset_bool(NeoMutt->sub, "copy_decode_weed");
725 if (c_copy_decode_weed)
726 {
727 *chflags |= CH_WEED; // and respect $weed
728 *cmflags |= MUTT_CM_WEED;
729 }
730 }
731}
732
743int mutt_save_message_mbox(struct Mailbox *m_src, struct Email *e, enum MessageSaveOpt save_opt,
744 enum MessageTransformOpt transform_opt, struct Mailbox *m_dst)
745{
747 CopyHeaderFlags chflags = CH_NONE;
748 int rc;
749
750 set_copy_flags(e, transform_opt, &cmflags, &chflags);
751
752 struct Message *msg = mx_msg_open(m_src, e);
753 if (msg && transform_opt != TRANSFORM_NONE)
754 {
756 }
757
758 rc = mutt_append_message(m_dst, m_src, e, msg, cmflags, chflags);
759 mx_msg_close(m_src, &msg);
760 if (rc != 0)
761 return rc;
762
763 if (save_opt == SAVE_MOVE)
764 {
765 mutt_set_flag(m_src, e, MUTT_DELETE, true, true);
766 mutt_set_flag(m_src, e, MUTT_PURGE, true, true);
767 const bool c_delete_untag = cs_subset_bool(NeoMutt->sub, "delete_untag");
768 if (c_delete_untag)
769 mutt_set_flag(m_src, e, MUTT_TAG, false, true);
770 }
771
772 return 0;
773}
774
784int mutt_save_message(struct Mailbox *m, struct EmailArray *ea,
785 enum MessageSaveOpt save_opt, enum MessageTransformOpt transform_opt)
786{
787 if (!ea || ARRAY_EMPTY(ea))
788 return -1;
789
790 int rc = -1;
791 int tagged_progress_count = 0;
792 unsigned int msg_count = ARRAY_SIZE(ea);
793 struct Mailbox *m_save = NULL;
794
795 struct Buffer *buf = buf_pool_get();
796 struct stat st = { 0 };
797 struct Email *e_cur = *ARRAY_GET(ea, 0);
798
799 const SecurityFlags security_flags = WithCrypto ? e_cur->security : SEC_NONE;
800 const bool is_passphrase_needed = security_flags & SEC_ENCRYPT;
801
802 const char *prompt = NULL;
803 const char *progress_msg = NULL;
804
805 // Set prompt and progress_msg
806 switch (save_opt)
807 {
808 case SAVE_COPY:
809 // L10N: Progress meter message when copying tagged messages
810 progress_msg = (msg_count > 1) ? _("Copying tagged messages...") : NULL;
811 switch (transform_opt)
812 {
813 case TRANSFORM_NONE:
814 prompt = (msg_count > 1) ? _("Copy tagged to mailbox") : _("Copy to mailbox");
815 break;
817 prompt = (msg_count > 1) ? _("Decrypt-copy tagged to mailbox") :
818 _("Decrypt-copy to mailbox");
819 break;
820 case TRANSFORM_DECODE:
821 prompt = (msg_count > 1) ? _("Decode-copy tagged to mailbox") :
822 _("Decode-copy to mailbox");
823 break;
824 }
825 break;
826
827 case SAVE_MOVE:
828 // L10N: Progress meter message when saving tagged messages
829 progress_msg = (msg_count > 1) ? _("Saving tagged messages...") : NULL;
830 switch (transform_opt)
831 {
832 case TRANSFORM_NONE:
833 prompt = (msg_count > 1) ? _("Save tagged to mailbox") : _("Save to mailbox");
834 break;
836 prompt = (msg_count > 1) ? _("Decrypt-save tagged to mailbox") :
837 _("Decrypt-save to mailbox");
838 break;
839 case TRANSFORM_DECODE:
840 prompt = (msg_count > 1) ? _("Decode-save tagged to mailbox") :
841 _("Decode-save to mailbox");
842 break;
843 }
844 break;
845 }
846
848 mutt_default_save(buf, e_cur);
849 pretty_mailbox(buf);
850
851 if (mw_enter_fname(prompt, buf, false, NULL, false, NULL, NULL, MUTT_SEL_NONE) == -1)
852 {
853 goto cleanup;
854 }
855
856 size_t pathlen = buf_len(buf);
857 if (pathlen == 0)
858 goto cleanup;
859
860 mutt_path_tidy(buf, true);
861
862 /* This is an undocumented feature of ELM pointed out to me by Felix von
863 * Leitner <leitner@prz.fu-berlin.de> */
866 if (mutt_str_equal(buf_string(buf), "."))
868 else
870
871 expand_path(buf, false);
872
873 /* check to make sure that this file is really the one the user wants */
874 if (mutt_save_confirm(buf_string(buf), &st) != 0)
875 goto cleanup;
876
877 if (is_passphrase_needed && (transform_opt != TRANSFORM_NONE) &&
878 !crypt_valid_passphrase(security_flags))
879 {
880 rc = -1;
881 goto errcleanup;
882 }
883
884 mutt_message(_("Copying to %s..."), buf_string(buf));
885
886 enum MailboxType mailbox_type = imap_path_probe(buf_string(buf), NULL);
887 if ((m->type == MUTT_IMAP) && (transform_opt == TRANSFORM_NONE) && (mailbox_type == MUTT_IMAP))
888 {
889 rc = imap_copy_messages(m, ea, buf_string(buf), save_opt);
890 switch (rc)
891 {
892 /* success */
893 case 0:
895 rc = 0;
896 if (save_opt == SAVE_MOVE)
897 {
898 const bool c_delete_untag = cs_subset_bool(NeoMutt->sub, "delete_untag");
899 if (c_delete_untag)
900 {
901 struct Email **ep = NULL;
902 ARRAY_FOREACH(ep, ea)
903 {
904 mutt_set_flag(m, *ep, MUTT_TAG, false, true);
905 }
906 }
907 }
908 goto cleanup;
909 /* non-fatal error: continue to fetch/append */
910 case 1:
911 break;
912 /* fatal error, abort */
913 case -1:
914 default:
915 goto errcleanup;
916 }
917 }
918
920 m_save = mx_path_resolve(buf_string(buf));
921 bool old_append = m_save->append;
922 OpenMailboxFlags mbox_flags = MUTT_APPEND;
923 /* Display a tagged message progress counter, rather than (for
924 * IMAP) a per-message progress counter */
925 if (msg_count > 1)
926 mbox_flags |= MUTT_QUIET;
927 if (!mx_mbox_open(m_save, mbox_flags))
928 {
929 rc = -1;
930 mailbox_free(&m_save);
931 goto errcleanup;
932 }
933 m_save->append = true;
934
935 /* If we're saving to a compressed mailbox, the stats won't be updated
936 * until the next open. Until then, improvise. */
937 struct Mailbox *m_comp = NULL;
938 if (m_save->compress_info)
939 {
940 m_comp = mailbox_find(m_save->realpath);
941 }
942 /* We probably haven't been opened yet */
943 if (m_comp && (m_comp->msg_count == 0))
944 m_comp = NULL;
945
946 if (msg_count == 1)
947 {
948 rc = mutt_save_message_mbox(m, e_cur, save_opt, transform_opt, m_save);
949 if (rc != 0)
950 {
951 mx_mbox_close(m_save);
952 m_save->append = old_append;
953 goto errcleanup;
954 }
955
956 if (m_comp)
957 {
958 m_comp->msg_count++;
959 if (!e_cur->read)
960 {
961 m_comp->msg_unread++;
962 if (!e_cur->old)
963 m_comp->msg_new++;
964 }
965 if (e_cur->flagged)
966 m_comp->msg_flagged++;
967 }
968 }
969 else
970 {
971 rc = 0;
972
973#ifdef USE_NOTMUCH
974 if (m->type == MUTT_NOTMUCH)
975 nm_db_longrun_init(m, true);
976#endif
977 struct Progress *progress = progress_new(MUTT_PROGRESS_WRITE, msg_count);
978 progress_set_message(progress, "%s", progress_msg);
979 struct Email **ep = NULL;
980 ARRAY_FOREACH(ep, ea)
981 {
982 struct Email *e = *ep;
983 progress_update(progress, ++tagged_progress_count, -1);
985 rc = mutt_save_message_mbox(m, e, save_opt, transform_opt, m_save);
986 if (rc != 0)
987 break;
988
989 if (m_comp)
990 {
991 struct Email *e2 = e;
992 m_comp->msg_count++;
993 if (!e2->read)
994 {
995 m_comp->msg_unread++;
996 if (!e2->old)
997 m_comp->msg_new++;
998 }
999 if (e2->flagged)
1000 m_comp->msg_flagged++;
1001 }
1002 }
1003 progress_free(&progress);
1004
1005#ifdef USE_NOTMUCH
1006 if (m->type == MUTT_NOTMUCH)
1008#endif
1009 if (rc != 0)
1010 {
1011 mx_mbox_close(m_save);
1012 m_save->append = old_append;
1013 goto errcleanup;
1014 }
1015 }
1016
1017 const bool need_mailbox_cleanup = ((m_save->type == MUTT_MBOX) ||
1018 (m_save->type == MUTT_MMDF));
1019
1020 mx_mbox_close(m_save);
1021 m_save->append = old_append;
1022
1023 if (need_mailbox_cleanup)
1025
1027 rc = 0;
1028
1029errcleanup:
1030 if (rc != 0)
1031 {
1032 switch (save_opt)
1033 {
1034 case SAVE_MOVE:
1035 if (msg_count > 1)
1036 {
1037 // L10N: Message when an index tagged save operation fails for some reason
1038 mutt_error(_("Error saving tagged messages"));
1039 }
1040 else
1041 {
1042 // L10N: Message when an index/pager save operation fails for some reason
1043 mutt_error(_("Error saving message"));
1044 }
1045 break;
1046 case SAVE_COPY:
1047 if (msg_count > 1)
1048 {
1049 // L10N: Message when an index tagged copy operation fails for some reason
1050 mutt_error(_("Error copying tagged messages"));
1051 }
1052 else
1053 {
1054 // L10N: Message when an index/pager copy operation fails for some reason
1055 mutt_error(_("Error copying message"));
1056 }
1057 break;
1058 }
1059 }
1060
1061 mailbox_free(&m_save);
1062
1063cleanup:
1064 buf_pool_release(&buf);
1065 return rc;
1066}
1067
1077bool mutt_edit_content_type(struct Email *e, struct Body *b, FILE *fp)
1078{
1079 struct Buffer *buf = buf_pool_get();
1080 struct Buffer *charset = buf_pool_get();
1081 struct Buffer *obuf = buf_pool_get();
1082 struct Buffer *tmp = buf_pool_get();
1083
1084 bool rc = false;
1085 bool charset_changed = false;
1086 bool type_changed = false;
1087 bool structure_changed = false;
1088
1089 char *cp = mutt_param_get(&b->parameter, "charset");
1090 buf_strcpy(charset, cp);
1091
1092 buf_printf(buf, "%s/%s", BODY_TYPE(b), b->subtype);
1093 buf_copy(obuf, buf);
1094 if (!TAILQ_EMPTY(&b->parameter))
1095 {
1096 struct Parameter *np = NULL;
1097 TAILQ_FOREACH(np, &b->parameter, entries)
1098 {
1099 mutt_addr_cat(tmp->data, tmp->dsize, np->value, MimeSpecials);
1100 buf_add_printf(buf, "; %s=%s", np->attribute, buf_string(tmp));
1101 }
1102 }
1103
1104 if ((mw_get_field("Content-Type: ", buf, MUTT_COMP_NONE, HC_OTHER, NULL, NULL) != 0) ||
1105 buf_is_empty(buf))
1106 {
1107 goto done;
1108 }
1109
1110 /* clean up previous junk */
1112 FREE(&b->subtype);
1113
1115
1116 buf_printf(tmp, "%s/%s", BODY_TYPE(b), NONULL(b->subtype));
1117 type_changed = !mutt_istr_equal(buf_string(tmp), buf_string(obuf));
1118 charset_changed = !mutt_istr_equal(buf_string(charset),
1119 mutt_param_get(&b->parameter, "charset"));
1120
1121 /* if in send mode, check for conversion - current setting is default. */
1122
1123 if (!e && (b->type == TYPE_TEXT) && charset_changed)
1124 {
1125 buf_printf(tmp, _("Convert to %s upon sending?"),
1126 mutt_param_get(&b->parameter, "charset"));
1127 enum QuadOption ans = query_yesorno(buf_string(tmp), b->noconv ? MUTT_NO : MUTT_YES);
1128 if (ans != MUTT_ABORT)
1129 b->noconv = (ans == MUTT_NO);
1130 }
1131
1132 /* inform the user */
1133
1134 buf_printf(tmp, "%s/%s", BODY_TYPE(b), NONULL(b->subtype));
1135 if (type_changed)
1136 mutt_message(_("Content-Type changed to %s"), buf_string(tmp));
1137 if ((b->type == TYPE_TEXT) && charset_changed)
1138 {
1139 if (type_changed)
1140 mutt_sleep(1);
1141 mutt_message(b->noconv ? _("Character set changed to %s; not converting") :
1142 _("Character set changed to %s; converting"),
1143 mutt_param_get(&b->parameter, "charset"));
1144 }
1145
1146 b->force_charset |= charset_changed;
1147
1148 if (!is_multipart(b) && b->parts)
1149 {
1150 structure_changed = true;
1151 mutt_body_free(&b->parts);
1152 }
1153 if (!mutt_is_message_type(b->type, b->subtype) && b->email)
1154 {
1155 structure_changed = true;
1156 b->email->body = NULL;
1157 email_free(&b->email);
1158 }
1159
1160 if (fp && !b->parts && (is_multipart(b) || mutt_is_message_type(b->type, b->subtype)))
1161 {
1162 structure_changed = true;
1163 mutt_parse_part(fp, b);
1164 }
1165
1166 if ((WithCrypto != 0) && e)
1167 {
1168 if (e->body == b)
1169 e->security = SEC_NONE;
1170
1171 e->security |= crypt_query(b);
1172 }
1173
1174 rc = structure_changed | type_changed;
1175
1176done:
1177 buf_pool_release(&buf);
1178 buf_pool_release(&charset);
1179 buf_pool_release(&obuf);
1180 buf_pool_release(&tmp);
1181 return rc;
1182}
1183
1190static bool check_traditional_pgp(struct Mailbox *m, struct Email *e)
1191{
1192 bool rc = false;
1193
1195
1196 struct Message *msg = mx_msg_open(m, e);
1197 if (msg)
1198 {
1199 mutt_parse_mime_message(e, msg->fp);
1200 if (crypt_pgp_check_traditional(msg->fp, e->body, false))
1201 {
1202 e->security = crypt_query(e->body);
1203 rc = true;
1204 }
1205
1207 mx_msg_close(m, &msg);
1208 }
1209 return rc;
1210}
1211
1218bool mutt_check_traditional_pgp(struct Mailbox *m, struct EmailArray *ea)
1219{
1220 bool rc = false;
1221
1222 struct Email **ep = NULL;
1223 ARRAY_FOREACH(ep, ea)
1224 {
1225 struct Email *e = *ep;
1227 rc = check_traditional_pgp(m, e) || rc;
1228 }
1229
1230 return rc;
1231}
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition address.c:1473
void mutt_addr_cat(char *buf, size_t buflen, const char *value, const char *specials)
Copy a string and wrap it in quotes if it contains special characters.
Definition address.c:715
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition address.c:1217
int mutt_addrlist_parse2(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition address.c:651
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition address.c:1304
Email Address Handling.
const struct CompleteOps CompleteAliasOps
Auto-Completion of Aliases.
Definition complete.c:108
Email Aliases.
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition alias.c:297
struct AddressList * mutt_get_address(struct Envelope *env, const char **prefix)
Get an Address from an Envelope.
Definition alias.c:329
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition array.h:74
#define ARRAY_SIZE(head)
The number of elements stored.
Definition array.h:87
#define ARRAY_GET(head, idx)
Return the element at index.
Definition array.h:109
void mutt_parse_mime_message(struct Email *e, FILE *fp)
Parse a MIME email.
Definition commands.c:629
GUI display the mailboxes in a side panel.
const struct CompleteOps CompleteFileOps
Auto-Completion of Files.
Definition complete.c:152
Select a Mailbox from a list.
@ MUTT_SEL_NONE
No flags are set.
Definition lib.h:59
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:168
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition buffer.c:211
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition buffer.c:497
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition buffer.c:383
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:89
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:298
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:401
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition buffer.c:607
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition buffer.c:342
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
@ CMD_MESSAGE_HOOK
:message-hook
Definition command.h:97
CommandResult
Error codes for command_t parse functions.
Definition command.h:37
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition command.h:40
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition command.h:38
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition command.h:39
const struct CompleteOps CompleteCommandOps
Auto-Completion of Commands.
Definition helpers.c:534
Auto-completion.
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition helpers.c:192
unsigned char cs_subset_enum(const struct ConfigSubset *sub, const char *name)
Get a enumeration config item by name.
Definition helpers.c:71
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition helpers.c:266
Convenience wrapper for the config headers.
#define CSR_SUC_NO_CHANGE
The value hasn't changed.
Definition set.h:42
#define CSR_ERR_CODE
Problem with the code.
Definition set.h:34
#define CSR_RESULT(x)
Extract the result code from CSR_* flags.
Definition set.h:53
#define CSR_SUCCESS
Action completed successfully.
Definition set.h:33
#define SORT_MASK
Mask for the sort id.
Definition sort.h:39
#define SORT_LAST
Sort thread by last-X, e.g. received date.
Definition sort.h:41
#define SORT_REVERSE
Reverse the order of the sort.
Definition sort.h:40
int mutt_append_message(struct Mailbox *m_dst, struct Mailbox *m_src, struct Email *e, struct Message *msg, CopyMessageFlags cmflags, CopyHeaderFlags chflags)
Append a message.
Definition copy_email.c:995
int mutt_copy_message(FILE *fp_out, struct Email *e, struct Message *msg, CopyMessageFlags cmflags, CopyHeaderFlags chflags, int wraplen)
Copy a message from a Mailbox.
Definition copy_email.c:920
@ MUTT_CM_DECODE_SMIME
Used for decoding S/MIME messages.
Definition copy_email.h:52
@ MUTT_CM_DECODE_PGP
Used for decoding PGP messages.
Definition copy_email.h:51
@ MUTT_CM_DECODE
Decode the message body into text/plain.
Definition copy_email.h:44
@ MUTT_CM_PRINTING
Printing the message - display light.
Definition copy_email.h:49
@ MUTT_CM_CHARCONV
Perform character set conversions.
Definition copy_email.h:48
@ MUTT_CM_WEED
Weed message/rfc822 attachment headers.
Definition copy_email.h:47
@ MUTT_CM_NONE
No flags are set.
Definition copy_email.h:41
uint32_t CopyHeaderFlags
Definition copy_email.h:89
@ CH_XMIT
Transmitting this message? (Ignore Lines: and Content-Length:).
Definition copy_email.h:69
@ CH_UPDATE_LEN
Update Lines: and Content-Length:
Definition copy_email.h:76
@ CH_WEED
Weed the headers?
Definition copy_email.h:67
@ CH_FROM
Retain the "From " message separator?
Definition copy_email.h:70
@ CH_MIME
Ignore MIME fields.
Definition copy_email.h:75
@ CH_NONE
No flags are set.
Definition copy_email.h:65
@ CH_TXTPLAIN
Generate text/plain MIME headers.
Definition copy_email.h:77
@ CH_DECODE
Do RFC2047 header decoding.
Definition copy_email.h:68
@ CH_NONEWLINE
Don't output terminating newline after the header.
Definition copy_email.h:74
@ CH_REORDER
Re-order output of headers (specified by 'header-order').
Definition copy_email.h:73
uint16_t CopyMessageFlags
Definition copy_email.h:55
Convenience wrapper for the core headers.
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition mailbox.c:90
struct Mailbox * mailbox_find(const char *path)
Find the mailbox with a given path.
Definition mailbox.c:151
MailboxType
Supported mailbox formats.
Definition mailbox.h:40
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition mailbox.h:50
@ MUTT_MMDF
'mmdf' Mailbox type
Definition mailbox.h:45
@ MUTT_IMAP
'IMAP' Mailbox type
Definition mailbox.h:49
@ MUTT_MBOX
'mbox' Mailbox type
Definition mailbox.h:44
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition crypt.c:610
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition crypt.c:131
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition crypt.c:444
SecurityFlags mutt_is_application_pgp(const struct Body *b)
Does the message use PGP?
Definition crypt.c:549
SecurityFlags crypt_query(struct Body *b)
Check out the type of encryption used.
Definition crypt.c:693
bool crypt_pgp_check_traditional(FILE *fp, struct Body *b, bool just_one)
Wrapper for CryptModuleSpecs::pgp_check_traditional().
Definition cryptglue.c:321
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition curs_lib.c:174
void mutt_endwin(void)
Shutdown curses.
Definition curs_lib.c:152
Edit a string.
@ MUTT_COMP_NONE
No flags are set.
Definition wdata.h:46
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition body.c:58
void email_free(struct Email **ptr)
Free an Email.
Definition email.c:46
Structs that make up an email.
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition parse.c:1982
void mutt_parse_content_type(const char *s, struct Body *b)
Parse a content type.
Definition parse.c:464
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition parse.c:1653
EmailSortType
Methods for sorting Emails.
Definition sort.h:53
@ EMAIL_SORT_LABEL
Sort by the emails label.
Definition sort.h:57
@ EMAIL_SORT_DATE_RECEIVED
Sort by when the message was delivered locally.
Definition sort.h:55
@ EMAIL_SORT_SPAM
Sort by the email's spam score.
Definition sort.h:60
@ EMAIL_SORT_SCORE
Sort by the email's score.
Definition sort.h:58
@ EMAIL_SORT_DATE
Sort by the date the email was sent.
Definition sort.h:54
@ EMAIL_SORT_THREADS
Sort by email threads.
Definition sort.h:62
@ EMAIL_SORT_SUBJECT
Sort by the email's subject.
Definition sort.h:61
@ EMAIL_SORT_FROM
Sort by the email's From field.
Definition sort.h:56
@ EMAIL_SORT_UNSORTED
Sort by the order the messages appear in the mailbox.
Definition sort.h:64
@ EMAIL_SORT_SIZE
Sort by the size of the email.
Definition sort.h:59
@ EMAIL_SORT_TO
Sort by the email's To field.
Definition sort.h:63
bool mutt_select_sort(bool reverse)
Ask the user for a sort method.
Definition external.c:475
void mutt_pipe_message(struct Mailbox *m, struct EmailArray *ea)
Pipe a message.
Definition external.c:404
bool mutt_check_traditional_pgp(struct Mailbox *m, struct EmailArray *ea)
Check if a message has inline PGP content.
Definition external.c:1218
static bool check_traditional_pgp(struct Mailbox *m, struct Email *e)
Check for an inline PGP content.
Definition external.c:1190
static void pipe_set_flags(bool decode, bool print, CopyMessageFlags *cmflags, CopyHeaderFlags *chflags)
Generate flags for copy header/message.
Definition external.c:187
int mutt_save_message_mbox(struct Mailbox *m_src, struct Email *e, enum MessageSaveOpt save_opt, enum MessageTransformOpt transform_opt, struct Mailbox *m_dst)
Save a message to a given mailbox.
Definition external.c:743
void index_bounce_message(struct Mailbox *m, struct EmailArray *ea)
Bounce an email.
Definition external.c:87
int mutt_save_message(struct Mailbox *m, struct EmailArray *ea, enum MessageSaveOpt save_opt, enum MessageTransformOpt transform_opt)
Save an email.
Definition external.c:784
static struct Buffer LastSaveFolder
The folder the user last saved to. Used by ci_save_message().
Definition external.c:72
bool mutt_shell_escape(void)
Invoke a command in a subshell.
Definition external.c:581
void external_cleanup(void)
Clean up commands globals.
Definition external.c:77
static void set_copy_flags(struct Email *e, enum MessageTransformOpt transform_opt, CopyMessageFlags *cmflags, CopyHeaderFlags *chflags)
Set the flags for a message copy.
Definition external.c:692
bool mutt_edit_content_type(struct Email *e, struct Body *b, FILE *fp)
Edit the content type of an attachment.
Definition external.c:1077
void mutt_enter_command(struct MuttWindow *win)
Enter a neomutt command.
Definition external.c:624
bool mutt_print_message(struct Mailbox *m, struct EmailArray *ea)
Print a message.
Definition external.c:437
static int pipe_message(struct Mailbox *m, struct EmailArray *ea, const char *cmd, bool decode, bool print, bool split, const char *sep)
Pipe message to a command.
Definition external.c:275
static void pipe_msg(struct Mailbox *m, struct Email *e, struct Message *msg, FILE *fp, bool decode, bool print)
Pipe a message.
Definition external.c:223
void mutt_display_address(struct Envelope *env)
Display the address of a message.
Definition external.c:667
Manage where the email is piped to external commands.
MessageTransformOpt
Message transformation option.
Definition external.h:42
@ TRANSFORM_NONE
No transformation.
Definition external.h:43
@ TRANSFORM_DECODE
Decode message.
Definition external.h:45
@ TRANSFORM_DECRYPT
Decrypt message.
Definition external.h:44
MessageSaveOpt
Message save option.
Definition external.h:52
@ SAVE_MOVE
Move message to another mailbox, removing the original.
Definition external.h:54
@ SAVE_COPY
Copy message, making a duplicate in another mailbox.
Definition external.h:53
void mutt_file_resolve_symlink(struct Buffer *buf)
Resolve a symlink in place.
Definition file.c:1555
#define mutt_file_fclose(FP)
Definition file.h:144
void mutt_set_flag(struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool upd_mbox)
Set a flag on an email.
Definition flags.c:54
bool OptKeepQuiet
(pseudo) shut up the message and refresh functions while we are executing an external program
Definition globals.c:49
Global variables.
int mw_enter_fname(const char *prompt, struct Buffer *fname, bool mailbox, struct Mailbox *m, bool multiple, char ***files, int *numfiles, SelectFileFlags flags)
Ask the user to select a file -.
Definition curs_lib.c:237
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition window.c:502
int mw_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question -.
Definition question.c:62
#define mutt_warning(...)
Definition logging2.h:92
#define mutt_error(...)
Definition logging2.h:94
#define mutt_message(...)
Definition logging2.h:93
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
#define mutt_perror(...)
Definition logging2.h:95
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox?
Definition imap.c:2683
Convenience wrapper for the gui headers.
@ UT_FLAT
Unthreaded.
Definition thread.h:104
@ UT_UNSET
Not yet set by user, stick to legacy semantics.
Definition thread.h:103
@ UT_THREADS
Normal threading (root above subthreads).
Definition thread.h:105
@ UT_REVERSE
Reverse threading (subthreads above root).
Definition thread.h:106
Read/write command history from/to a file.
@ HC_EXT_COMMAND
External commands.
Definition lib.h:56
@ HC_ALIAS
Aliases.
Definition lib.h:57
@ HC_NEO_COMMAND
NeoMutt commands.
Definition lib.h:58
@ HC_OTHER
Miscellaneous strings.
Definition lib.h:61
void mutt_default_save(struct Buffer *path, struct Email *e)
Find the default save path for an email.
Definition exec.c:218
void exec_message_hook(struct Mailbox *m, struct Email *e, enum CommandId id)
Perform a message hook.
Definition exec.c:137
Hook Commands.
IMAP network mailbox.
int imap_copy_messages(struct Mailbox *m, struct EmailArray *ea, const char *dest, enum MessageSaveOpt save_opt)
Server COPY messages to another folder.
Definition message.c:1722
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
const char MimeSpecials[]
Characters that need special treatment in MIME.
Definition mime.c:69
@ TYPE_TEXT
Type: 'text/*'.
Definition mime.h:38
#define BODY_TYPE(body)
Get the type name of a body part.
Definition mime.h:92
#define is_multipart(body)
Check if a body part is multipart or a message container.
Definition mime.h:84
void msgwin_clear_text(struct MuttWindow *win)
Clear the text in the Message Window.
Definition msgwin.c:556
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition filter.c:231
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, char **envlist)
Set up filter program.
Definition filter.c:220
Convenience wrapper for the library headers.
#define _(a)
Definition message.h:28
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition notify.c:173
bool mutt_path_tidy(struct Buffer *path, bool is_dir)
Remove unnecessary parts of a path.
Definition path.c:169
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:678
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:666
Many unsorted constants and some structs.
int mutt_system(const char *cmd)
Run an external command.
Definition system.c:51
@ MUTT_PURGE
Messages to be purged (bypass trash).
Definition mutt.h:96
@ MUTT_TAG
Tagged messages.
Definition mutt.h:99
@ MUTT_DELETE
Messages to be deleted.
Definition mutt.h:94
#define PATH_MAX
Definition mutt.h:49
void mutt_clear_error(void)
Clear the message line (bottom line of screen).
NeoMutt Logging.
void mailbox_restore_timestamp(const char *path, struct stat *st)
Restore the timestamp of a mailbox.
Mailbox helper functions.
void window_redraw(struct MuttWindow *win)
Reflow, recalc and repaint a tree of Windows.
void mutt_sleep(short s)
Sleep for a while.
Definition muttlib.c:795
void pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition muttlib.c:431
void expand_path(struct Buffer *buf, bool regex)
Create the canonical path.
Definition muttlib.c:122
int mutt_save_confirm(const char *s, struct stat *st)
Ask the user to save.
Definition muttlib.c:698
Some miscellaneous functions.
int mx_msg_close(struct Mailbox *m, struct Message **ptr)
Close a message.
Definition mx.c:1185
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition mx.c:285
struct Message * mx_msg_open(struct Mailbox *m, struct Email *e)
Return a stream pointer for a message.
Definition mx.c:1139
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition mx.c:1650
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
Definition mx.c:595
API for mailboxes.
uint8_t OpenMailboxFlags
Definition mxapi.h:51
@ MUTT_QUIET
Do not print any messages.
Definition mxapi.h:46
@ MUTT_APPEND
Open mailbox for appending messages.
Definition mxapi.h:44
API for encryption/signing of emails.
uint16_t SecurityFlags
Definition lib.h:104
@ SEC_NONE
No flags are set.
Definition lib.h:91
@ SEC_ENCRYPT
Email is encrypted.
Definition lib.h:92
#define PGP_TRADITIONAL_CHECKED
Email has a traditional (inline) signature.
Definition lib.h:108
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition lib.h:106
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition lib.h:107
#define WithCrypto
Definition lib.h:132
@ NT_GLOBAL_COMMAND
A NeoMutt command.
Definition neomutt.h:71
@ NT_GLOBAL
Not object-related, NotifyGlobal.
Definition notify_type.h:46
void nm_db_longrun_done(struct Mailbox *m)
Finish a long transaction.
Definition db.c:393
void nm_db_longrun_init(struct Mailbox *m, bool writable)
Start a long transaction.
Definition db.c:378
Notmuch virtual mailbox type.
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition parameter.c:85
void mutt_param_free(struct ParameterList *pl)
Free a ParameterList.
Definition parameter.c:62
Text parsing functions.
void parse_context_free(struct ParseContext **pptr)
Free a ParseContext.
Definition pcontext.c:48
struct ParseContext * parse_context_new(void)
Create a new ParseContext.
Definition pcontext.c:37
void parse_error_free(struct ParseError **pptr)
Free a ParseError.
Definition perror.c:50
struct ParseError * parse_error_new(void)
Create a new ParseError.
Definition perror.c:37
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
Progress Bar.
@ MUTT_PROGRESS_WRITE
Progress tracks elements, according to $write_inc.
Definition lib.h:85
struct Progress * progress_new(enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition progress.c:139
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition progress.c:110
void progress_set_message(struct Progress *progress, const char *fmt,...) __attribute__((__format__(__printf__
bool progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition progress.c:80
QuadOption
Possible values for a quad-option.
Definition quad.h:36
@ MUTT_ABORT
User aborted the question (with Ctrl-G).
Definition quad.h:37
@ MUTT_NO
User answered 'No', or assume 'No'.
Definition quad.h:38
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition quad.h:39
Ask the user a question.
enum QuadOption query_quadoption(const char *prompt, struct ConfigSubset *sub, const char *name)
Ask the user a quad-question.
Definition question.c:384
enum QuadOption query_yesorno(const char *prompt, enum QuadOption def)
Ask the user a Yes/No question.
Definition question.c:329
#define TAILQ_FOREACH(var, head, field)
Definition queue.h:782
#define TAILQ_HEAD_INITIALIZER(head)
Definition queue.h:694
#define TAILQ_EMPTY(head)
Definition queue.h:778
enum CommandResult parse_rc_line(struct Buffer *line, struct ParseContext *pc, struct ParseError *pe)
Parse a line of user config.
Definition rc.c:45
Convenience wrapper for the send headers.
int mutt_bounce_message(FILE *fp, struct Mailbox *m, struct Email *e, struct AddressList *to, struct ConfigSubset *sub)
Bounce an email message.
Definition sendlib.c:888
#define ASSERT(COND)
Definition signal2.h:59
#define NONULL(x)
Definition string2.h:44
#define S_BKG
Definition string2.h:48
The body of an email.
Definition body.h:36
struct Body * parts
parts of a multipart or message/rfc822
Definition body.h:73
bool noconv
Don't do character set conversion.
Definition body.h:46
struct ParameterList parameter
Parameters of the content-type.
Definition body.h:63
struct Email * email
header information for message/rfc822
Definition body.h:74
bool force_charset
Send mode: don't adjust the character set when in send-mode.
Definition body.h:44
char * subtype
content-type subtype
Definition body.h:61
unsigned int type
content-type primary type, ContentType
Definition body.h:40
String manipulation buffer.
Definition buffer.h:36
size_t dsize
Length of data.
Definition buffer.h:39
char * data
Pointer to data.
Definition buffer.h:37
The envelope/body of an email.
Definition email.h:39
bool read
Email is read.
Definition email.h:50
struct Envelope * env
Envelope information.
Definition email.h:68
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition email.h:43
struct Body * body
List of MIME parts.
Definition email.h:69
bool old
Email is seen, but unread.
Definition email.h:49
bool flagged
Marked important?
Definition email.h:47
The header of an Email.
Definition envelope.h:57
struct AddressList from
Email's 'From' list.
Definition envelope.h:59
Input for the file completion function.
Definition curs_lib.h:39
struct MuttWindow * win
Current Focused Window.
Definition curs_lib.h:44
A mailbox.
Definition mailbox.h:81
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition mailbox.h:83
bool append
Mailbox is opened in append mode.
Definition mailbox.h:111
int msg_new
Number of new messages.
Definition mailbox.h:94
int msg_count
Total number of messages.
Definition mailbox.h:90
enum MailboxType type
Mailbox type.
Definition mailbox.h:104
int msg_flagged
Number of flagged messages.
Definition mailbox.h:92
void * compress_info
Compressed mbox module private data.
Definition mailbox.h:123
int msg_unread
Number of unread messages.
Definition mailbox.h:91
A local copy of an email.
Definition message.h:34
FILE * fp
pointer to the message data
Definition message.h:35
Container for Accounts, Notifications.
Definition neomutt.h:41
char ** env
Private copy of the environment variables.
Definition neomutt.h:57
struct Notify * notify
Notifications handler.
Definition neomutt.h:45
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
Attribute associated with a MIME part.
Definition parameter.h:33
char * attribute
Parameter name.
Definition parameter.h:34
char * value
Parameter value.
Definition parameter.h:35
Context for config parsing (history/backtrace).
Definition pcontext.h:34
Detailed error information from config parsing.
Definition perror.h:34
struct Buffer * message
Error message.
Definition perror.h:35
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition subset.c:303