NeoMutt  2023-03-22-27-g3cb248
Teaching an old dog new tricks
DOXYGEN
mx.h File Reference

API for mailboxes. More...

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "config/lib.h"
#include "core/lib.h"
+ Include dependency graph for mx.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define MUTT_MSG_NO_FLAGS   0
 No flags are set. More...
 
#define MUTT_ADD_FROM   (1 << 0)
 add a From_ line More...
 
#define MUTT_SET_DRAFT   (1 << 1)
 set the message draft flag More...
 

Typedefs

typedef uint8_t MsgOpenFlags
 Flags for mx_msg_open_new(), e.g. MUTT_ADD_FROM. More...
 

Functions

enum MxStatus mx_mbox_check (struct Mailbox *m)
 Check for new mail - Wrapper for MxOps::mbox_check() More...
 
enum MxStatus mx_mbox_check_stats (struct Mailbox *m, uint8_t flags)
 Check the statistics for a mailbox - Wrapper for MxOps::mbox_check_stats() More...
 
enum MxStatus mx_mbox_close (struct Mailbox *m)
 Save changes and close mailbox. More...
 
bool mx_mbox_open (struct Mailbox *m, OpenMailboxFlags flags)
 Open a mailbox and parse it. More...
 
enum MxStatus mx_mbox_sync (struct Mailbox *m)
 Save changes to mailbox. More...
 
int mx_msg_close (struct Mailbox *m, struct Message **msg)
 Close a message. More...
 
int mx_msg_commit (struct Mailbox *m, struct Message *msg)
 Commit a message to a folder - Wrapper for MxOps::msg_commit() More...
 
struct Messagemx_msg_open_new (struct Mailbox *m, const struct Email *e, MsgOpenFlags flags)
 Open a new message. More...
 
struct Messagemx_msg_open (struct Mailbox *m, int msgno)
 Return a stream pointer for a message. More...
 
int mx_msg_padding_size (struct Mailbox *m)
 Bytes of padding between messages - Wrapper for MxOps::msg_padding_size() More...
 
int mx_save_hcache (struct Mailbox *m, struct Email *e)
 Save message to the header cache - Wrapper for MxOps::msg_save_hcache() More...
 
int mx_path_canon (char *buf, size_t buflen, const char *folder, enum MailboxType *type)
 Canonicalise a mailbox path - Wrapper for MxOps::path_canon() More...
 
int mx_path_canon2 (struct Mailbox *m, const char *folder)
 Canonicalise the path to realpath. More...
 
int mx_path_parent (const char *buf, size_t buflen)
 Find the parent of a mailbox path - Wrapper for MxOps::path_parent() More...
 
int mx_path_pretty (char *buf, size_t buflen, const char *folder)
 Abbreviate a mailbox path - Wrapper for MxOps::path_pretty() More...
 
enum MailboxType mx_path_probe (const char *path)
 Find a mailbox that understands a path. More...
 
struct Mailboxmx_path_resolve (const char *path)
 Get a Mailbox for a path. More...
 
struct Mailboxmx_resolve (const char *path_or_name)
 Get a Mailbox from either a path or name. More...
 
int mx_tags_commit (struct Mailbox *m, struct Email *e, const char *tags)
 Save tags to the Mailbox - Wrapper for MxOps::tags_commit() More...
 
int mx_tags_edit (struct Mailbox *m, const char *tags, struct Buffer *buf)
 Start the tag editor of the mailbox. More...
 
enum MailboxType mx_type (struct Mailbox *m)
 Return the type of the Mailbox. More...
 
struct Accountmx_ac_find (struct Mailbox *m)
 Find the Account owning a Mailbox. More...
 
struct Mailboxmx_mbox_find (struct Account *a, const char *path)
 Find a Mailbox on an Account. More...
 
struct Mailboxmx_mbox_find2 (const char *path)
 Find a Mailbox on an Account. More...
 
bool mx_mbox_ac_link (struct Mailbox *m)
 Link a Mailbox to an existing or new Account. More...
 
bool mx_ac_add (struct Account *a, struct Mailbox *m)
 Add a Mailbox to an Account - Wrapper for MxOps::ac_add() More...
 
int mx_ac_remove (struct Mailbox *m, bool keep_account)
 Remove a Mailbox from an Account and delete Account if empty. More...
 
int mx_access (const char *path, int flags)
 Wrapper for access, checks permissions on a given mailbox. More...
 
void mx_alloc_memory (struct Mailbox *m)
 Create storage for the emails. More...
 
int mx_path_is_empty (const char *path)
 Is the mailbox empty. More...
 
void mx_fastclose_mailbox (struct Mailbox *m, bool keep_account)
 Free up memory associated with the Mailbox. More...
 
const struct MxOpsmx_get_ops (enum MailboxType type)
 Get mailbox operations. More...
 
bool mx_tags_is_supported (struct Mailbox *m)
 Return true if mailbox support tagging. More...
 
int mx_toggle_write (struct Mailbox *m)
 Toggle the mailbox's readonly flag. More...
 

Variables

const struct MxOpsmx_ops []
 
struct EnumDef MboxTypeDef
 

Detailed Description

API for mailboxes.

Authors
  • Michael R. Elkins
  • Thomas Roessler
  • Richard Russon

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file mx.h.

Macro Definition Documentation

◆ MUTT_MSG_NO_FLAGS

#define MUTT_MSG_NO_FLAGS   0

No flags are set.

Definition at line 42 of file mx.h.

◆ MUTT_ADD_FROM

#define MUTT_ADD_FROM   (1 << 0)

add a From_ line

Definition at line 43 of file mx.h.

◆ MUTT_SET_DRAFT

#define MUTT_SET_DRAFT   (1 << 1)

set the message draft flag

Definition at line 44 of file mx.h.

Typedef Documentation

◆ MsgOpenFlags

typedef uint8_t MsgOpenFlags

Flags for mx_msg_open_new(), e.g. MUTT_ADD_FROM.

Definition at line 41 of file mx.h.

Function Documentation

◆ mx_mbox_check()

enum MxStatus mx_mbox_check ( struct Mailbox m)

Check for new mail - Wrapper for MxOps::mbox_check()

Parameters
mMailbox
Return values
enumMxStatus

Definition at line 1133 of file mx.c.

1134{
1135 if (!m || !m->mx_ops)
1136 return MX_STATUS_ERROR;
1137
1138 enum MxStatus rc = m->mx_ops->mbox_check(m);
1139 if ((rc == MX_STATUS_NEW_MAIL) || (rc == MX_STATUS_REOPENED))
1140 {
1142 }
1143
1144 return rc;
1145}
void mailbox_changed(struct Mailbox *m, enum NotifyMailbox action)
Notify observers of a change to a Mailbox.
Definition: mailbox.c:222
@ NT_MAILBOX_INVALID
Email list was changed.
Definition: mailbox.h:175
MxStatus
Return values from mbox_check(), mbox_check_stats(), mbox_snc(), and mbox_close()
Definition: mxapi.h:84
@ MX_STATUS_ERROR
An error occurred.
Definition: mxapi.h:85
@ MX_STATUS_REOPENED
Mailbox was reopened.
Definition: mxapi.h:89
@ MX_STATUS_NEW_MAIL
New mail received in Mailbox.
Definition: mxapi.h:87
const struct MxOps * mx_ops
MXAPI callback functions.
Definition: mailbox.h:107
enum MxStatus(* mbox_check)(struct Mailbox *m)
Definition: mxapi.h:183
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mx_mbox_check_stats()

enum MxStatus mx_mbox_check_stats ( struct Mailbox m,
uint8_t  flags 
)

Check the statistics for a mailbox - Wrapper for MxOps::mbox_check_stats()

Note
Emits: NT_MAILBOX_CHANGE

Definition at line 1807 of file mx.c.

1808{
1809 if (!m)
1810 return MX_STATUS_ERROR;
1811
1812 enum MxStatus rc = m->mx_ops->mbox_check_stats(m, flags);
1813 if (rc != MX_STATUS_ERROR)
1814 {
1815 struct EventMailbox ev_m = { m };
1817 }
1818
1819 return rc;
1820}
@ NT_MAILBOX_CHANGE
Mailbox has been changed.
Definition: mailbox.h:171
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:171
@ NT_MAILBOX
Mailbox has changed, NotifyMailbox, EventMailbox.
Definition: notify_type.h:49
An Event that happened to a Mailbox.
Definition: mailbox.h:185
struct Notify * notify
Notifications: NotifyMailbox, EventMailbox.
Definition: mailbox.h:143
enum MxStatus(* mbox_check_stats)(struct Mailbox *m, CheckStatsFlags flags)
Definition: mxapi.h:196
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mx_mbox_close()

