NeoMutt  2025-01-09-117-gace867
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 "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.
 
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.
 

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

◆ MUTT_ADD_FROM

#define MUTT_ADD_FROM   (1 << 0)

add a From_ line

Definition at line 39 of file mx.h.

◆ MUTT_SET_DRAFT

#define MUTT_SET_DRAFT   (1 << 1)

set the message draft flag

Definition at line 40 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 37 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 1110 of file mx.c.

1111{
1112 if (!m || !m->mx_ops)
1113 return MX_STATUS_ERROR;
1114
1115 const short c_mail_check = cs_subset_number(NeoMutt->sub, "mail_check");
1116
1117 time_t t = mutt_date_now();
1118 if ((t - m->last_checked) < c_mail_check)
1119 return MX_STATUS_OK;
1120
1121 m->last_checked = t;
1122
1123 enum MxStatus rc = m->mx_ops->mbox_check(m);
1124 if ((rc == MX_STATUS_NEW_MAIL) || (rc == MX_STATUS_REOPENED))
1125 {
1127 }
1128
1129 return rc;
1130}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:143
void mailbox_changed(struct Mailbox *m, enum NotifyMailbox action)
Notify observers of a change to a Mailbox.
Definition: mailbox.c:233
@ NT_MAILBOX_INVALID
Email list was changed.
Definition: mailbox.h:189
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:456
MxStatus
Return values from mbox_check(), mbox_check_stats(), mbox_sync(), and mbox_close()
Definition: mxapi.h:60
@ MX_STATUS_ERROR
An error occurred.
Definition: mxapi.h:61
@ MX_STATUS_OK
No changes.
Definition: mxapi.h:62
@ MX_STATUS_REOPENED
Mailbox was reopened.
Definition: mxapi.h:65
@ MX_STATUS_NEW_MAIL
New mail received in Mailbox.
Definition: mxapi.h:63
const struct MxOps * mx_ops
MXAPI callback functions.
Definition: mailbox.h:107
time_t last_checked
Last time we checked this mailbox for new mail.
Definition: mailbox.h:105
enum MxStatus(* mbox_check)(struct Mailbox *m)
Definition: mxapi.h:159
Container for Accounts, Notifications.
Definition: neomutt.h:43
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:47
+ 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 1764 of file mx.c.

1765{
1766 if (!m)
1767 return MX_STATUS_ERROR;
1768
1769 enum MxStatus rc = m->mx_ops->mbox_check_stats(m, flags);
1770 if (rc != MX_STATUS_ERROR)
1771 {
1772 struct EventMailbox ev_m = { m };
1774 }
1775
1776 return rc;
1777}
@ NT_MAILBOX_CHANGE
Mailbox has been changed.
Definition: mailbox.h:185
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:199
struct Notify * notify
Notifications: NotifyMailbox, EventMailbox.
Definition: mailbox.h:145
enum MxStatus(* mbox_check_stats)(struct Mailbox *m, CheckStatsFlags flags)
Definition: mxapi.h:172
+ 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 598 of file mx.c.

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

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

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

