NeoMutt  2023-11-03-85-g512e01
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
mx.h File Reference

API for mailboxes. More...

#include <stdbool.h>
#include <stdint.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.
 
#define MUTT_ADD_FROM   (1 << 0)
 add a From_ line
 
#define MUTT_SET_DRAFT   (1 << 1)
 set the message draft flag
 

Typedefs

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

Functions

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

Variables

const struct EnumDef MboxTypeDef
 Data for the $mbox_type enumeration.
 

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 39 of file mx.h.

◆ MUTT_ADD_FROM

#define MUTT_ADD_FROM   (1 << 0)

add a From_ line

Definition at line 40 of file mx.h.

◆ MUTT_SET_DRAFT

#define MUTT_SET_DRAFT   (1 << 1)

set the message draft flag

Definition at line 41 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 38 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 1099 of file mx.c.

1100{
1101 if (!m || !m->mx_ops)
1102 return MX_STATUS_ERROR;
1103
1104 const short c_mail_check = cs_subset_number(NeoMutt->sub, "mail_check");
1105
1106 time_t t = mutt_date_now();
1107 if ((t - MailboxTime) < c_mail_check)
1108 return MX_STATUS_OK;
1109
1110 MailboxTime = t;
1111
1112 enum MxStatus rc = m->mx_ops->mbox_check(m);
1113 if ((rc == MX_STATUS_NEW_MAIL) || (rc == MX_STATUS_REOPENED))
1114 {
1116 }
1117
1118 return rc;
1119}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:144
void mailbox_changed(struct Mailbox *m, enum NotifyMailbox action)
Notify observers of a change to a Mailbox.
Definition: mailbox.c:226
@ NT_MAILBOX_INVALID
Email list was changed.
Definition: mailbox.h:176
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:446
static time_t MailboxTime
last time we started checking for mail
Definition: mx.c:74
MxStatus
Return values from mbox_check(), mbox_check_stats(), mbox_snc(), and mbox_close()
Definition: mxapi.h:63
@ MX_STATUS_ERROR
An error occurred.
Definition: mxapi.h:64
@ MX_STATUS_OK
No changes.
Definition: mxapi.h:65
@ MX_STATUS_REOPENED
Mailbox was reopened.
Definition: mxapi.h:68
@ MX_STATUS_NEW_MAIL
New mail received in Mailbox.
Definition: mxapi.h:66
const struct MxOps * mx_ops
MXAPI callback functions.
Definition: mailbox.h:106
enum MxStatus(* mbox_check)(struct Mailbox *m)
Definition: mxapi.h:162
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
+ 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 1775 of file mx.c.

1776{
1777 if (!m)
1778 return MX_STATUS_ERROR;
1779
1780 enum MxStatus rc = m->mx_ops->mbox_check_stats(m, flags);
1781 if (rc != MX_STATUS_ERROR)
1782 {
1783 struct EventMailbox ev_m = { m };
1785 }
1786
1787 return rc;
1788}
@ NT_MAILBOX_CHANGE
Mailbox has been changed.
Definition: mailbox.h:172
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
@ NT_MAILBOX
Mailbox has changed, NotifyMailbox, EventMailbox.
Definition: notify_type.h:49
An Event that happened to a Mailbox.
Definition: mailbox.h:186
struct Notify * notify
Notifications: NotifyMailbox, EventMailbox.
Definition: mailbox.h:144
enum MxStatus(* mbox_check_stats)(struct Mailbox *m, CheckStatsFlags flags)
Definition: mxapi.h:175
+ 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 593 of file mx.c.