enum MxStatus mx_mbox_close ( struct Mailbox m)

Save changes and close mailbox.

Parameters
mMailbox
Return values
enumMxStatus
Note
The flag retvals come from a call to a backend sync function
It's very important to ensure the mailbox is properly closed before free'ing the context. For selected mailboxes, IMAP will cache the context inside connection->adata until imap_close_mailbox() removes it. Readonly, dontwrite, and append mailboxes are guaranteed to call mx_fastclose_mailbox(), so for most of NeoMutt's code you won't see return value checks for temporary contexts.

Definition at line 616 of file mx.c.

617{
618 if (!m)
619 return MX_STATUS_ERROR;
620
621 const bool c_mail_check_recent = cs_subset_bool(NeoMutt->sub, "mail_check_recent");
622 if (c_mail_check_recent && !m->peekonly)
623 m->has_new = false;
624
625 if (m->readonly || m->dontwrite || m->append || m->peekonly)
626 {
627 mx_fastclose_mailbox(m, false);
628 return 0;
629 }
630
631 int i, read_msgs = 0;
632 enum MxStatus rc = MX_STATUS_ERROR;
633 enum QuadOption move_messages = MUTT_NO;
634 enum QuadOption purge = MUTT_YES;
635 struct Buffer *mbox = NULL;
636 struct Buffer *buf = mutt_buffer_pool_get();
637
638#ifdef USE_NNTP
639 if ((m->msg_unread != 0) && (m->type == MUTT_NNTP))
640 {
641 struct NntpMboxData *mdata = m->mdata;
642
643 if (mdata && mdata->adata && mdata->group)
644 {
645 const enum QuadOption c_catchup_newsgroup = cs_subset_quad(NeoMutt->sub, "catchup_newsgroup");
646 enum QuadOption ans = query_quadoption(c_catchup_newsgroup,
647 _("Mark all articles read?"));
648 if (ans == MUTT_ABORT)
649 goto cleanup;
650 if (ans == MUTT_YES)
651 mutt_newsgroup_catchup(m, mdata->adata, mdata->group);
652 }
653 }
654#endif
655
656 const bool c_keep_flagged = cs_subset_bool(NeoMutt->sub, "keep_flagged");
657 for (i = 0; i < m->msg_count; i++)
658 {
659 struct Email *e = m->emails[i];
660 if (!e)
661 break;
662
663 if (!e->deleted && e->read && !(e->flagged && c_keep_flagged))
664 read_msgs++;
665 }
666
667#ifdef USE_NNTP
668 /* don't need to move articles from newsgroup */
669 if (m->type == MUTT_NNTP)
670 read_msgs = 0;
671#endif
672
673 const enum QuadOption c_move = cs_subset_quad(NeoMutt->sub, "move");
674 if ((read_msgs != 0) && (c_move != MUTT_NO))
675 {
676 bool is_spool;
677 mbox = mutt_buffer_pool_get();
678
680 if (p)
681 {
682 is_spool = true;
683 mutt_buffer_strcpy(mbox, p);
684 }
685 else
686 {
687 const char *const c_mbox = cs_subset_string(NeoMutt->sub, "mbox");
688 mutt_buffer_strcpy(mbox, c_mbox);
689 is_spool = mutt_is_spool(mailbox_path(m)) &&
691 }
692
693 if (is_spool && !mutt_buffer_is_empty(mbox))
694 {
697 /* L10N: The first argument is the number of read messages to be
698 moved, the second argument is the target mailbox. */
699 ngettext("Move %d read message to %s?",
700 "Move %d read messages to %s?", read_msgs),
701 read_msgs, mutt_buffer_string(mbox));
702 move_messages = query_quadoption(c_move, mutt_buffer_string(buf));
703 if (move_messages == MUTT_ABORT)
704 goto cleanup;
705 }
706 }
707
708 /* There is no point in asking whether or not to purge if we are
709 * just marking messages as "trash". */
710 const bool c_maildir_trash = cs_subset_bool(NeoMutt->sub, "maildir_trash");
711 if ((m->msg_deleted != 0) && !((m->type == MUTT_MAILDIR) && c_maildir_trash))
712 {
714 ngettext("Purge %d deleted message?",
715 "Purge %d deleted messages?", m->msg_deleted),
716 m->msg_deleted);
717 const enum QuadOption c_delete = cs_subset_quad(NeoMutt->sub, "delete");
718 purge = query_quadoption(c_delete, mutt_buffer_string(buf));
719 if (purge == MUTT_ABORT)
720 goto cleanup;
721 }
722
723 const bool c_mark_old = cs_subset_bool(NeoMutt->sub, "mark_old");
724 if (c_mark_old && !m->peekonly)
725 {
726 for (i = 0; i < m->msg_count; i++)
727 {
728 struct Email *e = m->emails[i];
729 if (!e)
730 break;
731 if (!e->deleted && !e->old && !e->read)
732 mutt_set_flag(m, e, MUTT_OLD, true);
733 }
734 }
735
736 if (move_messages)
737 {
738 if (m->verbose)
739 mutt_message(_("Moving read messages to %s..."), mutt_buffer_string(mbox));
740
741#ifdef USE_IMAP
742 /* try to use server-side copy first */
743 i = 1;
744
745 if ((m->type == MUTT_IMAP) && (imap_path_probe(mutt_buffer_string(mbox), NULL) == MUTT_IMAP))
746 {
747 /* add messages for moving, and clear old tags, if any */
748 struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
749 for (i = 0; i < m->msg_count; i++)
750 {
751 struct Email *e = m->emails[i];
752 if (!e)
753 break;
754
755 if (e->read && !e->deleted && !(e->flagged && c_keep_flagged))
756 {
757 e->tagged = true;
758 emaillist_add_email(&el, e);
759 }
760 else
761 {
762 e->tagged = false;
763 }
764 }
765
767 emaillist_clear(&el);
768 }
769
770 if (i == 0) /* success */
772 else if (i == -1) /* horrible error, bail */
773 goto cleanup;
774 else /* use regular append-copy mode */
775#endif
776 {
777 struct Mailbox *m_read = mx_path_resolve(mutt_buffer_string(mbox));
778 if (!mx_mbox_open(m_read, MUTT_APPEND))
779 {
780 mailbox_free(&m_read);
781 goto cleanup;
782 }
783
784 for (i = 0; i < m->msg_count; i++)
785 {
786 struct Email *e = m->emails[i];
787 if (!e)
788 break;
789 if (e->read && !e->deleted && !(e->flagged && c_keep_flagged))
790 {
791 if (mutt_append_message(m_read, m, e, NULL, MUTT_CM_NO_FLAGS, CH_UPDATE_LEN) == 0)
792 {
793 mutt_set_flag(m, e, MUTT_DELETE, true);
794 mutt_set_flag(m, e, MUTT_PURGE, true);
795 }
796 else
797 {
798 mx_mbox_close(m_read);
799 goto cleanup;
800 }
801 }
802 }
803
804 mx_mbox_close(m_read);
805 }
806 }
807 else if (!m->changed && (m->msg_deleted == 0))
808 {
809 if (m->verbose)
810 mutt_message(_("Mailbox is unchanged"));
811 if ((m->type == MUTT_MBOX) || (m->type == MUTT_MMDF))
812 mbox_reset_atime(m, NULL);
813 mx_fastclose_mailbox(m, false);
814 rc = MX_STATUS_OK;
815 goto cleanup;
816 }
817
818 /* copy mails to the trash before expunging */
819 const char *const c_trash = cs_subset_string(NeoMutt->sub, "trash");
820 const struct Mailbox *m_trash = mx_mbox_find(m->account, c_trash);
821 if (purge && (m->msg_deleted != 0) && (m != m_trash))
822 {
823 if (trash_append(m) != 0)
824 goto cleanup;
825 }
826
827#ifdef USE_IMAP
828 /* allow IMAP to preserve the deleted flag across sessions */
829 if (m->type == MUTT_IMAP)
830 {
831 const enum MxStatus check = imap_sync_mailbox(m, (purge != MUTT_NO), true);
832 if (check == MX_STATUS_ERROR)
833 {
834 rc = check;
835 goto cleanup;
836 }
837 }
838 else
839#endif
840 {
841 if (purge == MUTT_NO)
842 {
843 for (i = 0; i < m->msg_count; i++)
844 {
845 struct Email *e = m->emails[i];
846 if (!e)
847 break;
848
849 e->deleted = false;
850 e->purge = false;
851 }
852 m->msg_deleted = 0;
853 }
854
855 if (m->changed || (m->msg_deleted != 0))
856 {
857 enum MxStatus check = sync_mailbox(m);
858 if (check != MX_STATUS_OK)
859 {
860 rc = check;
861 goto cleanup;
862 }
863 }
864 }
865
866 if (m->verbose)
867 {
868 if (move_messages)
869 {
870 mutt_message(_("%d kept, %d moved, %d deleted"),
871 m->msg_count - m->msg_deleted, read_msgs, m->msg_deleted);
872 }
873 else
874 {
875 mutt_message(_("%d kept, %d deleted"), m->msg_count - m->msg_deleted, m->msg_deleted);
876 }
877 }
878
879 const bool c_save_empty = cs_subset_bool(NeoMutt->sub, "save_empty");
880 if ((m->msg_count == m->msg_deleted) &&
881 ((m->type == MUTT_MMDF) || (m->type == MUTT_MBOX)) &&
882 !mutt_is_spool(mailbox_path(m)) && !c_save_empty)
883 {
885 }
886
887#ifdef USE_SIDEBAR
888 if ((purge == MUTT_YES) && (m->msg_deleted != 0))
889 {
890 for (i = 0; i < m->msg_count; i++)
891 {
892 struct Email *e = m->emails[i];
893 if (!e)
894 break;
895 if (e->deleted && !e->read)
896 {
897 m->msg_unread--;
898 if (!e->old)
899 m->msg_new--;
900 }
901 if (e->deleted && e->flagged)
902 m->msg_flagged--;
903 }
904 }
905#endif
906
907 mx_fastclose_mailbox(m, false);
908
909 rc = MX_STATUS_OK;
910
911cleanup:
914 return rc;
915}
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:298
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:365
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:168
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:78
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition: helpers.c:218
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
int mutt_append_message(struct Mailbox *m_dst, struct Mailbox *m_src, struct Email *e, struct Message *msg, CopyMessageFlags cmflags, CopyHeaderFlags chflags)
Append a message.
Definition: copy.c:950
#define CH_UPDATE_LEN
Update Lines: and Content-Length:
Definition: copy.h:62
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:35
int emaillist_add_email(struct EmailList *el, struct Email *e)
Add an Email to a list.
Definition: email.c:159
void emaillist_clear(struct EmailList *el)
Drop a private list of Emails.
Definition: email.c:138
@ SAVE_MOVE
Move message to another mailbox, removing the original.
Definition: external.h:51
void mutt_file_unlink_empty(const char *path)
Delete a file if it's empty.
Definition: file.c:1354
#define mutt_message(...)
Definition: logging.h:86
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Definition: imap.c:2425
char * mutt_find_hook(HookFlags type, const char *pat)
Find a matching hook.
Definition: hook.c:635
#define MUTT_MBOX_HOOK
mbox-hook: move messages after reading them
Definition: hook.h:39
int imap_copy_messages(struct Mailbox *m, struct EmailList *el, const char *dest, enum MessageSaveOpt save_opt)
Server COPY messages to another folder.
Definition: message.c:1660
enum MxStatus imap_sync_mailbox(struct Mailbox *m, bool expunge, bool close)
Sync all the changes to the server.
Definition: imap.c:1545
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:87
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:209
@ MUTT_MMDF
'mmdf' Mailbox type
Definition: mailbox.h:46
@ 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_MAILDIR
'Maildir' Mailbox type
Definition: mailbox.h:48
void mbox_reset_atime(struct Mailbox *m, struct stat *st)
Reset the access time on the mailbox file.
Definition: mbox.c:851
#define _(a)
Definition: message.h:28
@ MUTT_OLD
Old messages.
Definition: mutt.h:79
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition: mutt.h:85
@ MUTT_DELETE
Messages to be deleted.
Definition: mutt.h:83
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:73
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:325
static enum MxStatus sync_mailbox(struct Mailbox *m)
Save changes to disk.
Definition: mx.c:473
static int trash_append(struct Mailbox *m)
Move deleted mails to the trash folder.
Definition: mx.c:504
void mx_fastclose_mailbox(struct Mailbox *m, bool keep_account)
Free up memory associated with the Mailbox.
Definition: mx.c:431
static bool mutt_is_spool(const char *str)
Is this the spool_file?
Definition: mx.c:154
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:305
struct Mailbox * mx_mbox_find(struct Account *a, const char *path)
Find a Mailbox on an Account.
Definition: mx.c:1594
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1684
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
Definition: mx.c:616
#define MUTT_APPEND
Open mailbox for appending messages.
Definition: mxapi.h:63
@ MX_STATUS_OK
No changes.
Definition: mxapi.h:86
struct NntpMboxData * mutt_newsgroup_catchup(struct Mailbox *m, struct NntpAccountData *adata, char *group)
Catchup newsgroup.
Definition: newsrc.c:1322
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:63
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
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: question.c:386
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
String manipulation buffer.
Definition: buffer.h:34
The envelope/body of an email.
Definition: email.h:37
bool read
Email is read.
Definition: email.h:48
bool purge
Skip trash folder when deleting.
Definition: email.h:77
bool old
Email is seen, but unread.
Definition: email.h:47
bool flagged
Marked important?
Definition: email.h:45
bool deleted
Email is deleted.
Definition: email.h:76
bool tagged
Email is tagged.
Definition: email.h:106
A mailbox.
Definition: mailbox.h:79
bool changed
Mailbox has been modified.
Definition: mailbox.h:110
bool has_new
Mailbox has new mail.
Definition: mailbox.h:85
bool append
Mailbox is opened in append mode.
Definition: mailbox.h:109
int msg_new
Number of new messages.
Definition: mailbox.h:92
int msg_count
Total number of messages.
Definition: mailbox.h:88
enum MailboxType type
Mailbox type.
Definition: mailbox.h:102
void * mdata
Driver specific data.
Definition: mailbox.h:132
struct Email ** emails
Array of Emails.
Definition: mailbox.h:96
bool peekonly
Just taking a glance, revert atime.
Definition: mailbox.h:113
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
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:90
bool readonly
Don't allow changes to the mailbox.
Definition: mailbox.h:115
bool verbose
Display status messages?
Definition: mailbox.h:114
int msg_unread
Number of unread messages.
Definition: mailbox.h:89
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
NNTP-specific Mailbox data -.
Definition: mdata.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mx_mbox_open()