1045{
1046 if (!m)
1047 return NULL;
1048
1049 struct Address *p = NULL;
1050 struct Message *msg = NULL;
1051
1052 if (!m->mx_ops || !m->mx_ops->msg_open_new)
1053 {
1054 mutt_debug(LL_DEBUG1, "function unimplemented for mailbox type %d\n", m->type);
1055 return NULL;
1056 }
1057
1058 msg = message_new();
1059 msg->write = true;
1060
1061 if (e)
1062 {
1063 msg->flags.flagged = e->flagged;
1064 msg->flags.replied = e->replied;
1065 msg->flags.read = e->read;
1066 msg->flags.draft = (flags & MUTT_SET_DRAFT);
1067 msg->received = e->received;
1068 }
1069
1070 if (msg->received == 0)
1071 msg->received = mutt_date_now();
1072
1073 if (m->mx_ops->msg_open_new(m, msg, e))
1074 {
1075 if (m->type == MUTT_MMDF)
1076 fputs(MMDF_SEP, msg->fp);
1077
1078 if (((m->type == MUTT_MBOX) || (m->type == MUTT_MMDF)) && (flags & MUTT_ADD_FROM))
1079 {
1080 if (e)
1081 {
1082 p = TAILQ_FIRST(&e->env->return_path);
1083 if (!p)
1084 p = TAILQ_FIRST(&e->env->sender);
1085 if (!p)
1086 p = TAILQ_FIRST(&e->env->from);
1087 }
1088
1089 // Use C locale for the date, so that day/month names are in English
1090 char buf[64] = { 0 };
1091 mutt_date_localtime_format_locale(buf, sizeof(buf), "%a %b %e %H:%M:%S %Y",
1093 fprintf(msg->fp, "From %s %s\n",
1094 p ? buf_string(p->mailbox) : NONULL(NeoMutt->username), buf);
1095 }
1096 }
1097 else
1098 {
1099 message_free(&msg);
1100 }
1101
1102 return msg;
1103}
struct Message * message_new(void)
Create a new Message.
Definition: message.c:53
#define MMDF_SEP
Definition: lib.h:62
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:969
#define MUTT_ADD_FROM
add a From_ line
Definition: mx.h:39
#define MUTT_SET_DRAFT
set the message draft flag
Definition: mx.h:40
#define TAILQ_FIRST(head)
Definition: queue.h:780
#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:68
bool replied
Email has been replied to.
Definition: email.h:51
time_t received
Time when the message was placed in the mailbox.
Definition: email.h:61
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:229
char * username
User's login name.
Definition: neomutt.h:54
locale_t time_c_locale
Current locale but LC_TIME=C.
Definition: neomutt.h:49
+ 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}
bool(* msg_open)(struct Mailbox *m, struct Message *msg, struct Email *e)
Definition: mxapi.h:213
+ 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 1510 of file mx.c.

1511{
1512 if (!m || !m->mx_ops || !m->mx_ops->msg_padding_size)
1513 return 0;
1514
1515 return m->mx_ops->msg_padding_size(m);
1516}
int(* msg_padding_size)(struct Mailbox *m)
Definition: mxapi.h:271
+ 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 1788 of file mx.c.