594{
595 if (!m)
596 return MX_STATUS_ERROR;
597
598 const bool c_mail_check_recent = cs_subset_bool(NeoMutt->sub, "mail_check_recent");
599 if (c_mail_check_recent && !m->peekonly)
600 m->has_new = false;
601
602 if (m->readonly || m->dontwrite || m->append || m->peekonly)
603 {
604 mx_fastclose_mailbox(m, false);
605 return 0;
606 }
607
608 int i, read_msgs = 0;
609 enum MxStatus rc = MX_STATUS_ERROR;
610 enum QuadOption move_messages = MUTT_NO;
611 enum QuadOption purge = MUTT_YES;
612 struct Buffer *mbox = NULL;
613 struct Buffer *buf = buf_pool_get();
614
615 if ((m->msg_unread != 0) && (m->type == MUTT_NNTP))
616 {
617 struct NntpMboxData *mdata = m->mdata;
618
619 if (mdata && mdata->adata && mdata->group)
620 {
621 enum QuadOption ans = query_quadoption(_("Mark all articles read?"),
622 NeoMutt->sub, "catchup_newsgroup");
623 if (ans == MUTT_ABORT)
624 goto cleanup;
625 if (ans == MUTT_YES)
626 mutt_newsgroup_catchup(m, mdata->adata, mdata->group);
627 }
628 }
629
630 const bool c_keep_flagged = cs_subset_bool(NeoMutt->sub, "keep_flagged");
631 for (i = 0; i < m->msg_count; i++)
632 {
633 struct Email *e = m->emails[i];
634 if (!e)
635 break;
636
637 if (!e->deleted && e->read && !(e->flagged && c_keep_flagged))
638 read_msgs++;
639 }
640
641 /* don't need to move articles from newsgroup */
642 if (m->type == MUTT_NNTP)
643 read_msgs = 0;
644
645 const enum QuadOption c_move = cs_subset_quad(NeoMutt->sub, "move");
646 if ((read_msgs != 0) && (c_move != MUTT_NO))
647 {
648 bool is_spool;
649 mbox = buf_pool_get();
650
652 if (p)
653 {
654 is_spool = true;
655 buf_strcpy(mbox, p);
656 }
657 else
658 {
659 const char *const c_mbox = cs_subset_string(NeoMutt->sub, "mbox");
660 buf_strcpy(mbox, c_mbox);
661 is_spool = mutt_is_spool(mailbox_path(m)) && !mutt_is_spool(buf_string(mbox));
662 }
663
664 if (is_spool && !buf_is_empty(mbox))
665 {
666 buf_expand_path(mbox);
667 buf_printf(buf,
668 /* L10N: The first argument is the number of read messages to be
669 moved, the second argument is the target mailbox. */
670 ngettext("Move %d read message to %s?", "Move %d read messages to %s?", read_msgs),
671 read_msgs, buf_string(mbox));
672 move_messages = query_quadoption(buf_string(buf), NeoMutt->sub, "move");
673 if (move_messages == MUTT_ABORT)
674 goto cleanup;
675 }
676 }
677
678 /* There is no point in asking whether or not to purge if we are
679 * just marking messages as "trash". */
680 const bool c_maildir_trash = cs_subset_bool(NeoMutt->sub, "maildir_trash");
681 if ((m->msg_deleted != 0) && !((m->type == MUTT_MAILDIR) && c_maildir_trash))
682 {
683 buf_printf(buf, ngettext("Purge %d deleted message?", "Purge %d deleted messages?", m->msg_deleted),
684 m->msg_deleted);
685 purge = query_quadoption(buf_string(buf), NeoMutt->sub, "delete");
686 if (purge == MUTT_ABORT)
687 goto cleanup;
688 }
689
690 const bool c_mark_old = cs_subset_bool(NeoMutt->sub, "mark_old");
691 if (c_mark_old && !m->peekonly)
692 {
693 for (i = 0; i < m->msg_count; i++)
694 {
695 struct Email *e = m->emails[i];
696 if (!e)
697 break;
698 if (!e->deleted && !e->old && !e->read)
699 mutt_set_flag(m, e, MUTT_OLD, true, true);
700 }
701 }
702
703 if (move_messages)
704 {
705 if (m->verbose)
706 mutt_message(_("Moving read messages to %s..."), buf_string(mbox));
707
708 /* try to use server-side copy first */
709 i = 1;
710
711 if ((m->type == MUTT_IMAP) && (imap_path_probe(buf_string(mbox), NULL) == MUTT_IMAP))
712 {
713 /* add messages for moving, and clear old tags, if any */
714 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
715 for (i = 0; i < m->msg_count; i++)
716 {
717 struct Email *e = m->emails[i];
718 if (!e)
719 break;
720
721 if (e->read && !e->deleted && !(e->flagged && c_keep_flagged))
722 {
723 e->tagged = true;
724 ARRAY_ADD(&ea, e);
725 }
726 else
727 {
728 e->tagged = false;
729 }
730 }
731
732 i = imap_copy_messages(m, &ea, buf_string(mbox), SAVE_MOVE);
733 if (i == 0)
734 {
735 const bool c_delete_untag = cs_subset_bool(NeoMutt->sub, "delete_untag");
736 if (c_delete_untag)
737 {
738 struct Email **ep = NULL;
739 ARRAY_FOREACH(ep, &ea)
740 {
741 mutt_set_flag(m, *ep, MUTT_TAG, false, true);
742 }
743 }
744 }
745 ARRAY_FREE(&ea);
746 }
747
748 if (i == 0) /* success */
749 {
751 }
752 else if (i == -1) /* horrible error, bail */
753 {
754 goto cleanup;
755 }
756 else /* use regular append-copy mode */
757 {
758 struct Mailbox *m_read = mx_path_resolve(buf_string(mbox));
759 if (!mx_mbox_open(m_read, MUTT_APPEND))
760 {
761 mailbox_free(&m_read);
762 goto cleanup;
763 }
764
765 for (i = 0; i < m->msg_count; i++)
766 {
767 struct Email *e = m->emails[i];
768 if (!e)
769 break;
770 if (e->read && !e->deleted && !(e->flagged && c_keep_flagged))
771 {
772 if (mutt_append_message(m_read, m, e, NULL, MUTT_CM_NO_FLAGS, CH_UPDATE_LEN) == 0)
773 {
774 mutt_set_flag(m, e, MUTT_DELETE, true, true);
775 mutt_set_flag(m, e, MUTT_PURGE, true, true);
776 }
777 else
778 {
779 mx_mbox_close(m_read);
780 goto cleanup;
781 }
782 }
783 }
784
785 mx_mbox_close(m_read);
786 }
787 }
788 else if (!m->changed && (m->msg_deleted == 0))
789 {
790 if (m->verbose)
791 mutt_message(_("Mailbox is unchanged"));
792 if ((m->type == MUTT_MBOX) || (m->type == MUTT_MMDF))
793 mbox_reset_atime(m, NULL);
794 mx_fastclose_mailbox(m, false);
795 rc = MX_STATUS_OK;
796 goto cleanup;
797 }
798
799 /* copy mails to the trash before expunging */
800 const char *const c_trash = cs_subset_string(NeoMutt->sub, "trash");
801 const struct Mailbox *m_trash = mx_mbox_find(m->account, c_trash);
802 if (purge && (m->msg_deleted != 0) && (m != m_trash))
803 {
804 if (trash_append(m) != 0)
805 goto cleanup;
806 }
807
808 /* allow IMAP to preserve the deleted flag across sessions */
809 if (m->type == MUTT_IMAP)
810 {
811 const enum MxStatus check = imap_sync_mailbox(m, (purge != MUTT_NO), true);
812 if (check == MX_STATUS_ERROR)
813 {
814 rc = check;
815 goto cleanup;
816 }
817 }
818 else
819 {
820 if (purge == MUTT_NO)
821 {
822 for (i = 0; i < m->msg_count; i++)
823 {
824 struct Email *e = m->emails[i];
825 if (!e)
826 break;
827
828 e->deleted = false;
829 e->purge = false;
830 }
831 m->msg_deleted = 0;
832 }
833
834 if (m->changed || (m->msg_deleted != 0))
835 {
836 enum MxStatus check = sync_mailbox(m);
837 if (check != MX_STATUS_OK)
838 {
839 rc = check;
840 goto cleanup;
841 }
842 }
843 }
844
845 if (m->verbose)
846 {
847 if (move_messages)
848 {
849 mutt_message(_("%d kept, %d moved, %d deleted"),
850 m->msg_count - m->msg_deleted, read_msgs, m->msg_deleted);
851 }
852 else
853 {
854 mutt_message(_("%d kept, %d deleted"), m->msg_count - m->msg_deleted, m->msg_deleted);
855 }
856 }
857
858 const bool c_save_empty = cs_subset_bool(NeoMutt->sub, "save_empty");
859 if ((m->msg_count == m->msg_deleted) &&
860 ((m->type == MUTT_MMDF) || (m->type == MUTT_MBOX)) &&
861 !mutt_is_spool(mailbox_path(m)) && !c_save_empty)
862 {
864 }
865
866 if ((purge == MUTT_YES) && (m->msg_deleted != 0))
867 {
868 for (i = 0; i < m->msg_count; i++)
869 {
870 struct Email *e = m->emails[i];
871 if (!e)
872 break;
873 if (e->deleted && !e->read)
874 {
875 m->msg_unread--;
876 if (!e->old)
877 m->msg_new--;
878 }
879 if (e->deleted && e->flagged)
880 m->msg_flagged--;
881 }
882 }
883
884 mx_fastclose_mailbox(m, false);
885
886 rc = MX_STATUS_OK;
887
888cleanup:
889 buf_pool_release(&mbox);
890 buf_pool_release(&buf);
891 return rc;
892}
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition: array.h:155
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:211
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:203
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition: array.h:57
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:173
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:303
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:407
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:93
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition: helpers.c:193
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
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:959
#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
@ 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:1376
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:53
#define mutt_message(...)
Definition: logging2.h:91
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Definition: imap.c:2327
char * mutt_find_hook(HookFlags type, const char *pat)
Find a matching hook.
Definition: hook.c:645
#define MUTT_MBOX_HOOK
mbox-hook: move messages after reading them
Definition: hook.h:38
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:1676
enum MxStatus imap_sync_mailbox(struct Mailbox *m, bool expunge, bool close)
Sync all the changes to the server.
Definition: imap.c:1458
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:90
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:210
@ 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:744
#define _(a)
Definition: message.h:28
@ MUTT_OLD
Old messages.
Definition: mutt.h:70
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition: mutt.h:76
@ MUTT_TAG
Tagged messages.
Definition: mutt.h:79
@ MUTT_DELETE
Messages to be deleted.
Definition: mutt.h:74
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:73
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:329
static enum MxStatus sync_mailbox(struct Mailbox *m)
Save changes to disk.
Definition: mx.c:452
static int trash_append(struct Mailbox *m)
Move deleted mails to the trash folder.
Definition: mx.c:483
void mx_fastclose_mailbox(struct Mailbox *m, bool keep_account)
Free up memory associated with the Mailbox.
Definition: mx.c:410
static bool mutt_is_spool(const char *str)
Is this the spool_file?
Definition: mx.c:137
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:284
struct Mailbox * mx_mbox_find(struct Account *a, const char *path)
Find a Mailbox on an Account.
Definition: mx.c:1559
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1652
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
Definition: mx.c:593
#define MUTT_APPEND
Open mailbox for appending messages.
Definition: mxapi.h:42
struct NntpMboxData * mutt_newsgroup_catchup(struct Mailbox *m, struct NntpAccountData *adata, char *group)
Catchup newsgroup.
Definition: newsrc.c:1300
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
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(const char *prompt, struct ConfigSubset *sub, const char *name)
Ask the user a quad-question.
Definition: question.c:369
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:108
A mailbox.
Definition: mailbox.h:79
bool changed
Mailbox has been modified.
Definition: mailbox.h:109
bool has_new
Mailbox has new mail.
Definition: mailbox.h:85
bool append
Mailbox is opened in append mode.
Definition: mailbox.h:108
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:131
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:126
bool dontwrite
Don't write the mailbox on close.
Definition: mailbox.h:110
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:116
int msg_unread
Number of unread messages.
Definition: mailbox.h:89
NNTP-specific Mailbox data -.
Definition: mdata.h:34
+ 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 284 of file mx.c.