bool mx_mbox_open ( struct Mailbox m,
OpenMailboxFlags  flags 
)

Open a mailbox and parse it.

Parameters
mMailbox to open
flagsFlags, see OpenMailboxFlags
Return values
trueSuccess
falseError

Definition at line 305 of file mx.c.

306{
307 if (!m)
308 return false;
309
310 if ((m->type == MUTT_UNKNOWN) && (flags & (MUTT_NEWFOLDER | MUTT_APPEND)))
311 {
312 m->type = cs_subset_enum(NeoMutt->sub, "mbox_type");
313 m->mx_ops = mx_get_ops(m->type);
314 }
315
316 const bool newly_linked_account = !m->account;
317 if (newly_linked_account)
318 {
319 if (!mx_mbox_ac_link(m))
320 {
321 return false;
322 }
323 }
324
325 m->verbose = !(flags & MUTT_QUIET);
326 m->readonly = (flags & MUTT_READONLY);
327 m->peekonly = (flags & MUTT_PEEK);
328
329 if (flags & (MUTT_APPEND | MUTT_NEWFOLDER))
330 {
331 if (!mx_open_mailbox_append(m, flags))
332 {
333 goto error;
334 }
335 return true;
336 }
337
338 if (m->opened > 0)
339 {
340 m->opened++;
341 return true;
342 }
343
344 m->size = 0;
345 m->msg_unread = 0;
346 m->msg_flagged = 0;
347 m->rights = MUTT_ACL_ALL;
348
349 if (m->type == MUTT_UNKNOWN)
350 {
352 m->mx_ops = mx_get_ops(m->type);
353 }
354
355 if ((m->type == MUTT_UNKNOWN) || (m->type == MUTT_MAILBOX_ERROR) || !m->mx_ops)
356 {
357 if (m->type == MUTT_MAILBOX_ERROR)
359 else if ((m->type == MUTT_UNKNOWN) || !m->mx_ops)
360 mutt_error(_("%s is not a mailbox"), mailbox_path(m));
361 goto error;
362 }
363
365
366 /* if the user has a 'push' command in their .neomuttrc, or in a folder-hook,
367 * it will cause the progress messages not to be displayed because
368 * mutt_refresh() will think we are in the middle of a macro. so set a
369 * flag to indicate that we should really refresh the screen. */
370 OptForceRefresh = true;
371
372 if (m->verbose)
373 mutt_message(_("Reading %s..."), mailbox_path(m));
374
375 // Clear out any existing emails
376 for (int i = 0; i < m->email_max; i++)
377 {
378 email_free(&m->emails[i]);
379 }
380
381 m->msg_count = 0;
382 m->msg_unread = 0;
383 m->msg_flagged = 0;
384 m->msg_new = 0;
385 m->msg_deleted = 0;
386 m->msg_tagged = 0;
387 m->vcount = 0;
388
389 enum MxOpenReturns rc = m->mx_ops->mbox_open(m);
390 m->opened++;
391
392 if ((rc == MX_OPEN_OK) || (rc == MX_OPEN_ABORT))
393 {
394 if ((flags & MUTT_NOSORT) == 0)
395 {
396 /* avoid unnecessary work since the mailbox is completely unthreaded
397 * to begin with */
398 OptSortSubthreads = false;
399 OptNeedRescore = false;
400 }
401 if (m->verbose)
403 if (rc == MX_OPEN_ABORT)
404 {
405 mutt_error(_("Reading from %s interrupted..."), mailbox_path(m));
406 }
407 }
408 else
409 {
410 goto error;
411 }
412
413 if (!m->peekonly)
414 m->has_new = false;
415 OptForceRefresh = false;
416
417 return true;
418
419error:
420 mx_fastclose_mailbox(m, newly_linked_account);
421 if (newly_linked_account)
423 return false;
424}
bool account_mailbox_remove(struct Account *a, struct Mailbox *m)
Remove a Mailbox from an Account.
Definition: account.c:96
unsigned char cs_subset_enum(const struct ConfigSubset *sub, const char *name)
Get a enumeration config item by name.
Definition: helpers.c:97
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:44
bool OptNeedRescore
(pseudo) set when the 'score' command is used
Definition: globals.c:75
bool OptForceRefresh
(pseudo) refresh even during macros
Definition: globals.c:70
bool OptSortSubthreads
(pseudo) used when $sort_aux changes
Definition: globals.c:87
#define mutt_error(...)
Definition: logging.h:87
#define mutt_perror(...)
Definition: logging.h:88
#define MUTT_ACL_ALL
Definition: mailbox.h:73
@ MUTT_MAILBOX_ERROR
Error occurred examining Mailbox.
Definition: mailbox.h:43
@ MUTT_UNKNOWN
Mailbox wasn't recognised.
Definition: mailbox.h:44
void mutt_make_label_hash(struct Mailbox *m)
Create a Hash Table to store the labels.
Definition: mutt_header.c:413
const struct MxOps * mx_get_ops(enum MailboxType type)
Get mailbox operations.
Definition: mx.c:140
bool mx_mbox_ac_link(struct Mailbox *m)
Link a Mailbox to an existing or new Account.
Definition: mx.c:268
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1334
static bool mx_open_mailbox_append(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox for appending.
Definition: mx.c:200
#define MUTT_READONLY
Open in read-only mode.
Definition: mxapi.h:64
#define MUTT_NEWFOLDER
Create a new folder - same as MUTT_APPEND, but uses mutt_file_fopen() with mode "w" for mbox-style fo...
Definition: mxapi.h:66
#define MUTT_QUIET
Do not print any messages.
Definition: mxapi.h:65
MxOpenReturns
Return values for mbox_open()
Definition: mxapi.h:97
@ MX_OPEN_ABORT
Open was aborted.
Definition: mxapi.h:100
@ MX_OPEN_OK
Open succeeded.
Definition: mxapi.h:98
#define MUTT_PEEK
Revert atime back after taking a look (if applicable)
Definition: mxapi.h:69
#define MUTT_NOSORT
Do not sort the mailbox after opening it.
Definition: mxapi.h:62
int vcount
The number of virtual messages.
Definition: mailbox.h:99
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:117
int email_max
Number of pointers in emails.
Definition: mailbox.h:97
off_t size
Size of the Mailbox.
Definition: mailbox.h:84
int opened
Number of times mailbox is opened.
Definition: mailbox.h:128
int msg_tagged
How many messages are tagged?
Definition: mailbox.h:94
enum MxOpenReturns(* mbox_open)(struct Mailbox *m)
Definition: mxapi.h:157
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mx_mbox_sync()

enum MxStatus mx_mbox_sync ( struct Mailbox m)

Save changes to mailbox.

Parameters
[in]mMailbox
Return values
enumMxStatus
Note
The flag retvals come from a call to a backend sync function

Definition at line 924 of file mx.c.

925{
926 if (!m)
927 return MX_STATUS_ERROR;
928
929 enum MxStatus rc = MX_STATUS_OK;
930 int purge = 1;
931 int msgcount, deleted;
932
933 if (m->dontwrite)
934 {
935 char buf[256], tmp[256];
936 if (km_expand_key(buf, sizeof(buf), km_find_func(MENU_INDEX, OP_TOGGLE_WRITE)))
937 snprintf(tmp, sizeof(tmp), _(" Press '%s' to toggle write"), buf);
938 else
939 mutt_str_copy(tmp, _("Use 'toggle-write' to re-enable write"), sizeof(tmp));
940
941 mutt_error(_("Mailbox is marked unwritable. %s"), tmp);
942 return MX_STATUS_ERROR;
943 }
944 else if (m->readonly)
945 {
946 mutt_error(_("Mailbox is read-only"));
947 return MX_STATUS_ERROR;
948 }
949
950 if (!m->changed && (m->msg_deleted == 0))
951 {
952 if (m->verbose)
953 mutt_message(_("Mailbox is unchanged"));
954 return MX_STATUS_OK;
955 }
956
957 if (m->msg_deleted != 0)
958 {
959 char buf[128] = { 0 };
960
961 snprintf(buf, sizeof(buf),
962 ngettext("Purge %d deleted message?", "Purge %d deleted messages?", m->msg_deleted),
963 m->msg_deleted);
964 const enum QuadOption c_delete = cs_subset_quad(NeoMutt->sub, "delete");
965 purge = query_quadoption(c_delete, buf);
966 if (purge == MUTT_ABORT)
967 return MX_STATUS_ERROR;
968 if (purge == MUTT_NO)
969 {
970 if (!m->changed)
971 return MX_STATUS_OK; /* nothing to do! */
972 /* let IMAP servers hold on to D flags */
973 if (m->type != MUTT_IMAP)
974 {
975 for (int i = 0; i < m->msg_count; i++)
976 {
977 struct Email *e = m->emails[i];
978 if (!e)
979 break;
980 e->deleted = false;
981 e->purge = false;
982 }
983 m->msg_deleted = 0;
984 }
985 }
987 }
988
989 /* really only for IMAP - imap_sync_mailbox results in a call to
990 * ctx_update_tables, so m->msg_deleted is 0 when it comes back */
991 msgcount = m->msg_count;
992 deleted = m->msg_deleted;
993
994 const char *const c_trash = cs_subset_string(NeoMutt->sub, "trash");
995 const struct Mailbox *m_trash = mx_mbox_find(m->account, c_trash);
996 if (purge && (m->msg_deleted != 0) && (m != m_trash))
997 {
998 if (trash_append(m) != 0)
999 return MX_STATUS_OK;
1000 }
1001
1002#ifdef USE_IMAP
1003 if (m->type == MUTT_IMAP)
1004 rc = imap_sync_mailbox(m, purge, false);
1005 else
1006#endif
1007 rc = sync_mailbox(m);
1008 if (rc != MX_STATUS_ERROR)
1009 {
1010#ifdef USE_IMAP
1011 if ((m->type == MUTT_IMAP) && !purge)
1012 {
1013 if (m->verbose)
1014 mutt_message(_("Mailbox checkpointed"));
1015 }
1016 else
1017#endif
1018 {
1019 if (m->verbose)
1020 mutt_message(_("%d kept, %d deleted"), msgcount - deleted, deleted);
1021 }
1022
1023 mutt_sleep(0);
1024
1025 const bool c_save_empty = cs_subset_bool(NeoMutt->sub, "save_empty");
1026 if ((m->msg_count == m->msg_deleted) &&
1027 ((m->type == MUTT_MBOX) || (m->type == MUTT_MMDF)) &&
1028 !mutt_is_spool(mailbox_path(m)) && !c_save_empty)
1029 {
1030 unlink(mailbox_path(m));
1031 mx_fastclose_mailbox(m, false);
1032 return MX_STATUS_OK;
1033 }
1034
1035 /* if we haven't deleted any messages, we don't need to resort
1036 * ... except for certain folder formats which need "unsorted"
1037 * sort order in order to synchronize folders.
1038 *
1039 * MH and maildir are safe. mbox-style seems to need re-sorting,
1040 * at least with the new threading code. */
1041 if (purge || ((m->type != MUTT_MAILDIR) && (m->type != MUTT_MH)))
1042 {
1043 /* IMAP does this automatically after handling EXPUNGE */
1044 if (m->type != MUTT_IMAP)
1045 {
1048 }
1049 }
1050 }
1051
1052 return rc;
1053}
struct Keymap * km_find_func(enum MenuType mtype, int func)
Find a function's mapping in a Menu.
Definition: keymap.c:960
int km_expand_key(char *s, size_t len, struct Keymap *map)
Get the key string bound to a Keymap.
Definition: keymap.c:932
@ NT_MAILBOX_UNTAG
Clear the 'last-tagged' pointer.
Definition: mailbox.h:178
@ NT_MAILBOX_RESORT
Email list needs resorting.
Definition: mailbox.h:176
@ NT_MAILBOX_UPDATE
Update internal tables.
Definition: mailbox.h:177
@ MUTT_MH
'MH' Mailbox type
Definition: mailbox.h:47
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:652
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:1408
@ MENU_INDEX
Index panel (list of emails)
Definition: type.h:50
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mx_msg_close()

int mx_msg_close ( struct Mailbox m,
struct Message **  msg 
)

Close a message.

Parameters
[in]mMailbox
[out]msgMessage to close
Return values
0Success
-1Failure

Definition at line 1200 of file mx.c.

1201{
1202 if (!m || !msg || !*msg)
1203 return 0;
1204
1205 int rc = 0;
1206
1207 if (m->mx_ops && m->mx_ops->msg_close)
1208 rc = m->mx_ops->msg_close(m, *msg);
1209
1210 if ((*msg)->path)
1211 {
1212 mutt_debug(LL_DEBUG1, "unlinking %s\n", (*msg)->path);
1213 unlink((*msg)->path);
1214 FREE(&(*msg)->path);
1215 }
1216
1217 FREE(&(*msg)->committed_path);
1218 FREE(msg);
1219 return rc;
1220}
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
#define FREE(x)
Definition: memory.h:43
int(* msg_close)(struct Mailbox *m, struct Message *msg)
Definition: mxapi.h:283
+ Here is the caller graph for this function:

◆ mx_msg_commit()

int mx_msg_commit ( struct Mailbox m,
struct Message msg 
)

Commit a message to a folder - Wrapper for MxOps::msg_commit()

Parameters
mMailbox
msgMessage to commit
Return values
0Success
-1Failure

Definition at line 1179 of file mx.c.

1180{
1181 if (!m || !m->mx_ops || !m->mx_ops->msg_commit || !msg)
1182 return -1;
1183
1184 if (!(msg->write && m->append))
1185 {
1186 mutt_debug(LL_DEBUG1, "msg->write = %d, m->append = %d\n", msg->write, m->append);
1187 return -1;
1188 }
1189
1190 return m->mx_ops->msg_commit(m, msg);
1191}
bool write
nonzero if message is open for writing
Definition: mxapi.h:47
int(* msg_commit)(struct Mailbox *m, struct Message *msg)
Definition: mxapi.h:268
+ Here is the caller graph for this function:

◆ mx_msg_open_new()

struct Message * mx_msg_open_new ( struct Mailbox m,
const struct Email e,
MsgOpenFlags  flags 
)

Open a new message.

Parameters
mDestination mailbox
eMessage being copied (required for maildir support, because the filename depends on the message flags)
flagsFlags, see MsgOpenFlags
Return values
ptrNew Message

Definition at line 1062 of file mx.c.

1063{
1064 if (!m)
1065 return NULL;
1066
1067 struct Address *p = NULL;
1068 struct Message *msg = NULL;
1069
1070 if (!m->mx_ops || !m->mx_ops->msg_open_new)
1071 {
1072 mutt_debug(LL_DEBUG1, "function unimplemented for mailbox type %d\n", m->type);
1073 return NULL;
1074 }
1075
1076 msg = mutt_mem_calloc(1, sizeof(struct Message));
1077 msg->write = true;
1078
1079 if (e)
1080 {
1081 msg->flags.flagged = e->flagged;
1082 msg->flags.replied = e->replied;
1083 msg->flags.read = e->read;
1084 msg->flags.draft = (flags & MUTT_SET_DRAFT);
1085 msg->received = e->received;
1086 }
1087
1088 if (msg->received == 0)
1089 msg->received = mutt_date_now();
1090
1091 if (m->mx_ops->msg_open_new(m, msg, e))
1092 {
1093 if (m->type == MUTT_MMDF)
1094 fputs(MMDF_SEP, msg->fp);
1095
1096 if (((m->type == MUTT_MBOX) || (m->type == MUTT_MMDF)) && (flags & MUTT_ADD_FROM))
1097 {
1098 if (e)
1099 {
1100 p = TAILQ_FIRST(&e->env->return_path);
1101 if (!p)
1102 p = TAILQ_FIRST(&e->env->sender);
1103 if (!p)
1104 p = TAILQ_FIRST(&e->env->from);
1105 }
1106
1107 // Force a 'C' locale for the date, so that day/month names are in English
1108 char buf[64] = { 0 };
1109 struct tm tm = mutt_date_localtime(msg->received);
1110#ifdef LC_TIME_MASK
1111 locale_t loc = newlocale(LC_TIME_MASK, "C", 0);
1112 strftime_l(buf, sizeof(buf), "%a %b %e %H:%M:%S %Y", &tm, loc);
1113 freelocale(loc);
1114#else /* !LC_TIME_MASK */
1115 strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Y", &tm);
1116#endif /* LC_TIME_MASK */
1117 fprintf(msg->fp, "From %s %s\n", p ? p->mailbox : NONULL(Username), buf);
1118 }
1119 }
1120 else
1121 {
1122 FREE(&msg);
1123 }
1124
1125 return msg;
1126}
struct tm mutt_date_localtime(time_t t)
Converts calendar time to a broken-down time structure expressed in user timezone.
Definition: date.c:657
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:432
char * Username
User's login name.
Definition: globals.c:41
#define MMDF_SEP
Definition: lib.h:61
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define MUTT_ADD_FROM
add a From_ line
Definition: mx.h:43
#define MUTT_SET_DRAFT
set the message draft flag
Definition: mx.h:44
#define TAILQ_FIRST(head)
Definition: queue.h:723
#define NONULL(x)
Definition: string2.h:37
An email address.
Definition: address.h:36
char * mailbox
Mailbox and host address.
Definition: address.h:38
struct Envelope * env
Envelope information.
Definition: email.h:66
bool replied
Email has been replied to.
Definition: email.h:49
time_t received
Time when the message was placed in the mailbox.
Definition: email.h:59
struct AddressList return_path
Return path for the Email.
Definition: envelope.h:58
struct AddressList sender
Email's sender.
Definition: envelope.h:63
struct AddressList from
Email's 'From' list.
Definition: envelope.h:59
A local copy of an email.
Definition: mxapi.h:43
FILE * fp
pointer to the message data
Definition: mxapi.h:44
bool draft
Message has been read.
Definition: mxapi.h:53
bool replied
Message has been replied to.
Definition: mxapi.h:52
time_t received
Time at which this message was received.
Definition: mxapi.h:55
bool flagged
Message is flagged.
Definition: mxapi.h:51
bool read
Message has been read.
Definition: mxapi.h:50
struct Message::@0 flags
Flags for the Message.
bool(* msg_open_new)(struct Mailbox *m, struct Message *msg, const struct Email *e)
Definition: mxapi.h:253
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mx_msg_open()

struct Message * mx_msg_open ( struct Mailbox m,
int  msgno 
)

Return a stream pointer for a message.

Parameters
mMailbox
msgnoMessage number
Return values
ptrMessage
NULLError

Definition at line 1154 of file mx.c.

1155{
1156 if (!m || !m->emails || (msgno < 0) || (msgno >= m->msg_count))
1157 return NULL;
1158
1159 if (!m->mx_ops || !m->mx_ops->msg_open)
1160 {
1161 mutt_debug(LL_DEBUG1, "function not implemented for mailbox type %d\n", m->type);
1162 return NULL;
1163 }
1164
1165 struct Message *msg = mutt_mem_calloc(1, sizeof(struct Message));
1166 if (!m->mx_ops->msg_open(m, msg, msgno))
1167 FREE(&msg);
1168
1169 return msg;
1170}
bool(* msg_open)(struct Mailbox *m, struct Message *msg, int msgno)
Definition: mxapi.h:237
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mx_msg_padding_size()

int mx_msg_padding_size ( struct Mailbox m)

Bytes of padding between messages - Wrapper for MxOps::msg_padding_size()

Parameters
mMailbox
Return values
numNumber of bytes of padding

mmdf and mbox add separators, which leads a small discrepancy when computing vsize for a limited view.

Definition at line 1556 of file mx.c.

1557{
1558 if (!m || !m->mx_ops || !m->mx_ops->msg_padding_size)
1559 return 0;
1560
1561 return m->mx_ops->msg_padding_size(m);
1562}
int(* msg_padding_size)(struct Mailbox *m)
Definition: mxapi.h:295
+ Here is the caller graph for this function:

◆ mx_save_hcache()

int mx_save_hcache ( struct Mailbox m,
struct Email e 
)

Save message to the header cache - Wrapper for MxOps::msg_save_hcache()

Parameters
mMailbox
eEmail
Return values
0Success
-1Failure

Write a single header out to the header cache.

Definition at line 1831 of file mx.c.

1832{
1833 if (!m || !m->mx_ops || !m->mx_ops->msg_save_hcache || !e)
1834 return 0;
1835
1836 return m->mx_ops->msg_save_hcache(m, e);
1837}
int(* msg_save_hcache)(struct Mailbox *m, struct Email *e)
Definition: mxapi.h:310
+ Here is the caller graph for this function:

◆ mx_path_canon()

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 at line 1380 of file mx.c.

1381{
1382 if (!buf)
1383 return -1;
1384
1385 for (size_t i = 0; i < 3; i++)
1386 {
1387 /* Look for !! ! - < > or ^ followed by / or NUL */
1388 if ((buf[0] == '!') && (buf[1] == '!'))
1389 {
1390 if (((buf[2] == '/') || (buf[2] == '\0')))
1391 {
1392 mutt_str_inline_replace(buf, buflen, 2, LastFolder);
1393 }
1394 }
1395 else if ((buf[0] == '+') || (buf[0] == '='))
1396 {
1397 size_t folder_len = mutt_str_len(folder);
1398 if ((folder_len > 0) && (folder[folder_len - 1] != '/'))
1399 {
1400 buf[0] = '/';
1401 mutt_str_inline_replace(buf, buflen, 0, folder);
1402 }
1403 else
1404 {
1405 mutt_str_inline_replace(buf, buflen, 1, folder);
1406 }
1407 }
1408 else if ((buf[1] == '/') || (buf[1] == '\0'))
1409 {
1410 if (buf[0] == '!')
1411 {
1412 const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
1413 mutt_str_inline_replace(buf, buflen, 1, c_spool_file);
1414 }
1415 else if (buf[0] == '-')
1416 {
1417 mutt_str_inline_replace(buf, buflen, 1, LastFolder);
1418 }
1419 else if (buf[0] == '<')
1420 {
1421 const char *const c_record = cs_subset_string(NeoMutt->sub, "record");
1422 mutt_str_inline_replace(buf, buflen, 1, c_record);
1423 }
1424 else if (buf[0] == '>')
1425 {
1426 const char *const c_mbox = cs_subset_string(NeoMutt->sub, "mbox");
1427 mutt_str_inline_replace(buf, buflen, 1, c_mbox);
1428 }
1429 else if (buf[0] == '^')
1430 {
1431 mutt_str_inline_replace(buf, buflen, 1, CurrentFolder);
1432 }
1433 else if (buf[0] == '~')
1434 {
1435 mutt_str_inline_replace(buf, buflen, 1, HomeDir);
1436 }
1437 }
1438 else if (buf[0] == '@')
1439 {
1440 /* elm compatibility, @ expands alias to user name */
1441 struct AddressList *al = alias_lookup(buf + 1);
1442 if (!al || TAILQ_EMPTY(al))
1443 break;
1444
1445 struct Email *e = email_new();
1446 e->env = mutt_env_new();
1447 mutt_addrlist_copy(&e->env->from, al, false);
1448 mutt_addrlist_copy(&e->env->to, al, false);
1449 mutt_default_save(buf, buflen, e);
1450 email_free(&e);
1451 break;
1452 }
1453 else
1454 {
1455 break;
1456 }
1457 }
1458
1459 // if (!folder) //XXX - use inherited version, or pass NULL to backend?
1460 // return -1;
1461
1462 enum MailboxType type2 = mx_path_probe(buf);
1463 if (type)
1464 *type = type2;
1465 const struct MxOps *ops = mx_get_ops(type2);
1466 if (!ops || !ops->path_canon)
1467 return -1;
1468
1469 if (ops->path_canon(buf, buflen) < 0)
1470 {
1471 mutt_path_canon(buf, buflen, HomeDir, true);
1472 }
1473
1474 return 0;
1475}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:745
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:280
char * HomeDir
User's home directory.
Definition: globals.c:38
struct Email * email_new(void)
Create a new Email.
Definition: email.c:78
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:43
char * LastFolder
Previously selected mailbox.
Definition: globals.c:44
char * CurrentFolder
Currently selected mailbox.
Definition: globals.c:43
void mutt_default_save(char *path, size_t pathlen, struct Email *e)
Find the default save path for an email.
Definition: hook.c:735
MailboxType
Supported mailbox formats.
Definition: mailbox.h:41
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
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:949
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
#define TAILQ_EMPTY(head)
Definition: queue.h:721
struct AddressList to
Email's 'To' list.
Definition: envelope.h:60
Definition: mxapi.h:112
int(* path_canon)(char *buf, size_t buflen)
Definition: mxapi.h:371
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mx_path_canon2()

int mx_path_canon2 ( struct Mailbox m,
const char *  folder 
)

Canonicalise the path to realpath.

Parameters
mMailbox
folderPath to canonicalise
Return values
0Success
-1Failure

Definition at line 1484 of file mx.c.

1485{
1486 if (!m)
1487 return -1;
1488
1489 char buf[PATH_MAX] = { 0 };
1490
1491 if (m->realpath)
1492 mutt_str_copy(buf, m->realpath, sizeof(buf));
1493 else
1494 mutt_str_copy(buf, mailbox_path(m), sizeof(buf));
1495
1496 int rc = mx_path_canon(buf, sizeof(buf), folder, &m->type);
1497
1498 mutt_str_replace(&m->realpath, buf);
1499
1500 if (rc >= 0)
1501 {
1502 m->mx_ops = mx_get_ops(m->type);
1504 }
1505
1506 return rc;
1507}
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:326
#define PATH_MAX
Definition: mutt.h:41
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:1380
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:81
struct Buffer pathbuf
Path of the Mailbox.
Definition: mailbox.h:80
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mx_path_parent()

int mx_path_parent ( const char *  buf,
size_t  buflen 
)

Find the parent of a mailbox path - Wrapper for MxOps::path_parent()

Definition at line 1540 of file mx.c.

1541{
1542 if (!buf)
1543 return -1;
1544
1545 return 0;
1546}

◆ mx_path_pretty()

int mx_path_pretty ( char *  buf,
size_t  buflen,
const char *  folder 
)

Abbreviate a mailbox path - Wrapper for MxOps::path_pretty()

Definition at line 1512 of file mx.c.

1513{
1514 if (!buf)
1515 return -1;
1516
1517 enum MailboxType type = mx_path_probe(buf);
1518 const struct MxOps *ops = mx_get_ops(type);
1519 if (!ops)
1520 return -1;
1521
1522 if (!ops->path_canon)
1523 return -1;
1524
1525 if (ops->path_canon(buf, buflen) < 0)
1526 return -1;
1527
1528 if (!ops->path_pretty)
1529 return -1;
1530
1531 if (ops->path_pretty(buf, buflen, folder) < 0)
1532 return -1;
1533
1534 return 0;
1535}
int(* path_pretty)(char *buf, size_t buflen, const char *folder)
Definition: mxapi.h:386
enum MailboxType type
Mailbox type, e.g. MUTT_IMAP.
Definition: mxapi.h:113
+ Here is the call graph for this function:

◆ mx_path_probe()

enum MailboxType mx_path_probe ( const char *  path)

Find a mailbox that understands a path.

Parameters
pathPath to examine
Return values
numType, e.g. MUTT_IMAP

Definition at line 1334 of file mx.c.

1335{
1336 if (!path)
1337 return MUTT_UNKNOWN;
1338
1339 enum MailboxType rc = MUTT_UNKNOWN;
1340
1341 // First, search the non-local Mailbox types (is_local == false)
1342 for (const struct MxOps **ops = MxOps; *ops; ops++)
1343 {
1344 if ((*ops)->is_local)
1345 continue;
1346 rc = (*ops)->path_probe(path, NULL);
1347 if (rc != MUTT_UNKNOWN)
1348 return rc;
1349 }
1350
1351 struct stat st = { 0 };
1352 if (stat(path, &st) != 0)
1353 {
1354 mutt_debug(LL_DEBUG1, "unable to stat %s: %s (errno %d)\n", path, strerror(errno), errno);
1355 return MUTT_UNKNOWN;
1356 }
1357
1358 if (S_ISFIFO(st.st_mode))
1359 {
1360 mutt_error(_("Can't open %s: it is a pipe"), path);
1361 return MUTT_UNKNOWN;
1362 }
1363
1364 // Next, search the local Mailbox types (is_local == true)
1365 for (const struct MxOps **ops = MxOps; *ops; ops++)
1366 {
1367 if (!(*ops)->is_local)
1368 continue;
1369 rc = (*ops)->path_probe(path, &st);
1370 if (rc != MUTT_UNKNOWN)
1371 return rc;
1372 }
1373
1374 return rc;
1375}
+ Here is the caller graph for this function:

◆ mx_path_resolve()

struct Mailbox * mx_path_resolve ( const char *  path)

Get a Mailbox for a path.

Parameters
pathMailbox path
Return values
ptrMailbox

If there isn't a Mailbox for the path, one will be created.

Definition at line 1684 of file mx.c.

1685{
1686 if (!path)
1687 return NULL;
1688
1689 struct Mailbox *m = mx_mbox_find2(path);
1690 if (m)
1691 return m;
1692
1693 m = mailbox_new();
1694 mutt_buffer_strcpy(&m->pathbuf, path);
1695 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
1696 mx_path_canon2(m, c_folder);
1697
1698 return m;
1699}
struct Mailbox * mailbox_new(void)
Create a new Mailbox.
Definition: mailbox.c:68
struct Mailbox * mx_mbox_find2(const char *path)
Find a Mailbox on an Account.
Definition: mx.c:1656
int mx_path_canon2(struct Mailbox *m, const char *folder)
Canonicalise the path to realpath.
Definition: mx.c:1484
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mx_resolve()

struct Mailbox * mx_resolve ( const char *  path_or_name)

Get a Mailbox from either a path or name.

Parameters
path_or_nameMailbox path or name
Return values
ptrMailbox

Order of resolving:

  1. Name
  2. Path

Definition at line 1753 of file mx.c.

1754{
1755 if (!path_or_name)
1756 return NULL;
1757
1758 // Order is name first because you can create a Mailbox from
1759 // a path, but can't from a name. So fallback behavior creates
1760 // a new Mailbox for us.
1761 struct Mailbox *m = mx_mbox_find_by_name(path_or_name);
1762 if (!m)
1763 m = mx_path_resolve(path_or_name);
1764
1765 return m;
1766}
static struct Mailbox * mx_mbox_find_by_name(const char *name)
Find a Mailbox with given name.
Definition: mx.c:1728
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mx_tags_commit()

int mx_tags_commit ( struct Mailbox m,
struct Email e,
const char *  tags 
)

Save tags to the Mailbox - Wrapper for MxOps::tags_commit()

Parameters
mMailbox
eEmail
tagsTags to save
Return values
0Success
-1Failure

Definition at line 1307 of file mx.c.

1308{
1309 if (!m || !e || !tags)
1310 return -1;
1311
1312 if (m->mx_ops->tags_commit)
1313 return m->mx_ops->tags_commit(m, e, tags);
1314
1315 mutt_message(_("Folder doesn't support tagging, aborting"));
1316 return -1;
1317}
int(* tags_commit)(struct Mailbox *m, struct Email *e, const char *buf)
Definition: mxapi.h:344
+ Here is the caller graph for this function:

◆ mx_tags_edit()

int mx_tags_edit ( struct Mailbox m,
const char *  tags,
struct Buffer buf 
)

Start the tag editor of the mailbox.

Parameters
mMailbox
tagsExisting tags
bufBuffer for the results
Return values
-1Error
0No valid user input
1Buffer set

Definition at line 1287 of file mx.c.

1288{
1289 if (!m || !buf)
1290 return -1;
1291
1292 if (m->mx_ops->tags_edit)
1293 return m->mx_ops->tags_edit(m, tags, buf);
1294
1295 mutt_message(_("Folder doesn't support tagging, aborting"));
1296 return -1;
1297}
int(* tags_edit)(struct Mailbox *m, const char *tags, struct Buffer *buf)
Definition: mxapi.h:327
+ Here is the caller graph for this function:

◆ mx_type()

enum MailboxType mx_type ( struct Mailbox m)

Return the type of the Mailbox.

Parameters
mMailbox
Return values
enumMailboxType

Definition at line 1844 of file mx.c.

1845{
1846 return m ? m->type : MUTT_MAILBOX_ERROR;
1847}
+ Here is the caller graph for this function:

◆ mx_ac_find()

struct Account * mx_ac_find ( struct Mailbox m)

Find the Account owning a Mailbox.

Parameters
mMailbox
Return values
ptrAccount
NULLNone found

Definition at line 1570 of file mx.c.

1571{
1572 if (!m || !m->mx_ops || !m->realpath)
1573 return NULL;
1574
1575 struct Account *np = NULL;
1576 TAILQ_FOREACH(np, &NeoMutt->accounts, entries)
1577 {
1578 if (np->type != m->type)
1579 continue;
1580
1581 if (m->mx_ops->ac_owns_path(np, m->realpath))
1582 return np;
1583 }
1584
1585 return NULL;
1586}
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
A group of associated Mailboxes.
Definition: account.h:37
enum MailboxType type
Type of Mailboxes this Account contains.
Definition: account.h:38
bool(* ac_owns_path)(struct Account *a, const char *path)
Definition: mxapi.h:130
struct AccountList accounts
List of all Accounts.
Definition: neomutt.h:40
+ Here is the caller graph for this function:

◆ mx_mbox_find()

struct Mailbox * mx_mbox_find ( struct Account a,
const char *  path 
)

Find a Mailbox on an Account.

Parameters
aAccount to search
pathPath to find
Return values
ptrMailbox

Definition at line 1594 of file mx.c.

1595{
1596 if (!a || !path)
1597 return NULL;
1598
1599 struct MailboxNode *np = NULL;
1600 struct Url *url_p = NULL;
1601 struct Url *url_a = NULL;
1602
1603 const bool use_url = (a->type == MUTT_IMAP);
1604 if (use_url)
1605 {
1606 url_p = url_parse(path);
1607 if (!url_p)
1608 goto done;
1609 }
1610
1611 STAILQ_FOREACH(np, &a->mailboxes, entries)
1612 {
1613 if (!use_url)
1614 {
1616 return np->mailbox;
1617 continue;
1618 }
1619
1620 url_free(&url_a);
1621 url_a = url_parse(np->mailbox->realpath);
1622 if (!url_a)
1623 continue;
1624
1625 if (!mutt_istr_equal(url_a->host, url_p->host))
1626 continue;
1627 if (url_p->user && !mutt_istr_equal(url_a->user, url_p->user))
1628 continue;
1629 if (a->type == MUTT_IMAP)
1630 {
1631 if (imap_mxcmp(url_a->path, url_p->path) == 0)
1632 break;
1633 }
1634 else
1635 {
1636 if (mutt_str_equal(url_a->path, url_p->path))
1637 break;
1638 }
1639 }
1640
1641done:
1642 url_free(&url_p);
1643 url_free(&url_a);
1644
1645 if (!np)
1646 return NULL;
1647 return np->mailbox;
1648}
int imap_mxcmp(const char *mx1, const char *mx2)
Compare mailbox names, giving priority to INBOX.
Definition: util.c:545
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:819
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:807
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
struct MailboxList mailboxes
List of Mailboxes.
Definition: account.h:41
List of Mailboxes.
Definition: mailbox.h:152
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:153
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
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:236
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition: url.c:123
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mx_mbox_find2()

struct Mailbox * mx_mbox_find2 ( const char *  path)

Find a Mailbox on an Account.

Parameters
pathPath to find
Return values
ptrMailbox
NULLNo match

Definition at line 1656 of file mx.c.

1657{
1658 if (!path)
1659 return NULL;
1660
1661 char buf[PATH_MAX] = { 0 };
1662 mutt_str_copy(buf, path, sizeof(buf));
1663 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
1664 mx_path_canon(buf, sizeof(buf), c_folder, NULL);
1665
1666 struct Account *np = NULL;
1667 TAILQ_FOREACH(np, &NeoMutt->accounts, entries)
1668 {
1669 struct Mailbox *m = mx_mbox_find(np, buf);
1670 if (m)
1671 return m;
1672 }
1673
1674 return NULL;
1675}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mx_mbox_ac_link()

bool mx_mbox_ac_link ( struct Mailbox m)

Link a Mailbox to an existing or new Account.

Parameters
mMailbox to link
Return values
trueSuccess
falseFailure

Definition at line 268 of file mx.c.

269{
270 if (!m)
271 return false;
272
273 if (m->account)
274 return true;
275
276 struct Account *a = mx_ac_find(m);
277 const bool new_account = !a;
278 if (new_account)
279 {
280 a = account_new(NULL, NeoMutt->sub);
281 a->type = m->type;
282 }
283 if (!mx_ac_add(a, m))
284 {
285 if (new_account)
286 {
287 account_free(&a);
288 }
289 return false;
290 }
291 if (new_account)
292 {
294 }
295 return true;
296}
struct Account * account_new(const char *name, struct ConfigSubset *sub)
Create a new Account.
Definition: account.c:43
void account_free(struct Account **ptr)
Free an Account.
Definition: account.c:141
bool mx_ac_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account - Wrapper for MxOps::ac_add()
Definition: mx.c:1771
struct Account * mx_ac_find(struct Mailbox *m)
Find the Account owning a Mailbox.
Definition: mx.c:1570
bool neomutt_account_add(struct NeoMutt *n, struct Account *a)
Add an Account to the global list.
Definition: neomutt.c:84
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mx_ac_add()

bool mx_ac_add ( struct Account a,
struct Mailbox m 
)

Add a Mailbox to an Account - Wrapper for MxOps::ac_add()

Definition at line 1771 of file mx.c.

1772{
1773 if (!a || !m || !m->mx_ops || !m->mx_ops->ac_add)
1774 return false;
1775
1776 return m->mx_ops->ac_add(a, m) && account_mailbox_add(a, m);
1777}
bool account_mailbox_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account.
Definition: account.c:66
bool(* ac_add)(struct Account *a, struct Mailbox *m)
Definition: mxapi.h:145
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mx_ac_remove()

int mx_ac_remove ( struct Mailbox m,
bool  keep_account 
)

Remove a Mailbox from an Account and delete Account if empty.

Parameters
mMailbox to remove
keep_accountMake sure not to remove the mailbox's account
Return values
0Success
-1Error
Note
The mailbox is NOT free'd

Definition at line 1788 of file mx.c.

1789{
1790 if (!m || !m->account)
1791 return -1;
1792
1793 struct Account *a = m->account;
1795 if (!keep_account && STAILQ_EMPTY(&a->mailboxes))
1796 {
1798 }
1799 return 0;
1800}
bool neomutt_account_remove(struct NeoMutt *n, const struct Account *a)
Remove an Account from the global list.
Definition: neomutt.c:106
#define STAILQ_EMPTY(head)
Definition: queue.h:348
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mx_access()

int mx_access ( const char *  path,
int  flags 
)

Wrapper for access, checks permissions on a given mailbox.

Parameters
pathPath of mailbox
flagsFlags, e.g. W_OK
Return values
0Success, allowed
<0Failure, not allowed

We may be interested in using ACL-style flags at some point, currently we use the normal access() flags.

Definition at line 183 of file mx.c.

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}
int imap_access(const char *path)
Check permissions on an IMAP mailbox with a new connection.
Definition: imap.c:479
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mx_alloc_memory()

