NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
commands.c
Go to the documentation of this file.
1 
31 #include "config.h"
32 #include <assert.h>
33 #include <errno.h>
34 #include <limits.h>
35 #include <stdbool.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <sys/stat.h>
39 #include <unistd.h>
40 #include "mutt/lib.h"
41 #include "address/lib.h"
42 #include "config/lib.h"
43 #include "email/lib.h"
44 #include "core/lib.h"
45 #include "alias/lib.h"
46 #include "gui/lib.h"
47 #include "mutt.h"
48 #include "commands.h"
49 #include "menu/lib.h"
50 #include "ncrypt/lib.h"
51 #include "pager/lib.h"
52 #include "progress/lib.h"
53 #include "question/lib.h"
54 #include "send/lib.h"
55 #include "attachments.h"
56 #include "browser.h"
57 #include "context.h"
58 #include "copy.h"
59 #include "format_flags.h"
60 #include "hdrline.h"
61 #include "hook.h"
62 #include "icommands.h"
63 #include "init.h"
64 #include "keymap.h"
65 #include "mutt_commands.h"
66 #include "mutt_globals.h"
67 #include "mutt_logging.h"
68 #include "mutt_mailbox.h"
69 #include "mutt_thread.h"
70 #include "muttlib.h"
71 #include "mx.h"
72 #include "options.h"
73 #include "protos.h"
74 #ifdef USE_IMAP
75 #include "imap/lib.h"
76 #endif
77 #ifdef USE_NOTMUCH
78 #include "notmuch/lib.h"
79 #endif
80 #ifdef ENABLE_NLS
81 #include <libintl.h>
82 #endif
83 #ifdef USE_AUTOCRYPT
84 #include "autocrypt/lib.h"
85 #endif
86 
87 static const char *ExtPagerProgress = "all";
88 
90 static struct Buffer LastSaveFolder = { 0 };
91 
96 {
97  mutt_buffer_dealloc(&LastSaveFolder);
98 }
99 
105 static void process_protected_headers(struct Mailbox *m, struct Email *e)
106 {
107  struct Envelope *prot_headers = NULL;
108  regmatch_t pmatch[1];
109 
110  const bool c_crypt_protected_headers_read =
111  cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_read");
112 #ifdef USE_AUTOCRYPT
113  const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
114  if (!c_crypt_protected_headers_read && !c_autocrypt)
115  return;
116 #else
117  if (!c_crypt_protected_headers_read)
118  return;
119 #endif
120 
121  /* Grab protected headers to update in the index */
122  if (e->security & SEC_SIGN)
123  {
124  /* Don't update on a bad signature.
125  *
126  * This is a simplification. It's possible the headers are in the
127  * encrypted part of a nested encrypt/signed. But properly handling that
128  * case would require more complexity in the decryption handlers, which
129  * I'm not sure is worth it. */
130  if (!(e->security & SEC_GOODSIGN))
131  return;
132 
133  if (mutt_is_multipart_signed(e->body) && e->body->parts)
134  {
135  prot_headers = e->body->parts->mime_headers;
136  }
137  else if (((WithCrypto & APPLICATION_SMIME) != 0) && mutt_is_application_smime(e->body))
138  {
139  prot_headers = e->body->mime_headers;
140  }
141  }
142  if (!prot_headers && (e->security & SEC_ENCRYPT))
143  {
144  if (((WithCrypto & APPLICATION_PGP) != 0) &&
147  {
148  prot_headers = e->body->mime_headers;
149  }
150  else if (((WithCrypto & APPLICATION_SMIME) != 0) && mutt_is_application_smime(e->body))
151  {
152  prot_headers = e->body->mime_headers;
153  }
154  }
155 
156  /* Update protected headers in the index and header cache. */
157  if (c_crypt_protected_headers_read && prot_headers && prot_headers->subject &&
158  !mutt_str_equal(e->env->subject, prot_headers->subject))
159  {
160  if (m->subj_hash && e->env->real_subj)
162 
163  mutt_str_replace(&e->env->subject, prot_headers->subject);
164  FREE(&e->env->disp_subj);
165  const struct Regex *c_reply_regex =
166  cs_subset_regex(NeoMutt->sub, "reply_regex");
167  if (mutt_regex_capture(c_reply_regex, e->env->subject, 1, pmatch))
168  e->env->real_subj = e->env->subject + pmatch[0].rm_eo;
169  else
170  e->env->real_subj = e->env->subject;
171 
172  if (m->subj_hash)
174 
175  mx_save_hcache(m, e);
176 
177  /* Also persist back to the message headers if this is set */
178  const bool c_crypt_protected_headers_save =
179  cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_save");
180  if (c_crypt_protected_headers_save)
181  {
183  e->changed = true;
184  m->changed = true;
185  }
186  }
187 
188 #ifdef USE_AUTOCRYPT
189  if (c_autocrypt && (e->security & SEC_ENCRYPT) && prot_headers && prot_headers->autocrypt_gossip)
190  {
191  mutt_autocrypt_process_gossip_header(m, e, prot_headers);
192  }
193 #endif
194 }
195 
207 int mutt_display_message(struct MuttWindow *win_index, struct MuttWindow *win_ibar,
208  struct MuttWindow *win_pager, struct MuttWindow *win_pbar,
209  struct Mailbox *m, struct Email *e)
210 {
211  int rc = 0;
212  bool builtin = false;
214  CopyHeaderFlags chflags;
215  pid_t filterpid = -1;
216  struct Buffer *tempfile = NULL;
217  int res;
218 
219  struct Message *msg = mx_msg_open(m, e->msgno);
220  if (!msg)
221  {
222  return -1;
223  }
224 
225  mutt_parse_mime_message(m, e, msg->fp);
227 
228  char columns[16];
229  // win_pager might not be visible and have a size yet, so use win_index
230  snprintf(columns, sizeof(columns), "%d", win_index->state.cols);
231  mutt_envlist_set("COLUMNS", columns, true);
232 
233  /* see if crypto is needed for this message. if so, we should exit curses */
234  if ((WithCrypto != 0) && e->security)
235  {
236  if (e->security & SEC_ENCRYPT)
237  {
238  if (e->security & APPLICATION_SMIME)
241  goto cleanup;
242 
243  cmflags |= MUTT_CM_VERIFY;
244  }
245  else if (e->security & SEC_SIGN)
246  {
247  /* find out whether or not the verify signature */
248  /* L10N: Used for the $crypt_verify_sig prompt */
249  const enum QuadOption c_crypt_verify_sig =
250  cs_subset_quad(NeoMutt->sub, "crypt_verify_sig");
251  if (query_quadoption(c_crypt_verify_sig, _("Verify signature?")) == MUTT_YES)
252  {
253  cmflags |= MUTT_CM_VERIFY;
254  }
255  }
256  }
257 
258  if (cmflags & MUTT_CM_VERIFY || e->security & SEC_ENCRYPT)
259  {
260  if (e->security & APPLICATION_PGP)
261  {
262  if (!TAILQ_EMPTY(&e->env->from))
264 
266  }
267 
268  if (e->security & APPLICATION_SMIME)
270  }
271 
272  FILE *fp_filter_out = NULL;
273  tempfile = mutt_buffer_pool_get();
274  mutt_buffer_mktemp(tempfile);
275  FILE *fp_out = mutt_file_fopen(mutt_buffer_string(tempfile), "w");
276  if (!fp_out)
277  {
278  mutt_error(_("Could not create temporary file"));
279  goto cleanup;
280  }
281 
282  const char *const c_display_filter =
283  cs_subset_string(NeoMutt->sub, "display_filter");
284  if (c_display_filter)
285  {
286  fp_filter_out = fp_out;
287  fp_out = NULL;
288  filterpid = filter_create_fd(c_display_filter, &fp_out, NULL, NULL, -1,
289  fileno(fp_filter_out), -1);
290  if (filterpid < 0)
291  {
292  mutt_error(_("Can't create display filter"));
293  mutt_file_fclose(&fp_filter_out);
294  unlink(mutt_buffer_string(tempfile));
295  goto cleanup;
296  }
297  }
298 
299  const char *const c_pager = cs_subset_string(NeoMutt->sub, "pager");
300  if (!c_pager || mutt_str_equal(c_pager, "builtin"))
301  builtin = true;
302  else
303  {
304  char buf[1024] = { 0 };
305  const char *const c_pager_format =
306  cs_subset_string(NeoMutt->sub, "pager_format");
307  mutt_make_string(buf, sizeof(buf), win_index->state.cols, NONULL(c_pager_format),
308  m, Context ? Context->msg_in_pager : -1, e,
310  fputs(buf, fp_out);
311  fputs("\n\n", fp_out);
312  }
313 
314  const bool c_weed = cs_subset_bool(NeoMutt->sub, "weed");
315  chflags = (c_weed ? (CH_WEED | CH_REORDER) : CH_NO_FLAGS) | CH_DECODE | CH_FROM | CH_DISPLAY;
316 #ifdef USE_NOTMUCH
317  if (m->type == MUTT_NOTMUCH)
318  chflags |= CH_VIRTUAL;
319 #endif
320  res = mutt_copy_message(fp_out, m, e, msg, cmflags, chflags, win_index->state.cols);
321 
322  if (((mutt_file_fclose(&fp_out) != 0) && (errno != EPIPE)) || (res < 0))
323  {
324  mutt_error(_("Could not copy message"));
325  if (fp_filter_out)
326  {
327  filter_wait(filterpid);
328  mutt_file_fclose(&fp_filter_out);
329  }
331  goto cleanup;
332  }
333 
334  if (fp_filter_out && (filter_wait(filterpid) != 0))
336 
337  mutt_file_fclose(&fp_filter_out); /* XXX - check result? */
338 
339  if (WithCrypto)
340  {
341  /* update crypto information for this message */
342  e->security &= ~(SEC_GOODSIGN | SEC_BADSIGN);
343  e->security |= crypt_query(e->body);
344 
345  /* Remove color cache for this message, in case there
346  * are color patterns for both ~g and ~V */
347  e->pair = 0;
348 
349  /* Process protected headers and autocrypt gossip headers */
351  }
352 
353  if (builtin)
354  {
355  if ((WithCrypto != 0) && (e->security & APPLICATION_SMIME) && (cmflags & MUTT_CM_VERIFY))
356  {
357  if (e->security & SEC_GOODSIGN)
358  {
359  if (crypt_smime_verify_sender(m, e, msg) == 0)
360  mutt_message(_("S/MIME signature successfully verified"));
361  else
362  mutt_error(_("S/MIME certificate owner does not match sender"));
363  }
364  else if (e->security & SEC_PARTSIGN)
365  mutt_message(_("Warning: Part of this message has not been signed"));
366  else if (e->security & SEC_SIGN || e->security & SEC_BADSIGN)
367  mutt_error(_("S/MIME signature could NOT be verified"));
368  }
369 
370  if ((WithCrypto != 0) && (e->security & APPLICATION_PGP) && (cmflags & MUTT_CM_VERIFY))
371  {
372  if (e->security & SEC_GOODSIGN)
373  mutt_message(_("PGP signature successfully verified"));
374  else if (e->security & SEC_PARTSIGN)
375  mutt_message(_("Warning: Part of this message has not been signed"));
376  else if (e->security & SEC_SIGN)
377  mutt_message(_("PGP signature could NOT be verified"));
378  }
379 
380  /* Invoke the builtin pager */
381  struct PagerData pdata = { 0 };
382  struct PagerView pview = { &pdata };
383 
384  pdata.fp = msg->fp;
385  pdata.fname = mutt_buffer_string(tempfile);
386 
387  pview.mode = PAGER_MODE_EMAIL;
388  pview.banner = NULL;
389  pview.flags = MUTT_PAGER_MESSAGE | (e->body->nowrap ? MUTT_PAGER_NOWRAP : 0);
390  pview.win_ibar = win_ibar;
391  pview.win_index = win_index;
392  pview.win_pbar = win_pbar;
393  pview.win_pager = win_pager;
394  rc = mutt_pager(&pview);
395  }
396  else
397  {
398  mutt_endwin();
399 
400  struct Buffer *cmd = mutt_buffer_pool_get();
401  mutt_buffer_printf(cmd, "%s %s", NONULL(c_pager), mutt_buffer_string(tempfile));
402  int r = mutt_system(mutt_buffer_string(cmd));
403  if (r == -1)
404  mutt_error(_("Error running \"%s\""), mutt_buffer_string(cmd));
405  unlink(mutt_buffer_string(tempfile));
407 
408  if (!OptNoCurses)
409  keypad(stdscr, true);
410  if (r != -1)
411  mutt_set_flag(m, e, MUTT_READ, true);
412  const bool c_prompt_after = cs_subset_bool(NeoMutt->sub, "prompt_after");
413  if ((r != -1) && c_prompt_after)
414  {
415  mutt_unget_event(mutt_any_key_to_continue(_("Command: ")), 0);
416  rc = km_dokey(MENU_PAGER);
417  }
418  else
419  rc = 0;
420  }
421 
422 cleanup:
423  mx_msg_close(m, &msg);
424  mutt_envlist_unset("COLUMNS");
425  mutt_buffer_pool_release(&tempfile);
426  return rc;
427 }
428 
434 void ci_bounce_message(struct Mailbox *m, struct EmailList *el)
435 {
436  if (!m || !el || STAILQ_EMPTY(el))
437  return;
438 
439  char prompt[8193];
440  char scratch[8192];
441  char buf[8192] = { 0 };
442  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
443  char *err = NULL;
444  int rc;
445  int msg_count = 0;
446 
447  struct EmailNode *en = NULL;
448  STAILQ_FOREACH(en, el, entries)
449  {
450  /* RFC5322 mandates a From: header,
451  * so warn before bouncing messages without one */
452  if (TAILQ_EMPTY(&en->email->env->from))
453  mutt_error(_("Warning: message contains no From: header"));
454 
455  msg_count++;
456  }
457 
458  if (msg_count == 1)
459  mutt_str_copy(prompt, _("Bounce message to: "), sizeof(prompt));
460  else
461  mutt_str_copy(prompt, _("Bounce tagged messages to: "), sizeof(prompt));
462 
463  rc = mutt_get_field(prompt, buf, sizeof(buf), MUTT_ALIAS, false, NULL, NULL);
464  if (rc || (buf[0] == '\0'))
465  return;
466 
467  mutt_addrlist_parse2(&al, buf);
468  if (TAILQ_EMPTY(&al))
469  {
470  mutt_error(_("Error parsing address"));
471  return;
472  }
473 
474  mutt_expand_aliases(&al);
475 
476  if (mutt_addrlist_to_intl(&al, &err) < 0)
477  {
478  mutt_error(_("Bad IDN: '%s'"), err);
479  FREE(&err);
480  mutt_addrlist_clear(&al);
481  return;
482  }
483 
484  buf[0] = '\0';
485  mutt_addrlist_write(&al, buf, sizeof(buf), true);
486 
487 #define EXTRA_SPACE (15 + 7 + 2)
488  snprintf(scratch, sizeof(scratch),
489  ngettext("Bounce message to %s?", "Bounce messages to %s?", msg_count), buf);
490 
491  const size_t width = msgwin_get_width();
492  if (mutt_strwidth(scratch) > (width - EXTRA_SPACE))
493  {
494  mutt_simple_format(prompt, sizeof(prompt), 0, width - EXTRA_SPACE,
495  JUSTIFY_LEFT, 0, scratch, sizeof(scratch), false);
496  mutt_str_cat(prompt, sizeof(prompt), "...?");
497  }
498  else
499  mutt_str_copy(prompt, scratch, sizeof(prompt));
500 
501  const enum QuadOption c_bounce = cs_subset_quad(NeoMutt->sub, "bounce");
502  if (query_quadoption(c_bounce, prompt) != MUTT_YES)
503  {
504  mutt_addrlist_clear(&al);
506  mutt_message(ngettext("Message not bounced", "Messages not bounced", msg_count));
507  return;
508  }
509 
511 
512  struct Message *msg = NULL;
513  STAILQ_FOREACH(en, el, entries)
514  {
515  msg = mx_msg_open(m, en->email->msgno);
516  if (!msg)
517  {
518  rc = -1;
519  break;
520  }
521 
522  rc = mutt_bounce_message(msg->fp, m, en->email, &al, NeoMutt->sub);
523  mx_msg_close(m, &msg);
524 
525  if (rc < 0)
526  break;
527  }
528 
529  mutt_addrlist_clear(&al);
530  /* If no error, or background, display message. */
531  if ((rc == 0) || (rc == S_BKG))
532  mutt_message(ngettext("Message bounced", "Messages bounced", msg_count));
533 }
534 
542 static void pipe_set_flags(bool decode, bool print, CopyMessageFlags *cmflags,
543  CopyHeaderFlags *chflags)
544 {
545  if (decode)
546  {
547  *chflags |= CH_DECODE | CH_REORDER;
548  *cmflags |= MUTT_CM_DECODE | MUTT_CM_CHARCONV;
549 
550  const bool c_print_decode_weed =
551  cs_subset_bool(NeoMutt->sub, "print_decode_weed");
552  const bool c_pipe_decode_weed =
553  cs_subset_bool(NeoMutt->sub, "pipe_decode_weed");
554  if (print ? c_print_decode_weed : c_pipe_decode_weed)
555  {
556  *chflags |= CH_WEED;
557  *cmflags |= MUTT_CM_WEED;
558  }
559 
560  /* Just as with copy-decode, we need to update the mime fields to avoid
561  * confusing programs that may process the email. However, we don't want
562  * to force those fields to appear in printouts. */
563  if (!print)
564  *chflags |= CH_MIME | CH_TXTPLAIN;
565  }
566 
567  if (print)
568  *cmflags |= MUTT_CM_PRINTING;
569 }
570 
580 static void pipe_msg(struct Mailbox *m, struct Email *e, struct Message *msg,
581  FILE *fp, bool decode, bool print)
582 {
584  CopyHeaderFlags chflags = CH_FROM;
585 
586  pipe_set_flags(decode, print, &cmflags, &chflags);
587 
588  if ((WithCrypto != 0) && decode && e->security & SEC_ENCRYPT)
589  {
591  return;
592  endwin();
593  }
594 
595  const bool own_msg = !msg;
596  if (own_msg)
597  {
598  msg = mx_msg_open(m, e->msgno);
599  if (!msg)
600  {
601  return;
602  }
603  }
604 
605  if (decode)
606  {
607  mutt_parse_mime_message(m, e, msg->fp);
608  }
609 
610  mutt_copy_message(fp, m, e, msg, cmflags, chflags, 0);
611 
612  if (own_msg)
613  {
614  mx_msg_close(m, &msg);
615  }
616 }
617 
632 static int pipe_message(struct Mailbox *m, struct EmailList *el, const char *cmd,
633  bool decode, bool print, bool split, const char *sep)
634 {
635  if (!m || !el)
636  return 1;
637 
638  struct EmailNode *en = STAILQ_FIRST(el);
639  if (!en)
640  return 1;
641 
642  int rc = 0;
643  pid_t pid;
644  FILE *fp_out = NULL;
645 
646  if (!STAILQ_NEXT(en, entries))
647  {
648  /* handle a single message */
650 
651  struct Message *msg = mx_msg_open(m, en->email->msgno);
652  if (msg && WithCrypto && decode)
653  {
654  mutt_parse_mime_message(m, en->email, msg->fp);
655  if ((en->email->security & SEC_ENCRYPT) &&
657  {
658  mx_msg_close(m, &msg);
659  return 1;
660  }
661  }
662  mutt_endwin();
663 
664  pid = filter_create(cmd, &fp_out, NULL, NULL);
665  if (pid < 0)
666  {
667  mutt_perror(_("Can't create filter process"));
668  mx_msg_close(m, &msg);
669  return 1;
670  }
671 
672  OptKeepQuiet = true;
673  pipe_msg(m, en->email, msg, fp_out, decode, print);
674  mx_msg_close(m, &msg);
675  mutt_file_fclose(&fp_out);
676  rc = filter_wait(pid);
677  OptKeepQuiet = false;
678  }
679  else
680  {
681  /* handle tagged messages */
682  if ((WithCrypto != 0) && decode)
683  {
684  STAILQ_FOREACH(en, el, entries)
685  {
686  struct Message *msg = mx_msg_open(m, en->email->msgno);
687  if (msg)
688  {
689  mutt_parse_mime_message(m, en->email, msg->fp);
691  mx_msg_close(m, &msg);
692  }
693  if ((en->email->security & SEC_ENCRYPT) &&
695  {
696  return 1;
697  }
698  }
699  }
700 
701  if (split)
702  {
703  STAILQ_FOREACH(en, el, entries)
704  {
706  mutt_endwin();
707  pid = filter_create(cmd, &fp_out, NULL, NULL);
708  if (pid < 0)
709  {
710  mutt_perror(_("Can't create filter process"));
711  return 1;
712  }
713  OptKeepQuiet = true;
714  pipe_msg(m, en->email, NULL, fp_out, decode, print);
715  /* add the message separator */
716  if (sep)
717  fputs(sep, fp_out);
718  mutt_file_fclose(&fp_out);
719  if (filter_wait(pid) != 0)
720  rc = 1;
721  OptKeepQuiet = false;
722  }
723  }
724  else
725  {
726  mutt_endwin();
727  pid = filter_create(cmd, &fp_out, NULL, NULL);
728  if (pid < 0)
729  {
730  mutt_perror(_("Can't create filter process"));
731  return 1;
732  }
733  OptKeepQuiet = true;
734  STAILQ_FOREACH(en, el, entries)
735  {
737  pipe_msg(m, en->email, NULL, fp_out, decode, print);
738  /* add the message separator */
739  if (sep)
740  fputs(sep, fp_out);
741  }
742  mutt_file_fclose(&fp_out);
743  if (filter_wait(pid) != 0)
744  rc = 1;
745  OptKeepQuiet = false;
746  }
747  }
748 
749  const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
750  if ((rc != 0) || c_wait_key)
752  return rc;
753 }
754 
760 void mutt_pipe_message(struct Mailbox *m, struct EmailList *el)
761 {
762  if (!m || !el)
763  return;
764 
765  struct Buffer *buf = mutt_buffer_pool_get();
766 
767  if (mutt_buffer_get_field(_("Pipe to command: "), buf, MUTT_CMD, false, NULL,
768  NULL, NULL) != 0)
769  {
770  goto cleanup;
771  }
772 
773  if (mutt_buffer_len(buf) == 0)
774  goto cleanup;
775 
777  const bool c_pipe_decode = cs_subset_bool(NeoMutt->sub, "pipe_decode");
778  const bool c_pipe_split = cs_subset_bool(NeoMutt->sub, "pipe_split");
779  const char *const c_pipe_sep = cs_subset_string(NeoMutt->sub, "pipe_sep");
780  pipe_message(m, el, mutt_buffer_string(buf), c_pipe_decode, false, c_pipe_split, c_pipe_sep);
781 
782 cleanup:
784 }
785 
791 void mutt_print_message(struct Mailbox *m, struct EmailList *el)
792 {
793  if (!m || !el)
794  return;
795 
796  const enum QuadOption c_print = cs_subset_quad(NeoMutt->sub, "print");
797  const char *const c_print_command =
798  cs_subset_string(NeoMutt->sub, "print_command");
799  if (c_print && !c_print_command)
800  {
801  mutt_message(_("No printing command has been defined"));
802  return;
803  }
804 
805  int msg_count = 0;
806  struct EmailNode *en = NULL;
807  STAILQ_FOREACH(en, el, entries)
808  {
809  msg_count++;
810  }
811 
812  if (query_quadoption(c_print, (msg_count == 1) ?
813  _("Print message?") :
814  _("Print tagged messages?")) != MUTT_YES)
815  {
816  return;
817  }
818 
819  const bool c_print_decode = cs_subset_bool(NeoMutt->sub, "print_decode");
820  const bool c_print_split = cs_subset_bool(NeoMutt->sub, "print_split");
821  if (pipe_message(m, el, c_print_command, c_print_decode, true, c_print_split, "\f") == 0)
822  mutt_message(ngettext("Message printed", "Messages printed", msg_count));
823  else
824  {
825  mutt_message(ngettext("Message could not be printed",
826  "Messages could not be printed", msg_count));
827  }
828 }
829 
835 bool mutt_select_sort(bool reverse)
836 {
837  enum SortType sort = SORT_DATE;
838 
839  switch (mutt_multi_choice(reverse ?
840  /* L10N: The highlighted letters must match the "Sort" options */
841  _("Rev-Sort "
842  "(d)ate,(f)rm,(r)ecv,(s)ubj,t(o),(t)hread,(u)"
843  "nsort,si(z)e,s(c)ore,s(p)am,(l)abel?") :
844  /* L10N: The highlighted letters must match the "Rev-Sort" options */
845  _("Sort "
846  "(d)ate,(f)rm,(r)ecv,(s)ubj,t(o),(t)hread,(u)"
847  "nsort,si(z)e,s(c)ore,s(p)am,(l)abel?"),
848  /* L10N: These must match the highlighted letters from "Sort" and "Rev-Sort" */
849  _("dfrsotuzcpl")))
850  {
851  case -1: /* abort - don't resort */
852  return -1;
853 
854  case 1: /* (d)ate */
855  sort = SORT_DATE;
856  break;
857 
858  case 2: /* (f)rm */
859  sort = SORT_FROM;
860  break;
861 
862  case 3: /* (r)ecv */
863  sort = SORT_RECEIVED;
864  break;
865 
866  case 4: /* (s)ubj */
867  sort = SORT_SUBJECT;
868  break;
869 
870  case 5: /* t(o) */
871  sort = SORT_TO;
872  break;
873 
874  case 6: /* (t)hread */
875  sort = SORT_THREADS;
876  break;
877 
878  case 7: /* (u)nsort */
879  sort = SORT_ORDER;
880  break;
881 
882  case 8: /* si(z)e */
883  sort = SORT_SIZE;
884  break;
885 
886  case 9: /* s(c)ore */
887  sort = SORT_SCORE;
888  break;
889 
890  case 10: /* s(p)am */
891  sort = SORT_SPAM;
892  break;
893 
894  case 11: /* (l)abel */
895  sort = SORT_LABEL;
896  break;
897  }
898 
899  const unsigned char c_use_threads =
900  cs_subset_enum(NeoMutt->sub, "use_threads");
901  const short c_sort = cs_subset_sort(NeoMutt->sub, "sort");
902  int rc = CSR_ERR_CODE;
903  if ((sort != SORT_THREADS) || (c_use_threads == UT_UNSET))
904  {
905  if ((sort != SORT_THREADS) && (c_sort & SORT_LAST))
906  sort |= SORT_LAST;
907  if (reverse)
908  sort |= SORT_REVERSE;
909 
910  rc = cs_subset_str_native_set(NeoMutt->sub, "sort", sort, NULL);
911  }
912  else
913  {
914  assert((c_sort & SORT_MASK) != SORT_THREADS); /* See index_config_observer() */
915  /* Preserve the value of $sort, and toggle whether we are threaded. */
916  switch (c_use_threads)
917  {
918  case UT_FLAT:
919  rc = cs_subset_str_native_set(NeoMutt->sub, "use_threads",
920  reverse ? UT_REVERSE : UT_THREADS, NULL);
921  break;
922  case UT_THREADS:
923  rc = cs_subset_str_native_set(NeoMutt->sub, "use_threads",
924  reverse ? UT_REVERSE : UT_FLAT, NULL);
925  break;
926  case UT_REVERSE:
927  rc = cs_subset_str_native_set(NeoMutt->sub, "use_threads",
928  reverse ? UT_FLAT : UT_THREADS, NULL);
929  break;
930  default:
931  assert(false);
932  }
933  }
934 
935  return ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE));
936 }
937 
944 {
945  char buf[1024];
946 
947  buf[0] = '\0';
948  if (mutt_get_field(_("Shell command: "), buf, sizeof(buf), MUTT_CMD, false, NULL, NULL) != 0)
949  {
950  return false;
951  }
952 
953  const char *const c_shell = cs_subset_string(NeoMutt->sub, "shell");
954  if ((buf[0] == '\0') && c_shell)
955  mutt_str_copy(buf, c_shell, sizeof(buf));
956  if (buf[0] == '\0')
957  {
958  return false;
959  }
960 
962  mutt_endwin();
963  fflush(stdout);
964  int rc = mutt_system(buf);
965  if (rc == -1)
966  mutt_debug(LL_DEBUG1, "Error running \"%s\"", buf);
967 
968  const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
969  if ((rc != 0) || c_wait_key)
971 
972  return true;
973 }
974 
979 {
980  char buf[1024] = { 0 };
981 
982  window_redraw(NULL);
983  /* if enter is pressed after : with no command, just return */
984  if ((mutt_get_field(":", buf, sizeof(buf), MUTT_COMMAND, false, NULL, NULL) != 0) ||
985  (buf[0] == '\0'))
986  {
987  return;
988  }
989 
990  struct Buffer err = mutt_buffer_make(256);
991 
992  /* check if buf is a valid icommand, else fall back quietly to parse_rc_lines */
993  enum CommandResult rc = mutt_parse_icommand(buf, &err);
994  if (!mutt_buffer_is_empty(&err))
995  {
996  /* since errbuf could potentially contain printf() sequences in it,
997  * we must call mutt_error() in this fashion so that vsprintf()
998  * doesn't expect more arguments that we passed */
999  if (rc == MUTT_CMD_ERROR)
1000  mutt_error("%s", err.data);
1001  else
1002  mutt_warning("%s", err.data);
1003  }
1004  else if (rc != MUTT_CMD_SUCCESS)
1005  {
1006  rc = mutt_parse_rc_line(buf, &err);
1007  if (!mutt_buffer_is_empty(&err))
1008  {
1009  if (rc == MUTT_CMD_SUCCESS) /* command succeeded with message */
1010  mutt_message("%s", err.data);
1011  else if (rc == MUTT_CMD_ERROR)
1012  mutt_error("%s", err.data);
1013  else if (rc == MUTT_CMD_WARNING)
1014  mutt_warning("%s", err.data);
1015  }
1016  }
1017  /* else successful command */
1018 
1019  mutt_buffer_dealloc(&err);
1020 }
1021 
1027 {
1028  const char *pfx = NULL;
1029  char buf[128];
1030 
1031  struct AddressList *al = mutt_get_address(env, &pfx);
1032  if (!al)
1033  return;
1034 
1035  /* Note: We don't convert IDNA to local representation this time.
1036  * That is intentional, so the user has an opportunity to copy &
1037  * paste the on-the-wire form of the address to other, IDN-unable
1038  * software. */
1039  buf[0] = '\0';
1040  mutt_addrlist_write(al, buf, sizeof(buf), false);
1041  mutt_message("%s: %s", pfx, buf);
1042 }
1043 
1051 static void set_copy_flags(struct Email *e, enum MessageTransformOpt transform_opt,
1052  CopyMessageFlags *cmflags, CopyHeaderFlags *chflags)
1053 {
1054  *cmflags = MUTT_CM_NO_FLAGS;
1055  *chflags = CH_UPDATE_LEN;
1056 
1057  const bool need_decrypt =
1058  (transform_opt == TRANSFORM_DECRYPT) && (e->security & SEC_ENCRYPT);
1059  const bool want_pgp = (WithCrypto & APPLICATION_PGP);
1060  const bool want_smime = (WithCrypto & APPLICATION_SMIME);
1061  const bool is_pgp = mutt_is_application_pgp(e->body) & SEC_ENCRYPT;
1062  const bool is_smime = mutt_is_application_smime(e->body) & SEC_ENCRYPT;
1063 
1064  if (need_decrypt && want_pgp && mutt_is_multipart_encrypted(e->body))
1065  {
1066  *chflags = CH_NONEWLINE | CH_XMIT | CH_MIME;
1067  *cmflags = MUTT_CM_DECODE_PGP;
1068  }
1069  else if (need_decrypt && want_pgp && is_pgp)
1070  {
1071  *chflags = CH_XMIT | CH_MIME | CH_TXTPLAIN;
1072  *cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1073  }
1074  else if (need_decrypt && want_smime && is_smime)
1075  {
1076  *chflags = CH_NONEWLINE | CH_XMIT | CH_MIME;
1077  *cmflags = MUTT_CM_DECODE_SMIME;
1078  }
1079  else if (transform_opt == TRANSFORM_DECODE)
1080  {
1081  *chflags = CH_XMIT | CH_MIME | CH_TXTPLAIN | CH_DECODE; // then decode RFC2047
1082  *cmflags = MUTT_CM_DECODE | MUTT_CM_CHARCONV;
1083  const bool c_copy_decode_weed =
1084  cs_subset_bool(NeoMutt->sub, "copy_decode_weed");
1085  if (c_copy_decode_weed)
1086  {
1087  *chflags |= CH_WEED; // and respect $weed
1088  *cmflags |= MUTT_CM_WEED;
1089  }
1090  }
1091 }
1092 
1103 int mutt_save_message_ctx(struct Mailbox *m_src, struct Email *e, enum MessageSaveOpt save_opt,
1104  enum MessageTransformOpt transform_opt, struct Mailbox *m_dst)
1105 {
1107  CopyHeaderFlags chflags = CH_NO_FLAGS;
1108  int rc;
1109 
1110  set_copy_flags(e, transform_opt, &cmflags, &chflags);
1111 
1112  struct Message *msg = mx_msg_open(m_src, e->msgno);
1113  if (msg && transform_opt != TRANSFORM_NONE)
1114  {
1115  mutt_parse_mime_message(m_src, e, msg->fp);
1116  }
1117 
1118  rc = mutt_append_message(m_dst, m_src, e, msg, cmflags, chflags);
1119  mx_msg_close(m_src, &msg);
1120  if (rc != 0)
1121  return rc;
1122 
1123  if (save_opt == SAVE_MOVE)
1124  {
1125  mutt_set_flag(m_src, e, MUTT_DELETE, true);
1126  mutt_set_flag(m_src, e, MUTT_PURGE, true);
1127  const bool c_delete_untag = cs_subset_bool(NeoMutt->sub, "delete_untag");
1128  if (c_delete_untag)
1129  mutt_set_flag(m_src, e, MUTT_TAG, false);
1130  }
1131 
1132  return 0;
1133 }
1134 
1144 int mutt_save_message(struct Mailbox *m, struct EmailList *el,
1145  enum MessageSaveOpt save_opt, enum MessageTransformOpt transform_opt)
1146 {
1147  if (!el || STAILQ_EMPTY(el))
1148  return -1;
1149 
1150  int rc = -1;
1151  int tagged_progress_count = 0;
1152  unsigned int msg_count = 0;
1153 
1154  struct Buffer *buf = mutt_buffer_pool_get();
1155  struct stat st;
1156  struct EmailNode *en = NULL;
1157 
1158  STAILQ_FOREACH(en, el, entries)
1159  {
1160  msg_count++;
1161  }
1162  en = STAILQ_FIRST(el);
1163 
1164  const SecurityFlags security_flags = WithCrypto ? en->email->security : SEC_NO_FLAGS;
1165  const bool is_passphrase_needed = security_flags & SEC_ENCRYPT;
1166 
1167  const char *prompt = NULL;
1168  const char *progress_msg = NULL;
1169 
1170  // Set prompt and progress_msg
1171  switch (save_opt)
1172  {
1173  case SAVE_COPY:
1174  // L10N: Progress meter message when copying tagged messages
1175  progress_msg = (msg_count > 1) ? _("Copying tagged messages...") : NULL;
1176  switch (transform_opt)
1177  {
1178  case TRANSFORM_NONE:
1179  prompt = (msg_count > 1) ? _("Copy tagged to mailbox") : _("Copy to mailbox");
1180  break;
1181  case TRANSFORM_DECRYPT:
1182  prompt = (msg_count > 1) ? _("Decrypt-copy tagged to mailbox") :
1183  _("Decrypt-copy to mailbox");
1184  break;
1185  case TRANSFORM_DECODE:
1186  prompt = (msg_count > 1) ? _("Decode-copy tagged to mailbox") :
1187  _("Decode-copy to mailbox");
1188  break;
1189  }
1190  break;
1191 
1192  case SAVE_MOVE:
1193  // L10N: Progress meter message when saving tagged messages
1194  progress_msg = (msg_count > 1) ? _("Saving tagged messages...") : NULL;
1195  switch (transform_opt)
1196  {
1197  case TRANSFORM_NONE:
1198  prompt = (msg_count > 1) ? _("Save tagged to mailbox") : _("Save to mailbox");
1199  break;
1200  case TRANSFORM_DECRYPT:
1201  prompt = (msg_count > 1) ? _("Decrypt-save tagged to mailbox") :
1202  _("Decrypt-save to mailbox");
1203  break;
1204  case TRANSFORM_DECODE:
1205  prompt = (msg_count > 1) ? _("Decode-save tagged to mailbox") :
1206  _("Decode-save to mailbox");
1207  break;
1208  }
1209  break;
1210  }
1211 
1213  mutt_default_save(buf->data, buf->dsize, en->email);
1214  mutt_buffer_fix_dptr(buf);
1216 
1217  if (mutt_buffer_enter_fname(prompt, buf, false, NULL, false, NULL, NULL,
1218  MUTT_SEL_NO_FLAGS) == -1)
1219  {
1220  goto cleanup;
1221  }
1222 
1223  size_t pathlen = mutt_buffer_len(buf);
1224  if (pathlen == 0)
1225  goto cleanup;
1226 
1227  /* Trim any trailing '/' */
1228  if (buf->data[pathlen - 1] == '/')
1229  buf->data[pathlen - 1] = '\0';
1230 
1231  /* This is an undocumented feature of ELM pointed out to me by Felix von
1232  * Leitner <leitner@prz.fu-berlin.de> */
1233  if (mutt_buffer_len(&LastSaveFolder) == 0)
1234  mutt_buffer_alloc(&LastSaveFolder, PATH_MAX);
1235  if (mutt_str_equal(mutt_buffer_string(buf), "."))
1236  mutt_buffer_copy(buf, &LastSaveFolder);
1237  else
1238  mutt_buffer_strcpy(&LastSaveFolder, mutt_buffer_string(buf));
1239 
1241 
1242  /* check to make sure that this file is really the one the user wants */
1243  if (mutt_save_confirm(mutt_buffer_string(buf), &st) != 0)
1244  goto cleanup;
1245 
1246  if (is_passphrase_needed && (transform_opt != TRANSFORM_NONE) &&
1247  !crypt_valid_passphrase(security_flags))
1248  {
1249  rc = -1;
1250  goto errcleanup;
1251  }
1252 
1253  mutt_message(_("Copying to %s..."), mutt_buffer_string(buf));
1254 
1255 #ifdef USE_IMAP
1256  enum MailboxType mailbox_type = imap_path_probe(mutt_buffer_string(buf), NULL);
1257  if ((m->type == MUTT_IMAP) && (transform_opt == TRANSFORM_NONE) && (mailbox_type == MUTT_IMAP))
1258  {
1259  rc = imap_copy_messages(m, el, mutt_buffer_string(buf), save_opt);
1260  switch (rc)
1261  {
1262  /* success */
1263  case 0:
1264  mutt_clear_error();
1265  rc = 0;
1266  goto cleanup;
1267  /* non-fatal error: continue to fetch/append */
1268  case 1:
1269  break;
1270  /* fatal error, abort */
1271  case -1:
1272  goto errcleanup;
1273  }
1274  }
1275 #endif
1276 
1278  struct Mailbox *m_save = mx_path_resolve(mutt_buffer_string(buf));
1279  bool old_append = m_save->append;
1280  OpenMailboxFlags mbox_flags = MUTT_NEWFOLDER;
1281  /* Display a tagged message progress counter, rather than (for
1282  * IMAP) a per-message progress counter */
1283  if (msg_count > 1)
1284  mbox_flags |= MUTT_QUIET;
1285  if (!mx_mbox_open(m_save, mbox_flags))
1286  {
1287  rc = -1;
1288  mailbox_free(&m_save);
1289  goto errcleanup;
1290  }
1291  m_save->append = true;
1292 
1293 #ifdef USE_COMP_MBOX
1294  /* If we're saving to a compressed mailbox, the stats won't be updated
1295  * until the next open. Until then, improvise. */
1296  struct Mailbox *m_comp = NULL;
1297  if (m_save->compress_info)
1298  {
1299  m_comp = mailbox_find(m_save->realpath);
1300  }
1301  /* We probably haven't been opened yet */
1302  if (m_comp && (m_comp->msg_count == 0))
1303  m_comp = NULL;
1304 #endif
1305  if (msg_count == 1)
1306  {
1307  rc = mutt_save_message_ctx(m, en->email, save_opt, transform_opt, m_save);
1308  if (rc != 0)
1309  {
1310  mx_mbox_close(m_save);
1311  m_save->append = old_append;
1312  goto errcleanup;
1313  }
1314 #ifdef USE_COMP_MBOX
1315  if (m_comp)
1316  {
1317  m_comp->msg_count++;
1318  if (!en->email->read)
1319  {
1320  m_comp->msg_unread++;
1321  if (!en->email->old)
1322  m_comp->msg_new++;
1323  }
1324  if (en->email->flagged)
1325  m_comp->msg_flagged++;
1326  }
1327 #endif
1328  }
1329  else
1330  {
1331  rc = 0;
1332 
1333 #ifdef USE_NOTMUCH
1334  if (m->type == MUTT_NOTMUCH)
1335  nm_db_longrun_init(m, true);
1336 #endif
1337  struct Progress *progress = progress_new(progress_msg, MUTT_PROGRESS_WRITE, msg_count);
1338  STAILQ_FOREACH(en, el, entries)
1339  {
1340  progress_update(progress, ++tagged_progress_count, -1);
1342  rc = mutt_save_message_ctx(m, en->email, save_opt, transform_opt, m_save);
1343  if (rc != 0)
1344  break;
1345 #ifdef USE_COMP_MBOX
1346  if (m_comp)
1347  {
1348  struct Email *e2 = en->email;
1349  m_comp->msg_count++;
1350  if (!e2->read)
1351  {
1352  m_comp->msg_unread++;
1353  if (!e2->old)
1354  m_comp->msg_new++;
1355  }
1356  if (e2->flagged)
1357  m_comp->msg_flagged++;
1358  }
1359 #endif
1360  }
1361  progress_free(&progress);
1362 
1363 #ifdef USE_NOTMUCH
1364  if (m->type == MUTT_NOTMUCH)
1365  nm_db_longrun_done(m);
1366 #endif
1367  if (rc != 0)
1368  {
1369  mx_mbox_close(m_save);
1370  m_save->append = old_append;
1371  goto errcleanup;
1372  }
1373  }
1374 
1375  const bool need_mailbox_cleanup =
1376  ((m_save->type == MUTT_MBOX) || (m_save->type == MUTT_MMDF));
1377 
1378  mx_mbox_close(m_save);
1379  m_save->append = old_append;
1380 
1381  if (need_mailbox_cleanup)
1383 
1384  mutt_clear_error();
1385  rc = 0;
1386 
1387 errcleanup:
1388  if (rc != 0)
1389  {
1390  switch (save_opt)
1391  {
1392  case SAVE_MOVE:
1393  if (msg_count > 1)
1394  {
1395  // L10N: Message when an index tagged save operation fails for some reason
1396  mutt_error(_("Error saving tagged messages"));
1397  }
1398  else
1399  {
1400  // L10N: Message when an index/pager save operation fails for some reason
1401  mutt_error(_("Error saving message"));
1402  }
1403  break;
1404  case SAVE_COPY:
1405  if (msg_count > 1)
1406  {
1407  // L10N: Message when an index tagged copy operation fails for some reason
1408  mutt_error(_("Error copying tagged messages"));
1409  }
1410  else
1411  {
1412  // L10N: Message when an index/pager copy operation fails for some reason
1413  mutt_error(_("Error copying message"));
1414  }
1415  break;
1416  }
1417  }
1418 
1419 cleanup:
1421  return rc;
1422 }
1423 
1433 bool mutt_edit_content_type(struct Email *e, struct Body *b, FILE *fp)
1434 {
1435  char buf[1024];
1436  char obuf[1024];
1437  char tmp[256];
1438  char charset[256];
1439 
1440  bool charset_changed = false;
1441  bool type_changed = false;
1442  bool structure_changed = false;
1443 
1444  char *cp = mutt_param_get(&b->parameter, "charset");
1445  mutt_str_copy(charset, cp, sizeof(charset));
1446 
1447  snprintf(buf, sizeof(buf), "%s/%s", TYPE(b), b->subtype);
1448  mutt_str_copy(obuf, buf, sizeof(obuf));
1449  if (!TAILQ_EMPTY(&b->parameter))
1450  {
1451  size_t l = strlen(buf);
1452  struct Parameter *np = NULL;
1453  TAILQ_FOREACH(np, &b->parameter, entries)
1454  {
1455  mutt_addr_cat(tmp, sizeof(tmp), np->value, MimeSpecials);
1456  l += snprintf(buf + l, sizeof(buf) - l, "; %s=%s", np->attribute, tmp);
1457  if (l >= sizeof(buf))
1458  {
1459  // L10N: e.g. "text/plain; charset=UTF-8; ..."
1460  mutt_error(_("Content type is too long"));
1461  return false;
1462  }
1463  }
1464  }
1465 
1466  if ((mutt_get_field("Content-Type: ", buf, sizeof(buf), MUTT_COMP_NO_FLAGS,
1467  false, NULL, NULL) != 0) ||
1468  (buf[0] == '\0'))
1469  {
1470  return false;
1471  }
1472 
1473  /* clean up previous junk */
1475  FREE(&b->subtype);
1476 
1477  mutt_parse_content_type(buf, b);
1478 
1479  snprintf(tmp, sizeof(tmp), "%s/%s", TYPE(b), NONULL(b->subtype));
1480  type_changed = !mutt_istr_equal(tmp, obuf);
1481  charset_changed =
1482  !mutt_istr_equal(charset, mutt_param_get(&b->parameter, "charset"));
1483 
1484  /* if in send mode, check for conversion - current setting is default. */
1485 
1486  if (!e && (b->type == TYPE_TEXT) && charset_changed)
1487  {
1488  snprintf(tmp, sizeof(tmp), _("Convert to %s upon sending?"),
1489  mutt_param_get(&b->parameter, "charset"));
1490  enum QuadOption ans = mutt_yesorno(tmp, b->noconv ? MUTT_NO : MUTT_YES);
1491  if (ans != MUTT_ABORT)
1492  b->noconv = (ans == MUTT_NO);
1493  }
1494 
1495  /* inform the user */
1496 
1497  snprintf(tmp, sizeof(tmp), "%s/%s", TYPE(b), NONULL(b->subtype));
1498  if (type_changed)
1499  mutt_message(_("Content-Type changed to %s"), tmp);
1500  if ((b->type == TYPE_TEXT) && charset_changed)
1501  {
1502  if (type_changed)
1503  mutt_sleep(1);
1504  mutt_message(b->noconv ? _("Character set changed to %s; not converting") :
1505  _("Character set changed to %s; converting"),
1506  mutt_param_get(&b->parameter, "charset"));
1507  }
1508 
1509  b->force_charset |= charset_changed;
1510 
1511  if (!is_multipart(b) && b->parts)
1512  {
1513  structure_changed = true;
1514  mutt_body_free(&b->parts);
1515  }
1516  if (!mutt_is_message_type(b->type, b->subtype) && b->email)
1517  {
1518  structure_changed = true;
1519  b->email->body = NULL;
1520  email_free(&b->email);
1521  }
1522 
1523  if (fp && !b->parts && (is_multipart(b) || mutt_is_message_type(b->type, b->subtype)))
1524  {
1525  structure_changed = true;
1526  mutt_parse_part(fp, b);
1527  }
1528 
1529  if ((WithCrypto != 0) && e)
1530  {
1531  if (e->body == b)
1532  e->security = SEC_NO_FLAGS;
1533 
1534  e->security |= crypt_query(b);
1535  }
1536 
1537  return structure_changed | type_changed;
1538 }
1539 
1546 static bool check_traditional_pgp(struct Mailbox *m, struct Email *e)
1547 {
1548  bool rc = false;
1549 
1551 
1552  struct Message *msg = mx_msg_open(m, e->msgno);
1553  if (msg)
1554  {
1555  mutt_parse_mime_message(m, e, msg->fp);
1556  if (crypt_pgp_check_traditional(msg->fp, e->body, false))
1557  {
1558  e->security = crypt_query(e->body);
1559  rc = true;
1560  }
1561 
1563  mx_msg_close(m, &msg);
1564  }
1565  return rc;
1566 }
1567 
1574 bool mutt_check_traditional_pgp(struct Mailbox *m, struct EmailList *el)
1575 {
1576  bool rc = false;
1577  struct EmailNode *en = NULL;
1578  STAILQ_FOREACH(en, el, entries)
1579  {
1580  if (!(en->email->security & PGP_TRADITIONAL_CHECKED))
1581  rc = check_traditional_pgp(m, en->email) || rc;
1582  }
1583 
1584  return rc;
1585 }
1586 
1590 void mutt_check_stats(struct Mailbox *m)
1591 {
1593 }
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
void mutt_parse_mime_message(struct Mailbox *m, struct Email *e, FILE *fp)
Parse a MIME email.
Definition: attachments.c:591
char * attribute
Parameter name.
Definition: parameter.h:34
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
Convenience wrapper for the gui headers.
The "current" mailbox.
Definition: context.h:37
struct HashElem * mutt_hash_insert(struct HashTable *table, const char *strkey, void *data)
Add a new element to the Hash Table (with string keys)
Definition: hash.c:327
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
#define CH_MIME
Ignore MIME fields.
Definition: copy.h:61
Manage keymappings.
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
Decrypt message.
Definition: commands.h:42
#define NONULL(x)
Definition: string2.h:37
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
int msg_count
Total number of messages.
Definition: mailbox.h:91
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:66
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
#define WithCrypto
Definition: lib.h:113
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1385
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:304
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:300
int msg_in_pager
Message currently shown in the pager.
Definition: context.h:43
IMAP network mailbox.
void mutt_pipe_message(struct Mailbox *m, struct EmailList *el)
Pipe a message.
Definition: commands.c:760
Left justify the text.
Definition: curs_lib.h:43
The envelope/body of an email.
Definition: email.h:37
SortType
Methods for sorting.
Definition: sort2.h:41
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define TAILQ_FIRST(head)
Definition: queue.h:723
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:44
CommandResult
Error codes for command_t parse functions.
Definition: mutt_commands.h:34
#define MUTT_ALIAS
Do alias "completion" by calling up the alias-menu.
Definition: mutt.h:53
int crypt_smime_verify_sender(struct Mailbox *m, struct Email *e, struct Message *msg)
Wrapper for CryptModuleSpecs::smime_verify_sender()
Definition: cryptglue.c:472
Config/command parsing.
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
struct Body * body
List of MIME parts.
Definition: email.h:91
int msg_unread
Number of unread messages.
Definition: mailbox.h:92
Error: Can&#39;t help the user.
Definition: mutt_commands.h:36
struct AutocryptHeader * autocrypt_gossip
Definition: envelope.h:86
Structs that make up an email.
String processing routines to generate the mail index.
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer&#39;s contents to another Buffer.
Definition: buffer.c:445
#define mutt_error(...)
Definition: logging.h:88
The "currently-open" mailbox.
#define is_multipart(body)
Definition: mime.h:82
Autocrypt end-to-end encryption.
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:74
void mutt_mailbox_cleanup(const char *path, struct stat *st)
Restore the timestamp of a mailbox.
Definition: mutt_mailbox.c:360
Convenience wrapper for the send headers.
int mutt_buffer_get_field(const char *field, struct Buffer *buf, CompletionFlags complete, bool multiple, struct Mailbox *m, char ***files, int *numfiles)
Ask the user for a string.
Definition: curs_lib.c:268
int mutt_autocrypt_process_gossip_header(struct Mailbox *m, struct Email *e, struct Envelope *prot_headers)
Parse an Autocrypt email gossip header.
Definition: autocrypt.c:419
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:93
int mutt_save_message_ctx(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: commands.c:1103
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1470
int mutt_get_field(const char *field, char *buf, size_t buflen, CompletionFlags complete, bool multiple, char ***files, int *numfiles)
Ask the user for a string.
Definition: curs_lib.c:335
void mutt_display_address(struct Envelope *env)
Display the address of a message.
Definition: commands.c:1026
char * disp_subj
Display subject (modified copy of subject)
Definition: envelope.h:68
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:75
bool mutt_shell_escape(void)
invoke a command in a subshell
Definition: commands.c:943
struct Mailbox * mailbox_find(const char *path)
Find the mailbox with a given path.
Definition: mailbox.c:125
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
NeoMutt Logging.
bool mutt_check_traditional_pgp(struct Mailbox *m, struct EmailList *el)
Check if a message has inline PGP content.
Definition: commands.c:1574
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
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.c:923
bool noconv
Don&#39;t do character set conversion.
Definition: body.h:73
size_t msgwin_get_width(void)
Get the width of the Message Window.
Definition: msgwin.c:262
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:623
No transformation.
Definition: commands.h:41
void mutt_enter_command(void)
enter a neomutt command
Definition: commands.c:978
#define MUTT_CM_WEED
Weed message/rfc822 attachment headers.
Definition: copy.h:41
String manipulation buffer.
Definition: buffer.h:33
enum CommandResult mutt_parse_rc_line(const char *line, struct Buffer *err)
Parse a line of user config.
Definition: init.c:1039
Paged view into some data.
Definition: lib.h:154
int mutt_is_valid_multipart_pgp_encrypted(struct Body *b)
Is this a valid multi-part encrypted message?
Definition: crypt.c:484
Sort by the email&#39;s From field.
Definition: sort2.h:47
void mutt_unget_event(int ch, int op)
Return a keystroke to the input buffer.
Definition: curs_lib.c:583
#define CH_FROM
Retain the "From " message separator?
Definition: copy.h:56
#define _(a)
Definition: message.h:28
Sort by the email&#39;s score.
Definition: sort2.h:52
char * real_subj
Offset of the real subject.
Definition: envelope.h:67
bool changed
Email has been edited.
Definition: email.h:48
Normal threading (root above subthreads)
Definition: mutt_thread.h:81
static const char * ExtPagerProgress
Definition: commands.c:87
void window_redraw(struct MuttWindow *win)
Reflow, recalc and repaint a tree of Windows.
Definition: mutt_window.c:632
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:47
#define MUTT_SEL_NO_FLAGS
No flags are set.
Definition: browser.h:36
Not yet set by user, stick to legacy semantics.
Definition: mutt_thread.h:79
Messages to be purged (bypass trash)
Definition: mutt.h:96
void nm_db_longrun_init(struct Mailbox *m, bool writable)
Start a long transaction.
Definition: db.c:314
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:71
#define S_BKG
Definition: string2.h:42
#define MUTT_MESSAGE_HOOK
message-hook: run before displaying a message
Definition: hook.h:46
uint16_t CopyMessageFlags
Flags for mutt_copy_message(), e.g. MUTT_CM_NOHEADER.
Definition: copy.h:32
Sort by the emails label.
Definition: sort2.h:62
Information commands.
Copy message, making a duplicate in another mailbox.
Definition: commands.h:51
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
Definition: mx.c:610
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
int mutt_addrlist_parse2(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:616
int mx_save_hcache(struct Mailbox *m, struct Email *e)
Save message to the header cache - Wrapper for MxOps::msg_save_hcache()
Definition: mx.c:1806
void mutt_default_save(char *path, size_t pathlen, struct Email *e)
Find the default save path for an email.
Definition: hook.c:677
Flags to control mutt_expando_format()
#define MUTT_CM_PRINTING
Printing the message - display light.
Definition: copy.h:43
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:35
void msgwin_clear_text(void)
Clear the text in the Message Window.
Definition: msgwin.c:242
#define mutt_perror(...)
Definition: logging.h:89
struct MuttWindow * win_index
Definition: lib.h:162
Container for Accounts, Notifications.
Definition: neomutt.h:36
A Progress Bar.
Definition: progress.c:47
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:603
static int pipe_message(struct Mailbox *m, struct EmailList *el, const char *cmd, bool decode, bool print, bool split, const char *sep)
Pipe message to a command.
Definition: commands.c:632
enum CommandResult mutt_parse_icommand(char *line, struct Buffer *err)
Parse an informational command.
Definition: icommands.c:78
#define MUTT_ENV_CHANGED_SUBJECT
Protected header update.
Definition: envelope.h:35
int mutt_save_confirm(const char *s, struct stat *st)
Ask the user to save.
Definition: muttlib.c:1360
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
The body of an email.
Definition: body.h:34
QuadOption
Possible values for a quad-option.
Definition: quad.h:35
Convenience wrapper for the config headers.
GUI component for displaying/selecting items from a list.
#define CSR_RESULT(x)
Definition: set.h:52
int imap_copy_messages(struct Mailbox *m, struct EmailList *el, const char *dest, enum MessageSaveOpt save_opt)
Server COPY messages to another folder.
Definition: message.c:1643
Email Address Handling.
unsigned char changed
Changed fields, e.g. MUTT_ENV_CHANGED_SUBJECT.
Definition: envelope.h:88
void mutt_print_message(struct Mailbox *m, struct EmailList *el)
Print a message.
Definition: commands.c:791
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
Some miscellaneous functions.
int mutt_pager(struct PagerView *pview)
Display an email, attachment, or help, in a window.
Definition: dlg_pager.c:2360
const struct Regex * cs_subset_regex(const struct ConfigSubset *sub, const char *name)
Get a regex config item by name.
Definition: helpers.c:243
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:305
static void pipe_msg(struct Mailbox *m, struct Email *e, struct Message *msg, FILE *fp, bool decode, bool print)
Pipe a message.
Definition: commands.c:580
Progress bar.
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1186
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:135
Pager pager (email viewer)
Definition: type.h:54
Sort by the size of the email.
Definition: sort2.h:44
size_t dsize
Length of data.
Definition: buffer.h:37
bool read
Email is read.
Definition: email.h:51
Data to be displayed by PagerView.
Definition: lib.h:143
static void set_copy_flags(struct Email *e, enum MessageTransformOpt transform_opt, CopyMessageFlags *cmflags, CopyHeaderFlags *chflags)
Set the flags for a message copy.
Definition: commands.c:1051
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:1461
Parse and execute user-defined hooks.
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:1379
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:460
#define MUTT_CM_DISPLAY
Output is displayed to the user.
Definition: copy.h:39
Many unsorted constants and some structs.
API for mailboxes.
bool old
Email is seen, but unread.
Definition: email.h:50
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:87
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:52
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
Sort by the order the messages appear in the mailbox.
Definition: sort2.h:48
#define CH_WEED
Weed the headers?
Definition: copy.h:53
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
void mutt_make_string(char *buf, size_t buflen, int cols, const char *s, struct Mailbox *m, int inpgr, struct Email *e, MuttFormatFlags flags, const char *progress)
Create formatted strings using mailbox expandos.
Definition: hdrline.c:1409
bool force_charset
Send mode: don&#39;t adjust the character set when in send-mode.
Definition: body.h:75
struct Envelope * env
Envelope information.
Definition: email.h:90
Convenience wrapper for the core headers.
#define CH_VIRTUAL
Write virtual header lines too.
Definition: copy.h:73
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
#define MUTT_COMMAND
Do command completion.
Definition: mutt.h:59
int mutt_display_message(struct MuttWindow *win_index, struct MuttWindow *win_ibar, struct MuttWindow *win_pager, struct MuttWindow *win_pbar, struct Mailbox *m, struct Email *e)
Display a message in the pager.
Definition: commands.c:207
#define MUTT_PAGER_MESSAGE
Definition: lib.h:70
#define CSR_SUC_NO_CHANGE
The value hasn&#39;t changed.
Definition: set.h:44
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Definition: imap.c:2402
static void process_protected_headers(struct Mailbox *m, struct Email *e)
Get the protected header and update the index.
Definition: commands.c:105
void mutt_param_free(struct ParameterList *pl)
Free a ParameterList.
Definition: parameter.c:61
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:420
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: question.c:347
bool nowrap
Do not wrap the output in the pager.
Definition: body.h:74
Email Aliases.
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:112
MessageTransformOpt
Message transformation option.
Definition: commands.h:39
User aborted the question (with Ctrl-G)
Definition: quad.h:37
struct HashTable * subj_hash
Hash Table by subject.
Definition: mailbox.h:128
#define mutt_warning(...)
Definition: logging.h:86
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:181
bool mutt_select_sort(bool reverse)
Ask the user for a sort method.
Definition: commands.c:835
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
char * subtype
content-type subtype
Definition: body.h:37
#define CH_TXTPLAIN
Generate text/plain MIME headers.
Definition: copy.h:63
enum PagerMode mode
Pager mode.
Definition: lib.h:157
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:60
#define MUTT_CMD
Do completion on previous word.
Definition: mutt.h:56
void crypt_invoke_message(SecurityFlags type)
Display an informative message.
Definition: cryptglue.c:158
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:88
int mutt_save_message(struct Mailbox *m, struct EmailList *el, enum MessageSaveOpt save_opt, enum MessageTransformOpt transform_opt)
Save an email.
Definition: commands.c:1144
Pager is invoked via 1st path. The mime part is selected automatically.
Definition: lib.h:131
Prototypes for many functions.
bool crypt_pgp_check_traditional(FILE *fp, struct Body *b, bool just_one)
Wrapper for CryptModuleSpecs::pgp_check_traditional()
Definition: cryptglue.c:288
Notmuch virtual mailbox type.
Sort by email threads.
Definition: sort2.h:49
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:127
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:87
struct AddressList * mutt_get_address(struct Envelope *env, const char **prefix)
Get an Address from an Envelope.
Definition: alias.c:332
A local copy of an email.
Definition: mxapi.h:41
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:422
Create/manipulate threading in emails.
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:356
Messages to be deleted.
Definition: mutt.h:94
A mailbox.
Definition: mailbox.h:81
int mutt_strwidth(const char *s)
Measure a string&#39;s width in screen cells.
Definition: curs_lib.c:983
#define PATH_MAX
Definition: mutt.h:40
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:137
bool mutt_envlist_unset(const char *name)
Unset an environment variable.
Definition: envlist.c:132
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:51
#define MUTT_CM_DECODE
Decode the message body into text/plain.
Definition: copy.h:38
static bool check_traditional_pgp(struct Mailbox *m, struct Email *e)
Check for an inline PGP content.
Definition: commands.c:1546
Manage where the email is piped to external commands.
#define CH_REORDER
Re-order output of headers (specified by &#39;hdr_order&#39;)
Definition: copy.h:59
Type: &#39;text/*&#39;.
Definition: mime.h:38
const char MimeSpecials[]
Characters that need special treatment in MIME.
Definition: mime.c:67
#define MUTT_CM_CHARCONV
Perform character set conversions.
Definition: copy.h:42
void crypt_smime_getkeys(struct Envelope *env)
Wrapper for CryptModuleSpecs::smime_getkeys()
Definition: cryptglue.c:463
Tagged messages.
Definition: mutt.h:99
char * data
Pointer to data.
Definition: buffer.h:35
#define CH_DECODE
Do RFC2047 header decoding.
Definition: copy.h:54
#define CH_XMIT
Transmitting this message? (Ignore Lines: and Content-Length:)
Definition: copy.h:55
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
void crypt_pgp_invoke_getkeys(struct Address *addr)
Wrapper for CryptModuleSpecs::pgp_invoke_getkeys()
Definition: cryptglue.c:279
&#39;mmdf&#39; Mailbox type
Definition: mailbox.h:49
#define CH_DISPLAY
Display result to user.
Definition: copy.h:70
void nm_db_longrun_done(struct Mailbox *m)
Finish a long transaction.
Definition: db.c:329
Messages that have been read.
Definition: mutt.h:92
Definitions of NeoMutt commands.
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
void mutt_file_resolve_symlink(struct Buffer *buf)
Resolve a symlink in place.
Definition: file.c:1620
API for encryption/signing of emails.
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition: crypt.c:521
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: question.c:49
bool append
Mailbox is opened in append mode.
Definition: mailbox.h:113
uint8_t OpenMailboxFlags
Flags for mutt_open_mailbox(), e.g. MUTT_NOSORT.
Definition: mxapi.h:59
Ask the user a question.
Sort by the email&#39;s spam score.
Definition: sort2.h:57
#define MUTT_NEWFOLDER
Create a new folder - same as MUTT_APPEND,.
Definition: mxapi.h:65
#define CH_UPDATE_LEN
Update Lines: and Content-Length:
Definition: copy.h:62
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
#define MUTT_QUIET
Do not print any messages.
Definition: mxapi.h:64
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
PagerFlags flags
Additional settings to tweak pager&#39;s function.
Definition: lib.h:158
Sort by the email&#39;s To field.
Definition: sort2.h:51
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
#define MUTT_CM_VERIFY
Do signature verification.
Definition: copy.h:47
#define STAILQ_NEXT(elm, field)
Definition: queue.h:400
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition: helpers.c:218
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition: progress.c:228
#define SEC_BADSIGN
Email has a bad signature.
Definition: lib.h:78
void progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:175
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:180
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
#define MUTT_MAILBOX_CHECK_FORCE
Definition: mutt_mailbox.h:32
Unthreaded.
Definition: mutt_thread.h:80
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:54
&#39;mbox&#39; Mailbox type
Definition: mailbox.h:48
char * mutt_str_cat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
Definition: string.c:385
bool mutt_regex_capture(const struct Regex *regex, const char *str, size_t nmatch, regmatch_t matches[])
match a regex against a string, with provided options
Definition: regex.c:596
#define SEC_SIGN
Email is signed.
Definition: lib.h:76
#define MUTT_CM_DECODE_SMIME
Used for decoding S/MIME messages.
Definition: copy.h:46
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:455
#define TYPE(body)
Definition: mime.h:89
void mutt_parse_content_type(const char *s, struct Body *ct)
Parse a content type.
Definition: parse.c:427
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1678
void ci_bounce_message(struct Mailbox *m, struct EmailList *el)
Bounce an email.
Definition: commands.c:434
Success: Command worked.
Definition: mutt_commands.h:38
char * subject
Email&#39;s subject.
Definition: envelope.h:66
char * value
Parameter value.
Definition: parameter.h:35
int mutt_buffer_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:513
Duplicate the structure of an entire email.
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:322
MailboxType
Supported mailbox formats.
Definition: mailbox.h:43
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1305
Move message to another mailbox, removing the original.
Definition: commands.h:52
Log at debug level 1.
Definition: logging.h:40
Warning: Help given to the user.
Definition: mutt_commands.h:37
bool flagged
Marked important?
Definition: email.h:43
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:749
FILE * fp
Source stream.
Definition: lib.h:146
pid_t filter_create_fd(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, int fdin, int fdout, int fderr)
Run a command on a pipe (optionally connect stdin/stdout)
Definition: filter.c:61
int msg_new
Number of new messages.
Definition: mailbox.h:95
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
Progress tracks elements, according to $write_inc
Definition: lib.h:47
struct Email * email
Email in the list.
Definition: email.h:131
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:50
Cached regular expression.
Definition: regex3.h:89
struct Progress * progress_new(const char *msg, enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition: progress.c:246
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
Definition: crypt.c:565
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:124
FILE * fp
pointer to the message data
Definition: mxapi.h:43
Attribute associated with a MIME part.
Definition: parameter.h:32
MessageSaveOpt
Message save option.
Definition: commands.h:49
void mutt_check_stats(struct Mailbox *m)
Forcibly update mailbox stats.
Definition: commands.c:1590
SecurityFlags crypt_query(struct Body *b)
Check out the type of encryption used.
Definition: crypt.c:698
int mutt_copy_message(FILE *fp_out, struct Mailbox *m, struct Email *e, struct Message *msg, CopyMessageFlags cmflags, CopyHeaderFlags chflags, int wraplen)
Copy a message from a Mailbox.
Definition: copy.c:853
#define MUTT_CM_DECODE_PGP
Used for decoding PGP messages.
Definition: copy.h:45
#define mutt_message(...)
Definition: logging.h:87
unsigned char cs_subset_enum(const struct ConfigSubset *sub, const char *name)
Get a enumeration config item by name.
Definition: helpers.c:97
#define FREE(x)
Definition: memory.h:40
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1668
#define STAILQ_EMPTY(head)
Definition: queue.h:348
Decode message.
Definition: commands.h:43
struct MuttWindow * win_pager
Definition: lib.h:164
void mutt_hash_delete(struct HashTable *table, const char *strkey, const void *data)
Remove an element from a Hash Table.
Definition: hash.c:419
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
void mutt_commands_cleanup(void)
Clean up commands globals.
Definition: commands.c:95
struct MuttWindow * win_pbar
Definition: lib.h:163
bool mutt_envlist_set(const char *name, const char *value, bool overwrite)
Set an environment variable.
Definition: envlist.c:85
List of Emails.
Definition: email.h:129
#define MUTT_PAGER_NOWRAP
Format for term width, ignore $wrap.
Definition: lib.h:67
#define PGP_TRADITIONAL_CHECKED
Email has a traditional (inline) signature.
Definition: lib.h:89
struct MuttWindow * win_ibar
Definition: lib.h:161
#define CSR_ERR_CODE
Problem with the code.
Definition: set.h:36
bool changed
Mailbox has been modified.
Definition: mailbox.h:114
Hundreds of global variables to back the user variables.
Handling of global boolean variables.
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
void mutt_message_hook(struct Mailbox *m, struct Email *e, HookFlags type)
Perform a message hook.
Definition: hook.c:598
Sort by when the message were delivered locally.
Definition: sort2.h:50
const char * fname
Name of the file to read.
Definition: lib.h:148
#define TAILQ_EMPTY(head)
Definition: queue.h:721
bool mutt_edit_content_type(struct Email *e, struct Body *b, FILE *fp)
Edit the content type of an attachment.
Definition: commands.c:1433
#define EXTRA_SPACE
int km_dokey(enum MenuType mtype)
Determine what a keypress should do.
Definition: keymap.c:635
Sort by the date the email was sent.
Definition: sort2.h:43
Convenience wrapper for the library headers.
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:79
const char * banner
Title to display in status bar.
Definition: lib.h:159
WHERE bool OptKeepQuiet
(pseudo) shut up the message and refresh functions while we are executing an external program ...
Definition: options.h:38
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
GUI display a file/email/help in a viewport with paging.
Miscellaneous email parsing routines.
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
Reverse threading (subthreads above root)
Definition: mutt_thread.h:82
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
#define SORT_LAST
Sort thread by last-X, e.g. received date.
Definition: sort2.h:80
struct Email * email
header information for message/rfc822
Definition: body.h:55
#define STAILQ_FIRST(head)
Definition: queue.h:350
#define SEC_GOODSIGN
Email has a valid signature.
Definition: lib.h:77
size_t mutt_addrlist_write(const struct AddressList *al, char *buf, size_t buflen, bool display)
Write an Address to a buffer.
Definition: address.c:1150
int pair
Color-pair to use when displaying in the index.
Definition: email.h:80
Mailbox helper functions.
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:681
Sort by the email&#39;s subject.
Definition: sort2.h:46
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
return a stream pointer for a message
Definition: mx.c:1140
#define SEC_PARTSIGN
Not all parts of the email is signed.
Definition: lib.h:79
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:78
#define CH_NONEWLINE
Don&#39;t output terminating newline after the header.
Definition: copy.h:60
The header of an Email.
Definition: envelope.h:54
int msgno
Number displayed to the user.
Definition: email.h:87
void mutt_simple_format(char *buf, size_t buflen, int min_width, int max_width, enum FormatJustify justify, char pad_char, const char *s, size_t n, bool arboreal)
Format a string, like snprintf()
Definition: curs_lib.c:716
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:265
#define MUTT_MAILBOX_CHECK_FORCE_STATS
Definition: mutt_mailbox.h:33
static void pipe_set_flags(bool decode, bool print, CopyMessageFlags *cmflags, CopyHeaderFlags *chflags)
Generate flags for copy header/message.
Definition: commands.c:542