285{
286 if (!m)
287 return false;
288
289 if ((m->type == MUTT_UNKNOWN) && (flags & (MUTT_NEWFOLDER | MUTT_APPEND)))
290 {
291 m->type = cs_subset_enum(NeoMutt->sub, "mbox_type");
292 m->mx_ops = mx_get_ops(m->type);
293 }
294
295 const bool newly_linked_account = !m->account;
296 if (newly_linked_account)
297 {
298 if (!mx_mbox_ac_link(m))
299 {
300 return false;
301 }
302 }
303
304 m->verbose = !(flags & MUTT_QUIET);
305 m->readonly = (flags & MUTT_READONLY);
306 m->peekonly = (flags & MUTT_PEEK);
307
308 if (flags & (MUTT_APPEND | MUTT_NEWFOLDER))
309 {
310 if (!mx_open_mailbox_append(m, flags))
311 {
312 goto error;
313 }
314 return true;
315 }
316
317 if (m->opened > 0)
318 {
319 m->opened++;
320 return true;
321 }
322
323 m->size = 0;
324 m->msg_unread = 0;
325 m->msg_flagged = 0;
326 m->rights = MUTT_ACL_ALL;
327
328 if (m->type == MUTT_UNKNOWN)
329 {
331 m->mx_ops = mx_get_ops(m->type);
332 }
333
334 if ((m->type == MUTT_UNKNOWN) || (m->type == MUTT_MAILBOX_ERROR) || !m->mx_ops)
335 {
336 if (m->type == MUTT_MAILBOX_ERROR)
337 mutt_perror("%s", mailbox_path(m));
338 else if ((m->type == MUTT_UNKNOWN) || !m->mx_ops)
339 mutt_error(_("%s is not a mailbox"), mailbox_path(m));
340 goto error;
341 }
342
344
345 /* if the user has a 'push' command in their .neomuttrc, or in a folder-hook,
346 * it will cause the progress messages not to be displayed because
347 * mutt_refresh() will think we are in the middle of a macro. so set a
348 * flag to indicate that we should really refresh the screen. */
349 OptForceRefresh = true;
350
351 if (m->verbose)
352 mutt_message(_("Reading %s..."), mailbox_path(m));
353
354 // Clear out any existing emails
355 for (int i = 0; i < m->email_max; i++)
356 {
357 email_free(&m->emails[i]);
358 }
359
360 m->msg_count = 0;
361 m->msg_unread = 0;
362 m->msg_flagged = 0;
363 m->msg_new = 0;
364 m->msg_deleted = 0;
365 m->msg_tagged = 0;
366 m->vcount = 0;
367
368 enum MxOpenReturns rc = m->mx_ops->mbox_open(m);
369 m->opened++;
370
371 if ((rc == MX_OPEN_OK) || (rc == MX_OPEN_ABORT))
372 {
373 if ((flags & MUTT_NOSORT) == 0)
374 {
375 /* avoid unnecessary work since the mailbox is completely unthreaded
376 * to begin with */
377 OptSortSubthreads = false;
378 OptNeedRescore = false;
379 }
380 if (m->verbose)
382 if (rc == MX_OPEN_ABORT)
383 {
384 mutt_error(_("Reading from %s interrupted..."), mailbox_path(m));
385 }
386 }
387 else
388 {
389 goto error;
390 }
391
392 if (!m->peekonly)
393 m->has_new = false;
394 OptForceRefresh = false;
395
396 return true;
397
398error:
399 mx_fastclose_mailbox(m, newly_linked_account);
400 if (newly_linked_account)
402 return false;
403}
bool account_mailbox_remove(struct Account *a, struct Mailbox *m)
Remove a Mailbox from an Account.
Definition: account.c:97
unsigned char cs_subset_enum(const struct ConfigSubset *sub, const char *name)
Get a enumeration config item by name.
Definition: helpers.c:72
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:73
bool OptForceRefresh
(pseudo) refresh even during macros
Definition: globals.c:70
bool OptSortSubthreads
(pseudo) used when $sort_aux changes
Definition: globals.c:80
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_perror(...)
Definition: logging2.h:93
#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:417
const struct MxOps * mx_get_ops(enum MailboxType type)
Get mailbox operations.
Definition: mx.c:123
bool mx_mbox_ac_link(struct Mailbox *m)
Link a Mailbox to an existing or new Account.
Definition: mx.c:247
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1326
static bool mx_open_mailbox_append(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox for appending.
Definition: mx.c:181
#define MUTT_READONLY
Open in read-only mode.
Definition: mxapi.h:43
#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:45
#define MUTT_QUIET
Do not print any messages.
Definition: mxapi.h:44
MxOpenReturns
Return values for mbox_open()
Definition: mxapi.h:76
@ MX_OPEN_ABORT
Open was aborted.
Definition: mxapi.h:79
@ MX_OPEN_OK
Open succeeded.
Definition: mxapi.h:77
#define MUTT_PEEK
Revert atime back after taking a look (if applicable)
Definition: mxapi.h:48
#define MUTT_NOSORT
Do not sort the mailbox after opening it.
Definition: mxapi.h:41
int vcount
The number of virtual messages.
Definition: mailbox.h:99
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:118
int email_max
Size of emails array.
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:127
int msg_tagged
How many messages are tagged?
Definition: mailbox.h:94
enum MxOpenReturns(* mbox_open)(struct Mailbox *m)
Definition: mxapi.h:136
+ 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 901 of file mx.c.

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

Close a message.

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

Definition at line 1185 of file mx.c.

1186{
1187 if (!m || !ptr || !*ptr)
1188 return 0;
1189
1190 int rc = 0;
1191 struct Message *msg = *ptr;
1192
1193 if (m->mx_ops && m->mx_ops->msg_close)
1194 rc = m->mx_ops->msg_close(m, msg);
1195
1196 if (msg->path)
1197 {
1198 mutt_debug(LL_DEBUG1, "unlinking %s\n", msg->path);
1199 unlink(msg->path);
1200 }
1201
1202 message_free(ptr);
1203 return rc;
1204}
void message_free(struct Message **ptr)
Free a Message.
Definition: message.c:37
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
A local copy of an email.
Definition: message.h:34
char * path
path to temp file
Definition: message.h:36
int(* msg_close)(struct Mailbox *m, struct Message *msg)
Definition: mxapi.h:262
+ Here is the call graph for this function:
+ 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 1164 of file mx.c.

1165{
1166 if (!m || !m->mx_ops || !m->mx_ops->msg_commit || !msg)
1167 return -1;
1168
1169 if (!(msg->write && m->append))
1170 {
1171 mutt_debug(LL_DEBUG1, "msg->write = %d, m->append = %d\n", msg->write, m->append);
1172 return -1;
1173 }
1174
1175 return m->mx_ops->msg_commit(m, msg);
1176}
bool write
nonzero if message is open for writing
Definition: message.h:38
int(* msg_commit)(struct Mailbox *m, struct Message *msg)
Definition: mxapi.h:247
+ 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 1034 of file mx.c.

1035{
1036 if (!m)
1037 return NULL;
1038
1039 struct Address *p = NULL;
1040 struct Message *msg = NULL;
1041
1042 if (!m->mx_ops || !m->mx_ops->msg_open_new)
1043 {
1044 mutt_debug(LL_DEBUG1, "function unimplemented for mailbox type %d\n", m->type);
1045 return NULL;
1046 }
1047
1048 msg = mutt_mem_calloc(1, sizeof(struct Message));
1049 msg->write = true;
1050
1051 if (e)
1052 {
1053 msg->flags.flagged = e->flagged;
1054 msg->flags.replied = e->replied;
1055 msg->flags.read = e->read;
1056 msg->flags.draft = (flags & MUTT_SET_DRAFT);
1057 msg->received = e->received;
1058 }
1059
1060 if (msg->received == 0)
1061 msg->received = mutt_date_now();
1062
1063 if (m->mx_ops->msg_open_new(m, msg, e))
1064 {
1065 if (m->type == MUTT_MMDF)
1066 fputs(MMDF_SEP, msg->fp);
1067
1068 if (((m->type == MUTT_MBOX) || (m->type == MUTT_MMDF)) && (flags & MUTT_ADD_FROM))
1069 {
1070 if (e)
1071 {
1072 p = TAILQ_FIRST(&e->env->return_path);
1073 if (!p)
1074 p = TAILQ_FIRST(&e->env->sender);
1075 if (!p)
1076 p = TAILQ_FIRST(&e->env->from);
1077 }
1078
1079 // Use C locale for the date, so that day/month names are in English
1080 char buf[64] = { 0 };
1081 mutt_date_localtime_format_locale(buf, sizeof(buf), "%a %b %e %H:%M:%S %Y",
1083 fprintf(msg->fp, "From %s %s\n", p ? buf_string(p->mailbox) : NONULL(Username), buf);
1084 }
1085 }
1086 else
1087 {
1088 FREE(&msg);
1089 }
1090
1091 return msg;
1092}
char * Username
User's login name.
Definition: globals.c:42
#define MMDF_SEP
Definition: lib.h:62
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define FREE(x)
Definition: memory.h:45
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:942
#define MUTT_ADD_FROM
add a From_ line
Definition: mx.h:40
#define MUTT_SET_DRAFT
set the message draft flag
Definition: mx.h:41
#define TAILQ_FIRST(head)
Definition: queue.h:723
#define NONULL(x)
Definition: string2.h:37
An email address.
Definition: address.h:36
struct Buffer * 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
FILE * fp
pointer to the message data
Definition: message.h:35
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 flagged
Message is flagged.
Definition: message.h:42
bool read
Message has been read.
Definition: message.h:41
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:232
locale_t time_c_locale
Current locale but LC_TIME=C.
Definition: neomutt.h:47
+ 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,
struct Email e 
)

Return a stream pointer for a message.

Parameters
mMailbox
eEmail
Return values
ptrMessage
NULLError

Definition at line 1139 of file mx.c.

1140{
1141 if (!m || !e)
1142 return NULL;
1143
1144 if (!m->mx_ops || !m->mx_ops->msg_open)
1145 {
1146 mutt_debug(LL_DEBUG1, "function not implemented for mailbox type %d\n", m->type);
1147 return NULL;
1148 }
1149
1150 struct Message *msg = message_new();
1151 if (!m->mx_ops->msg_open(m, msg, e))
1152 message_free(&msg);
1153
1154 return msg;
1155}
struct Message * message_new(void)
Create a new Message.
Definition: message.c:53
bool(* msg_open)(struct Mailbox *m, struct Message *msg, struct Email *e)
Definition: mxapi.h:216
+ 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 1521 of file mx.c.

1522{
1523 if (!m || !m->mx_ops || !m->mx_ops->msg_padding_size)
1524 return 0;
1525
1526 return m->mx_ops->msg_padding_size(m);
1527}
int(* msg_padding_size)(struct Mailbox *m)
Definition: mxapi.h:274
+ 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 1799 of file mx.c.

1800{
1801 if (!m || !m->mx_ops || !m->mx_ops->msg_save_hcache || !e)
1802 return 0;
1803
1804 return m->mx_ops->msg_save_hcache(m, e);
1805}
int(* msg_save_hcache)(struct Mailbox *m, struct Email *e)
Definition: mxapi.h:289
+ Here is the caller graph for this function:

◆ mx_path_canon()

int mx_path_canon ( struct Buffer path,
const char *  folder,
enum MailboxType type 
)

Canonicalise a mailbox path - Wrapper for MxOps::path_canon()

Definition at line 1372 of file mx.c.

1373{
1374 if (buf_is_empty(path))
1375 return -1;
1376
1377 for (size_t i = 0; i < 3; i++)
1378 {
1379 /* Look for !! ! - < > or ^ followed by / or NUL */
1380 if ((buf_at(path, 0) == '!') && (buf_at(path, 1) == '!'))
1381 {
1382 if (((buf_at(path, 2) == '/') || (buf_at(path, 2) == '\0')))
1383 {
1384 mutt_str_inline_replace(path->data, path->dsize, 2, LastFolder);
1385 }
1386 }
1387 else if ((buf_at(path, 0) == '+') || (buf_at(path, 0) == '='))
1388 {
1389 size_t folder_len = mutt_str_len(folder);
1390 if ((folder_len > 0) && (folder[folder_len - 1] != '/'))
1391 {
1392 path->data[0] = '/';
1393 mutt_str_inline_replace(path->data, path->dsize, 0, folder);
1394 }
1395 else
1396 {
1397 mutt_str_inline_replace(path->data, path->dsize, 1, folder);
1398 }
1399 }
1400 else if ((buf_at(path, 1) == '/') || (buf_at(path, 1) == '\0'))
1401 {
1402 if (buf_at(path, 0) == '!')
1403 {
1404 const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
1405 mutt_str_inline_replace(path->data, path->dsize, 1, c_spool_file);
1406 }
1407 else if (buf_at(path, 0) == '-')
1408 {
1409 mutt_str_inline_replace(path->data, path->dsize, 1, LastFolder);
1410 }
1411 else if (buf_at(path, 0) == '<')
1412 {
1413 const char *const c_record = cs_subset_string(NeoMutt->sub, "record");
1414 mutt_str_inline_replace(path->data, path->dsize, 1, c_record);
1415 }
1416 else if (buf_at(path, 0) == '>')
1417 {
1418 const char *const c_mbox = cs_subset_string(NeoMutt->sub, "mbox");
1419 mutt_str_inline_replace(path->data, path->dsize, 1, c_mbox);
1420 }
1421 else if (buf_at(path, 0) == '^')
1422 {
1424 }
1425 else if (buf_at(path, 0) == '~')
1426 {
1427 mutt_str_inline_replace(path->data, path->dsize, 1, HomeDir);
1428 }
1429 }
1430 else if (buf_at(path, 0) == '@')
1431 {
1432 /* elm compatibility, @ expands alias to user name */
1433 struct AddressList *al = alias_lookup(buf_string(path));
1434 if (!al || TAILQ_EMPTY(al))
1435 break;
1436
1437 struct Email *e = email_new();
1438 e->env = mutt_env_new();
1439 mutt_addrlist_copy(&e->env->from, al, false);
1440 mutt_addrlist_copy(&e->env->to, al, false);
1442 email_free(&e);
1443 break;
1444 }
1445 else
1446 {
1447 break;
1448 }
1449 }
1450
1451 // if (!folder) //XXX - use inherited version, or pass NULL to backend?
1452 // return -1;
1453
1455 if (type)
1456 *type = type2;
1457 const struct MxOps *ops = mx_get_ops(type2);
1458 if (!ops || !ops->path_canon)
1459 return -1;
1460
1461 if (ops->path_canon(path) < 0)
1462 {
1463 mutt_path_canon(path, HomeDir, true);
1464 }
1465
1466 return 0;
1467}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:762
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:280
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
Definition: buffer.c:638
char * HomeDir
User's home directory.
Definition: globals.c:39
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:45
char * CurrentFolder
Currently selected mailbox.
Definition: globals.c:44
void mutt_default_save(struct Buffer *path, struct Email *e)
Find the default save path for an email.
Definition: hook.c:744
MailboxType
Supported mailbox formats.
Definition: mailbox.h:41
bool mutt_path_canon(struct Buffer *path, const char *homedir, bool is_dir)
Create the canonical version of a path.
Definition: path.c:244
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:940
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:568
#define TAILQ_EMPTY(head)
Definition: queue.h:721
size_t dsize
Length of data.
Definition: buffer.h:37
char * data
Pointer to data.
Definition: buffer.h:35
char * path
Path of Email (for local Mailboxes)
Definition: email.h:68
struct AddressList to
Email's 'To' list.
Definition: envelope.h:60
Definition: mxapi.h:91
int(* path_canon)(struct Buffer *path)
Definition: mxapi.h:349
+ 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 1476 of file mx.c.

1477{
1478 if (!m)
1479 return -1;
1480
1481 struct Buffer *path = buf_pool_get();
1482
1483 if (m->realpath)
1484 buf_strcpy(path, m->realpath);
1485 else
1486 buf_strcpy(path, mailbox_path(m));
1487
1488 int rc = mx_path_canon(path, folder, &m->type);
1489
1491 buf_pool_release(&path);
1492
1493 if (rc >= 0)
1494 {
1495 m->mx_ops = mx_get_ops(m->type);
1496 buf_strcpy(&m->pathbuf, m->realpath);
1497 }
1498
1499 return rc;
1500}
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:327
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:1372
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 ( struct Buffer path)

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

Definition at line 1505 of file mx.c.

1506{
1507 if (buf_is_empty(path))
1508 return -1;
1509
1510 return 0;
1511}
+ 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
enumMailboxType, e.g. MUTT_IMAP

Definition at line 1326 of file mx.c.

1327{
1328 if (!path)
1329 return MUTT_UNKNOWN;
1330
1331 enum MailboxType rc = MUTT_UNKNOWN;
1332
1333 // First, search the non-local Mailbox types (is_local == false)
1334 for (const struct MxOps **ops = MxOps; *ops; ops++)
1335 {
1336 if ((*ops)->is_local)
1337 continue;
1338 rc = (*ops)->path_probe(path, NULL);
1339 if (rc != MUTT_UNKNOWN)
1340 return rc;
1341 }
1342
1343 struct stat st = { 0 };
1344 if (stat(path, &st) != 0)
1345 {
1346 mutt_debug(LL_DEBUG1, "unable to stat %s: %s (errno %d)\n", path, strerror(errno), errno);
1347 return MUTT_UNKNOWN;
1348 }
1349
1350 if (S_ISFIFO(st.st_mode))
1351 {
1352 mutt_error(_("Can't open %s: it is a pipe"), path);
1353 return MUTT_UNKNOWN;
1354 }
1355
1356 // Next, search the local Mailbox types (is_local == true)
1357 for (const struct MxOps **ops = MxOps; *ops; ops++)
1358 {
1359 if (!(*ops)->is_local)
1360 continue;
1361 rc = (*ops)->path_probe(path, &st);
1362 if (rc != MUTT_UNKNOWN)
1363 return rc;
1364 }
1365
1366 return rc;
1367}
+ 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 1652 of file mx.c.

1653{
1654 if (!path)
1655 return NULL;
1656
1657 struct Mailbox *m = mx_mbox_find2(path);
1658 if (m)
1659 return m;
1660
1661 m = mailbox_new();
1662 buf_strcpy(&m->pathbuf, path);
1663 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
1664 mx_path_canon2(m, c_folder);
1665
1666 return m;
1667}
struct Mailbox * mailbox_new(void)
Create a new Mailbox.
Definition: mailbox.c:69
struct Mailbox * mx_mbox_find2(const char *path)
Find a Mailbox on an Account.
Definition: mx.c:1621
int mx_path_canon2(struct Mailbox *m, const char *folder)
Canonicalise the path to realpath.
Definition: mx.c:1476
+ 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 1721 of file mx.c.

1722{
1723 if (!path_or_name)
1724 return NULL;
1725
1726 // Order is name first because you can create a Mailbox from
1727 // a path, but can't from a name. So fallback behavior creates
1728 // a new Mailbox for us.
1729 struct Mailbox *m = mx_mbox_find_by_name(path_or_name);
1730 if (!m)
1731 m = mx_path_resolve(path_or_name);
1732
1733 return m;
1734}
static struct Mailbox * mx_mbox_find_by_name(const char *name)
Find a Mailbox with given name.
Definition: mx.c:1696
+ 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 1299 of file mx.c.

1300{
1301 if (!m || !e || !tags)
1302 return -1;
1303
1304 if (m->mx_ops->tags_commit)
1305 return m->mx_ops->tags_commit(m, e, tags);
1306
1307 mutt_message(_("Folder doesn't support tagging, aborting"));
1308 return -1;
1309}
int(* tags_commit)(struct Mailbox *m, struct Email *e, const char *buf)
Definition: mxapi.h:323
+ 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 1279 of file mx.c.

1280{
1281 if (!m || !buf)
1282 return -1;
1283
1284 if (m->mx_ops->tags_edit)
1285 return m->mx_ops->tags_edit(m, tags, buf);
1286
1287 mutt_message(_("Folder doesn't support tagging, aborting"));
1288 return -1;
1289}
int(* tags_edit)(struct Mailbox *m, const char *tags, struct Buffer *buf)
Definition: mxapi.h:306
+ 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 1812 of file mx.c.

1813{
1814 return m ? m->type : MUTT_MAILBOX_ERROR;
1815}
+ 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 1535 of file mx.c.

1536{
1537 if (!m || !m->mx_ops || !m->realpath)
1538 return NULL;
1539
1540 struct Account *np = NULL;
1541 TAILQ_FOREACH(np, &NeoMutt->accounts, entries)
1542 {
1543 if (np->type != m->type)
1544 continue;
1545
1546 if (m->mx_ops->ac_owns_path(np, m->realpath))
1547 return np;
1548 }
1549
1550 return NULL;
1551}
#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:109
struct AccountList accounts
List of all Accounts.
Definition: neomutt.h:46
+ 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 1559 of file mx.c.

1560{
1561 if (!a || !path)
1562 return NULL;
1563
1564 struct MailboxNode *np = NULL;
1565 struct Url *url_p = NULL;
1566 struct Url *url_a = NULL;
1567
1568 const bool use_url = (a->type == MUTT_IMAP);
1569 if (use_url)
1570 {
1571 url_p = url_parse(path);
1572 if (!url_p)
1573 goto done;
1574 }
1575
1576 STAILQ_FOREACH(np, &a->mailboxes, entries)
1577 {
1578 if (!use_url)
1579 {
1581 return np->mailbox;
1582 continue;
1583 }
1584
1585 url_free(&url_a);
1586 url_a = url_parse(np->mailbox->realpath);
1587 if (!url_a)
1588 continue;
1589
1590 if (!mutt_istr_equal(url_a->host, url_p->host))
1591 continue;
1592 if (url_p->user && !mutt_istr_equal(url_a->user, url_p->user))
1593 continue;
1594 if (a->type == MUTT_IMAP)
1595 {
1596 if (imap_mxcmp(url_a->path, url_p->path) == 0)
1597 break;
1598 }
1599 else
1600 {
1601 if (mutt_str_equal(url_a->path, url_p->path))
1602 break;
1603 }
1604 }
1605
1606done:
1607 url_free(&url_p);
1608 url_free(&url_a);
1609
1610 if (!np)
1611 return NULL;
1612 return np->mailbox;
1613}
int imap_mxcmp(const char *mx1, const char *mx2)
Compare mailbox names, giving priority to INBOX.
Definition: util.c:543
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:810
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:798
#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:153
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:154
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:238
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 1621 of file mx.c.

1622{
1623 if (!path)
1624 return NULL;
1625
1626 struct Buffer *buf = buf_new(path);
1627 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
1628 mx_path_canon(buf, c_folder, NULL);
1629
1630 struct Account *np = NULL;
1631 TAILQ_FOREACH(np, &NeoMutt->accounts, entries)
1632 {
1633 struct Mailbox *m = mx_mbox_find(np, buf_string(buf));
1634 if (m)
1635 {
1636 buf_free(&buf);
1637 return m;
1638 }
1639 }
1640
1641 buf_free(&buf);
1642 return NULL;
1643}
void buf_free(struct Buffer **ptr)
Deallocates a buffer.
Definition: buffer.c:331
struct Buffer * buf_new(const char *str)
Allocate a new Buffer.
Definition: buffer.c:316
+ 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 247 of file mx.c.

248{
249 if (!m)
250 return false;
251
252 if (m->account)
253 return true;
254
255 struct Account *a = mx_ac_find(m);
256 const bool new_account = !a;
257 if (new_account)
258 {
259 a = account_new(NULL, NeoMutt->sub);
260 a->type = m->type;
261 }
262 if (!mx_ac_add(a, m))
263 {
264 if (new_account)
265 {
266 account_free(&a);
267 }
268 return false;
269 }
270 if (new_account)
271 {
273 }
274 return true;
275}
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:142
bool mx_ac_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account - Wrapper for MxOps::ac_add()
Definition: mx.c:1739
struct Account * mx_ac_find(struct Mailbox *m)
Find the Account owning a Mailbox.
Definition: mx.c:1535
bool neomutt_account_add(struct NeoMutt *n, struct Account *a)
Add an Account to the global list.
Definition: neomutt.c:104
+ 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 1739 of file mx.c.

1740{
1741 if (!a || !m || !m->mx_ops || !m->mx_ops->ac_add)
1742 return false;
1743
1744 return m->mx_ops->ac_add(a, m) && account_mailbox_add(a, m);
1745}
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:124
+ 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 1756 of file mx.c.

1757{
1758 if (!m || !m->account)
1759 return -1;
1760
1761 struct Account *a = m->account;
1763 if (!keep_account && STAILQ_EMPTY(&a->mailboxes))
1764 {
1766 }
1767 return 0;
1768}
bool neomutt_account_remove(struct NeoMutt *n, const struct Account *a)
Remove an Account from the global list.
Definition: neomutt.c:127
#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 166 of file mx.c.

167{
168 if (imap_path_probe(path, NULL) == MUTT_IMAP)
169 return imap_access(path);
170
171 return access(path, flags);
172}
int imap_access(const char *path)
Check permissions on an IMAP mailbox with a new connection.
Definition: imap.c:455
+ 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,
int  req_size 
)