void mx_alloc_memory ( struct Mailbox m)

Create storage for the emails.

Parameters
mMailbox

Definition at line 1226 of file mx.c.

1227{
1228 const int grow = 25;
1229 size_t s = MAX(sizeof(struct Email *), sizeof(int));
1230
1231 if (((m->email_max + grow) * s) < (m->email_max * s))
1232 {
1233 mutt_error(_("Out of memory"));
1234 mutt_exit(1);
1235 }
1236
1237 m->email_max += grow;
1238 if (m->emails)
1239 {
1240 mutt_mem_realloc(&m->emails, m->email_max * sizeof(struct Email *));
1241 mutt_mem_realloc(&m->v2r, m->email_max * sizeof(int));
1242 }
1243 else
1244 {
1245 m->emails = mutt_mem_calloc(m->email_max, sizeof(struct Email *));
1246 m->v2r = mutt_mem_calloc(m->email_max, sizeof(int));
1247 }
1248 for (int i = m->email_max - grow; i < m->email_max; i++)
1249 {
1250 if (i < m->email_max)
1251 {
1252 m->emails[i] = NULL;
1253 m->v2r[i] = -1;
1254 }
1255 }
1256}
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:243
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
#define MAX(a, b)
Definition: memory.h:30
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:98
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mx_path_is_empty()