1789{
1790 if (!m || !m->mx_ops || !m->mx_ops->msg_save_hcache || !e)
1791 return 0;
1792
1793 return m->mx_ops->msg_save_hcache(m, e);
1794}
int(* msg_save_hcache)(struct Mailbox *m, struct Email *e)
Definition: mxapi.h:286
+ 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 buf_inline_replace(path, 0, 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 buf_inline_replace(path, 0, 0, folder);
1394 }
1395 else
1396 {
1397 buf_inline_replace(path, 0, 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 buf_inline_replace(path, 0, 1, c_spool_file);
1406 }
1407 else if (buf_at(path, 0) == '-')
1408 {
1409 buf_inline_replace(path, 0, 1, LastFolder);
1410 }
1411 else if (buf_at(path, 0) == '<')
1412 {
1413 const char *const c_record = cs_subset_string(NeoMutt->sub, "record");
1414 buf_inline_replace(path, 0, 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 buf_inline_replace(path, 0, 1, c_mbox);
1420 }
1421 else if (buf_at(path, 0) == '^')
1422 {
1423 buf_inline_replace(path, 0, 1, CurrentFolder);
1424 }
1425 else if (buf_at(path, 0) == '~')
1426 {
1427 buf_inline_replace(path, 0, 1, NeoMutt->home_dir);
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, NeoMutt->home_dir, 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:765
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:277
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
Definition: buffer.c:668
void buf_inline_replace(struct Buffer *buf, size_t pos, size_t len, const char *str)
Definition: buffer.c:768
MailboxType
Supported mailbox formats.
Definition: mailbox.h:41
struct Email * email_new(void)
Create a new Email.
Definition: email.c:77
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:46
char * LastFolder
Previously selected mailbox.
Definition: globals.c:40
char * CurrentFolder
Currently selected mailbox.
Definition: globals.c:39
void mutt_default_save(struct Buffer *path, struct Email *e)
Find the default save path for an email.
Definition: hook.c:779
bool mutt_path_canon(struct Buffer *path, const char *homedir, bool is_dir)
Create the canonical version of a path.
Definition: path.c:248
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:497
#define TAILQ_EMPTY(head)
Definition: queue.h:778
char * data
Pointer to data.
Definition: buffer.h:37
char * path
Path of Email (for local Mailboxes)
Definition: email.h:70
struct AddressList to
Email's 'To' list.
Definition: envelope.h:60
Definition: mxapi.h:88
int(* path_canon)(struct Buffer *path)
Definition: mxapi.h:346
char * home_dir
User's home directory.
Definition: neomutt.h:53
+ 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:281
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_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 1641 of file mx.c.

1642{
1643 if (!path)
1644 return NULL;
1645
1646 struct Mailbox *m = mx_mbox_find2(path);
1647 if (m)
1648 return m;
1649
1650 m = mailbox_new();
1651 buf_strcpy(&m->pathbuf, path);
1652 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
1653 mx_path_canon2(m, c_folder);
1654
1655 return m;
1656}
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:1610
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 1710 of file mx.c.

1711{
1712 if (!path_or_name)
1713 return NULL;
1714
1715 // Order is name first because you can create a Mailbox from
1716 // a path, but can't from a name. So fallback behavior creates
1717 // a new Mailbox for us.
1718 struct Mailbox *m = mx_mbox_find_by_name(path_or_name);
1719 if (!m)
1720 m = mx_path_resolve(path_or_name);
1721
1722 return m;
1723}
static struct Mailbox * mx_mbox_find_by_name(const char *name)
Find a Mailbox with given name.
Definition: mx.c:1685
+ 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:320
+ 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:303
+ 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 1801 of file mx.c.

1802{
1803 return m ? m->type : MUTT_MAILBOX_ERROR;
1804}
+ 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 1524 of file mx.c.

1525{
1526 if (!m || !m->mx_ops || !m->realpath)
1527 return NULL;
1528
1529 struct Account *np = NULL;
1530 TAILQ_FOREACH(np, &NeoMutt->accounts, entries)
1531 {
1532 if (np->type != m->type)
1533 continue;
1534
1535 if (m->mx_ops->ac_owns_path(np, m->realpath))
1536 return np;
1537 }
1538
1539 return NULL;
1540}
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:782
A group of associated Mailboxes.
Definition: account.h:36
enum MailboxType type
Type of Mailboxes this Account contains.
Definition: account.h:37
bool(* ac_owns_path)(struct Account *a, const char *path)
Definition: mxapi.h:106
struct AccountList accounts
List of all Accounts.
Definition: neomutt.h:48
+ 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 1548 of file mx.c.

1549{
1550 if (!a || !path)
1551 return NULL;
1552
1553 struct MailboxNode *np = NULL;
1554 struct Url *url_p = NULL;
1555 struct Url *url_a = NULL;
1556
1557 const bool use_url = (a->type == MUTT_IMAP);
1558 if (use_url)
1559 {
1560 url_p = url_parse(path);
1561 if (!url_p)
1562 goto done;
1563 }
1564
1565 STAILQ_FOREACH(np, &a->mailboxes, entries)
1566 {
1567 if (!use_url)
1568 {
1570 return np->mailbox;
1571 continue;
1572 }
1573
1574 url_free(&url_a);
1575 url_a = url_parse(np->mailbox->realpath);
1576 if (!url_a)
1577 continue;
1578
1579 if (!mutt_istr_equal(url_a->host, url_p->host))
1580 continue;
1581 if (url_p->user && !mutt_istr_equal(url_a->user, url_p->user))
1582 continue;
1583 if (a->type == MUTT_IMAP)
1584 {
1585 if (imap_mxcmp(url_a->path, url_p->path) == 0)
1586 break;
1587 }
1588 else
1589 {
1590 if (mutt_str_equal(url_a->path, url_p->path))
1591 break;
1592 }
1593 }
1594
1595done:
1596 url_free(&url_p);
1597 url_free(&url_a);
1598
1599 if (!np)
1600 return NULL;
1601 return np->mailbox;
1602}
int imap_mxcmp(const char *mx1, const char *mx2)
Compare mailbox names, giving priority to INBOX.
Definition: util.c:548
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:673
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:661
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:390
struct MailboxList mailboxes
List of Mailboxes.
Definition: account.h:40
List of Mailboxes.
Definition: mailbox.h:166
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:167
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:239
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition: url.c:124
+ 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 1610 of file mx.c.

1611{
1612 if (!path)
1613 return NULL;
1614
1615 struct Buffer *buf = buf_new(path);
1616 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
1617 mx_path_canon(buf, c_folder, NULL);
1618
1619 struct Account *np = NULL;
1620 TAILQ_FOREACH(np, &NeoMutt->accounts, entries)
1621 {
1622 struct Mailbox *m = mx_mbox_find(np, buf_string(buf));
1623 if (m)
1624 {
1625 buf_free(&buf);
1626 return m;
1627 }
1628 }
1629
1630 buf_free(&buf);
1631 return NULL;
1632}
void buf_free(struct Buffer **ptr)
Deallocates a buffer.
Definition: buffer.c:319
struct Buffer * buf_new(const char *str)
Allocate a new Buffer.
Definition: buffer.c:304
+ 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 251 of file mx.c.

252{
253 if (!m)
254 return false;
255
256 if (m->account)
257 return true;
258
259 struct Account *a = mx_ac_find(m);
260 const bool new_account = !a;
261 if (new_account)
262 {
263 a = account_new(NULL, NeoMutt->sub);
264 a->type = m->type;
265 }
266 if (!mx_ac_add(a, m))
267 {
268 if (new_account)
269 {
270 account_free(&a);
271 }
272 return false;
273 }
274 if (new_account)
275 {
277 }
278 return true;
279}
struct Account * account_new(const char *name, struct ConfigSubset *sub)
Create a new Account.
Definition: account.c:44
void account_free(struct Account **ptr)
Free an Account.
Definition: account.c:143
bool mx_ac_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account - Wrapper for MxOps::ac_add()
Definition: mx.c:1728
struct Account * mx_ac_find(struct Mailbox *m)
Find the Account owning a Mailbox.
Definition: mx.c:1524
bool neomutt_account_add(struct NeoMutt *n, struct Account *a)
Add an Account to the global list.
Definition: neomutt.c:115
+ 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 1728 of file mx.c.

1729{
1730 if (!a || !m || !m->mx_ops || !m->mx_ops->ac_add)
1731 return false;
1732
1733 return m->mx_ops->ac_add(a, m) && account_mailbox_add(a, m);
1734}
bool account_mailbox_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account.
Definition: account.c:67
bool(* ac_add)(struct Account *a, struct Mailbox *m)
Definition: mxapi.h:121
+ 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 1745 of file mx.c.

1746{
1747 if (!m || !m->account)
1748 return -1;
1749
1750 struct Account *a = m->account;
1752 if (!keep_account && STAILQ_EMPTY(&a->mailboxes))
1753 {
1755 }
1756 return 0;
1757}
bool neomutt_account_remove(struct NeoMutt *n, const struct Account *a)
Remove an Account from the global list.
Definition: neomutt.c:138
#define STAILQ_EMPTY(head)
Definition: queue.h:382
+ 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 170 of file mx.c.

171{
172 if (imap_path_probe(path, NULL) == MUTT_IMAP)
173 return imap_access(path);
174
175 return access(path, flags);
176}
int imap_access(const char *path)
Check permissions on an IMAP mailbox with a new connection.
Definition: imap.c:463
+ 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("%s", strerror(ENOMEM));
1227 mutt_exit(1);
1228 }
1229
1230 if (m->emails)
1231 {
1232 MUTT_MEM_REALLOC(&m->emails, req_size, struct Email *);
1233 MUTT_MEM_REALLOC(&m->v2r, req_size, int);
1234 }
1235 else
1236 {
1237 m->emails = MUTT_MEM_CALLOC(req_size, struct Email *);
1238 m->v2r = MUTT_MEM_CALLOC(req_size, 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: exit.c:41
#define ROUND_UP(NUM, STEP)
Definition: memory.h:36
#define MUTT_MEM_CALLOC(n, type)
Definition: memory.h:40
#define MUTT_MEM_REALLOC(pptr, n, type)
Definition: memory.h:43
#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:360
enum MailboxType type
Mailbox type, e.g. MUTT_IMAP.
Definition: mxapi.h:89
+ 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 414 of file mx.c.

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

128{
129 for (const struct MxOps **ops = MxOps; *ops; ops++)
130 if ((*ops)->type == type)
131 return *ops;
132
133 return NULL;
134}
+ 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 1812 of file mx.c.

1813{
1814 if (!m)
1815 return -1;
1816
1817 if (m->readonly)
1818 {
1819 mutt_error(_("Can't toggle write on a readonly mailbox"));
1820 return -1;
1821 }
1822
1823 if (m->dontwrite)
1824 {
1825 m->dontwrite = false;
1826 mutt_message(_("Changes to folder will be written on folder exit"));
1827 }
1828 else
1829 {
1830 m->dontwrite = true;
1831 mutt_message(_("Changes to folder will not be written"));
1832 }
1833
1834 struct EventMailbox ev_m = { m };
1836 return 0;
1837}
+ 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 92 of file mx.c.