Create storage for the emails.

Parameters
mMailbox
req_sizeSpace required

Definition at line 1211 of file mx.c.

1212{
1213 if ((req_size + 1) <= m->email_max)
1214 return;
1215
1216 // Step size to increase by
1217 // Larger mailboxes get a larger step (limited to 1000)
1218 const int grow = CLAMP(m->email_max, 25, 1000);
1219
1220 // Sanity checks
1221 req_size = ROUND_UP(req_size + 1, grow);
1222
1223 const size_t s = MAX(sizeof(struct Email *), sizeof(int));
1224 if ((req_size * s) < (m->email_max * s))
1225 {
1226 mutt_error(_("Out of memory"));
1227 mutt_exit(1);
1228 }
1229
1230 if (m->emails)
1231 {
1232 mutt_mem_realloc(&m->emails, req_size * sizeof(struct Email *));
1233 mutt_mem_realloc(&m->v2r, req_size * sizeof(int));
1234 }
1235 else
1236 {
1237 m->emails = mutt_mem_calloc(req_size, sizeof(struct Email *));
1238 m->v2r = mutt_mem_calloc(req_size, sizeof(int));
1239 }
1240
1241 for (int i = m->email_max; i < req_size; i++)
1242 {
1243 m->emails[i] = NULL;
1244 m->v2r[i] = -1;
1245 }
1246
1247 m->email_max = req_size;
1248}
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:228
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
#define ROUND_UP(NUM, STEP)
Definition: memory.h:36
#define MAX(a, b)
Definition: memory.h:31
#define CLAMP(val, lo, hi)
Definition: memory.h:33
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 ( struct Buffer path)