int mx_path_is_empty ( const char *  path)

Is the mailbox empty.

Parameters
pathMailbox to check
Return values
1Mailbox is empty
0Mailbox contains mail
-1Error

Definition at line 1265 of file mx.c.

1266{
1267 if (!path || (*path == '\0'))
1268 return -1;
1269
1270 enum MailboxType type = mx_path_probe(path);
1271 const struct MxOps *ops = mx_get_ops(type);
1272 if (!ops || !ops->path_is_empty)
1273 return -1;
1274
1275 return ops->path_is_empty(path);
1276}
int(* path_is_empty)(const char *path)
Definition: mxapi.h:414
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mx_fastclose_mailbox()

void mx_fastclose_mailbox ( struct Mailbox m,
bool  keep_account 
)

Free up memory associated with the Mailbox.

Parameters
mMailbox
keep_accountMake sure not to remove the mailbox's account

Definition at line 431 of file mx.c.

432{
433 if (!m)
434 return;
435
436 m->opened--;
437 if (m->opened != 0)
438 return;
439
440 /* never announce that a mailbox we've just left has new mail.
441 * TODO: really belongs in mx_mbox_close, but this is a nice hook point */
442 if (!m->peekonly)
444
445 if (m->mx_ops)
446 m->mx_ops->mbox_close(m);
447
451
452 if (m->emails)
453 {
454 for (int i = 0; i < m->msg_count; i++)
455 {
456 if (!m->emails[i])
457 break;
458 email_free(&m->emails[i]);
459 }
460 }
461
462 if (!m->visible)
463 {
464 mx_ac_remove(m, keep_account);
465 }
466}
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:457
void mutt_mailbox_set_notified(struct Mailbox *m)
Note when the user was last notified of new mail.
Definition: mutt_mailbox.c:312
int mx_ac_remove(struct Mailbox *m, bool keep_account)
Remove a Mailbox from an Account and delete Account if empty.
Definition: mx.c:1788
struct HashTable * subj_hash
Hash Table by subject.
Definition: mailbox.h:124
struct HashTable * id_hash
Hash Table by msg id.
Definition: mailbox.h:123
struct HashTable * label_hash
Hash Table for x-labels.
Definition: mailbox.h:125
bool visible
True if a result of "mailboxes".
Definition: mailbox.h:130
enum MxStatus(* mbox_close)(struct Mailbox *m)
Definition: mxapi.h:220
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mx_get_ops()

