Thanks to visit codestin.com
Credit goes to code.neomutt.org

NeoMutt  2025-12-11-189-gceedb6
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
mx.c
Go to the documentation of this file.
1
29
35
36#include "config.h"
37#include <errno.h>
38#include <stdbool.h>
39#include <stdio.h>
40#include <string.h>
41#include <sys/stat.h>
42#include <time.h>
43#include <unistd.h>
44#include "mutt/lib.h"
45#include "address/lib.h"
46#include "config/lib.h"
47#include "email/lib.h"
48#include "core/lib.h"
49#include "alias/lib.h"
50#include "gui/lib.h"
51#include "mutt.h"
52#include "mx.h"
53#include "compmbox/lib.h"
54#include "hooks/lib.h"
55#include "imap/lib.h"
56#include "key/lib.h"
57#include "maildir/lib.h"
58#include "mbox/lib.h"
59#include "menu/lib.h"
60#include "mh/lib.h"
61#include "nntp/lib.h"
62#include "pop/lib.h"
63#include "question/lib.h"
64#include "external.h"
65#include "globals.h"
66#include "mutt_logging.h"
67#include "mutt_mailbox.h"
68#include "muttlib.h"
69#include "nntp/mdata.h" // IWYU pragma: keep
70#ifdef USE_NOTMUCH
71#include "notmuch/lib.h"
72#endif
73#ifdef ENABLE_NLS
74#include <libintl.h>
75#endif
76
78static const struct Mapping MboxTypeMap[] = {
79 // clang-format off
80 { "mbox", MUTT_MBOX, },
81 { "mmdf", MUTT_MMDF, },
82 { "mh", MUTT_MH, },
83 { "maildir", MUTT_MAILDIR, },
84 { NULL, 0, },
85 // clang-format on
86};
87
89const struct EnumDef MboxTypeDef = {
90 "mbox_type",
91 4,
92 (struct Mapping *) &MboxTypeMap,
93};
94
98static const struct MxOps *MxOps[] = {
99 /* These mailboxes can be recognised by their Url scheme */
100 &MxImapOps,
101#ifdef USE_NOTMUCH
103#endif
104 &MxPopOps,
105 &MxNntpOps,
106
107 /* Local mailboxes */
109 &MxMboxOps,
110 &MxMhOps,
111 &MxMmdfOps,
112
113 /* If everything else fails... */
114 &MxCompOps,
115 NULL,
116};
117
124const struct MxOps *mx_get_ops(enum MailboxType type)
125{
126 for (const struct MxOps **ops = MxOps; *ops; ops++)
127 if ((*ops)->type == type)
128 return *ops;
129
130 return NULL;
131}
132
138static bool mutt_is_spool(const char *str)
139{
140 const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
141 if (mutt_str_equal(str, c_spool_file))
142 return true;
143
144 struct Url *ua = url_parse(str);
145 struct Url *ub = url_parse(c_spool_file);
146
147 const bool is_spool = ua && ub && (ua->scheme == ub->scheme) &&
148 mutt_istr_equal(ua->host, ub->host) &&
149 mutt_istr_equal(ua->path, ub->path) &&
150 (!ua->user || !ub->user || mutt_str_equal(ua->user, ub->user));
151
152 url_free(&ua);
153 url_free(&ub);
154 return is_spool;
155}
156
167int mx_access(const char *path, int flags)
168{
169 if (imap_path_probe(path, NULL) == MUTT_IMAP)
170 return imap_access(path);
171
172 return access(path, flags);
173}
174
183{
184 if (!m)
185 return false;
186
187 struct stat st = { 0 };
188
189 m->append = true;
190 if ((m->type == MUTT_UNKNOWN) || (m->type == MUTT_MAILBOX_ERROR))
191 {
193
194 if (m->type == MUTT_UNKNOWN)
195 {
196 if (flags & MUTT_APPEND)
197 {
199 }
200 else
201 {
202 mutt_error(_("%s is not a mailbox"), mailbox_path(m));
203 return false;
204 }
205 }
206
207 if (m->type == MUTT_MAILBOX_ERROR)
208 {
209 if (stat(mailbox_path(m), &st) == -1)
210 {
211 if (errno == ENOENT)
212 {
215 else
216 m->type = cs_subset_enum(NeoMutt->sub, "mbox_type");
217 flags |= MUTT_APPENDNEW;
218 }
219 else
220 {
221 mutt_perror("%s", mailbox_path(m));
222 return false;
223 }
224 }
225 else
226 {
227 return false;
228 }
229 }
230
231 m->mx_ops = mx_get_ops(m->type);
232 }
233
234 if (!m->mx_ops || !m->mx_ops->mbox_open_append)
235 return false;
236
237 const bool rc = m->mx_ops->mbox_open_append(m, flags);
238 m->opened++;
239 return rc;
240}
241
249{
250 if (!m)
251 return false;
252
253 if (m->account)
254 return true;
255
256 struct Account *a = mx_ac_find(m);
257 const bool new_account = !a;
258 if (new_account)
259 {
260 a = account_new(NULL, NeoMutt->sub);
261 a->type = m->type;
262 }
263 if (!mx_ac_add(a, m))
264 {
265 if (new_account)
266 {
267 account_free(&a);
268 }
269 return false;
270 }
271 if (new_account)
272 {
274 }
275 return true;
276}
277
286{
287 if (!m)
288 return false;
289
290 if ((m->type == MUTT_UNKNOWN) && (flags & MUTT_APPEND))
291 {
292 m->type = cs_subset_enum(NeoMutt->sub, "mbox_type");
293 m->mx_ops = mx_get_ops(m->type);
294 }
295
296 const bool newly_linked_account = !m->account;
297 if (newly_linked_account)
298 {
299 if (!mx_mbox_ac_link(m))
300 {
301 return false;
302 }
303 }
304
305 m->verbose = !(flags & MUTT_QUIET);
306 m->readonly = (flags & MUTT_READONLY);
307 m->peekonly = (flags & MUTT_PEEK);
308
309 if (flags & MUTT_APPEND)
310 {
311 if (!mx_open_mailbox_append(m, flags))
312 {
313 goto error;
314 }
315 return true;
316 }
317
318 if (m->opened > 0)
319 {
320 m->opened++;
321 return true;
322 }
323
324 m->size = 0;
325 m->msg_unread = 0;
326 m->msg_flagged = 0;
327 m->rights = MUTT_ACL_ALL;
328
329 if (m->type == MUTT_UNKNOWN)
330 {
332 m->mx_ops = mx_get_ops(m->type);
333 }
334
335 if ((m->type == MUTT_UNKNOWN) || (m->type == MUTT_MAILBOX_ERROR) || !m->mx_ops)
336 {
337 if (m->type == MUTT_MAILBOX_ERROR)
338 mutt_perror("%s", mailbox_path(m));
339 else if ((m->type == MUTT_UNKNOWN) || !m->mx_ops)
340 mutt_error(_("%s is not a mailbox"), mailbox_path(m));
341 goto error;
342 }
343
345
346 /* if the user has a 'push' command in their .neomuttrc, or in a folder-hook,
347 * it will cause the progress messages not to be displayed because
348 * mutt_refresh() will think we are in the middle of a macro. so set a
349 * flag to indicate that we should really refresh the screen. */
350 OptForceRefresh = true;
351
352 if (m->verbose)
353 mutt_message(_("Reading %s..."), mailbox_path(m));
354
355 // Clear out any existing emails
356 for (int i = 0; i < m->email_max; i++)
357 {
358 email_free(&m->emails[i]);
359 }
360
361 m->msg_count = 0;
362 m->msg_unread = 0;
363 m->msg_flagged = 0;
364 m->msg_new = 0;
365 m->msg_deleted = 0;
366 m->msg_tagged = 0;
367 m->vcount = 0;
368
369 enum MxOpenReturns rc = m->mx_ops->mbox_open(m);
370 m->opened++;
371
372 if ((rc == MX_OPEN_OK) || (rc == MX_OPEN_ABORT))
373 {
374 if ((flags & MUTT_NOSORT) == 0)
375 {
376 /* avoid unnecessary work since the mailbox is completely unthreaded
377 * to begin with */
378 OptSortSubthreads = false;
379 OptNeedRescore = false;
380 }
381 if (m->verbose)
383 if (rc == MX_OPEN_ABORT)
384 {
385 mutt_error(_("Reading from %s interrupted..."), mailbox_path(m));
386 }
387 }
388 else
389 {
390 goto error;
391 }
392
393 if (!m->peekonly)
394 m->has_new = false;
395 OptForceRefresh = false;
396
397 return true;
398
399error:
400 mx_fastclose_mailbox(m, newly_linked_account);
401 if (newly_linked_account)
403 return false;
404}
405
411void mx_fastclose_mailbox(struct Mailbox *m, bool keep_account)
412{
413 if (!m)
414 return;
415
416 m->opened--;
417 if (m->opened != 0)
418 return;
419
420 /* never announce that a mailbox we've just left has new mail.
421 * TODO: really belongs in mx_mbox_close, but this is a nice hook point */
422 if (!m->peekonly)
424
425 if (m->mx_ops)
426 m->mx_ops->mbox_close(m);
427
431
432 if (m->emails)
433 {
434 for (int i = 0; i < m->msg_count; i++)
435 {
436 if (!m->emails[i])
437 break;
438 email_free(&m->emails[i]);
439 }
440 }
441
442 if (!m->visible)
443 {
444 mx_ac_remove(m, keep_account);
445 }
446}
447
453static enum MxStatus sync_mailbox(struct Mailbox *m)
454{
455 if (!m || !m->mx_ops || !m->mx_ops->mbox_sync)
456 return MX_STATUS_ERROR;
457
458 if (m->verbose)
459 {
460 /* L10N: Displayed before/as a mailbox is being synced */
461 mutt_message(_("Writing %s..."), mailbox_path(m));
462 }
463
464 enum MxStatus rc = m->mx_ops->mbox_sync(m);
465 if (rc != MX_STATUS_OK)
466 {
467 mutt_debug(LL_DEBUG2, "mbox_sync returned: %d\n", rc);
468 if ((rc == MX_STATUS_ERROR) && m->verbose)
469 {
470 /* L10N: Displayed if a mailbox sync fails */
471 mutt_error(_("Unable to write %s"), mailbox_path(m));
472 }
473 }
474
475 return rc;
476}
477
484static int trash_append(struct Mailbox *m)
485{
486 if (!m)
487 return -1;
488
489 struct stat st = { 0 };
490 struct stat stc = { 0 };
491 int rc;
492
493 const bool c_maildir_trash = cs_subset_bool(NeoMutt->sub, "maildir_trash");
494 const char *const c_trash = cs_subset_string(NeoMutt->sub, "trash");
495 if (!c_trash || (m->msg_deleted == 0) || ((m->type == MUTT_MAILDIR) && c_maildir_trash))
496 {
497 return 0;
498 }
499
500 int delmsgcount = 0;
501 int first_del = -1;
502 for (int i = 0; i < m->msg_count; i++)
503 {
504 struct Email *e = m->emails[i];
505 if (!e)
506 break;
507
508 if (e->deleted && !e->purge)
509 {
510 if (first_del < 0)
511 first_del = i;
512 delmsgcount++;
513 }
514 }
515
516 if (delmsgcount == 0)
517 return 0; /* nothing to be done */
518
519 /* avoid the "append messages" prompt */
520 const bool c_confirm_append = cs_subset_bool(NeoMutt->sub, "confirm_append");
521 cs_subset_str_native_set(NeoMutt->sub, "confirm_append", false, NULL);
522 rc = mutt_save_confirm(c_trash, &st);
523 cs_subset_str_native_set(NeoMutt->sub, "confirm_append", c_confirm_append, NULL);
524 if (rc != 0)
525 {
526 /* L10N: Although we know the precise number of messages, we do not show it to the user.
527 So feel free to use a "generic plural" as plural translation if your language has one. */
528 mutt_error(ngettext("message not deleted", "messages not deleted", delmsgcount));
529 return -1;
530 }
531
532 if ((lstat(mailbox_path(m), &stc) == 0) && (stc.st_ino == st.st_ino) &&
533 (stc.st_dev == st.st_dev) && (stc.st_rdev == st.st_rdev))
534 {
535 return 0; /* we are in the trash folder: simple sync */
536 }
537
538 if ((m->type == MUTT_IMAP) && (imap_path_probe(c_trash, NULL) == MUTT_IMAP))
539 {
540 if (imap_fast_trash(m, c_trash) == 0)
541 return 0;
542 }
543
544 struct Mailbox *m_trash = mx_path_resolve(c_trash);
545 const bool old_append = m_trash->append;
546 if (!mx_mbox_open(m_trash, MUTT_APPEND))
547 {
548 mutt_error(_("Can't open trash folder"));
549 mailbox_free(&m_trash);
550 return -1;
551 }
552
553 /* continue from initial scan above */
554 for (int i = first_del; i < m->msg_count; i++)
555 {
556 struct Email *e = m->emails[i];
557 if (!e)
558 break;
559
560 if (e->deleted && !e->purge)
561 {
562 if (mutt_append_message(m_trash, m, e, NULL, MUTT_CM_NO_FLAGS, CH_NO_FLAGS) == -1)
563 {
564 mx_mbox_close(m_trash);
565 // L10N: Displayed if appending to $trash fails when syncing or closing a mailbox
566 mutt_error(_("Unable to append to trash folder"));
567 m_trash->append = old_append;
568 mailbox_free(&m_trash);
569 return -1;
570 }
571 }
572 }
573
574 mx_mbox_close(m_trash);
575 m_trash->append = old_append;
576 mailbox_free(&m_trash);
577
578 return 0;
579}
580
596{
597 if (!m)
598 return MX_STATUS_ERROR;
599
600 const bool c_mail_check_recent = cs_subset_bool(NeoMutt->sub, "mail_check_recent");
601 if (c_mail_check_recent && !m->peekonly)
602 m->has_new = false;
603
604 if (m->readonly || m->dontwrite || m->append || m->peekonly)
605 {
606 mx_fastclose_mailbox(m, false);
607 return 0;
608 }
609
610 int i, read_msgs = 0;
611 enum MxStatus rc = MX_STATUS_ERROR;
612 enum QuadOption move_messages = MUTT_NO;
614 struct Buffer *mbox = NULL;
615 struct Buffer *buf = buf_pool_get();
616
617 if ((m->msg_unread != 0) && (m->type == MUTT_NNTP))
618 {
619 struct NntpMboxData *mdata = m->mdata;
620
621 if (mdata && mdata->adata && mdata->group)
622 {
623 enum QuadOption ans = query_quadoption(_("Mark all articles read?"),
624 NeoMutt->sub, "catchup_newsgroup");
625 if (ans == MUTT_ABORT)
626 goto cleanup;
627 if (ans == MUTT_YES)
628 mutt_newsgroup_catchup(m, mdata->adata, mdata->group);
629 }
630 }
631
632 const bool c_keep_flagged = cs_subset_bool(NeoMutt->sub, "keep_flagged");
633 for (i = 0; i < m->msg_count; i++)
634 {
635 struct Email *e = m->emails[i];
636 if (!e)
637 break;
638
639 if (!e->deleted && e->read && !(e->flagged && c_keep_flagged))
640 read_msgs++;
641 }
642
643 /* don't need to move articles from newsgroup */
644 if (m->type == MUTT_NNTP)
645 read_msgs = 0;
646
647 const enum QuadOption c_move = cs_subset_quad(NeoMutt->sub, "move");
648 if ((read_msgs != 0) && (c_move != MUTT_NO))
649 {
650 bool is_spool;
651 mbox = buf_pool_get();
652
654 if (p)
655 {
656 is_spool = true;
657 buf_strcpy(mbox, p);
658 }
659 else
660 {
661 const char *const c_mbox = cs_subset_string(NeoMutt->sub, "mbox");
662 buf_strcpy(mbox, c_mbox);
663 is_spool = mutt_is_spool(mailbox_path(m)) && !mutt_is_spool(buf_string(mbox));
664 }
665
666 if (is_spool && !buf_is_empty(mbox))
667 {
668 expand_path(mbox, false);
669 buf_printf(buf,
670 /* L10N: The first argument is the number of read messages to be
671 moved, the second argument is the target mailbox. */
672 ngettext("Move %d read message to %s?", "Move %d read messages to %s?", read_msgs),
673 read_msgs, buf_string(mbox));
674 move_messages = query_quadoption(buf_string(buf), NeoMutt->sub, "move");
675 if (move_messages == MUTT_ABORT)
676 goto cleanup;
677 }
678 }
679
680 /* There is no point in asking whether or not to purge if we are
681 * just marking messages as "trash". */
682 const bool c_maildir_trash = cs_subset_bool(NeoMutt->sub, "maildir_trash");
683 if ((m->msg_deleted != 0) && !((m->type == MUTT_MAILDIR) && c_maildir_trash))
684 {
685 buf_printf(buf, ngettext("Purge %d deleted message?", "Purge %d deleted messages?", m->msg_deleted),
686 m->msg_deleted);
687 purge = query_quadoption(buf_string(buf), NeoMutt->sub, "delete");
688 if (purge == MUTT_ABORT)
689 goto cleanup;
690 }
691
692 const bool c_mark_old = cs_subset_bool(NeoMutt->sub, "mark_old");
693 if (c_mark_old && !m->peekonly)
694 {
695 for (i = 0; i < m->msg_count; i++)
696 {
697 struct Email *e = m->emails[i];
698 if (!e)
699 break;
700 if (!e->deleted && !e->old && !e->read)
701 mutt_set_flag(m, e, MUTT_OLD, true, true);
702 }
703 }
704
705 if (move_messages)
706 {
707 if (m->verbose)
708 mutt_message(_("Moving read messages to %s..."), buf_string(mbox));
709
710 /* try to use server-side copy first */
711 i = 1;
712
713 if ((m->type == MUTT_IMAP) && (imap_path_probe(buf_string(mbox), NULL) == MUTT_IMAP))
714 {
715 /* add messages for moving, and clear old tags, if any */
716 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
717 for (i = 0; i < m->msg_count; i++)
718 {
719 struct Email *e = m->emails[i];
720 if (!e)
721 break;
722
723 if (e->read && !e->deleted && !(e->flagged && c_keep_flagged))
724 {
725 e->tagged = true;
726 ARRAY_ADD(&ea, e);
727 }
728 else
729 {
730 e->tagged = false;
731 }
732 }
733
734 i = imap_copy_messages(m, &ea, buf_string(mbox), SAVE_MOVE);
735 if (i == 0)
736 {
737 const bool c_delete_untag = cs_subset_bool(NeoMutt->sub, "delete_untag");
738 if (c_delete_untag)
739 {
740 struct Email **ep = NULL;
741 ARRAY_FOREACH(ep, &ea)
742 {
743 mutt_set_flag(m, *ep, MUTT_TAG, false, true);
744 }
745 }
746 }
747 ARRAY_FREE(&ea);
748 }
749
750 if (i == 0) /* success */
751 {
753 }
754 else if (i == -1) /* horrible error, bail */
755 {
756 goto cleanup;
757 }
758 else /* use regular append-copy mode */
759 {
760 struct Mailbox *m_read = mx_path_resolve(buf_string(mbox));
761 if (!mx_mbox_open(m_read, MUTT_APPEND))
762 {
763 mailbox_free(&m_read);
764 goto cleanup;
765 }
766
767 for (i = 0; i < m->msg_count; i++)
768 {
769 struct Email *e = m->emails[i];
770 if (!e)
771 break;
772 if (e->read && !e->deleted && !(e->flagged && c_keep_flagged))
773 {
774 if (mutt_append_message(m_read, m, e, NULL, MUTT_CM_NO_FLAGS, CH_UPDATE_LEN) == 0)
775 {
776 mutt_set_flag(m, e, MUTT_DELETE, true, true);
777 mutt_set_flag(m, e, MUTT_PURGE, true, true);
778 }
779 else
780 {
781 mx_mbox_close(m_read);
782 goto cleanup;
783 }
784 }
785 }
786
787 mx_mbox_close(m_read);
788 }
789 }
790 else if (!m->changed && (m->msg_deleted == 0))
791 {
792 if (m->verbose)
793 mutt_message(_("Mailbox is unchanged"));
794 if ((m->type == MUTT_MBOX) || (m->type == MUTT_MMDF))
795 mbox_reset_atime(m, NULL);
796 mx_fastclose_mailbox(m, false);
797 rc = MX_STATUS_OK;
798 goto cleanup;
799 }
800
801 /* copy mails to the trash before expunging */
802 const char *const c_trash = cs_subset_string(NeoMutt->sub, "trash");
803 const struct Mailbox *m_trash = mx_mbox_find(m->account, c_trash);
804 if (purge && (m->msg_deleted != 0) && (m != m_trash))
805 {
806 if (trash_append(m) != 0)
807 goto cleanup;
808 }
809
810 /* allow IMAP to preserve the deleted flag across sessions */
811 if (m->type == MUTT_IMAP)
812 {
813 const enum MxStatus check = imap_sync_mailbox(m, (purge != MUTT_NO), true);
814 if (check == MX_STATUS_ERROR)
815 {
816 rc = check;
817 goto cleanup;
818 }
819 }
820 else
821 {
822 if (purge == MUTT_NO)
823 {
824 for (i = 0; i < m->msg_count; i++)
825 {
826 struct Email *e = m->emails[i];
827 if (!e)
828 break;
829
830 e->deleted = false;
831 e->purge = false;
832 }
833 m->msg_deleted = 0;
834 }
835
836 if (m->changed || (m->msg_deleted != 0))
837 {
838 enum MxStatus check = sync_mailbox(m);
839 if (check != MX_STATUS_OK)
840 {
841 rc = check;
842 goto cleanup;
843 }
844 }
845 }
846
847 if (m->verbose)
848 {
849 if (move_messages)
850 {
851 mutt_message(_("%d kept, %d moved, %d deleted"),
852 m->msg_count - m->msg_deleted, read_msgs, m->msg_deleted);
853 }
854 else
855 {
856 mutt_message(_("%d kept, %d deleted"), m->msg_count - m->msg_deleted, m->msg_deleted);
857 }
858 }
859
860 const bool c_save_empty = cs_subset_bool(NeoMutt->sub, "save_empty");
861 if ((m->msg_count == m->msg_deleted) &&
862 ((m->type == MUTT_MMDF) || (m->type == MUTT_MBOX)) &&
863 !mutt_is_spool(mailbox_path(m)) && !c_save_empty)
864 {
866 }
867
868 if ((purge == MUTT_YES) && (m->msg_deleted != 0))
869 {
870 for (i = 0; i < m->msg_count; i++)
871 {
872 struct Email *e = m->emails[i];
873 if (!e)
874 break;
875 if (e->deleted && !e->read)
876 {
877 m->msg_unread--;
878 if (!e->old)
879 m->msg_new--;
880 }
881 if (e->deleted && e->flagged)
882 m->msg_flagged--;
883 }
884 }
885
886 mx_fastclose_mailbox(m, false);
887
888 rc = MX_STATUS_OK;
889
890cleanup:
891 buf_pool_release(&mbox);
892 buf_pool_release(&buf);
893 return rc;
894}
895
904{
905 if (!m)
906 return MX_STATUS_ERROR;
907
908 enum MxStatus rc = MX_STATUS_OK;
909 int purge = 1;
910 int msgcount, deleted;
911
912 if (m->dontwrite)
913 {
914 struct Buffer *buf = buf_pool_get();
915 struct Buffer *tmp = buf_pool_get();
916
917 if (keymap_expand_key(km_find_func(MENU_INDEX, OP_TOGGLE_WRITE), buf))
918 buf_printf(tmp, _(" Press '%s' to toggle write"), buf_string(buf));
919 else
920 buf_addstr(tmp, _("Use 'toggle-write' to re-enable write"));
921
922 mutt_error(_("Mailbox is marked unwritable. %s"), buf_string(tmp));
923
924 buf_pool_release(&buf);
925 buf_pool_release(&tmp);
926 return MX_STATUS_ERROR;
927 }
928 else if (m->readonly)
929 {
930 mutt_error(_("Mailbox is read-only"));
931 return MX_STATUS_ERROR;
932 }
933
934 if (!m->changed && (m->msg_deleted == 0))
935 {
936 if (m->verbose)
937 mutt_message(_("Mailbox is unchanged"));
938 return MX_STATUS_OK;
939 }
940
941 if (m->msg_deleted != 0)
942 {
943 char buf[128] = { 0 };
944
945 snprintf(buf, sizeof(buf),
946 ngettext("Purge %d deleted message?", "Purge %d deleted messages?", m->msg_deleted),
947 m->msg_deleted);
948 purge = query_quadoption(buf, NeoMutt->sub, "delete");
949 if (purge == MUTT_ABORT)
950 return MX_STATUS_ERROR;
951 if (purge == MUTT_NO)
952 {
953 if (!m->changed)
954 return MX_STATUS_OK; /* nothing to do! */
955 /* let IMAP servers hold on to D flags */
956 if (m->type != MUTT_IMAP)
957 {
958 for (int i = 0; i < m->msg_count; i++)
959 {
960 struct Email *e = m->emails[i];
961 if (!e)
962 break;
963 e->deleted = false;
964 e->purge = false;
965 }
966 m->msg_deleted = 0;
967 }
968 }
970 }
971
972 /* really only for IMAP - imap_sync_mailbox results in a call to
973 * ctx_update_tables, so m->msg_deleted is 0 when it comes back */
974 msgcount = m->msg_count;
975 deleted = m->msg_deleted;
976
977 const char *const c_trash = cs_subset_string(NeoMutt->sub, "trash");
978 const struct Mailbox *m_trash = mx_mbox_find(m->account, c_trash);
979 if (purge && (m->msg_deleted != 0) && (m != m_trash))
980 {
981 if (trash_append(m) != 0)
982 return MX_STATUS_OK;
983 }
984
985 if (m->type == MUTT_IMAP)
986 rc = imap_sync_mailbox(m, purge, false);
987 else
988 rc = sync_mailbox(m);
989 if (rc != MX_STATUS_ERROR)
990 {
991 if ((m->type == MUTT_IMAP) && !purge)
992 {
993 if (m->verbose)
994 mutt_message(_("Mailbox checkpointed"));
995 }
996 else
997 {
998 if (m->verbose)
999 mutt_message(_("%d kept, %d deleted"), msgcount - deleted, deleted);
1000 }
1001
1002 mutt_sleep(0);
1003
1004 const bool c_save_empty = cs_subset_bool(NeoMutt->sub, "save_empty");
1005 if ((m->msg_count == m->msg_deleted) &&
1006 ((m->type == MUTT_MBOX) || (m->type == MUTT_MMDF)) &&
1007 !mutt_is_spool(mailbox_path(m)) && !c_save_empty)
1008 {
1009 unlink(mailbox_path(m));
1010 mx_fastclose_mailbox(m, false);
1011 return MX_STATUS_OK;
1012 }
1013
1014 /* if we haven't deleted any messages, we don't need to resort
1015 * ... except for certain folder formats which need "unsorted"
1016 * sort order in order to synchronize folders.
1017 *
1018 * MH and maildir are safe. mbox-style seems to need re-sorting,
1019 * at least with the new threading code. */
1020 if (purge || ((m->type != MUTT_MAILDIR) && (m->type != MUTT_MH)))
1021 {
1022 /* IMAP does this automatically after handling EXPUNGE */
1023 if (m->type != MUTT_IMAP)
1024 {
1027 }
1028 }
1029 }
1030
1031 return rc;
1032}
1033
1041struct Message *mx_msg_open_new(struct Mailbox *m, const struct Email *e, MsgOpenFlags flags)
1042{
1043 if (!m)
1044 return NULL;
1045
1046 struct Address *p = NULL;
1047 struct Message *msg = NULL;
1048
1049 if (!m->mx_ops || !m->mx_ops->msg_open_new)
1050 {
1051 mutt_debug(LL_DEBUG1, "function unimplemented for mailbox type %d\n", m->type);
1052 return NULL;
1053 }
1054
1055 msg = message_new();
1056 msg->write = true;
1057
1058 if (e)
1059 {
1060 msg->flags.flagged = e->flagged;
1061 msg->flags.replied = e->replied;
1062 msg->flags.read = e->read;
1063 msg->flags.draft = (flags & MUTT_SET_DRAFT);
1064 msg->received = e->received;
1065 }
1066
1067 if (msg->received == 0)
1068 msg->received = mutt_date_now();
1069
1070 if (m->mx_ops->msg_open_new(m, msg, e))
1071 {
1072 if (m->type == MUTT_MMDF)
1073 fputs(MMDF_SEP, msg->fp);
1074
1075 if (((m->type == MUTT_MBOX) || (m->type == MUTT_MMDF)) && (flags & MUTT_ADD_FROM))
1076 {
1077 if (e)
1078 {
1079 p = TAILQ_FIRST(&e->env->return_path);
1080 if (!p)
1081 p = TAILQ_FIRST(&e->env->sender);
1082 if (!p)
1083 p = TAILQ_FIRST(&e->env->from);
1084 }
1085
1086 // Use C locale for the date, so that day/month names are in English
1087 char buf[64] = { 0 };
1088 mutt_date_localtime_format_locale(buf, sizeof(buf), "%a %b %e %H:%M:%S %Y",
1090 fprintf(msg->fp, "From %s %s\n",
1091 p ? buf_string(p->mailbox) : NONULL(NeoMutt->username), buf);
1092 }
1093 }
1094 else
1095 {
1096 message_free(&msg);
1097 }
1098
1099 return msg;
1100}
1101
1108{
1109 if (!m || !m->mx_ops)
1110 return MX_STATUS_ERROR;
1111
1112 const short c_mail_check = cs_subset_number(NeoMutt->sub, "mail_check");
1113
1114 time_t t = mutt_date_now();
1115 if ((t - m->last_checked) < c_mail_check)
1116 return MX_STATUS_OK;
1117
1118 m->last_checked = t;
1119
1120 enum MxStatus rc = m->mx_ops->mbox_check(m);
1121 if ((rc == MX_STATUS_NEW_MAIL) || (rc == MX_STATUS_REOPENED))
1122 {
1124 }
1125
1126 return rc;
1127}
1128
1136struct Message *mx_msg_open(struct Mailbox *m, struct Email *e)
1137{
1138 if (!m || !e)
1139 return NULL;
1140
1141 if (!m->mx_ops || !m->mx_ops->msg_open)
1142 {
1143 mutt_debug(LL_DEBUG1, "function not implemented for mailbox type %d\n", m->type);
1144 return NULL;
1145 }
1146
1147 struct Message *msg = message_new();
1148 if (!m->mx_ops->msg_open(m, msg, e))
1149 message_free(&msg);
1150
1151 return msg;
1152}
1153
1161int mx_msg_commit(struct Mailbox *m, struct Message *msg)
1162{
1163 if (!m || !m->mx_ops || !m->mx_ops->msg_commit || !msg)
1164 return -1;
1165
1166 if (!(msg->write && m->append))
1167 {
1168 mutt_debug(LL_DEBUG1, "msg->write = %d, m->append = %d\n", msg->write, m->append);
1169 return -1;
1170 }
1171
1172 return m->mx_ops->msg_commit(m, msg);
1173}
1174
1182int mx_msg_close(struct Mailbox *m, struct Message **ptr)
1183{
1184 if (!m || !ptr || !*ptr)
1185 return 0;
1186
1187 int rc = 0;
1188 struct Message *msg = *ptr;
1189
1190 if (m->mx_ops && m->mx_ops->msg_close)
1191 rc = m->mx_ops->msg_close(m, msg);
1192
1193 if (msg->path)
1194 {
1195 mutt_debug(LL_DEBUG1, "unlinking %s\n", msg->path);
1196 unlink(msg->path);
1197 }
1198
1199 message_free(ptr);
1200 return rc;
1201}
1202
1208void mx_alloc_memory(struct Mailbox *m, int req_size)
1209{
1210 if ((req_size + 1) <= m->email_max)
1211 return;
1212
1213 // Step size to increase by
1214 // Larger mailboxes get a larger step (limited to 1000)
1215 const int grow = CLAMP(m->email_max, 25, 1000);
1216
1217 // Sanity checks
1218 req_size = ROUND_UP(req_size + 1, grow);
1219
1220 const size_t s = MAX(sizeof(struct Email *), sizeof(int));
1221 if ((req_size * s) < (m->email_max * s))
1222 {
1223 mutt_error("%s", strerror(ENOMEM));
1224 mutt_exit(1);
1225 }
1226
1227 if (m->emails)
1228 {
1229 MUTT_MEM_REALLOC(&m->emails, req_size, struct Email *);
1230 MUTT_MEM_REALLOC(&m->v2r, req_size, int);
1231 }
1232 else
1233 {
1234 m->emails = MUTT_MEM_CALLOC(req_size, struct Email *);
1235 m->v2r = MUTT_MEM_CALLOC(req_size, int);
1236 }
1237
1238 for (int i = m->email_max; i < req_size; i++)
1239 {
1240 m->emails[i] = NULL;
1241 m->v2r[i] = -1;
1242 }
1243
1244 m->email_max = req_size;
1245}
1246
1255{
1256 if (buf_is_empty(path))
1257 return -1;
1258
1260 const struct MxOps *ops = mx_get_ops(type);
1261 if (!ops || !ops->path_is_empty)
1262 return -1;
1263
1264 return ops->path_is_empty(path);
1265}
1266
1276int mx_tags_edit(struct Mailbox *m, const char *tags, struct Buffer *buf)
1277{
1278 if (!m || !buf)
1279 return -1;
1280
1281 if (m->mx_ops->tags_edit)
1282 return m->mx_ops->tags_edit(m, tags, buf);
1283
1284 mutt_message(_("Folder doesn't support tagging, aborting"));
1285 return -1;
1286}
1287
1296int mx_tags_commit(struct Mailbox *m, struct Email *e, const char *tags)
1297{
1298 if (!m || !e || !tags)
1299 return -1;
1300
1301 if (m->mx_ops->tags_commit)
1302 return m->mx_ops->tags_commit(m, e, tags);
1303
1304 mutt_message(_("Folder doesn't support tagging, aborting"));
1305 return -1;
1306}
1307
1314{
1315 return m && m->mx_ops->tags_commit && m->mx_ops->tags_edit;
1316}
1317
1323enum MailboxType mx_path_probe(const char *path)
1324{
1325 if (!path)
1326 return MUTT_UNKNOWN;
1327
1328 enum MailboxType rc = MUTT_UNKNOWN;
1329
1330 // First, search the non-local Mailbox types (is_local == false)
1331 for (const struct MxOps **ops = MxOps; *ops; ops++)
1332 {
1333 if ((*ops)->is_local)
1334 continue;
1335 rc = (*ops)->path_probe(path, NULL);
1336 if (rc != MUTT_UNKNOWN)
1337 return rc;
1338 }
1339
1340 struct stat st = { 0 };
1341 if (stat(path, &st) != 0)
1342 {
1343 mutt_debug(LL_DEBUG1, "unable to stat %s: %s (errno %d)\n", path, strerror(errno), errno);
1344 return MUTT_UNKNOWN;
1345 }
1346
1347 if (S_ISFIFO(st.st_mode))
1348 {
1349 mutt_error(_("Can't open %s: it is a pipe"), path);
1350 return MUTT_UNKNOWN;
1351 }
1352
1353 // Next, search the local Mailbox types (is_local == true)
1354 for (const struct MxOps **ops = MxOps; *ops; ops++)
1355 {
1356 if (!(*ops)->is_local)
1357 continue;
1358 rc = (*ops)->path_probe(path, &st);
1359 if (rc != MUTT_UNKNOWN)
1360 return rc;
1361 }
1362
1363 return rc;
1364}
1365
1369int mx_path_canon(struct Buffer *path, const char *folder, enum MailboxType *type)
1370{
1371 if (buf_is_empty(path))
1372 return -1;
1373
1374 for (size_t i = 0; i < 3; i++)
1375 {
1376 /* Look for !! ! - < > or ^ followed by / or NUL */
1377 if ((buf_at(path, 0) == '!') && (buf_at(path, 1) == '!'))
1378 {
1379 if (((buf_at(path, 2) == '/') || (buf_at(path, 2) == '\0')))
1380 {
1381 buf_inline_replace(path, 0, 2, LastFolder);
1382 }
1383 }
1384 else if ((buf_at(path, 0) == '+') || (buf_at(path, 0) == '='))
1385 {
1386 size_t folder_len = mutt_str_len(folder);
1387 if ((folder_len > 0) && (folder[folder_len - 1] != '/'))
1388 {
1389 path->data[0] = '/';
1390 buf_inline_replace(path, 0, 0, folder);
1391 }
1392 else
1393 {
1394 buf_inline_replace(path, 0, 1, folder);
1395 }
1396 }
1397 else if ((buf_at(path, 1) == '/') || (buf_at(path, 1) == '\0'))
1398 {
1399 if (buf_at(path, 0) == '!')
1400 {
1401 const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
1402 buf_inline_replace(path, 0, 1, c_spool_file);
1403 }
1404 else if (buf_at(path, 0) == '-')
1405 {
1406 buf_inline_replace(path, 0, 1, LastFolder);
1407 }
1408 else if (buf_at(path, 0) == '<')
1409 {
1410 const char *const c_record = cs_subset_string(NeoMutt->sub, "record");
1411 buf_inline_replace(path, 0, 1, c_record);
1412 }
1413 else if (buf_at(path, 0) == '>')
1414 {
1415 const char *const c_mbox = cs_subset_string(NeoMutt->sub, "mbox");
1416 buf_inline_replace(path, 0, 1, c_mbox);
1417 }
1418 else if (buf_at(path, 0) == '^')
1419 {
1420 buf_inline_replace(path, 0, 1, CurrentFolder);
1421 }
1422 else if (buf_at(path, 0) == '~')
1423 {
1424 buf_inline_replace(path, 0, 1, NeoMutt->home_dir);
1425 }
1426 }
1427 else if (buf_at(path, 0) == '@')
1428 {
1429 /* elm compatibility, @ expands alias to user name */
1430 struct AddressList *al = alias_lookup(buf_string(path));
1431 if (!al || TAILQ_EMPTY(al))
1432 break;
1433
1434 struct Email *e = email_new();
1435 e->env = mutt_env_new();
1436 mutt_addrlist_copy(&e->env->from, al, false);
1437 mutt_addrlist_copy(&e->env->to, al, false);
1439 email_free(&e);
1440 break;
1441 }
1442 else
1443 {
1444 break;
1445 }
1446 }
1447
1448 // if (!folder) //XXX - use inherited version, or pass NULL to backend?
1449 // return -1;
1450
1452 if (type)
1453 *type = type2;
1454 const struct MxOps *ops = mx_get_ops(type2);
1455 if (!ops || !ops->path_canon)
1456 return -1;
1457
1458 if (ops->path_canon(path) < 0)
1459 {
1460 mutt_path_canon(path, NeoMutt->home_dir, true);
1461 }
1462
1463 return 0;
1464}
1465
1473int mx_path_canon2(struct Mailbox *m, const char *folder)
1474{
1475 if (!m)
1476 return -1;
1477
1478 struct Buffer *path = buf_pool_get();
1479
1480 if (m->realpath)
1481 buf_strcpy(path, m->realpath);
1482 else
1483 buf_strcpy(path, mailbox_path(m));
1484
1485 int rc = mx_path_canon(path, folder, &m->type);
1486
1488 buf_pool_release(&path);
1489
1490 if (rc >= 0)
1491 {
1492 m->mx_ops = mx_get_ops(m->type);
1493 buf_strcpy(&m->pathbuf, m->realpath);
1494 }
1495
1496 return rc;
1497}
1498
1508{
1509 if (!m || !m->mx_ops || !m->mx_ops->msg_padding_size)
1510 return 0;
1511
1512 return m->mx_ops->msg_padding_size(m);
1513}
1514
1521struct Account *mx_ac_find(struct Mailbox *m)
1522{
1523 if (!m || !m->mx_ops || !m->realpath)
1524 return NULL;
1525
1526 struct Account **ap = NULL;
1528 {
1529 struct Account *a = *ap;
1530 if (a->type != m->type)
1531 continue;
1532
1533 if (m->mx_ops->ac_owns_path(a, m->realpath))
1534 return a;
1535 }
1536
1537 return NULL;
1538}
1539
1546struct Mailbox *mx_mbox_find(struct Account *a, const char *path)
1547{
1548 if (!a || !path)
1549 return NULL;
1550
1551 struct Mailbox *m_match = NULL;
1552 struct Mailbox **mp = NULL;
1553 struct Url *url_p = NULL;
1554 struct Url *url_a = NULL;
1555
1556 const bool use_url = (a->type == MUTT_IMAP);
1557 if (use_url)
1558 {
1559 url_p = url_parse(path);
1560 if (!url_p)
1561 goto done;
1562 }
1563
1564 ARRAY_FOREACH(mp, &a->mailboxes)
1565 {
1566 struct Mailbox *m = *mp;
1567
1568 if (!use_url)
1569 {
1570 if (mutt_str_equal(m->realpath, path))
1571 return m;
1572 continue;
1573 }
1574
1575 url_free(&url_a);
1576 url_a = url_parse(m->realpath);
1577 if (!url_a)
1578 continue;
1579
1580 if (!mutt_istr_equal(url_a->host, url_p->host))
1581 continue;
1582 if (url_p->user && !mutt_istr_equal(url_a->user, url_p->user))
1583 continue;
1584 if (a->type == MUTT_IMAP)
1585 {
1586 if (imap_mxcmp(url_a->path, url_p->path) == 0)
1587 {
1588 m_match = *mp;
1589 break;
1590 }
1591 }
1592 else
1593 {
1594 if (mutt_str_equal(url_a->path, url_p->path))
1595 {
1596 m_match = *mp;
1597 break;
1598 }
1599 }
1600 }
1601
1602done:
1603 url_free(&url_p);
1604 url_free(&url_a);
1605
1606 return m_match;
1607}
1608
1615struct Mailbox *mx_mbox_find2(const char *path)
1616{
1617 if (!path)
1618 return NULL;
1619
1620 struct Buffer *buf = buf_new(path);
1621 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
1622 mx_path_canon(buf, c_folder, NULL);
1623
1624 struct Account **ap = NULL;
1626 {
1627 struct Account *a = *ap;
1628 struct Mailbox *m = mx_mbox_find(a, buf_string(buf));
1629 if (m)
1630 {
1631 buf_free(&buf);
1632 return m;
1633 }
1634 }
1635
1636 buf_free(&buf);
1637 return NULL;
1638}
1639
1647struct Mailbox *mx_path_resolve(const char *path)
1648{
1649 if (!path)
1650 return NULL;
1651
1652 struct Mailbox *m = mx_mbox_find2(path);
1653 if (m)
1654 return m;
1655
1656 m = mailbox_new();
1657 buf_strcpy(&m->pathbuf, path);
1658 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
1659 mx_path_canon2(m, c_folder);
1660
1661 return m;
1662}
1663
1670static struct Mailbox *mx_mbox_find_by_name_ac(struct Account *a, const char *name)
1671{
1672 if (!a || !name)
1673 return NULL;
1674
1675 struct Mailbox **mp = NULL;
1676
1677 ARRAY_FOREACH(mp, &a->mailboxes)
1678 {
1679 struct Mailbox *m = *mp;
1680
1681 if (mutt_str_equal(m->name, name))
1682 return m;
1683 }
1684
1685 return NULL;
1686}
1687
1693static struct Mailbox *mx_mbox_find_by_name(const char *name)
1694{
1695 if (!name)
1696 return NULL;
1697
1698 struct Account **ap = NULL;
1700 {
1701 struct Account *a = *ap;
1702 struct Mailbox *m = mx_mbox_find_by_name_ac(a, name);
1703 if (m)
1704 return m;
1705 }
1706
1707 return NULL;
1708}
1709
1719struct Mailbox *mx_resolve(const char *path_or_name)
1720{
1721 if (!path_or_name)
1722 return NULL;
1723
1724 // Order is name first because you can create a Mailbox from
1725 // a path, but can't from a name. So fallback behavior creates
1726 // a new Mailbox for us.
1727 struct Mailbox *m = mx_mbox_find_by_name(path_or_name);
1728 if (!m)
1729 m = mx_path_resolve(path_or_name);
1730
1731 return m;
1732}
1733
1737bool mx_ac_add(struct Account *a, struct Mailbox *m)
1738{
1739 if (!a || !m || !m->mx_ops || !m->mx_ops->ac_add)
1740 return false;
1741
1742 return m->mx_ops->ac_add(a, m) && account_mailbox_add(a, m);
1743}
1744
1754int mx_ac_remove(struct Mailbox *m, bool keep_account)
1755{
1756 if (!m || !m->account)
1757 return -1;
1758
1759 struct Account *a = m->account;
1761 if (!keep_account && ARRAY_EMPTY(&a->mailboxes))
1762 {
1764 }
1765 return 0;
1766}
1767
1773enum MxStatus mx_mbox_check_stats(struct Mailbox *m, uint8_t flags)
1774{
1775 if (!m)
1776 return MX_STATUS_ERROR;
1777
1778 enum MxStatus rc = m->mx_ops->mbox_check_stats(m, flags);
1779 if (rc != MX_STATUS_ERROR)
1780 {
1781 struct EventMailbox ev_m = { m };
1783 }
1784
1785 return rc;
1786}
1787
1797int mx_save_hcache(struct Mailbox *m, struct Email *e)
1798{
1799 if (!m || !m->mx_ops || !m->mx_ops->msg_save_hcache || !e)
1800 return 0;
1801
1802 return m->mx_ops->msg_save_hcache(m, e);
1803}
1804
1811{
1812 return m ? m->type : MUTT_MAILBOX_ERROR;
1813}
1814
1822{
1823 if (!m)
1824 return -1;
1825
1826 if (m->readonly)
1827 {
1828 mutt_error(_("Can't toggle write on a readonly mailbox"));
1829 return -1;
1830 }
1831
1832 if (m->dontwrite)
1833 {
1834 m->dontwrite = false;
1835 mutt_message(_("Changes to folder will be written on folder exit"));
1836 }
1837 else
1838 {
1839 m->dontwrite = true;
1840 mutt_message(_("Changes to folder will not be written"));
1841 }
1842
1843 struct EventMailbox ev_m = { m };
1845 return 0;
1846}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition address.c:765
Email Address Handling.
Email Aliases.
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition alias.c:274
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition array.h:157
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition array.h:74
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:209
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition array.h:58
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:291
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
Definition buffer.c:668
void buf_free(struct Buffer **ptr)
Deallocates a buffer.
Definition buffer.c:319
void buf_inline_replace(struct Buffer *buf, size_t pos, size_t len, const char *str)
Definition buffer.c:768
struct Buffer * buf_new(const char *str)
Allocate a new Buffer.
Definition buffer.c:304
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:226
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
@ CMD_MBOX_HOOK
:mbox-hook
Definition command.h:91
bool mutt_comp_can_append(struct Mailbox *m)
Can we append to this path?
Definition compress.c:334
Compressed mbox local mailbox type.
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition helpers.c:192
unsigned char cs_subset_enum(const struct ConfigSubset *sub, const char *name)
Get a enumeration config item by name.
Definition helpers.c:71
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition helpers.c:143
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
Convenience wrapper for the config headers.
int mutt_append_message(struct Mailbox *m_dst, struct Mailbox *m_src, struct Email *e, struct Message *msg, CopyMessageFlags cmflags, CopyHeaderFlags chflags)
Append a message.
Definition copy_email.c:991
#define CH_UPDATE_LEN
Update Lines: and Content-Length:
Definition copy_email.h:64
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition copy_email.h:37
#define CH_NO_FLAGS
No flags are set.
Definition copy_email.h:53
void account_mailbox_remove(struct Account *a, struct Mailbox *m)
Remove a Mailbox from an Account.
Definition account.c:94
struct Account * account_new(const char *name, struct ConfigSubset *sub)
Create a new Account.
Definition account.c:44
bool account_mailbox_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account.
Definition account.c:67
void account_free(struct Account **ptr)
Free an Account.
Definition account.c:148
Convenience wrapper for the core headers.
struct Mailbox * mailbox_new(void)
Create a new Mailbox.
Definition mailbox.c:69
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition mailbox.c:90
void mailbox_changed(struct Mailbox *m, enum NotifyMailbox action)
Notify observers of a change to a Mailbox.
Definition mailbox.c:232
@ NT_MAILBOX_UNTAG
Clear the 'last-tagged' pointer.
Definition mailbox.h:183
@ NT_MAILBOX_CHANGE
Mailbox has been changed.
Definition mailbox.h:176
@ NT_MAILBOX_RESORT
Email list needs resorting.
Definition mailbox.h:181
@ NT_MAILBOX_INVALID
Email list was changed.
Definition mailbox.h:180
@ NT_MAILBOX_UPDATE
Update internal tables.
Definition mailbox.h:182
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition mailbox.h:214
#define MUTT_ACL_ALL
Definition mailbox.h:73
MailboxType
Supported mailbox formats.
Definition mailbox.h:41
@ MUTT_MMDF
'mmdf' Mailbox type
Definition mailbox.h:46
@ MUTT_MAILBOX_ERROR
Error occurred examining Mailbox.
Definition mailbox.h:43
@ MUTT_MH
'MH' Mailbox type
Definition mailbox.h:47
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
Definition mailbox.h:49
@ MUTT_IMAP
'IMAP' Mailbox type
Definition mailbox.h:50
@ MUTT_MBOX
'mbox' Mailbox type
Definition mailbox.h:45
@ MUTT_COMPRESSED
Compressed file Mailbox type.
Definition mailbox.h:53
@ MUTT_UNKNOWN
Mailbox wasn't recognised.
Definition mailbox.h:44
@ MUTT_MAILDIR
'Maildir' Mailbox type
Definition mailbox.h:48
struct Message * message_new(void)
Create a new Message.
Definition message.c:53
void message_free(struct Message **ptr)
Free a Message.
Definition message.c:37
struct Email * email_new(void)
Create a new Email.
Definition email.c:77
void email_free(struct Email **ptr)
Free an Email.
Definition email.c:46
void mutt_make_label_hash(struct Mailbox *m)
Create a Hash Table to store the labels.
Definition header.c:405
Structs that make up an email.
bool OptNeedRescore
(pseudo) set when the 'score' command is used
Definition globals.c:62
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition envelope.c:45
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition exit.c:41
Manage where the email is piped to external commands.
@ SAVE_MOVE
Move message to another mailbox, removing the original.
Definition external.h:54
void mutt_file_unlink_empty(const char *path)
Delete a file if it's empty.
Definition file.c:1229
void mutt_set_flag(struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool upd_mbox)
Set a flag on an email.
Definition flags.c:54
char * LastFolder
Previously selected mailbox.
Definition globals.c:40
bool OptForceRefresh
(pseudo) refresh even during macros
Definition globals.c:58
char * CurrentFolder
Currently selected mailbox.
Definition globals.c:39
bool OptSortSubthreads
(pseudo) used when $sort_aux changes
Definition globals.c:68
Global variables.
#define mutt_error(...)
Definition logging2.h:94
#define mutt_message(...)
Definition logging2.h:93
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
#define mutt_perror(...)
Definition logging2.h:95
const struct MxOps MxNntpOps
NNTP Mailbox - Implements MxOps -.
Definition nntp.c:2805
const struct MxOps MxMboxOps
Mbox Mailbox - Implements MxOps -.
Definition mbox.c:1709
const struct MxOps MxNotmuchOps
Notmuch Mailbox - Implements MxOps -.
Definition notmuch.c:2490
const struct MxOps MxMhOps
MH Mailbox - Implements MxOps -.
Definition mh.c:1236
const struct MxOps MxPopOps
POP Mailbox - Implements MxOps -.
Definition pop.c:1177
const struct MxOps MxImapOps
IMAP Mailbox - Implements MxOps -.
Definition imap.c:2528
const struct MxOps MxCompOps
Compressed Mailbox - Implements MxOps -.
Definition compress.c:886
const struct MxOps MxMmdfOps
MMDF Mailbox - Implements MxOps -.
Definition mbox.c:1739
const struct MxOps MxMaildirOps
Maildir Mailbox - Implements MxOps -.
Definition maildir.c:44
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox?
Definition imap.c:2470
Convenience wrapper for the gui headers.
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition hash.c:458
Hook Commands.
IMAP network mailbox.
int imap_mxcmp(const char *mx1, const char *mx2)
Compare mailbox names, giving priority to INBOX.
Definition util.c:549
int imap_copy_messages(struct Mailbox *m, struct EmailArray *ea, const char *dest, enum MessageSaveOpt save_opt)
Server COPY messages to another folder.
Definition message.c:1703
int imap_fast_trash(struct Mailbox *m, const char *dest)
Use server COPY command to copy deleted messages to trash.
Definition imap.c:1470
enum MxStatus imap_sync_mailbox(struct Mailbox *m, bool expunge, bool close)
Sync all the changes to the server.
Definition imap.c:1588
int imap_access(const char *path)
Check permissions on an IMAP mailbox with a new connection.
Definition imap.c:562
bool keymap_expand_key(struct Keymap *km, struct Buffer *buf)
Get the key string bound to a Keymap.
Definition keymap.c:229
Manage keymappings.
struct Keymap * km_find_func(enum MenuType mtype, int func)
Find a function's mapping in a Menu.
Definition menu.c:164
@ LL_DEBUG2
Log at debug level 2.
Definition logging2.h:46
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
Maildir local mailbox type.
Mbox local mailbox type.
#define MMDF_SEP
Definition lib.h:63
void mbox_reset_atime(struct Mailbox *m, struct stat *st)
Reset the access time on the mailbox file.
Definition mbox.c:744
#define ROUND_UP(NUM, STEP)
Definition memory.h:42
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:48
#define MUTT_MEM_REALLOC(pptr, n, type)
Definition memory.h:51
#define MAX(a, b)
Definition memory.h:37
#define CLAMP(val, lo, hi)
Definition memory.h:39
GUI present the user with a selectable list.
Mh local mailbox type.
size_t mutt_date_localtime_format_locale(char *buf, size_t buflen, const char *format, time_t t, locale_t loc)
Format localtime using a given locale.
Definition date.c:970
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition date.c:457
Convenience wrapper for the library headers.
#define _(a)
Definition message.h:28
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition notify.c:173
bool mutt_path_canon(struct Buffer *path, const char *homedir, bool is_dir)
Create the canonical version of a path.
Definition path.c:248
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:674
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:662
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:500
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition string.c:284
Many unsorted constants and some structs.
@ MUTT_OLD
Old messages.
Definition mutt.h:90
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition mutt.h:96
@ MUTT_TAG
Tagged messages.
Definition mutt.h:99
@ MUTT_DELETE
Messages to be deleted.
Definition mutt.h:94
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
NeoMutt Logging.
void mutt_mailbox_set_notified(struct Mailbox *m)
Note when the user was last notified of new mail.
Mailbox helper functions.
void mutt_sleep(short s)
Sleep for a while.
Definition muttlib.c:830
void expand_path(struct Buffer *buf, bool regex)
Create the canonical path.
Definition muttlib.c:121
int mutt_save_confirm(const char *s, struct stat *st)
Ask the user to save.
Definition muttlib.c:733
Some miscellaneous functions.
void mx_alloc_memory(struct Mailbox *m, int req_size)
Create storage for the emails.
Definition mx.c:1208
int mx_tags_edit(struct Mailbox *m, const char *tags, struct Buffer *buf)
Start the tag editor of the mailbox.
Definition mx.c:1276
int mx_msg_close(struct Mailbox *m, struct Message **ptr)
Close a message.
Definition mx.c:1182
int mx_ac_remove(struct Mailbox *m, bool keep_account)
Remove a Mailbox from an Account and delete Account if empty.
Definition mx.c:1754
int mx_access(const char *path, int flags)
Wrapper for access, checks permissions on a given mailbox.
Definition mx.c:167
const struct EnumDef MboxTypeDef
Data for the $mbox_type enumeration.
Definition mx.c:89
static enum MxStatus sync_mailbox(struct Mailbox *m)
Save changes to disk.
Definition mx.c:453
static int trash_append(struct Mailbox *m)
Move deleted mails to the trash folder.
Definition mx.c:484
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size()
Definition mx.c:1507
void mx_fastclose_mailbox(struct Mailbox *m, bool keep_account)
Free up memory associated with the Mailbox.
Definition mx.c:411
enum MxStatus 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:1773
int mx_path_canon(struct Buffer *path, const char *folder, enum MailboxType *type)
Canonicalise a mailbox path - Wrapper for MxOps::path_canon()
Definition mx.c:1369
static bool mutt_is_spool(const char *str)
Is this the spool_file?
Definition mx.c:138
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition mx.c:285
struct Mailbox * mx_mbox_find(struct Account *a, const char *path)
Find a Mailbox on an Account.
Definition mx.c:1546
struct Mailbox * mx_resolve(const char *path_or_name)
Get a Mailbox from either a path or name.
Definition mx.c:1719
static struct Mailbox * mx_mbox_find_by_name(const char *name)
Find a Mailbox with given name.
Definition mx.c:1693
bool mx_ac_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account - Wrapper for MxOps::ac_add()
Definition mx.c:1737
struct Mailbox * mx_mbox_find2(const char *path)
Find a Mailbox on an Account.
Definition mx.c:1615
struct Message * mx_msg_open(struct Mailbox *m, struct Email *e)
Return a stream pointer for a message.
Definition mx.c:1136
const struct MxOps * mx_get_ops(enum MailboxType type)
Get mailbox operations.
Definition mx.c:124
bool mx_tags_is_supported(struct Mailbox *m)
Return true if mailbox support tagging.
Definition mx.c:1313
int mx_tags_commit(struct Mailbox *m, struct Email *e, const char *tags)
Save tags to the Mailbox - Wrapper for MxOps::tags_commit()
Definition mx.c:1296
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:1797
static const struct Mapping MboxTypeMap[]
Lookup table of mailbox types.
Definition mx.c:78
bool mx_mbox_ac_link(struct Mailbox *m)
Link a Mailbox to an existing or new Account.
Definition mx.c:248
struct Account * mx_ac_find(struct Mailbox *m)
Find the Account owning a Mailbox.
Definition mx.c:1521
enum MailboxType mx_type(struct Mailbox *m)
Return the type of the Mailbox.
Definition mx.c:1810
int mx_path_is_empty(struct Buffer *path)
Is the mailbox empty.
Definition mx.c:1254
struct Message * mx_msg_open_new(struct Mailbox *m, const struct Email *e, MsgOpenFlags flags)
Open a new message.
Definition mx.c:1041
int mx_toggle_write(struct Mailbox *m)
Toggle the mailbox's readonly flag.
Definition mx.c:1821
int mx_msg_commit(struct Mailbox *m, struct Message *msg)
Commit a message to a folder - Wrapper for MxOps::msg_commit()
Definition mx.c:1161
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:1670
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition mx.c:1323
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition mx.c:1647
int mx_path_canon2(struct Mailbox *m, const char *folder)
Canonicalise the path to realpath.
Definition mx.c:1473
enum MxStatus mx_mbox_check(struct Mailbox *m)
Check for new mail - Wrapper for MxOps::mbox_check()
Definition mx.c:1107
enum MxStatus mx_mbox_sync(struct Mailbox *m)
Save changes to mailbox.
Definition mx.c:903
static bool mx_open_mailbox_append(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox for appending.
Definition mx.c:182
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
Definition mx.c:595
API for mailboxes.
uint8_t MsgOpenFlags
Flags for mx_msg_open_new(), e.g. MUTT_ADD_FROM.
Definition mx.h:37
#define MUTT_ADD_FROM
add a From_ line
Definition mx.h:39
#define MUTT_SET_DRAFT
set the message draft flag
Definition mx.h:40
#define MUTT_READONLY
Open in read-only mode.
Definition mxapi.h:43
uint8_t OpenMailboxFlags
Flags for mutt_open_mailbox(), e.g. MUTT_NOSORT.
Definition mxapi.h:39
#define MUTT_APPEND
Open mailbox for appending messages.
Definition mxapi.h:42
#define MUTT_QUIET
Do not print any messages.
Definition mxapi.h:44
MxOpenReturns
Return values for mbox_open()
Definition mxapi.h:73
@ MX_OPEN_ABORT
Open was aborted.
Definition mxapi.h:76
@ MX_OPEN_OK
Open succeeded.
Definition mxapi.h:74
#define MUTT_PEEK
Revert atime back after taking a look (if applicable)
Definition mxapi.h:45
#define MUTT_NOSORT
Do not sort the mailbox after opening it.
Definition mxapi.h:41
#define MUTT_APPENDNEW
Set in mx_open_mailbox_append if the mailbox doesn't exist.
Definition mxapi.h:46
MxStatus
Return values from mbox_check(), mbox_check_stats(), mbox_sync(), and mbox_close()
Definition mxapi.h:60
@ MX_STATUS_ERROR
An error occurred.
Definition mxapi.h:61
@ MX_STATUS_OK
No changes.
Definition mxapi.h:62
@ MX_STATUS_REOPENED
Mailbox was reopened.
Definition mxapi.h:65
@ MX_STATUS_NEW_MAIL
New mail received in Mailbox.
Definition mxapi.h:63
void neomutt_account_remove(struct NeoMutt *n, struct Account *a)
Remove an Account from the global list.
Definition neomutt.c:438
bool neomutt_account_add(struct NeoMutt *n, struct Account *a)
Add an Account to the global list.
Definition neomutt.c:418
Usenet network mailbox type; talk to an NNTP server.
struct NntpMboxData * mutt_newsgroup_catchup(struct Mailbox *m, struct NntpAccountData *adata, char *group)
Catchup newsgroup.
Definition newsrc.c:1225
Nntp-specific Mailbox data.
@ NT_MAILBOX
Mailbox has changed, NotifyMailbox, EventMailbox.
Definition notify_type.h:49
Notmuch virtual mailbox type.
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:96
POP network mailbox.
QuadOption
Possible values for a quad-option.
Definition quad.h:36
@ MUTT_ABORT
User aborted the question (with Ctrl-G)
Definition quad.h:37
@ MUTT_NO
User answered 'No', or assume 'No'.
Definition quad.h:38
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition quad.h:39
Ask the user a question.
enum QuadOption query_quadoption(const char *prompt, struct ConfigSubset *sub, const char *name)
Ask the user a quad-question.
Definition question.c:378
#define TAILQ_FIRST(head)
Definition queue.h:780
#define TAILQ_EMPTY(head)
Definition queue.h:778
void mutt_default_save(struct Buffer *path, struct Email *e)
Find the default save path for an email.
Definition run.c:211
char * mutt_find_hook(enum CommandId id, const char *pat)
Find a matching hook.
Definition run.c:111
#define NONULL(x)
Definition string2.h:44
A group of associated Mailboxes.
Definition account.h:36
enum MailboxType type
Type of Mailboxes this Account contains.
Definition account.h:37
struct MailboxArray mailboxes
All Mailboxes.
Definition account.h:40
An email address.
Definition address.h:35
struct Buffer * mailbox
Mailbox and host address.
Definition address.h:37
String manipulation buffer.
Definition buffer.h:36
char * data
Pointer to data.
Definition buffer.h:37
The envelope/body of an email.
Definition email.h:39
bool read
Email is read.
Definition email.h:50
bool purge
Skip trash folder when deleting.
Definition email.h:79
struct Envelope * env
Envelope information.
Definition email.h:68
bool old
Email is seen, but unread.
Definition email.h:49
bool flagged
Marked important?
Definition email.h:47
bool replied
Email has been replied to.
Definition email.h:51
char * path
Path of Email (for local Mailboxes)
Definition email.h:70
bool deleted
Email is deleted.
Definition email.h:78
bool tagged
Email is tagged.
Definition email.h:107
time_t received
Time when the message was placed in the mailbox.
Definition email.h:61
An enumeration.
Definition enum.h:30
struct AddressList return_path
Return path for the Email.
Definition envelope.h:58
struct AddressList to
Email's 'To' list.
Definition envelope.h:60
struct AddressList sender
Email's sender.
Definition envelope.h:63
struct AddressList from
Email's 'From' list.
Definition envelope.h:59
An Event that happened to a Mailbox.
Definition mailbox.h:190
A mailbox.
Definition mailbox.h:79
int vcount
The number of virtual messages.
Definition mailbox.h:99
bool changed
Mailbox has been modified.
Definition mailbox.h:110
bool has_new
Mailbox has new mail.
Definition mailbox.h:85
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition mailbox.h:81
bool append
Mailbox is opened in append mode.
Definition mailbox.h:109
int * v2r
Mapping from virtual to real msgno.
Definition mailbox.h:98
const struct MxOps * mx_ops
MXAPI callback functions.
Definition mailbox.h:107
int msg_new
Number of new messages.
Definition mailbox.h:92
time_t last_checked
Last time we checked this mailbox for new mail.
Definition mailbox.h:105
int msg_count
Total number of messages.
Definition mailbox.h:88
AclFlags rights
ACL bits, see AclFlags.
Definition mailbox.h:119
int email_max
Size of emails array.
Definition mailbox.h:97
enum MailboxType type
Mailbox type.
Definition mailbox.h:102
void * mdata
Driver specific data.
Definition mailbox.h:132
struct HashTable * subj_hash
Hash Table: "subject" -> Email.
Definition mailbox.h:124
struct Email ** emails
Array of Emails.
Definition mailbox.h:96
char * name
A short name for the Mailbox.
Definition mailbox.h:82
struct Notify * notify
Notifications: NotifyMailbox, EventMailbox.
Definition mailbox.h:145
struct HashTable * id_hash
Hash Table: "message-id" -> Email.
Definition mailbox.h:123
struct Buffer pathbuf
Path of the Mailbox.
Definition mailbox.h:80
bool peekonly
Just taking a glance, revert atime.
Definition mailbox.h:114
int msg_deleted
Number of deleted messages.
Definition mailbox.h:93
struct Account * account
Account that owns this Mailbox.
Definition mailbox.h:127
bool dontwrite
Don't write the mailbox on close.
Definition mailbox.h:111
off_t size
Size of the Mailbox.
Definition mailbox.h:84
struct HashTable * label_hash
Hash Table: "x-labels" -> Email.
Definition mailbox.h:125
bool visible
True if a result of "mailboxes".
Definition mailbox.h:130
int msg_flagged
Number of flagged messages.
Definition mailbox.h:90
int opened
Number of times mailbox is opened.
Definition mailbox.h:128
bool readonly
Don't allow changes to the mailbox.
Definition mailbox.h:116
int msg_tagged
How many messages are tagged?
Definition mailbox.h:94
bool verbose
Display status messages?
Definition mailbox.h:117
int msg_unread
Number of unread messages.
Definition mailbox.h:89
Mapping between user-readable string and a constant.
Definition mapping.h:33
A local copy of an email.
Definition message.h:34
FILE * fp
pointer to the message data
Definition message.h:35
char * path
path to temp file
Definition message.h:36
struct Message::@264267271004327071125374067057142037276212342100 flags
Flags for the Message.
bool draft
Message has been read.
Definition message.h:44
bool replied
Message has been replied to.
Definition message.h:43
time_t received
Time at which this message was received.
Definition message.h:46
bool write
nonzero if message is open for writing
Definition message.h:38
bool flagged
Message is flagged.
Definition message.h:42
bool read
Message has been read.
Definition message.h:41
Definition mxapi.h:88
int(* path_is_empty)(struct Buffer *path)
Definition mxapi.h:360
bool(* msg_open)(struct Mailbox *m, struct Message *msg, struct Email *e)
Definition mxapi.h:213
int(* tags_commit)(struct Mailbox *m, struct Email *e, const char *buf)
Definition mxapi.h:320
int(* msg_save_hcache)(struct Mailbox *m, struct Email *e)
Definition mxapi.h:286
enum MailboxType type
Mailbox type, e.g. MUTT_IMAP.
Definition mxapi.h:89
int(* msg_padding_size)(struct Mailbox *m)
Definition mxapi.h:271
bool(* ac_owns_path)(struct Account *a, const char *path)
Definition mxapi.h:106
int(* tags_edit)(struct Mailbox *m, const char *tags, struct Buffer *buf)
Definition mxapi.h:303
int(* msg_commit)(struct Mailbox *m, struct Message *msg)
Definition mxapi.h:244
enum MxStatus(* mbox_check_stats)(struct Mailbox *m, CheckStatsFlags flags)
Definition mxapi.h:172
bool(* ac_add)(struct Account *a, struct Mailbox *m)
Definition mxapi.h:121
enum MxOpenReturns(* mbox_open)(struct Mailbox *m)
Definition mxapi.h:133
int(* msg_close)(struct Mailbox *m, struct Message *msg)
Definition mxapi.h:259
bool(* msg_open_new)(struct Mailbox *m, struct Message *msg, const struct Email *e)
Definition mxapi.h:229
int(* path_canon)(struct Buffer *path)
Definition mxapi.h:346
enum MxStatus(* mbox_close)(struct Mailbox *m)
Definition mxapi.h:196
enum MxStatus(* mbox_sync)(struct Mailbox *m)
Definition mxapi.h:184
bool(* mbox_open_append)(struct Mailbox *m, OpenMailboxFlags flags)
Definition mxapi.h:147
enum MxStatus(* mbox_check)(struct Mailbox *m)
Definition mxapi.h:159
Container for Accounts, Notifications.
Definition neomutt.h:128
struct AccountArray accounts
All Accounts.
Definition neomutt.h:135
char * username
User's login name.
Definition neomutt.h:142
char * home_dir
User's home directory.
Definition neomutt.h:141
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:134
locale_t time_c_locale
Current locale but LC_TIME=C.
Definition neomutt.h:136
NNTP-specific Mailbox data -.
Definition mdata.h:34
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition url.h:69
char * user
Username.
Definition url.h:71
char * host
Host.
Definition url.h:73
char * path
Path.
Definition url.h:75
enum UrlScheme scheme
Scheme, e.g. U_SMTPS.
Definition url.h:70
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition subset.c:303
@ MENU_INDEX
Index panel (list of emails)
Definition type.h:44
struct Url * url_parse(const char *src)
Fill in Url.
Definition url.c:239
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition url.c:124