Is the mailbox empty.

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

Definition at line 1257 of file mx.c.

1258{
1259 if (buf_is_empty(path))
1260 return -1;
1261
1262 enum MailboxType type = mx_path_probe(buf_string(path));
1263 const struct MxOps *ops = mx_get_ops(type);
1264 if (!ops || !ops->path_is_empty)
1265 return -1;
1266
1267 return ops->path_is_empty(path);
1268}
int(* path_is_empty)(struct Buffer *path)
Definition: mxapi.h:376
enum MailboxType type
Mailbox type, e.g. MUTT_IMAP.
Definition: mxapi.h:92
+ 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 410 of file mx.c.

411{
412 if (!m)
413 return;
414
415 m->opened--;
416 if (m->opened != 0)
417 return;
418
419 /* never announce that a mailbox we've just left has new mail.
420 * TODO: really belongs in mx_mbox_close, but this is a nice hook point */
421 if (!m->peekonly)
423
424 if (m->mx_ops)
425 m->mx_ops->mbox_close(m);
426
430
431 if (m->emails)
432 {
433 for (int i = 0; i < m->msg_count; i++)
434 {
435 if (!m->emails[i])
436 break;
437 email_free(&m->emails[i]);
438 }
439 }
440
441 if (!m->visible)
442 {
443 mx_ac_remove(m, keep_account);
444 }
445}
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:300
int mx_ac_remove(struct Mailbox *m, bool keep_account)
Remove a Mailbox from an Account and delete Account if empty.
Definition: mx.c:1756
struct HashTable * subj_hash
Hash Table: "subject" -> Email.
Definition: mailbox.h:123
struct HashTable * id_hash
Hash Table: "message-id" -> Email.
Definition: mailbox.h:122
struct HashTable * label_hash
Hash Table: "x-labels" -> Email.
Definition: mailbox.h:124
bool visible
True if a result of "mailboxes".
Definition: mailbox.h:129
enum MxStatus(* mbox_close)(struct Mailbox *m)
Definition: mxapi.h:199
+ 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 123 of file mx.c.

