NeoMutt  2021-02-05
Teaching an old dog new tricks
DOXYGEN
mx.c
Go to the documentation of this file.
1 
32 #include "config.h"
33 #include <errno.h>
34 #include <limits.h>
35 #include <locale.h>
36 #include <stdbool.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 "email/lib.h"
43 #include "core/lib.h"
44 #include "alias/lib.h"
45 #include "gui/lib.h"
46 #include "mutt.h"
47 #include "mx.h"
48 #include "maildir/lib.h"
49 #include "mbox/lib.h"
50 #include "context.h"
51 #include "copy.h"
52 #include "hook.h"
53 #include "keymap.h"
54 #include "mutt_globals.h"
55 #include "mutt_header.h"
56 #include "mutt_logging.h"
57 #include "mutt_mailbox.h"
58 #include "muttlib.h"
59 #include "opcodes.h"
60 #include "options.h"
61 #include "protos.h"
62 #include "sort.h"
63 #ifdef USE_COMP_MBOX
64 #include "compmbox/lib.h"
65 #endif
66 #ifdef USE_IMAP
67 #include "imap/lib.h"
68 #endif
69 #ifdef USE_POP
70 #include "pop/lib.h"
71 #endif
72 #ifdef USE_NNTP
73 #include "nntp/lib.h"
74 #endif
75 #ifdef USE_NOTMUCH
76 #include "notmuch/lib.h"
77 #endif
78 #ifdef ENABLE_NLS
79 #include <libintl.h>
80 #endif
81 
82 /* These Config Variables are only used in mx.c */
84 unsigned char C_MboxType;
85 unsigned char C_Move;
86 char *C_Trash;
87 
88 // clang-format off
89 static struct Mapping MboxTypeMap[] = {
90  { "mbox", MUTT_MBOX, },
91  { "MMDF", MUTT_MMDF, },
92  { "MH", MUTT_MH, },
93  { "Maildir", MUTT_MAILDIR, },
94  { NULL, 0, },
95 };
96 // clang-format on
97 
98 struct EnumDef MboxTypeDef = {
99  "mbox_type",
100  4,
101  (struct Mapping *) &MboxTypeMap,
102 };
103 
107 const struct MxOps *mx_ops[] = {
108 /* These mailboxes can be recognised by their Url scheme */
109 #ifdef USE_IMAP
110  &MxImapOps,
111 #endif
112 #ifdef USE_NOTMUCH
113  &MxNotmuchOps,
114 #endif
115 #ifdef USE_POP
116  &MxPopOps,
117 #endif
118 #ifdef USE_NNTP
119  &MxNntpOps,
120 #endif
121 
122  /* Local mailboxes */
123  &MxMaildirOps,
124  &MxMboxOps,
125  &MxMhOps,
126  &MxMmdfOps,
127 
128 /* If everything else fails... */
129 #ifdef USE_COMP_MBOX
130  &MxCompOps,
131 #endif
132  NULL,
133 };
134 
141 const struct MxOps *mx_get_ops(enum MailboxType type)
142 {
143  for (const struct MxOps **ops = mx_ops; *ops; ops++)
144  if ((*ops)->type == type)
145  return *ops;
146 
147  return NULL;
148 }
149 
155 static bool mutt_is_spool(const char *str)
156 {
157  if (mutt_str_equal(str, C_Spoolfile))
158  return true;
159 
160  struct Url *ua = url_parse(str);
161  struct Url *ub = url_parse(C_Spoolfile);
162 
163  const bool is_spool =
164  ua && ub && (ua->scheme == ub->scheme) &&
165  mutt_istr_equal(ua->host, ub->host) && mutt_istr_equal(ua->path, ub->path) &&
166  (!ua->user || !ub->user || mutt_str_equal(ua->user, ub->user));
167 
168  url_free(&ua);
169  url_free(&ub);
170  return is_spool;
171 }
172 
183 int mx_access(const char *path, int flags)
184 {
185 #ifdef USE_IMAP
186  if (imap_path_probe(path, NULL) == MUTT_IMAP)
187  return imap_access(path);
188 #endif
189 
190  return access(path, flags);
191 }
192 
200 static int mx_open_mailbox_append(struct Mailbox *m, OpenMailboxFlags flags)
201 {
202  if (!m)
203  return -1;
204 
205  struct stat sb;
206 
207  m->append = true;
208  if ((m->type == MUTT_UNKNOWN) || (m->type == MUTT_MAILBOX_ERROR))
209  {
211 
212  if (m->type == MUTT_UNKNOWN)
213  {
214  if (flags & (MUTT_APPEND | MUTT_NEWFOLDER))
215  {
217  }
218  else
219  {
220  mutt_error(_("%s is not a mailbox"), mailbox_path(m));
221  return -1;
222  }
223  }
224 
225  if (m->type == MUTT_MAILBOX_ERROR)
226  {
227  if (stat(mailbox_path(m), &sb) == -1)
228  {
229  if (errno == ENOENT)
230  {
231 #ifdef USE_COMP_MBOX
232  if (mutt_comp_can_append(m))
233  m->type = MUTT_COMPRESSED;
234  else
235 #endif
236  m->type = C_MboxType;
237  flags |= MUTT_APPENDNEW;
238  }
239  else
240  {
242  return -1;
243  }
244  }
245  else
246  return -1;
247  }
248 
249  m->mx_ops = mx_get_ops(m->type);
250  }
251 
252  if (!m->mx_ops || !m->mx_ops->mbox_open_append)
253  return -1;
254 
255  int rc = m->mx_ops->mbox_open_append(m, flags);
256  m->opened++;
257  return rc;
258 }
259 
266 bool mx_mbox_ac_link(struct Mailbox *m)
267 {
268  if (!m)
269  return false;
270 
271  if (m->account)
272  return true;
273 
274  struct Account *a = mx_ac_find(m);
275  const bool new_account = !a;
276  if (new_account)
277  {
278  a = account_new(NULL, NeoMutt->sub);
279  a->type = m->type;
280  }
281  if (mx_ac_add(a, m) < 0)
282  {
283  if (new_account)
284  {
285  FREE(&a);
286  }
287  return false;
288  }
289  if (new_account)
290  {
292  }
293  return true;
294 }
295 
303 struct Context *mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
304 {
305  if (!m)
306  return NULL;
307 
308  struct Context *ctx = ctx_new(m);
309 
310  struct EventContext ev_ctx = { ctx };
311  notify_send(ctx->notify, NT_CONTEXT, NT_CONTEXT_OPEN, &ev_ctx);
312 
313  // If the Mailbox is closed, Context->mailbox must be set to NULL
315 
316  if ((m->type == MUTT_UNKNOWN) && (flags & (MUTT_NEWFOLDER | MUTT_APPEND)))
317  {
318  m->type = C_MboxType;
319  m->mx_ops = mx_get_ops(m->type);
320  }
321 
322  const bool newly_linked_account = !m->account;
323  if (newly_linked_account)
324  {
325  if (!mx_mbox_ac_link(m))
326  {
327  ctx_free(&ctx);
328  return NULL;
329  }
330  }
331 
332  ctx->msg_in_pager = -1;
333  ctx->collapsed = false;
334 
335  m->verbose = !(flags & MUTT_QUIET);
336  if (flags & MUTT_READONLY)
337  m->readonly = true;
338  m->peekonly = (flags & MUTT_PEEK);
339 
340  if (flags & (MUTT_APPEND | MUTT_NEWFOLDER))
341  {
342  if (mx_open_mailbox_append(ctx->mailbox, flags) != 0)
343  {
344  goto error;
345  }
346  return ctx;
347  }
348 
349  if (m->opened > 0)
350  {
351  m->opened++;
352  return ctx;
353  }
354 
355  m->size = 0;
356  m->msg_unread = 0;
357  m->msg_flagged = 0;
358  m->rights = MUTT_ACL_ALL;
359 
360  if (m->type == MUTT_UNKNOWN)
361  {
363  m->mx_ops = mx_get_ops(m->type);
364  }
365 
366  if ((m->type == MUTT_UNKNOWN) || (m->type == MUTT_MAILBOX_ERROR) || !m->mx_ops)
367  {
368  if (m->type == MUTT_MAILBOX_ERROR)
370  else if ((m->type == MUTT_UNKNOWN) || !m->mx_ops)
371  mutt_error(_("%s is not a mailbox"), mailbox_path(m));
372  goto error;
373  }
374 
376 
377  /* if the user has a 'push' command in their .neomuttrc, or in a folder-hook,
378  * it will cause the progress messages not to be displayed because
379  * mutt_refresh() will think we are in the middle of a macro. so set a
380  * flag to indicate that we should really refresh the screen. */
381  OptForceRefresh = true;
382 
383  if (m->verbose)
384  mutt_message(_("Reading %s..."), mailbox_path(m));
385 
386  // Clear out any existing emails
387  for (int i = 0; i < m->email_max; i++)
388  {
389  email_free(&m->emails[i]);
390  }
391 
392  m->msg_count = 0;
393  m->msg_unread = 0;
394  m->msg_flagged = 0;
395  m->msg_new = 0;
396  m->msg_deleted = 0;
397  m->msg_tagged = 0;
398  m->vcount = 0;
399 
400  int rc = m->mx_ops->mbox_open(ctx->mailbox);
401  m->opened++;
402  if (rc == 0)
403  ctx_update(ctx);
404 
405  if ((rc == 0) || (rc == -2))
406  {
407  if ((flags & MUTT_NOSORT) == 0)
408  {
409  /* avoid unnecessary work since the mailbox is completely unthreaded
410  * to begin with */
411  OptSortSubthreads = false;
412  OptNeedRescore = false;
413  }
414  if (m->verbose)
416  if (rc == -2)
417  {
418  mutt_error(_("Reading from %s interrupted..."), mailbox_path(m));
419  mutt_sort_headers(ctx->mailbox, ctx->threads, true, &ctx->vsize);
420  }
421  }
422  else
423  {
424  goto error;
425  }
426 
427  if (!m->peekonly)
428  m->has_new = false;
429  OptForceRefresh = false;
430 
431  return ctx;
432 
433 error:
435  if (newly_linked_account)
437  ctx_free(&ctx);
438  return NULL;
439 }
440 
446 {
447  if (!m)
448  return;
449 
450  m->opened--;
451  if (m->opened != 0)
452  return;
453 
454  /* never announce that a mailbox we've just left has new mail.
455  * TODO: really belongs in mx_mbox_close, but this is a nice hook point */
456  if (!m->peekonly)
458 
459  if (m->mx_ops)
460  m->mx_ops->mbox_close(m);
461 
463  mutt_hash_free(&m->id_hash);
465 
466  if (m->emails)
467  {
468  for (int i = 0; i < m->msg_count; i++)
469  {
470  if (!m->emails[i])
471  break;
472  email_free(&m->emails[i]);
473  }
474  }
475 }
476 
483 static int sync_mailbox(struct Mailbox *m)
484 {
485  if (!m || !m->mx_ops || !m->mx_ops->mbox_sync)
486  return -1;
487 
488  if (m->verbose)
489  {
490  /* L10N: Displayed before/as a mailbox is being synced */
491  mutt_message(_("Writing %s..."), mailbox_path(m));
492  }
493 
494  int rc = m->mx_ops->mbox_sync(m);
495  if (rc != 0)
496  {
497  mutt_debug(LL_DEBUG2, "mbox_sync returned: %d\n", rc);
498  if ((rc < 0) && m->verbose)
499  {
500  /* L10N: Displayed if a mailbox sync fails */
501  mutt_error(_("Unable to write %s"), mailbox_path(m));
502  }
503  }
504 
505  return rc;
506 }
507 
514 static int trash_append(struct Mailbox *m)
515 {
516  if (!m)
517  return -1;
518 
519  struct stat st, stc;
520  int opt_confappend, rc;
521 
522  if (!C_Trash || (m->msg_deleted == 0) || ((m->type == MUTT_MAILDIR) && C_MaildirTrash))
523  {
524  return 0;
525  }
526 
527  int delmsgcount = 0;
528  int first_del = -1;
529  for (int i = 0; i < m->msg_count; i++)
530  {
531  struct Email *e = m->emails[i];
532  if (!e)
533  break;
534 
535  if (e->deleted && !e->purge)
536  {
537  if (first_del < 0)
538  first_del = i;
539  delmsgcount++;
540  }
541  }
542 
543  if (delmsgcount == 0)
544  return 0; /* nothing to be done */
545 
546  /* avoid the "append messages" prompt */
547  opt_confappend = C_Confirmappend;
548  if (opt_confappend)
549  C_Confirmappend = false;
550  rc = mutt_save_confirm(C_Trash, &st);
551  if (opt_confappend)
552  C_Confirmappend = true;
553  if (rc != 0)
554  {
555  /* L10N: Although we know the precise number of messages, we do not show it to the user.
556  So feel free to use a "generic plural" as plural translation if your language has one. */
557  mutt_error(ngettext("message not deleted", "messages not deleted", delmsgcount));
558  return -1;
559  }
560 
561  if ((lstat(mailbox_path(m), &stc) == 0) && (stc.st_ino == st.st_ino) &&
562  (stc.st_dev == st.st_dev) && (stc.st_rdev == st.st_rdev))
563  {
564  return 0; /* we are in the trash folder: simple sync */
565  }
566 
567 #ifdef USE_IMAP
568  if ((m->type == MUTT_IMAP) && (imap_path_probe(C_Trash, NULL) == MUTT_IMAP))
569  {
570  if (imap_fast_trash(m, C_Trash) == 0)
571  return 0;
572  }
573 #endif
574 
575  struct Mailbox *m_trash = mx_path_resolve(C_Trash);
576  const bool old_append = m_trash->append;
577  struct Context *ctx_trash = mx_mbox_open(m_trash, MUTT_APPEND);
578  if (ctx_trash)
579  {
580  /* continue from initial scan above */
581  for (int i = first_del; i < m->msg_count; i++)
582  {
583  struct Email *e = m->emails[i];
584  if (!e)
585  break;
586 
587  if (e->deleted && !e->purge)
588  {
589  if (mutt_append_message(ctx_trash->mailbox, m, e, MUTT_CM_NO_FLAGS, CH_NO_FLAGS) == -1)
590  {
591  mx_mbox_close(&ctx_trash);
592  m_trash->append = old_append;
593  return -1;
594  }
595  }
596  }
597 
598  mx_mbox_close(&ctx_trash);
599  m_trash->append = old_append;
600  }
601  else
602  {
603  mutt_error(_("Can't open trash folder"));
604  mailbox_free(&m_trash);
605  return -1;
606  }
607 
608  return 0;
609 }
610 
630 int mx_mbox_close(struct Context **ptr)
631 {
632  if (!ptr || !*ptr)
633  return 0;
634 
635  struct Context *ctx = *ptr;
636  if (!ctx || !ctx->mailbox)
637  return -1;
638 
639  struct Mailbox *m = ctx->mailbox;
640 
641  if (C_MailCheckRecent && !m->peekonly)
642  m->has_new = false;
643 
644  if (m->readonly || m->dontwrite || m->append || m->peekonly)
645  {
647  ctx_free(ptr);
648  return 0;
649  }
650 
651  int i, read_msgs = 0;
652  int rc = -1;
653  enum QuadOption move_messages = MUTT_NO;
654  enum QuadOption purge = MUTT_YES;
655  struct Buffer *mbox = NULL;
656  struct Buffer *buf = mutt_buffer_pool_get();
657 
658 #ifdef USE_NNTP
659  if ((m->msg_unread != 0) && (m->type == MUTT_NNTP))
660  {
661  struct NntpMboxData *mdata = m->mdata;
662 
663  if (mdata && mdata->adata && mdata->group)
664  {
665  enum QuadOption ans =
666  query_quadoption(C_CatchupNewsgroup, _("Mark all articles read?"));
667  if (ans == MUTT_ABORT)
668  goto cleanup;
669  if (ans == MUTT_YES)
670  mutt_newsgroup_catchup(m, mdata->adata, mdata->group);
671  }
672  }
673 #endif
674 
675  for (i = 0; i < m->msg_count; i++)
676  {
677  struct Email *e = m->emails[i];
678  if (!e)
679  break;
680 
681  if (!e->deleted && e->read && !(e->flagged && C_KeepFlagged))
682  read_msgs++;
683  }
684 
685 #ifdef USE_NNTP
686  /* don't need to move articles from newsgroup */
687  if (m->type == MUTT_NNTP)
688  read_msgs = 0;
689 #endif
690 
691  if ((read_msgs != 0) && (C_Move != MUTT_NO))
692  {
693  bool is_spool;
694  mbox = mutt_buffer_pool_get();
695 
697  if (p)
698  {
699  is_spool = true;
700  mutt_buffer_strcpy(mbox, p);
701  }
702  else
703  {
704  mutt_buffer_strcpy(mbox, C_Mbox);
705  is_spool = mutt_is_spool(mailbox_path(m)) &&
707  }
708 
709  if (is_spool && !mutt_buffer_is_empty(mbox))
710  {
712  mutt_buffer_printf(buf,
713  /* L10N: The first argument is the number of read messages to be
714  moved, the second argument is the target mailbox. */
715  ngettext("Move %d read message to %s?",
716  "Move %d read messages to %s?", read_msgs),
717  read_msgs, mutt_buffer_string(mbox));
718  move_messages = query_quadoption(C_Move, mutt_buffer_string(buf));
719  if (move_messages == MUTT_ABORT)
720  goto cleanup;
721  }
722  }
723 
724  /* There is no point in asking whether or not to purge if we are
725  * just marking messages as "trash". */
726  if ((m->msg_deleted != 0) && !((m->type == MUTT_MAILDIR) && C_MaildirTrash))
727  {
728  mutt_buffer_printf(buf,
729  ngettext("Purge %d deleted message?",
730  "Purge %d deleted messages?", m->msg_deleted),
731  m->msg_deleted);
733  if (purge == MUTT_ABORT)
734  goto cleanup;
735  }
736 
737  if (C_MarkOld && !m->peekonly)
738  {
739  for (i = 0; i < m->msg_count; i++)
740  {
741  struct Email *e = m->emails[i];
742  if (!e)
743  break;
744  if (!e->deleted && !e->old && !e->read)
745  mutt_set_flag(m, e, MUTT_OLD, true);
746  }
747  }
748 
749  if (move_messages)
750  {
751  if (m->verbose)
752  mutt_message(_("Moving read messages to %s..."), mutt_buffer_string(mbox));
753 
754 #ifdef USE_IMAP
755  /* try to use server-side copy first */
756  i = 1;
757 
758  if ((m->type == MUTT_IMAP) && (imap_path_probe(mutt_buffer_string(mbox), NULL) == MUTT_IMAP))
759  {
760  /* add messages for moving, and clear old tags, if any */
761  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
762  for (i = 0; i < m->msg_count; i++)
763  {
764  struct Email *e = m->emails[i];
765  if (!e)
766  break;
767 
768  if (e->read && !e->deleted && !(e->flagged && C_KeepFlagged))
769  {
770  e->tagged = true;
771  emaillist_add_email(&el, e);
772  }
773  else
774  e->tagged = false;
775  }
776 
777  i = imap_copy_messages(ctx->mailbox, &el, mutt_buffer_string(mbox), true);
778  emaillist_clear(&el);
779  }
780 
781  if (i == 0) /* success */
783  else if (i == -1) /* horrible error, bail */
784  goto cleanup;
785  else /* use regular append-copy mode */
786 #endif
787  {
788  struct Mailbox *m_read = mx_path_resolve(mutt_buffer_string(mbox));
789  struct Context *ctx_read = mx_mbox_open(m_read, MUTT_APPEND);
790  if (!ctx_read)
791  {
792  mailbox_free(&m_read);
793  goto cleanup;
794  }
795 
796  for (i = 0; i < m->msg_count; i++)
797  {
798  struct Email *e = m->emails[i];
799  if (!e)
800  break;
801  if (e->read && !e->deleted && !(e->flagged && C_KeepFlagged))
802  {
803  if (mutt_append_message(ctx_read->mailbox, ctx->mailbox, e,
805  {
806  mutt_set_flag(m, e, MUTT_DELETE, true);
807  mutt_set_flag(m, e, MUTT_PURGE, true);
808  }
809  else
810  {
811  mx_mbox_close(&ctx_read);
812  goto cleanup;
813  }
814  }
815  }
816 
817  mx_mbox_close(&ctx_read);
818  }
819  }
820  else if (!m->changed && (m->msg_deleted == 0))
821  {
822  if (m->verbose)
823  mutt_message(_("Mailbox is unchanged"));
824  if ((m->type == MUTT_MBOX) || (m->type == MUTT_MMDF))
825  mbox_reset_atime(m, NULL);
827  ctx_free(ptr);
828  rc = 0;
829  goto cleanup;
830  }
831 
832  /* copy mails to the trash before expunging */
833  const struct Mailbox *m_trash = mx_mbox_find(m->account, C_Trash);
834  if (purge && (m->msg_deleted != 0) && (m != m_trash))
835  {
836  if (trash_append(ctx->mailbox) != 0)
837  goto cleanup;
838  }
839 
840 #ifdef USE_IMAP
841  /* allow IMAP to preserve the deleted flag across sessions */
842  if (m->type == MUTT_IMAP)
843  {
844  int check = imap_sync_mailbox(ctx->mailbox, (purge != MUTT_NO), true);
845  if (check < 0)
846  {
847  rc = check;
848  goto cleanup;
849  }
850  }
851  else
852 #endif
853  {
854  if (purge == MUTT_NO)
855  {
856  for (i = 0; i < m->msg_count; i++)
857  {
858  struct Email *e = m->emails[i];
859  if (!e)
860  break;
861 
862  e->deleted = false;
863  e->purge = false;
864  }
865  m->msg_deleted = 0;
866  }
867 
868  if (m->changed || (m->msg_deleted != 0))
869  {
870  int check = sync_mailbox(ctx->mailbox);
871  if (check != 0)
872  {
873  rc = check;
874  goto cleanup;
875  }
876  }
877  }
878 
879  if (m->verbose)
880  {
881  if (move_messages)
882  {
883  mutt_message(_("%d kept, %d moved, %d deleted"),
884  m->msg_count - m->msg_deleted, read_msgs, m->msg_deleted);
885  }
886  else
887  mutt_message(_("%d kept, %d deleted"), m->msg_count - m->msg_deleted, m->msg_deleted);
888  }
889 
890  if ((m->msg_count == m->msg_deleted) &&
891  ((m->type == MUTT_MMDF) || (m->type == MUTT_MBOX)) &&
893  {
895  }
896 
897 #ifdef USE_SIDEBAR
898  if ((purge == MUTT_YES) && (m->msg_deleted != 0))
899  {
900  for (i = 0; i < m->msg_count; i++)
901  {
902  struct Email *e = m->emails[i];
903  if (!e)
904  break;
905  if (e->deleted && !e->read)
906  {
907  m->msg_unread--;
908  if (!e->old)
909  m->msg_new--;
910  }
911  if (e->deleted && e->flagged)
912  m->msg_flagged--;
913  }
914  }
915 #endif
916 
918  ctx_free(ptr);
919 
920  rc = 0;
921 
922 cleanup:
925  return rc;
926 }
927 
938 int mx_mbox_sync(struct Mailbox *m)
939 {
940  if (!m)
941  return -1;
942 
943  int rc;
944  int purge = 1;
945  int msgcount, deleted;
946 
947  if (m->dontwrite)
948  {
949  char buf[256], tmp[256];
950  if (km_expand_key(buf, sizeof(buf), km_find_func(MENU_MAIN, OP_TOGGLE_WRITE)))
951  snprintf(tmp, sizeof(tmp), _(" Press '%s' to toggle write"), buf);
952  else
953  mutt_str_copy(tmp, _("Use 'toggle-write' to re-enable write"), sizeof(tmp));
954 
955  mutt_error(_("Mailbox is marked unwritable. %s"), tmp);
956  return -1;
957  }
958  else if (m->readonly)
959  {
960  mutt_error(_("Mailbox is read-only"));
961  return -1;
962  }
963 
964  if (!m->changed && (m->msg_deleted == 0))
965  {
966  if (m->verbose)
967  mutt_message(_("Mailbox is unchanged"));
968  return 0;
969  }
970 
971  if (m->msg_deleted != 0)
972  {
973  char buf[128];
974 
975  snprintf(buf, sizeof(buf),
976  ngettext("Purge %d deleted message?", "Purge %d deleted messages?", m->msg_deleted),
977  m->msg_deleted);
978  purge = query_quadoption(C_Delete, buf);
979  if (purge == MUTT_ABORT)
980  return -1;
981  if (purge == MUTT_NO)
982  {
983  if (!m->changed)
984  return 0; /* nothing to do! */
985  /* let IMAP servers hold on to D flags */
986  if (m->type != MUTT_IMAP)
987  {
988  for (int i = 0; i < m->msg_count; i++)
989  {
990  struct Email *e = m->emails[i];
991  if (!e)
992  break;
993  e->deleted = false;
994  e->purge = false;
995  }
996  m->msg_deleted = 0;
997  }
998  }
1000  }
1001 
1002  /* really only for IMAP - imap_sync_mailbox results in a call to
1003  * ctx_update_tables, so m->msg_deleted is 0 when it comes back */
1004  msgcount = m->msg_count;
1005  deleted = m->msg_deleted;
1006 
1007  const struct Mailbox *m_trash = mx_mbox_find(m->account, C_Trash);
1008  if (purge && (m->msg_deleted != 0) && (m != m_trash))
1009  {
1010  if (trash_append(m) != 0)
1011  return -1;
1012  }
1013 
1014 #ifdef USE_IMAP
1015  if (m->type == MUTT_IMAP)
1016  rc = imap_sync_mailbox(m, purge, false);
1017  else
1018 #endif
1019  rc = sync_mailbox(m);
1020  if (rc >= 0)
1021  {
1022 #ifdef USE_IMAP
1023  if ((m->type == MUTT_IMAP) && !purge)
1024  {
1025  if (m->verbose)
1026  mutt_message(_("Mailbox checkpointed"));
1027  }
1028  else
1029 #endif
1030  {
1031  if (m->verbose)
1032  mutt_message(_("%d kept, %d deleted"), msgcount - deleted, deleted);
1033  }
1034 
1035  mutt_sleep(0);
1036 
1037  if ((m->msg_count == m->msg_deleted) &&
1038  ((m->type == MUTT_MBOX) || (m->type == MUTT_MMDF)) &&
1040  {
1041  unlink(mailbox_path(m));
1043  return 0;
1044  }
1045 
1046  /* if we haven't deleted any messages, we don't need to resort */
1047  /* ... except for certain folder formats which need "unsorted"
1048  * sort order in order to synchronize folders.
1049  *
1050  * MH and maildir are safe. mbox-style seems to need re-sorting,
1051  * at least with the new threading code. */
1052  if (purge || ((m->type != MUTT_MAILDIR) && (m->type != MUTT_MH)))
1053  {
1054  /* IMAP does this automatically after handling EXPUNGE */
1055  if (m->type != MUTT_IMAP)
1056  {
1059  }
1060  }
1061  }
1062 
1063  return rc;
1064 }
1065 
1073 struct Message *mx_msg_open_new(struct Mailbox *m, const struct Email *e, MsgOpenFlags flags)
1074 {
1075  if (!m)
1076  return NULL;
1077 
1078  struct Address *p = NULL;
1079  struct Message *msg = NULL;
1080 
1081  if (!m->mx_ops || !m->mx_ops->msg_open_new)
1082  {
1083  mutt_debug(LL_DEBUG1, "function unimplemented for mailbox type %d\n", m->type);
1084  return NULL;
1085  }
1086 
1087  msg = mutt_mem_calloc(1, sizeof(struct Message));
1088  msg->write = true;
1089 
1090  if (e)
1091  {
1092  msg->flags.flagged = e->flagged;
1093  msg->flags.replied = e->replied;
1094  msg->flags.read = e->read;
1095  msg->flags.draft = (flags & MUTT_SET_DRAFT);
1096  msg->received = e->received;
1097  }
1098 
1099  if (msg->received == 0)
1100  msg->received = mutt_date_epoch();
1101 
1102  if (m->mx_ops->msg_open_new(m, msg, e) == 0)
1103  {
1104  if (m->type == MUTT_MMDF)
1105  fputs(MMDF_SEP, msg->fp);
1106 
1107  if (((m->type == MUTT_MBOX) || (m->type == MUTT_MMDF)) && (flags & MUTT_ADD_FROM))
1108  {
1109  if (e)
1110  {
1111  p = TAILQ_FIRST(&e->env->return_path);
1112  if (!p)
1113  p = TAILQ_FIRST(&e->env->sender);
1114  if (!p)
1115  p = TAILQ_FIRST(&e->env->from);
1116  }
1117 
1118  // Force a 'C' locale for the date, so that day/month names are in English
1119  locale_t loc = newlocale(LC_TIME_MASK, "C", 0);
1120  char buf[64] = { 0 };
1121  struct tm tm = mutt_date_localtime(msg->received);
1122  strftime_l(buf, sizeof(buf), "%a %b %e %H:%M:%S %Y", &tm, loc);
1123  freelocale(loc);
1124  fprintf(msg->fp, "From %s %s\n", p ? p->mailbox : NONULL(Username), buf);
1125  }
1126  }
1127  else
1128  FREE(&msg);
1129 
1130  return msg;
1131 }
1132 
1140 int mx_mbox_check(struct Mailbox *m)
1141 {
1142  if (!m || !m->mx_ops)
1143  return -1;
1144 
1145  int rc = m->mx_ops->mbox_check(m);
1146  if ((rc == MUTT_NEW_MAIL) || (rc == MUTT_REOPENED))
1148 
1149  return rc;
1150 }
1151 
1159 struct Message *mx_msg_open(struct Mailbox *m, int msgno)
1160 {
1161  if (!m || !m->emails || (msgno < 0) || (msgno >= m->msg_count))
1162  return NULL;
1163 
1164  if (!m->mx_ops || !m->mx_ops->msg_open)
1165  {
1166  mutt_debug(LL_DEBUG1, "function not implemented for mailbox type %d\n", m->type);
1167  return NULL;
1168  }
1169 
1170  struct Message *msg = mutt_mem_calloc(1, sizeof(struct Message));
1171  if (m->mx_ops->msg_open(m, msg, msgno) < 0)
1172  FREE(&msg);
1173 
1174  return msg;
1175 }
1176 
1184 int mx_msg_commit(struct Mailbox *m, struct Message *msg)
1185 {
1186  if (!m || !m->mx_ops || !m->mx_ops->msg_commit || !msg)
1187  return -1;
1188 
1189  if (!(msg->write && m->append))
1190  {
1191  mutt_debug(LL_DEBUG1, "msg->write = %d, m->append = %d\n", msg->write, m->append);
1192  return -1;
1193  }
1194 
1195  return m->mx_ops->msg_commit(m, msg);
1196 }
1197 
1205 int mx_msg_close(struct Mailbox *m, struct Message **msg)
1206 {
1207  if (!m || !msg || !*msg)
1208  return 0;
1209 
1210  int rc = 0;
1211 
1212  if (m->mx_ops && m->mx_ops->msg_close)
1213  rc = m->mx_ops->msg_close(m, *msg);
1214 
1215  if ((*msg)->path)
1216  {
1217  mutt_debug(LL_DEBUG1, "unlinking %s\n", (*msg)->path);
1218  unlink((*msg)->path);
1219  FREE(&(*msg)->path);
1220  }
1221 
1222  FREE(&(*msg)->committed_path);
1223  FREE(msg);
1224  return rc;
1225 }
1226 
1231 void mx_alloc_memory(struct Mailbox *m)
1232 {
1233  size_t s = MAX(sizeof(struct Email *), sizeof(int));
1234 
1235  if ((m->email_max + 25) * s < m->email_max * s)
1236  {
1237  mutt_error(_("Out of memory"));
1238  mutt_exit(1);
1239  }
1240 
1241  m->email_max += 25;
1242  if (m->emails)
1243  {
1244  mutt_mem_realloc(&m->emails, sizeof(struct Email *) * m->email_max);
1245  mutt_mem_realloc(&m->v2r, sizeof(int) * m->email_max);
1246  }
1247  else
1248  {
1249  m->emails = mutt_mem_calloc(m->email_max, sizeof(struct Email *));
1250  m->v2r = mutt_mem_calloc(m->email_max, sizeof(int));
1251  }
1252  for (int i = m->email_max - 25; i < m->email_max; i++)
1253  {
1254  m->emails[i] = NULL;
1255  m->v2r[i] = -1;
1256  }
1257 }
1258 
1266 int mx_path_is_empty(const char *path)
1267 {
1268  if (!path || (*path == '\0'))
1269  return -1;
1270 
1271  enum MailboxType type = mx_path_probe(path);
1272  const struct MxOps *ops = mx_get_ops(type);
1273  if (!ops || !ops->path_is_empty)
1274  return -1;
1275 
1276  return ops->path_is_empty(path);
1277 }
1278 
1289 int mx_tags_edit(struct Mailbox *m, const char *tags, char *buf, size_t buflen)
1290 {
1291  if (!m || !buf)
1292  return -1;
1293 
1294  if (m->mx_ops->tags_edit)
1295  return m->mx_ops->tags_edit(m, tags, buf, buflen);
1296 
1297  mutt_message(_("Folder doesn't support tagging, aborting"));
1298  return -1;
1299 }
1300 
1309 int mx_tags_commit(struct Mailbox *m, struct Email *e, char *tags)
1310 {
1311  if (!m || !e || !tags)
1312  return -1;
1313 
1314  if (m->mx_ops->tags_commit)
1315  return m->mx_ops->tags_commit(m, e, tags);
1316 
1317  mutt_message(_("Folder doesn't support tagging, aborting"));
1318  return -1;
1319 }
1320 
1327 {
1328  return m && m->mx_ops->tags_commit && m->mx_ops->tags_edit;
1329 }
1330 
1336 enum MailboxType mx_path_probe(const char *path)
1337 {
1338  if (!path)
1339  return MUTT_UNKNOWN;
1340 
1341  enum MailboxType rc;
1342 
1343  // First, search the non-local Mailbox types (is_local == false)
1344  for (const struct MxOps **ops = mx_ops; *ops; ops++)
1345  {
1346  if ((*ops)->is_local)
1347  continue;
1348  rc = (*ops)->path_probe(path, NULL);
1349  if (rc != MUTT_UNKNOWN)
1350  return rc;
1351  }
1352 
1353  struct stat st = { 0 };
1354  if (stat(path, &st) != 0)
1355  {
1356  mutt_debug(LL_DEBUG1, "unable to stat %s: %s (errno %d)\n", path, strerror(errno), errno);
1357  return MUTT_UNKNOWN;
1358  }
1359 
1360  if (S_ISFIFO(st.st_mode))
1361  {
1362  mutt_error(_("Can't open %s: it is a pipe"), path);
1363  return MUTT_UNKNOWN;
1364  }
1365 
1366  // Next, search the local Mailbox types (is_local == true)
1367  for (const struct MxOps **ops = mx_ops; *ops; ops++)
1368  {
1369  if (!(*ops)->is_local)
1370  continue;
1371  rc = (*ops)->path_probe(path, &st);
1372  if (rc != MUTT_UNKNOWN)
1373  return rc;
1374  }
1375 
1376  return rc;
1377 }
1378 
1382 int mx_path_canon(char *buf, size_t buflen, const char *folder, enum MailboxType *type)
1383 {
1384  if (!buf)
1385  return -1;
1386 
1387  for (size_t i = 0; i < 3; i++)
1388  {
1389  /* Look for !! ! - < > or ^ followed by / or NUL */
1390  if ((buf[0] == '!') && (buf[1] == '!'))
1391  {
1392  if (((buf[2] == '/') || (buf[2] == '\0')))
1393  {
1394  mutt_str_inline_replace(buf, buflen, 2, LastFolder);
1395  }
1396  }
1397  else if ((buf[0] == '+') || (buf[0] == '='))
1398  {
1399  size_t folder_len = mutt_str_len(folder);
1400  if ((folder_len > 0) && (folder[folder_len - 1] != '/'))
1401  {
1402  buf[0] = '/';
1403  mutt_str_inline_replace(buf, buflen, 0, folder);
1404  }
1405  else
1406  {
1407  mutt_str_inline_replace(buf, buflen, 1, folder);
1408  }
1409  }
1410  else if ((buf[1] == '/') || (buf[1] == '\0'))
1411  {
1412  if (buf[0] == '!')
1413  {
1414  mutt_str_inline_replace(buf, buflen, 1, C_Spoolfile);
1415  }
1416  else if (buf[0] == '-')
1417  {
1418  mutt_str_inline_replace(buf, buflen, 1, LastFolder);
1419  }
1420  else if (buf[0] == '<')
1421  {
1422  mutt_str_inline_replace(buf, buflen, 1, C_Record);
1423  }
1424  else if (buf[0] == '>')
1425  {
1426  mutt_str_inline_replace(buf, buflen, 1, C_Mbox);
1427  }
1428  else if (buf[0] == '^')
1429  {
1430  mutt_str_inline_replace(buf, buflen, 1, CurrentFolder);
1431  }
1432  else if (buf[0] == '~')
1433  {
1434  mutt_str_inline_replace(buf, buflen, 1, HomeDir);
1435  }
1436  }
1437  else if (buf[0] == '@')
1438  {
1439  /* elm compatibility, @ expands alias to user name */
1440  struct AddressList *al = alias_lookup(buf + 1);
1441  if (!al || TAILQ_EMPTY(al))
1442  break;
1443 
1444  struct Email *e = email_new();
1445  e->env = mutt_env_new();
1446  mutt_addrlist_copy(&e->env->from, al, false);
1447  mutt_addrlist_copy(&e->env->to, al, false);
1448  mutt_default_save(buf, buflen, e);
1449  email_free(&e);
1450  break;
1451  }
1452  else
1453  {
1454  break;
1455  }
1456  }
1457 
1458  // if (!folder) //XXX - use inherited version, or pass NULL to backend?
1459  // return -1;
1460 
1461  enum MailboxType type2 = mx_path_probe(buf);
1462  if (type)
1463  *type = type2;
1464  const struct MxOps *ops = mx_get_ops(type2);
1465  if (!ops || !ops->path_canon)
1466  return -1;
1467 
1468  if (ops->path_canon(buf, buflen) < 0)
1469  {
1470  mutt_path_canon(buf, buflen, HomeDir, true);
1471  }
1472 
1473  return 0;
1474 }
1475 
1483 int mx_path_canon2(struct Mailbox *m, const char *folder)
1484 {
1485  if (!m)
1486  return -1;
1487 
1488  char buf[PATH_MAX];
1489 
1490  if (m->realpath)
1491  mutt_str_copy(buf, m->realpath, sizeof(buf));
1492  else
1493  mutt_str_copy(buf, mailbox_path(m), sizeof(buf));
1494 
1495  int rc = mx_path_canon(buf, sizeof(buf), folder, &m->type);
1496 
1497  mutt_str_replace(&m->realpath, buf);
1498 
1499  if (rc >= 0)
1500  {
1501  m->mx_ops = mx_get_ops(m->type);
1503  }
1504 
1505  return rc;
1506 }
1507 
1511 int mx_path_pretty(char *buf, size_t buflen, const char *folder)
1512 {
1513  if (!buf)
1514  return -1;
1515 
1516  enum MailboxType type = mx_path_probe(buf);
1517  const struct MxOps *ops = mx_get_ops(type);
1518  if (!ops)
1519  return -1;
1520 
1521  if (!ops->path_canon)
1522  return -1;
1523 
1524  if (ops->path_canon(buf, buflen) < 0)
1525  return -1;
1526 
1527  if (!ops->path_pretty)
1528  return -1;
1529 
1530  if (ops->path_pretty(buf, buflen, folder) < 0)
1531  return -1;
1532 
1533  return 0;
1534 }
1535 
1539 int mx_path_parent(char *buf, size_t buflen)
1540 {
1541  if (!buf)
1542  return -1;
1543 
1544  return 0;
1545 }
1546 
1556 {
1557  if (!m || !m->mx_ops || !m->mx_ops->msg_padding_size)
1558  return 0;
1559 
1560  return m->mx_ops->msg_padding_size(m);
1561 }
1562 
1569 struct Account *mx_ac_find(struct Mailbox *m)
1570 {
1571  if (!m || !m->mx_ops || !m->realpath)
1572  return NULL;
1573 
1574  struct Account *np = NULL;
1575  TAILQ_FOREACH(np, &NeoMutt->accounts, entries)
1576  {
1577  if (np->type != m->type)
1578  continue;
1579 
1580  if (m->mx_ops->ac_owns_path(np, m->realpath))
1581  return np;
1582  }
1583 
1584  return NULL;
1585 }
1586 
1593 struct Mailbox *mx_mbox_find(struct Account *a, const char *path)
1594 {
1595  if (!a || !path)
1596  return NULL;
1597 
1598  struct MailboxNode *np = NULL;
1599  struct Url *url_p = NULL;
1600  struct Url *url_a = NULL;
1601 
1602  const bool use_url = (a->type == MUTT_IMAP);
1603  if (use_url)
1604  {
1605  url_p = url_parse(path);
1606  if (!url_p)
1607  goto done;
1608  }
1609 
1610  STAILQ_FOREACH(np, &a->mailboxes, entries)
1611  {
1612  if (!use_url)
1613  {
1614  if (mutt_str_equal(np->mailbox->realpath, path))
1615  return np->mailbox;
1616  continue;
1617  }
1618 
1619  url_free(&url_a);
1620  url_a = url_parse(np->mailbox->realpath);
1621  if (!url_a)
1622  continue;
1623 
1624  if (!mutt_istr_equal(url_a->host, url_p->host))
1625  continue;
1626  if (url_p->user && !mutt_istr_equal(url_a->user, url_p->user))
1627  continue;
1628  if (a->type == MUTT_IMAP)
1629  {
1630  if (imap_mxcmp(url_a->path, url_p->path) == 0)
1631  break;
1632  }
1633  else
1634  {
1635  if (mutt_str_equal(url_a->path, url_p->path))
1636  break;
1637  }
1638  }
1639 
1640 done:
1641  url_free(&url_p);
1642  url_free(&url_a);
1643 
1644  if (!np)
1645  return NULL;
1646  return np->mailbox;
1647 }
1648 
1655 struct Mailbox *mx_mbox_find2(const char *path)
1656 {
1657  if (!path)
1658  return NULL;
1659 
1660  char buf[PATH_MAX];
1661  mutt_str_copy(buf, path, sizeof(buf));
1662  mx_path_canon(buf, sizeof(buf), C_Folder, NULL);
1663 
1664  struct Account *np = NULL;
1665  TAILQ_FOREACH(np, &NeoMutt->accounts, entries)
1666  {
1667  struct Mailbox *m = mx_mbox_find(np, buf);
1668  if (m)
1669  return m;
1670  }
1671 
1672  return NULL;
1673 }
1674 
1682 struct Mailbox *mx_path_resolve(const char *path)
1683 {
1684  if (!path)
1685  return NULL;
1686 
1687  struct Mailbox *m = mx_mbox_find2(path);
1688  if (m)
1689  return m;
1690 
1691  m = mailbox_new();
1692  m->flags = MB_HIDDEN;
1693  mutt_buffer_strcpy(&m->pathbuf, path);
1695 
1696  return m;
1697 }
1698 
1705 static struct Mailbox *mx_mbox_find_by_name_ac(struct Account *a, const char *name)
1706 {
1707  if (!a || !name)
1708  return NULL;
1709 
1710  struct MailboxNode *np = NULL;
1711 
1712  STAILQ_FOREACH(np, &a->mailboxes, entries)
1713  {
1714  if (mutt_str_equal(np->mailbox->name, name))
1715  return np->mailbox;
1716  }
1717 
1718  return NULL;
1719 }
1720 
1726 static struct Mailbox *mx_mbox_find_by_name(const char *name)
1727 {
1728  if (!name)
1729  return NULL;
1730 
1731  struct Account *np = NULL;
1732  TAILQ_FOREACH(np, &NeoMutt->accounts, entries)
1733  {
1734  struct Mailbox *m = mx_mbox_find_by_name_ac(np, name);
1735  if (m)
1736  return m;
1737  }
1738 
1739  return NULL;
1740 }
1741 
1751 struct Mailbox *mx_resolve(const char *path_or_name)
1752 {
1753  if (!path_or_name)
1754  return NULL;
1755 
1756  // Order is name first because you can create a Mailbox from
1757  // a path, but can't from a name. So fallback behavior creates
1758  // a new Mailbox for us.
1759  struct Mailbox *m = mx_mbox_find_by_name(path_or_name);
1760  if (!m)
1761  m = mx_path_resolve(path_or_name);
1762 
1763  return m;
1764 }
1765 
1769 int mx_ac_add(struct Account *a, struct Mailbox *m)
1770 {
1771  if (!a || !m || !m->mx_ops || !m->mx_ops->ac_add)
1772  return -1;
1773 
1774  if (m->mx_ops->ac_add(a, m) < 0)
1775  return -1;
1776 
1777  account_mailbox_add(a, m);
1778  return 0;
1779 }
1780 
1785 int mx_ac_remove(struct Mailbox *m)
1786 {
1787  if (!m || !m->account)
1788  return -1;
1789 
1790  struct Account *a = m->account;
1792  mailbox_free(&m);
1793  if (STAILQ_EMPTY(&a->mailboxes))
1794  {
1796  }
1797  return 0;
1798 }
1799 
1803 int mx_mbox_check_stats(struct Mailbox *m, uint8_t flags)
1804 {
1805  if (!m)
1806  return -1;
1807 
1808  return m->mx_ops->mbox_check_stats(m, flags);
1809 }
1810 
1820 int mx_save_hcache(struct Mailbox *m, struct Email *e)
1821 {
1822  if (!m || !m->mx_ops || !m->mx_ops->msg_save_hcache || !e)
1823  return 0;
1824 
1825  return m->mx_ops->msg_save_hcache(m, e);
1826 }
#define MUTT_APPEND
Open mailbox for appending messages.
Definition: mx.h:53
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
Convenience wrapper for the gui headers.
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:416
int mx_path_is_empty(const char *path)
Is the mailbox empty.
Definition: mx.c:1266
The "current" mailbox.
Definition: context.h:38
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:204
#define MUTT_APPENDNEW
Set in mx_open_mailbox_append if the mailbox doesn&#39;t exist.
Definition: mx.h:60
An enumeration.
Definition: enum.h:31
int ctx_mailbox_observer(struct NotifyCallback *nc)
Watch for changes affecting the Context - Implements observer_t.
Definition: context.c:297
int(* msg_commit)(struct Mailbox *m, struct Message *msg)
Save changes to an email.
Definition: mx.h:246
const struct MxOps * mx_get_ops(enum MailboxType type)
Get mailbox operations.
Definition: mx.c:141
Manage keymappings.
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
#define MUTT_ACL_ALL
Definition: mailbox.h:76
#define NONULL(x)
Definition: string2.h:37
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
int msg_count
Total number of messages.
Definition: mailbox.h:91
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:67
off_t size
Size of the Mailbox.
Definition: mailbox.h:87
Representation of the email&#39;s header.
int msg_in_pager
Message currently shown in the pager.
Definition: context.h:44
IMAP network mailbox.
bool C_MarkOld
Config: Mark new emails as old when leaving the mailbox.
Definition: globals.c:36
The envelope/body of an email.
Definition: email.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define TAILQ_FIRST(head)
Definition: queue.h:716
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:43
#define mutt_perror(...)
Definition: logging.h:85
Clear the &#39;last-tagged&#39; pointer.
Definition: mailbox.h:177
WHERE bool C_SaveEmpty
Config: (mbox,mmdf) Preserve empty mailboxes.
Definition: mutt_globals.h:158
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2367
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
Update internal tables.
Definition: mailbox.h:176
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:96
int msg_unread
Number of unread messages.
Definition: mailbox.h:92
int mx_ac_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account - Wrapper for MxOps::ac_add()
Definition: mx.c:1769
int mx_path_canon2(struct Mailbox *m, const char *folder)
Canonicalise the path to realpath.
Definition: mx.c:1483
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: mailbox.h:52
int mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:630
Structs that make up an email.
void mbox_reset_atime(struct Mailbox *m, struct stat *st)
Reset the access time on the mailbox file.
Definition: mbox.c:837
struct MxOps MxNotmuchOps
Notmuch Mailbox - Implements MxOps.
Definition: notmuch.c:2656
The "currently-open" mailbox.
struct MxOps MxMhOps
MH Mailbox - Implements MxOps.
Definition: mh.c:1242
struct tm mutt_date_localtime(time_t t)
Converts calendar time to a broken-down time structure expressed in user timezone.
Definition: date.c:643
bool replied
Definition: mx.h:92
int mx_path_pretty(char *buf, size_t buflen, const char *folder)
Abbreviate a mailbox path - Wrapper for MxOps::path_pretty()
Definition: mx.c:1511
struct HashTable * label_hash
Hash Table for x-labels.
Definition: mailbox.h:129
struct MxOps MxCompOps
Compressed Mailbox - Implements MxOps.
Definition: compress.c:932
int mx_path_parent(char *buf, size_t buflen)
Find the parent of a mailbox path - Wrapper for MxOps::path_parent()
Definition: mx.c:1539
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:447
#define mutt_message(...)
Definition: logging.h:83
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:93
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:67
static int sync_mailbox(struct Mailbox *m)
save changes to disk
Definition: mx.c:483
struct AccountList accounts
List of all Accounts.
Definition: neomutt.h:40
static struct Mailbox * mx_mbox_find_by_name(const char *name)
Find a Mailbox with given name.
Definition: mx.c:1726
void mutt_sort_headers(struct Mailbox *m, struct ThreadsContext *threads, bool init, off_t *vsize)
Sort emails by their headers.
Definition: sort.c:367
static int trash_append(struct Mailbox *m)
move deleted mails to the trash folder
Definition: mx.c:514
bool peekonly
Just taking a glance, revert atime.
Definition: mailbox.h:117
struct NntpAccountData * adata
Definition: lib.h:153
enum UrlScheme scheme
Scheme, e.g. U_SMTPS.
Definition: url.h:69
unsigned char C_Move
Config: Move emails from $spoolfile to $mbox when read.
Definition: mx.c:85
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
NeoMutt Logging.
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:737
struct MailboxList mailboxes
List of Mailboxes.
Definition: account.h:41
struct ThreadsContext * threads
Threads context.
Definition: context.h:43
A group of associated Mailboxes.
Definition: account.h:36
struct MxOps MxMaildirOps
Maildir Mailbox - Implements MxOps.
Definition: maildir.c:1632
String manipulation buffer.
Definition: buffer.h:33
void mx_alloc_memory(struct Mailbox *m)
Create storage for the emails.
Definition: mx.c:1231
#define _(a)
Definition: message.h:28
Mailbox wasn&#39;t recognised.
Definition: mailbox.h:47
Error occurred examining Mailbox.
Definition: mailbox.h:46
An email address.
Definition: address.h:34
struct MxOps MxNntpOps
NNTP Mailbox - Implements MxOps.
Definition: nntp.c:2834
struct Mailbox * mx_mbox_find(struct Account *a, const char *path)
Find a Mailbox on an Account.
Definition: mx.c:1593
static struct Mailbox * mx_mbox_find_by_name_ac(struct Account *a, const char *name)
Find a Mailbox with given name under an Account.
Definition: mx.c:1705
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:303
char * mailbox
Mailbox and host address.
Definition: address.h:37
Messages to be purged (bypass trash)
Definition: mutt.h:100
int(* ac_add)(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account.
Definition: mx.h:134
bool(* ac_owns_path)(struct Account *a, const char *path)
Check whether an Account owns a Mailbox path.
Definition: mx.h:121
void emaillist_clear(struct EmailList *el)
Drop a private list of Emails.
Definition: email.c:130
Index panel (list of emails)
Definition: keymap.h:80
uint8_t OpenMailboxFlags
Flags for mutt_open_mailbox(), e.g. MUTT_NOSORT.
Definition: mx.h:50
int(* path_is_empty)(const char *path)
Is the Mailbox empty?
Definition: mx.h:373
Email list was changed.
Definition: mailbox.h:173
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition: url.c:123
#define MUTT_READONLY
Open in read-only mode.
Definition: mx.h:54
enum MailboxType type
Type of Mailboxes this Account contains.
Definition: account.h:38
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
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:1820
struct Mailbox * mx_mbox_find2(const char *path)
Find a Mailbox on an Account.
Definition: mx.c:1655
WHERE bool OptNeedRescore
(pseudo) set when the &#39;score&#39; command is used
Definition: options.h:42
struct Account * mx_ac_find(struct Mailbox *m)
Find the Account owning a Mailbox.
Definition: mx.c:1569
void mutt_default_save(char *path, size_t pathlen, struct Email *e)
Find the default save path for an email.
Definition: hook.c:654
All user-callable functions.
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:34
Container for Accounts, Notifications.
Definition: neomutt.h:36
int mutt_save_confirm(const char *s, struct stat *st)
Ask the user to save.
Definition: muttlib.c:1350
int vcount
The number of virtual messages.
Definition: mailbox.h:102
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
#define MUTT_SET_DRAFT
set the message draft flag
Definition: mx.h:66
int mx_mbox_sync(struct Mailbox *m)
Save changes to mailbox.
Definition: mx.c:938
int imap_sync_mailbox(struct Mailbox *m, bool expunge, bool close)
Sync all the changes to the server.
Definition: imap.c:1509
char * HomeDir
User&#39;s home directory.
Definition: mutt_globals.h:49
Email Address Handling.
struct Email * email_new(void)
Create a new Email.
Definition: email.c:72
Assorted sorting methods.
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
WHERE char * Username
User&#39;s login name.
Definition: mutt_globals.h:52
int(* mbox_open)(struct Mailbox *m)
Open a Mailbox.
Definition: mx.h:146
int(* mbox_open_append)(struct Mailbox *m, OpenMailboxFlags flags)
Open a Mailbox for appending.
Definition: mx.h:158
Some miscellaneous functions.
#define MAX(a, b)
Definition: memory.h:30
bool has_new
Mailbox has new mail.
Definition: mailbox.h:88
char * C_Trash
Config: Folder to put deleted emails.
Definition: mx.c:86
int(* path_canon)(char *buf, size_t buflen)
Canonicalise a Mailbox path.
Definition: mx.h:336
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1205
bool tagged
Email is tagged.
Definition: email.h:44
bool read
Email is read.
Definition: email.h:51
char * name
A short name for the Mailbox.
Definition: mailbox.h:85
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:1447
struct Message * mx_msg_open_new(struct Mailbox *m, const struct Email *e, MsgOpenFlags flags)
Open a new message.
Definition: mx.c:1073
struct Mailbox * mailbox
Definition: context.h:50
struct HashTable * id_hash
Hash Table by msg id.
Definition: mailbox.h:127
Parse and execute user-defined hooks.
Many unsorted constants and some structs.
Log at debug level 2.
Definition: logging.h:41
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:70
#define MUTT_PEEK
Revert atime back after taking a look (if applicable)
Definition: mx.h:59
void mutt_file_unlink_empty(const char *path)
Delete a file if it&#39;s empty.
Definition: file.c:1311
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:276
bool readonly
Don&#39;t allow changes to the mailbox.
Definition: mailbox.h:119
The Context has been opened.
Definition: context.h:61
struct Mailbox * mx_resolve(const char *path_or_name)
Get a Mailbox from either a path or name.
Definition: mx.c:1751
struct Envelope * env
Envelope information.
Definition: email.h:90
Convenience wrapper for the core headers.
int mx_tags_commit(struct Mailbox *m, struct Email *e, char *tags)
Save tags to the Mailbox - Wrapper for MxOps::tags_commit()
Definition: mx.c:1309
struct Notify * notify
Notifications handler.
Definition: context.h:51
void mx_fastclose_mailbox(struct Mailbox *m)
free up memory associated with the Mailbox
Definition: mx.c:445
struct MxOps MxImapOps
IMAP Mailbox - Implements MxOps.
Definition: imap.c:2454
char * group
Definition: lib.h:140
struct MxOps MxPopOps
POP Mailbox - Implements MxOps.
Definition: pop.c:1242
int opened
Number of times mailbox is opened.
Definition: mailbox.h:132
Email Aliases.
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
User aborted the question (with Ctrl-G)
Definition: quad.h:38
unsigned char C_CatchupNewsgroup
Config: (nntp) Mark all articles as read when leaving a newsgroup.
Definition: config.c:37
Compressed mbox local mailbox type.
int(* msg_padding_size)(struct Mailbox *m)
Bytes of padding between messages.
Definition: mx.h:269
void * mdata
Driver specific data.
Definition: mailbox.h:136
bool notify_observer_add(struct Notify *notify, enum NotifyType type, observer_t callback, void *global_data)
Add an observer to an object.
Definition: notify.c:169
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
int mx_mbox_check_stats(struct Mailbox *m, uint8_t flags)
Check the statistics for a mailbox - Wrapper for MxOps::mbox_check_stats()
Definition: mx.c:1803
struct HashTable * subj_hash
Hash Table by subject.
Definition: mailbox.h:128
#define MUTT_MBOX_HOOK
mbox-hook: move messages after reading them
Definition: hook.h:46
&#39;Maildir&#39; Mailbox type
Definition: mailbox.h:51
Usenet network mailbox type; talk to an NNTP server.
enum MailboxType type
Mailbox type, e.g. MUTT_IMAP.
Definition: mx.h:106
int imap_mxcmp(const char *mx1, const char *mx2)
Compare mailbox names, giving priority to INBOX.
Definition: util.c:690
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
struct Keymap * km_find_func(enum MenuType menu, int func)
Find a function&#39;s mapping in a Menu.
Definition: keymap.c:939
Old messages.
Definition: mutt.h:94
off_t vsize
Size (in bytes) of the messages shown.
Definition: context.h:40
Email list needs resorting.
Definition: mailbox.h:174
int(* mbox_check)(struct Mailbox *m)
Check for new mail.
Definition: mx.h:169
WHERE bool OptForceRefresh
(pseudo) refresh even during macros
Definition: options.h:37
Prototypes for many functions.
#define MB_HIDDEN
Definition: mailbox.h:38
Notmuch virtual mailbox type.
int(* tags_edit)(struct Mailbox *m, const char *tags, char *buf, size_t buflen)
Prompt and validate new messages tags.
Definition: mx.h:298
struct Context * ctx_new(struct Mailbox *m)
Create a new Context.
Definition: context.c:76
bool flagged
Definition: mx.h:91
A local copy of an email.
Definition: mx.h:82
int email_max
Number of pointers in emails.
Definition: mailbox.h:100
int imap_copy_messages(struct Mailbox *m, struct EmailList *el, const char *dest, bool delete_original)
Server COPY messages to another folder.
Definition: message.c:1564
void ctx_update(struct Context *ctx)
Update the Context&#39;s message counts.
Definition: context.c:112
struct Message::@0 flags
int imap_access(const char *path)
Check permissions on an IMAP mailbox with a new connection.
Definition: imap.c:470
Messages to be deleted.
Definition: mutt.h:98
A mailbox.
Definition: mailbox.h:81
#define PATH_MAX
Definition: mutt.h:44
char * mutt_find_hook(HookFlags type, const char *pat)
Find a matching hook.
Definition: hook.c:552
char * user
Username.
Definition: url.h:70
#define MUTT_NOSORT
Do not sort the mailbox after opening it.
Definition: mx.h:52
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:50
int km_expand_key(char *s, size_t len, struct Keymap *map)
Get the key string bound to a Keymap.
Definition: keymap.c:911
struct MxOps MxMmdfOps
MMDF Mailbox - Implements MxOps.
Definition: mbox.c:1843
int(* mbox_sync)(struct Mailbox *m)
Save changes to the Mailbox.
Definition: mx.h:193
bool dontwrite
Don&#39;t write the mailbox on close.
Definition: mailbox.h:115
int(* msg_save_hcache)(struct Mailbox *m, struct Email *e)
Save message to the header cache.
Definition: mx.h:282
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: mutt_globals.h:96
&#39;mmdf&#39; Mailbox type
Definition: mailbox.h:49
int(* msg_open)(struct Mailbox *m, struct Message *msg, int msgno)
Open an email message in a Mailbox.
Definition: mx.h:219
POP network mailbox.
Compressed file Mailbox type.
Definition: mailbox.h:56
bool append
Mailbox is opened in append mode.
Definition: mailbox.h:113
&#39;MH&#39; Mailbox type
Definition: mailbox.h:50
bool verbose
Display status messages?
Definition: mailbox.h:118
const struct MxOps * mx_ops
MXAPI callback functions.
Definition: mailbox.h:111
char * host
Host.
Definition: url.h:72
#define CH_UPDATE_LEN
Update Lines: and Content-Length:
Definition: copy.h:61
bool purge
Skip trash folder when deleting.
Definition: email.h:46
int mx_tags_edit(struct Mailbox *m, const char *tags, char *buf, size_t buflen)
start the tag editor of the mailbox
Definition: mx.c:1289
unsigned char C_MboxType
Config: Default type for creating new mailboxes.
Definition: mx.c:84
int msg_tagged
How many messages are tagged?
Definition: mailbox.h:97
WHERE bool C_MailCheckRecent
Config: Notify the user about new mail since the last time the mailbox was opened.
Definition: mutt_globals.h:150
bool draft
Definition: mx.h:93
#define MUTT_QUIET
Do not print any messages.
Definition: mx.h:55
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:121
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
struct Account * account_new(const char *name, struct ConfigSubset *sub)
Create a new Account.
Definition: account.c:43
int mx_mbox_check(struct Mailbox *m)
Check for new mail - Wrapper for MxOps::mbox_check()
Definition: mx.c:1140
int emaillist_add_email(struct EmailList *el, struct Email *e)
Add an Email to a list.
Definition: email.c:151
uint8_t MsgOpenFlags
Flags for mx_msg_open_new(), e.g. MUTT_ADD_FROM.
Definition: mx.h:63
NNTP-specific Mailbox data -.
Definition: lib.h:138
Maildir local mailbox type.
#define MMDF_SEP
Definition: lib.h:64
WHERE char * LastFolder
Previously selected mailbox.
Definition: mutt_globals.h:55
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
char * path
Path.
Definition: url.h:74
&#39;mbox&#39; Mailbox type
Definition: mailbox.h:48
bool write
nonzero if message is open for writing
Definition: mx.h:87
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:138
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:101
uint8_t flags
e.g. MB_NORMAL
Definition: mailbox.h:134
void mutt_make_label_hash(struct Mailbox *m)
Create a Hash Table to store the labels.
Definition: mutt_header.c:365
WHERE char * C_Record
Config: Folder to save &#39;sent&#39; messages.
Definition: mutt_globals.h:98
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: curs_lib.c:517
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
struct Mailbox * mailbox_new(void)
Create a new Mailbox.
Definition: mailbox.c:51
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1336
WHERE unsigned char C_Delete
Config: Really delete messages, when the mailbox is closed.
Definition: mutt_globals.h:125
bool mutt_path_canon(char *buf, size_t buflen, const char *homedir, bool is_dir)
Create the canonical version of a path.
Definition: path.c:285
Context has changed, NotifyContext, EventContext.
Definition: notify_type.h:38
Duplicate the structure of an entire email.
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:323
MailboxType
Supported mailbox formats.
Definition: mailbox.h:43
struct AddressList return_path
Return path for the Email.
Definition: envelope.h:56
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:131
WHERE char * C_Spoolfile
Config: Inbox.
Definition: mutt_globals.h:108
Log at debug level 1.
Definition: logging.h:40
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:716
int(* msg_open_new)(struct Mailbox *m, struct Message *msg, const struct Email *e)
Open a new message in a Mailbox.
Definition: mx.h:233
int(* mbox_close)(struct Mailbox *m)
Close a Mailbox.
Definition: mx.h:204
static int mx_open_mailbox_append(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox for appending.
Definition: mx.c:200
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
bool collapsed
Are all threads collapsed?
Definition: context.h:48
bool deleted
Email is deleted.
Definition: email.h:45
int(* path_pretty)(char *buf, size_t buflen, const char *folder)
Abbreviate a Mailbox path.
Definition: mx.h:349
bool C_MaildirTrash
Config: Use the maildir &#39;trashed&#39; flag, rather than deleting.
Definition: config.c:42
#define mutt_error(...)
Definition: logging.h:84
bool replied
Email has been replied to.
Definition: email.h:54
int mx_msg_commit(struct Mailbox *m, struct Message *msg)
Commit a message to a folder - Wrapper for MxOps::msg_commit()
Definition: mx.c:1184
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: mutt_globals.h:54
int mutt_append_message(struct Mailbox *dest, struct Mailbox *src, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags)
Append a message.
Definition: copy.c:905
FILE * fp
pointer to the message data
Definition: mx.h:84
bool account_mailbox_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account.
Definition: account.c:66
#define FREE(x)
Definition: memory.h:40
int(* msg_close)(struct Mailbox *m, struct Message *msg)
Close an email.
Definition: mx.h:259
bool account_mailbox_remove(struct Account *a, struct Mailbox *m)
Remove a Mailbox from an Account.
Definition: account.c:94
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1682
Mailbox has changed, NotifyMailbox, EventMailbox.
Definition: notify_type.h:42
Mapping between user-readable string and a constant.
Definition: mapping.h:31
int mx_access(const char *path, int flags)
Wrapper for access, checks permissions on a given mailbox.
Definition: mx.c:183
bool mx_mbox_ac_link(struct Mailbox *m)
Link a Mailbox to an existing or new Account.
Definition: mx.c:266
#define STAILQ_EMPTY(head)
Definition: queue.h:345
time_t received
the time at which this message was received
Definition: mx.h:95
struct MxOps MxMboxOps
Mbox Mailbox - Implements MxOps.
Definition: mbox.c:1813
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:321
bool neomutt_account_remove(struct NeoMutt *n, struct Account *a)
Remove an Account from the global list.
Definition: neomutt.c:105
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:39
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
struct AddressList sender
Email&#39;s sender.
Definition: envelope.h:61
WHERE bool OptSortSubthreads
(pseudo) used when $sort_aux changes
Definition: options.h:54
List of Mailboxes.
Definition: mailbox.h:152
bool changed
Mailbox has been modified.
Definition: mailbox.h:114
void ctx_free(struct Context **ptr)
Free a Context.
Definition: context.c:50
Hundreds of global variables to back the user variables.
Handling of global boolean variables.
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
void mutt_mailbox_set_notified(struct Mailbox *m)
Note when the user was last notified of new mail.
Definition: mutt_mailbox.c:286
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size()
Definition: mx.c:1555
New mail received in Mailbox.
Definition: mx.h:73
bool mutt_str_inline_replace(char *buf, size_t buflen, size_t xlen, const char *rstr)
Replace the beginning of a string.
Definition: string.c:1013
bool mx_tags_is_supported(struct Mailbox *m)
return true if mailbox support tagging
Definition: mx.c:1326
struct Notify * notify
Notifications handler.
Definition: mailbox.h:144
bool C_KeepFlagged
Config: Don&#39;t move flagged messages from $spoolfile to $mbox
Definition: mx.c:83
An Event that happened to an Context.
Definition: context.h:68
#define TAILQ_EMPTY(head)
Definition: queue.h:714
#define MUTT_NEWFOLDER
Create a new folder - same as MUTT_APPEND,.
Definition: mx.h:56
bool neomutt_account_add(struct NeoMutt *n, struct Account *a)
Add an Account to the global list.
Definition: neomutt.c:84
int mx_ac_remove(struct Mailbox *m)
Remove a Mailbox from an Account and delete Account if empty.
Definition: mx.c:1785
struct NntpMboxData * mutt_newsgroup_catchup(struct Mailbox *m, struct NntpAccountData *adata, char *group)
Catchup newsgroup.
Definition: newsrc.c:1294
struct Buffer pathbuf
Definition: mailbox.h:83
Convenience wrapper for the library headers.
bool read
Definition: mx.h:90
int(* mbox_check_stats)(struct Mailbox *m, uint8_t flags)
Check the Mailbox statistics.
Definition: mx.h:182
#define MUTT_ADD_FROM
add a From_ line
Definition: mx.h:65
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
Mailbox was reopened.
Definition: mx.h:75
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
int mx_path_canon(char *buf, size_t buflen, const char *folder, enum MailboxType *type)
Canonicalise a mailbox path - Wrapper for MxOps::path_canon()
Definition: mx.c:1382
int imap_fast_trash(struct Mailbox *m, char *dest)
Use server COPY command to copy deleted messages to trash.
Definition: imap.c:1397
WHERE char * C_Mbox
Config: Folder that receives read emails (see Move)
Definition: mutt_globals.h:94
void mailbox_changed(struct Mailbox *m, enum NotifyMailbox action)
Notify observers of a change to a Mailbox.
Definition: mailbox.c:184
static bool mutt_is_spool(const char *str)
Is this the spoolfile?
Definition: mx.c:155
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
return a stream pointer for a message
Definition: mx.c:1159
time_t received
Time when the message was placed in the mailbox.
Definition: email.h:83
char * path
path to temp file
Definition: mx.h:85
bool mutt_comp_can_append(struct Mailbox *m)
Can we append to this path?
Definition: compress.c:356
The Mailbox API.
Definition: mx.h:104
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:154
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:234
int(* tags_commit)(struct Mailbox *m, struct Email *e, char *buf)
Save the tags to a message.
Definition: mx.h:313
WHERE bool C_Confirmappend
Config: Confirm before appending emails to a mailbox.
Definition: mutt_globals.h:141
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:152