const struct MxOps * mx_get_ops ( enum MailboxType  type)

Get mailbox operations.

Parameters
typeMailbox type
Return values
ptrMailbox function
NULLError

Definition at line 140 of file mx.c.

141{
142 for (const struct MxOps **ops = MxOps; *ops; ops++)
143 if ((*ops)->type == type)
144 return *ops;
145
146 return NULL;
147}
+ Here is the caller graph for this function:

◆ mx_tags_is_supported()

bool mx_tags_is_supported ( struct Mailbox m)

Return true if mailbox support tagging.

Parameters
mMailbox
Return values
trueTagging is supported

Definition at line 1324 of file mx.c.

1325{
1326 return m && m->mx_ops->tags_commit && m->mx_ops->tags_edit;
1327}
+ Here is the caller graph for this function:

◆ mx_toggle_write()

int mx_toggle_write ( struct Mailbox m)

Toggle the mailbox's readonly flag.

Parameters
mMailbox
Return values
0Success
-1Error

Definition at line 1855 of file mx.c.

1856{
1857 if (!m)
1858 return -1;
1859
1860 if (m->readonly)
1861 {
1862 mutt_error(_("Can't toggle write on a readonly mailbox"));
1863 return -1;
1864 }
1865
1866 if (m->dontwrite)
1867 {
1868 m->dontwrite = false;
1869 mutt_message(_("Changes to folder will be written on folder exit"));
1870 }
1871 else
1872 {
1873 m->dontwrite = true;
1874 mutt_message(_("Changes to folder will not be written"));
1875 }
1876
1877 struct EventMailbox ev_m = { m };
1879 return 0;
1880}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ mx_ops

const struct MxOps* mx_ops[]
extern

◆ MboxTypeDef

struct EnumDef MboxTypeDef
extern

Definition at line 97 of file mx.c.