124{
125 for (const struct MxOps **ops = MxOps; *ops; ops++)
126 if ((*ops)->type == type)
127 return *ops;
128
129 return NULL;
130}
+ 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 1316 of file mx.c.

1317{
1318 return m && m->mx_ops->tags_commit && m->mx_ops->tags_edit;
1319}
+ 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 1823 of file mx.c.

1824{
1825 if (!m)
1826 return -1;
1827
1828 if (m->readonly)
1829 {
1830 mutt_error(_("Can't toggle write on a readonly mailbox"));
1831 return -1;
1832 }
1833
1834 if (m->dontwrite)
1835 {
1836 m->dontwrite = false;
1837 mutt_message(_("Changes to folder will be written on folder exit"));
1838 }
1839 else
1840 {
1841 m->dontwrite = true;
1842 mutt_message(_("Changes to folder will not be written"));
1843 }
1844
1845 struct EventMailbox ev_m = { m };
1847 return 0;
1848}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mx_mbox_reset_check()

void mx_mbox_reset_check ( void  )

Reset last mail check time.

Note
This effectively forces a check on the next mx_mbox_check() call.

Definition at line 1126 of file mx.c.

1127{
1128 const short c_mail_check = cs_subset_number(NeoMutt->sub, "mail_check");
1129 MailboxTime = mutt_date_now() - c_mail_check - 1;
1130}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ MboxTypeDef

const struct EnumDef MboxTypeDef
extern

Data for the $mbox_type enumeration.

Definition at line 88 of file mx.c.