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

NeoMutt  2025-12-11-189-gceedb6
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
mx.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 1107 of file mx.c.

1108{
1109 if (!m || !m->mx_ops)
1110 return MX_STATUS_ERROR;
1111
1112 const short c_mail_check = cs_subset_number(NeoMutt->sub, "mail_check");
1113
1114 time_t t = mutt_date_now();
1115 if ((t - m->last_checked) < c_mail_check)
1116 return MX_STATUS_OK;
1117
1118 m->last_checked = t;
1119
1120 enum MxStatus rc = m->mx_ops->mbox_check(m);
1121 if ((rc == MX_STATUS_NEW_MAIL) || (rc == MX_STATUS_REOPENED))
1122 {
1124 }
1125
1126 return rc;
1127}
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:232
@ NT_MAILBOX_INVALID
Email list was changed.
Definition mailbox.h:180
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition date.c:457
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:128
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:134
+ 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 1773 of file mx.c.

1774{
1775 if (!m)
1776 return MX_STATUS_ERROR;
1777
1778 enum MxStatus rc = m->mx_ops->mbox_check_stats(m, flags);
1779 if (rc != MX_STATUS_ERROR)
1780 {
1781 struct EventMailbox ev_m = { m };
1783 }
1784
1785 return rc;
1786}
@ NT_MAILBOX_CHANGE
Mailbox has been changed.
Definition mailbox.h:176
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:190
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 595 of file mx.c.

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

286{
287 if (!m)
288 return false;
289
290 if ((m->type == MUTT_UNKNOWN) && (flags & MUTT_APPEND))
291 {
292 m->type = cs_subset_enum(NeoMutt->sub, "mbox_type");
293 m->mx_ops = mx_get_ops(m->type);
294 }
295
296 const bool newly_linked_account = !m->account;
297 if (newly_linked_account)
298 {
299 if (!mx_mbox_ac_link(m))
300 {
301 return false;
302 }
303 }
304
305 m->verbose = !(flags & MUTT_QUIET);
306 m->readonly = (flags & MUTT_READONLY);
307 m->peekonly = (flags & MUTT_PEEK);
308
309 if (flags & MUTT_APPEND)
310 {
311 if (!mx_open_mailbox_append(m, flags))
312 {
313 goto error;
314 }
315 return true;
316 }
317
318 if (m->opened > 0)
319 {
320 m->opened++;
321 return true;
322 }
323
324 m->size = 0;
325 m->msg_unread = 0;
326 m->msg_flagged = 0;
327 m->rights = MUTT_ACL_ALL;
328
329 if (m->type == MUTT_UNKNOWN)
330 {
332 m->mx_ops = mx_get_ops(m->type);
333 }
334
335 if ((m->type == MUTT_UNKNOWN) || (m->type == MUTT_MAILBOX_ERROR) || !m->mx_ops)
336 {
337 if (m->type == MUTT_MAILBOX_ERROR)
338 mutt_perror("%s", mailbox_path(m));
339 else if ((m->type == MUTT_UNKNOWN) || !m->mx_ops)
340 mutt_error(_("%s is not a mailbox"), mailbox_path(m));
341 goto error;
342 }
343
345
346 /* if the user has a 'push' command in their .neomuttrc, or in a folder-hook,
347 * it will cause the progress messages not to be displayed because
348 * mutt_refresh() will think we are in the middle of a macro. so set a
349 * flag to indicate that we should really refresh the screen. */
350 OptForceRefresh = true;
351
352 if (m->verbose)
353 mutt_message(_("Reading %s..."), mailbox_path(m));
354
355 // Clear out any existing emails
356 for (int i = 0; i < m->email_max; i++)
357 {
358 email_free(&m->emails[i]);
359 }
360
361 m->msg_count = 0;
362 m->msg_unread = 0;
363 m->msg_flagged = 0;
364 m->msg_new = 0;
365 m->msg_deleted = 0;
366 m->msg_tagged = 0;
367 m->vcount = 0;
368
369 enum MxOpenReturns rc = m->mx_ops->mbox_open(m);
370 m->opened++;
371
372 if ((rc == MX_OPEN_OK) || (rc == MX_OPEN_ABORT))
373 {
374 if ((flags & MUTT_NOSORT) == 0)
375 {
376 /* avoid unnecessary work since the mailbox is completely unthreaded
377 * to begin with */
378 OptSortSubthreads = false;
379 OptNeedRescore = false;
380 }
381 if (m->verbose)
383 if (rc == MX_OPEN_ABORT)
384 {
385 mutt_error(_("Reading from %s interrupted..."), mailbox_path(m));
386 }
387 }
388 else
389 {
390 goto error;
391 }
392
393 if (!m->peekonly)
394 m->has_new = false;
395 OptForceRefresh = false;
396
397 return true;
398
399error:
400 mx_fastclose_mailbox(m, newly_linked_account);
401 if (newly_linked_account)
403 return false;
404}
unsigned char cs_subset_enum(const struct ConfigSubset *sub, const char *name)
Get a enumeration config item by name.
Definition helpers.c:71
void account_mailbox_remove(struct Account *a, struct Mailbox *m)
Remove a Mailbox from an Account.
Definition account.c:94
#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
void mutt_make_label_hash(struct Mailbox *m)
Create a Hash Table to store the labels.
Definition header.c:405
bool OptNeedRescore
(pseudo) set when the 'score' command is used
Definition globals.c:62
bool OptForceRefresh
(pseudo) refresh even during macros
Definition globals.c:58
bool OptSortSubthreads
(pseudo) used when $sort_aux changes
Definition globals.c:68
#define mutt_error(...)
Definition logging2.h:94
#define mutt_perror(...)
Definition logging2.h:95
const struct MxOps * mx_get_ops(enum MailboxType type)
Get mailbox operations.
Definition mx.c:124
bool mx_mbox_ac_link(struct Mailbox *m)
Link a Mailbox to an existing or new Account.
Definition mx.c:248
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition mx.c:1323
static bool mx_open_mailbox_append(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox for appending.
Definition mx.c:182
#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 903 of file mx.c.

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

1183{
1184 if (!m || !ptr || !*ptr)
1185 return 0;
1186
1187 int rc = 0;
1188 struct Message *msg = *ptr;
1189
1190 if (m->mx_ops && m->mx_ops->msg_close)
1191 rc = m->mx_ops->msg_close(m, msg);
1192
1193 if (msg->path)
1194 {
1195 mutt_debug(LL_DEBUG1, "unlinking %s\n", msg->path);
1196 unlink(msg->path);
1197 }
1198
1199 message_free(ptr);
1200 return rc;
1201}
void message_free(struct Message **ptr)
Free a Message.
Definition message.c:37
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
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 1161 of file mx.c.

1162{
1163 if (!m || !m->mx_ops || !m->mx_ops->msg_commit || !msg)
1164 return -1;
1165
1166 if (!(msg->write && m->append))
1167 {
1168 mutt_debug(LL_DEBUG1, "msg->write = %d, m->append = %d\n", msg->write, m->append);
1169 return -1;
1170 }
1171
1172 return m->mx_ops->msg_commit(m, msg);
1173}
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 1041 of file mx.c.

1042{
1043 if (!m)
1044 return NULL;
1045
1046 struct Address *p = NULL;
1047 struct Message *msg = NULL;
1048
1049 if (!m->mx_ops || !m->mx_ops->msg_open_new)
1050 {
1051 mutt_debug(LL_DEBUG1, "function unimplemented for mailbox type %d\n", m->type);
1052 return NULL;
1053 }
1054
1055 msg = message_new();
1056 msg->write = true;
1057
1058 if (e)
1059 {
1060 msg->flags.flagged = e->flagged;
1061 msg->flags.replied = e->replied;
1062 msg->flags.read = e->read;
1063 msg->flags.draft = (flags & MUTT_SET_DRAFT);
1064 msg->received = e->received;
1065 }
1066
1067 if (msg->received == 0)
1068 msg->received = mutt_date_now();
1069
1070 if (m->mx_ops->msg_open_new(m, msg, e))
1071 {
1072 if (m->type == MUTT_MMDF)
1073 fputs(MMDF_SEP, msg->fp);
1074
1075 if (((m->type == MUTT_MBOX) || (m->type == MUTT_MMDF)) && (flags & MUTT_ADD_FROM))
1076 {
1077 if (e)
1078 {
1079 p = TAILQ_FIRST(&e->env->return_path);
1080 if (!p)
1081 p = TAILQ_FIRST(&e->env->sender);
1082 if (!p)
1083 p = TAILQ_FIRST(&e->env->from);
1084 }
1085
1086 // Use C locale for the date, so that day/month names are in English
1087 char buf[64] = { 0 };
1088 mutt_date_localtime_format_locale(buf, sizeof(buf), "%a %b %e %H:%M:%S %Y",
1090 fprintf(msg->fp, "From %s %s\n",
1091 p ? buf_string(p->mailbox) : NONULL(NeoMutt->username), buf);
1092 }
1093 }
1094 else
1095 {
1096 message_free(&msg);
1097 }
1098
1099 return msg;
1100}
struct Message * message_new(void)
Create a new Message.
Definition message.c:53
#define MMDF_SEP
Definition lib.h:63
size_t mutt_date_localtime_format_locale(char *buf, size_t buflen, const char *format, time_t t, locale_t loc)
Format localtime using a given locale.
Definition date.c:970
#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:44
An email address.
Definition address.h:35
struct Buffer * mailbox
Mailbox and host address.
Definition address.h:37
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
struct Message::@264267271004327071125374067057142037276212342100 flags
Flags for the Message.
bool draft
Message has been read.
Definition message.h:44
bool replied
Message has been replied to.
Definition message.h:43
time_t received
Time at which this message was received.
Definition message.h:46
bool flagged
Message is flagged.
Definition message.h:42
bool read
Message has been read.
Definition message.h:41
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:142
locale_t time_c_locale
Current locale but LC_TIME=C.
Definition neomutt.h:136
+ 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 1136 of file mx.c.

1137{
1138 if (!m || !e)
1139 return NULL;
1140
1141 if (!m->mx_ops || !m->mx_ops->msg_open)
1142 {
1143 mutt_debug(LL_DEBUG1, "function not implemented for mailbox type %d\n", m->type);
1144 return NULL;
1145 }
1146
1147 struct Message *msg = message_new();
1148 if (!m->mx_ops->msg_open(m, msg, e))
1149 message_free(&msg);
1150
1151 return msg;
1152}
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 1507 of file mx.c.

1508{
1509 if (!m || !m->mx_ops || !m->mx_ops->msg_padding_size)
1510 return 0;
1511
1512 return m->mx_ops->msg_padding_size(m);
1513}
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 1797 of file mx.c.

1798{
1799 if (!m || !m->mx_ops || !m->mx_ops->msg_save_hcache || !e)
1800 return 0;
1801
1802 return m->mx_ops->msg_save_hcache(m, e);
1803}
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 1369 of file mx.c.

1370{
1371 if (buf_is_empty(path))
1372 return -1;
1373
1374 for (size_t i = 0; i < 3; i++)
1375 {
1376 /* Look for !! ! - < > or ^ followed by / or NUL */
1377 if ((buf_at(path, 0) == '!') && (buf_at(path, 1) == '!'))
1378 {
1379 if (((buf_at(path, 2) == '/') || (buf_at(path, 2) == '\0')))
1380 {
1381 buf_inline_replace(path, 0, 2, LastFolder);
1382 }
1383 }
1384 else if ((buf_at(path, 0) == '+') || (buf_at(path, 0) == '='))
1385 {
1386 size_t folder_len = mutt_str_len(folder);
1387 if ((folder_len > 0) && (folder[folder_len - 1] != '/'))
1388 {
1389 path->data[0] = '/';
1390 buf_inline_replace(path, 0, 0, folder);
1391 }
1392 else
1393 {
1394 buf_inline_replace(path, 0, 1, folder);
1395 }
1396 }
1397 else if ((buf_at(path, 1) == '/') || (buf_at(path, 1) == '\0'))
1398 {
1399 if (buf_at(path, 0) == '!')
1400 {
1401 const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
1402 buf_inline_replace(path, 0, 1, c_spool_file);
1403 }
1404 else if (buf_at(path, 0) == '-')
1405 {
1406 buf_inline_replace(path, 0, 1, LastFolder);
1407 }
1408 else if (buf_at(path, 0) == '<')
1409 {
1410 const char *const c_record = cs_subset_string(NeoMutt->sub, "record");
1411 buf_inline_replace(path, 0, 1, c_record);
1412 }
1413 else if (buf_at(path, 0) == '>')
1414 {
1415 const char *const c_mbox = cs_subset_string(NeoMutt->sub, "mbox");
1416 buf_inline_replace(path, 0, 1, c_mbox);
1417 }
1418 else if (buf_at(path, 0) == '^')
1419 {
1420 buf_inline_replace(path, 0, 1, CurrentFolder);
1421 }
1422 else if (buf_at(path, 0) == '~')
1423 {
1424 buf_inline_replace(path, 0, 1, NeoMutt->home_dir);
1425 }
1426 }
1427 else if (buf_at(path, 0) == '@')
1428 {
1429 /* elm compatibility, @ expands alias to user name */
1430 struct AddressList *al = alias_lookup(buf_string(path));
1431 if (!al || TAILQ_EMPTY(al))
1432 break;
1433
1434 struct Email *e = email_new();
1435 e->env = mutt_env_new();
1436 mutt_addrlist_copy(&e->env->from, al, false);
1437 mutt_addrlist_copy(&e->env->to, al, false);
1439 email_free(&e);
1440 break;
1441 }
1442 else
1443 {
1444 break;
1445 }
1446 }
1447
1448 // if (!folder) //XXX - use inherited version, or pass NULL to backend?
1449 // return -1;
1450
1452 if (type)
1453 *type = type2;
1454 const struct MxOps *ops = mx_get_ops(type2);
1455 if (!ops || !ops->path_canon)
1456 return -1;
1457
1458 if (ops->path_canon(path) < 0)
1459 {
1460 mutt_path_canon(path, NeoMutt->home_dir, true);
1461 }
1462
1463 return 0;
1464}
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:274
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:45
char * LastFolder
Previously selected mailbox.
Definition globals.c:40
char * CurrentFolder
Currently selected mailbox.
Definition globals.c:39
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:500
#define TAILQ_EMPTY(head)
Definition queue.h:778
void mutt_default_save(struct Buffer *path, struct Email *e)
Find the default save path for an email.
Definition run.c:211
char * 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:141
+ 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 1473 of file mx.c.

1474{
1475 if (!m)
1476 return -1;
1477
1478 struct Buffer *path = buf_pool_get();
1479
1480 if (m->realpath)
1481 buf_strcpy(path, m->realpath);
1482 else
1483 buf_strcpy(path, mailbox_path(m));
1484
1485 int rc = mx_path_canon(path, folder, &m->type);
1486
1488 buf_pool_release(&path);
1489
1490 if (rc >= 0)
1491 {
1492 m->mx_ops = mx_get_ops(m->type);
1493 buf_strcpy(&m->pathbuf, m->realpath);
1494 }
1495
1496 return rc;
1497}
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition string.c:284
int mx_path_canon(struct Buffer *path, const char *folder, enum MailboxType *type)
Canonicalise a mailbox path - Wrapper for MxOps::path_canon()
Definition mx.c:1369
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 1323 of file mx.c.

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

1648{
1649 if (!path)
1650 return NULL;
1651
1652 struct Mailbox *m = mx_mbox_find2(path);
1653 if (m)
1654 return m;
1655
1656 m = mailbox_new();
1657 buf_strcpy(&m->pathbuf, path);
1658 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
1659 mx_path_canon2(m, c_folder);
1660
1661 return m;
1662}
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:1615
int mx_path_canon2(struct Mailbox *m, const char *folder)
Canonicalise the path to realpath.
Definition mx.c:1473
+ 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 1719 of file mx.c.

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

1297{
1298 if (!m || !e || !tags)
1299 return -1;
1300
1301 if (m->mx_ops->tags_commit)
1302 return m->mx_ops->tags_commit(m, e, tags);
1303
1304 mutt_message(_("Folder doesn't support tagging, aborting"));
1305 return -1;
1306}
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 1276 of file mx.c.

1277{
1278 if (!m || !buf)
1279 return -1;
1280
1281 if (m->mx_ops->tags_edit)
1282 return m->mx_ops->tags_edit(m, tags, buf);
1283
1284 mutt_message(_("Folder doesn't support tagging, aborting"));
1285 return -1;
1286}
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 1810 of file mx.c.

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

1522{
1523 if (!m || !m->mx_ops || !m->realpath)
1524 return NULL;
1525
1526 struct Account **ap = NULL;
1528 {
1529 struct Account *a = *ap;
1530 if (a->type != m->type)
1531 continue;
1532
1533 if (m->mx_ops->ac_owns_path(a, m->realpath))
1534 return a;
1535 }
1536
1537 return NULL;
1538}
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 AccountArray accounts
All Accounts.
Definition neomutt.h:135
+ 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 1546 of file mx.c.

1547{
1548 if (!a || !path)
1549 return NULL;
1550
1551 struct Mailbox *m_match = NULL;
1552 struct Mailbox **mp = NULL;
1553 struct Url *url_p = NULL;
1554 struct Url *url_a = NULL;
1555
1556 const bool use_url = (a->type == MUTT_IMAP);
1557 if (use_url)
1558 {
1559 url_p = url_parse(path);
1560 if (!url_p)
1561 goto done;
1562 }
1563
1564 ARRAY_FOREACH(mp, &a->mailboxes)
1565 {
1566 struct Mailbox *m = *mp;
1567
1568 if (!use_url)
1569 {
1570 if (mutt_str_equal(m->realpath, path))
1571 return m;
1572 continue;
1573 }
1574
1575 url_free(&url_a);
1576 url_a = url_parse(m->realpath);
1577 if (!url_a)
1578 continue;
1579
1580 if (!mutt_istr_equal(url_a->host, url_p->host))
1581 continue;
1582 if (url_p->user && !mutt_istr_equal(url_a->user, url_p->user))
1583 continue;
1584 if (a->type == MUTT_IMAP)
1585 {
1586 if (imap_mxcmp(url_a->path, url_p->path) == 0)
1587 {
1588 m_match = *mp;
1589 break;
1590 }
1591 }
1592 else
1593 {
1594 if (mutt_str_equal(url_a->path, url_p->path))
1595 {
1596 m_match = *mp;
1597 break;
1598 }
1599 }
1600 }
1601
1602done:
1603 url_free(&url_p);
1604 url_free(&url_a);
1605
1606 return m_match;
1607}
int imap_mxcmp(const char *mx1, const char *mx2)
Compare mailbox names, giving priority to INBOX.
Definition util.c:549
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:674
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:662
struct MailboxArray mailboxes
All Mailboxes.
Definition account.h:40
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 1615 of file mx.c.

1616{
1617 if (!path)
1618 return NULL;
1619
1620 struct Buffer *buf = buf_new(path);
1621 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
1622 mx_path_canon(buf, c_folder, NULL);
1623
1624 struct Account **ap = NULL;
1626 {
1627 struct Account *a = *ap;
1628 struct Mailbox *m = mx_mbox_find(a, buf_string(buf));
1629 if (m)
1630 {
1631 buf_free(&buf);
1632 return m;
1633 }
1634 }
1635
1636 buf_free(&buf);
1637 return NULL;
1638}
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 248 of file mx.c.

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

1738{
1739 if (!a || !m || !m->mx_ops || !m->mx_ops->ac_add)
1740 return false;
1741
1742 return m->mx_ops->ac_add(a, m) && account_mailbox_add(a, m);
1743}
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 1754 of file mx.c.

1755{
1756 if (!m || !m->account)
1757 return -1;
1758
1759 struct Account *a = m->account;
1761 if (!keep_account && ARRAY_EMPTY(&a->mailboxes))
1762 {
1764 }
1765 return 0;
1766}
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition array.h:74
void neomutt_account_remove(struct NeoMutt *n, struct Account *a)
Remove an Account from the global list.
Definition neomutt.c:438
+ 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 167 of file mx.c.

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

1209{
1210 if ((req_size + 1) <= m->email_max)
1211 return;
1212
1213 // Step size to increase by
1214 // Larger mailboxes get a larger step (limited to 1000)
1215 const int grow = CLAMP(m->email_max, 25, 1000);
1216
1217 // Sanity checks
1218 req_size = ROUND_UP(req_size + 1, grow);
1219
1220 const size_t s = MAX(sizeof(struct Email *), sizeof(int));
1221 if ((req_size * s) < (m->email_max * s))
1222 {
1223 mutt_error("%s", strerror(ENOMEM));
1224 mutt_exit(1);
1225 }
1226
1227 if (m->emails)
1228 {
1229 MUTT_MEM_REALLOC(&m->emails, req_size, struct Email *);
1230 MUTT_MEM_REALLOC(&m->v2r, req_size, int);
1231 }
1232 else
1233 {
1234 m->emails = MUTT_MEM_CALLOC(req_size, struct Email *);
1235 m->v2r = MUTT_MEM_CALLOC(req_size, int);
1236 }
1237
1238 for (int i = m->email_max; i < req_size; i++)
1239 {
1240 m->emails[i] = NULL;
1241 m->v2r[i] = -1;
1242 }
1243
1244 m->email_max = req_size;
1245}
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition exit.c:41
#define ROUND_UP(NUM, STEP)
Definition memory.h:42
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:48
#define MUTT_MEM_REALLOC(pptr, n, type)
Definition memory.h:51
#define MAX(a, b)
Definition memory.h:37
#define CLAMP(val, lo, hi)
Definition memory.h:39
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 1254 of file mx.c.

1255{
1256 if (buf_is_empty(path))
1257 return -1;
1258
1259 enum MailboxType type = mx_path_probe(buf_string(path));
1260 const struct MxOps *ops = mx_get_ops(type);
1261 if (!ops || !ops->path_is_empty)
1262 return -1;
1263
1264 return ops->path_is_empty(path);
1265}
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 411 of file mx.c.

412{
413 if (!m)
414 return;
415
416 m->opened--;
417 if (m->opened != 0)
418 return;
419
420 /* never announce that a mailbox we've just left has new mail.
421 * TODO: really belongs in mx_mbox_close, but this is a nice hook point */
422 if (!m->peekonly)
424
425 if (m->mx_ops)
426 m->mx_ops->mbox_close(m);
427
431
432 if (m->emails)
433 {
434 for (int i = 0; i < m->msg_count; i++)
435 {
436 if (!m->emails[i])
437 break;
438 email_free(&m->emails[i]);
439 }
440 }
441
442 if (!m->visible)
443 {
444 mx_ac_remove(m, keep_account);
445 }
446}
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition hash.c:458
void mutt_mailbox_set_notified(struct Mailbox *m)
Note when the user was last notified of new mail.
int mx_ac_remove(struct Mailbox *m, bool keep_account)
Remove a Mailbox from an Account and delete Account if empty.
Definition mx.c:1754
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 124 of file mx.c.

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

1314{
1315 return m && m->mx_ops->tags_commit && m->mx_ops->tags_edit;
1316}
+ 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 1821 of file mx.c.

1822{
1823 if (!m)
1824 return -1;
1825
1826 if (m->readonly)
1827 {
1828 mutt_error(_("Can't toggle write on a readonly mailbox"));
1829 return -1;
1830 }
1831
1832 if (m->dontwrite)
1833 {
1834 m->dontwrite = false;
1835 mutt_message(_("Changes to folder will be written on folder exit"));
1836 }
1837 else
1838 {
1839 m->dontwrite = true;
1840 mutt_message(_("Changes to folder will not be written"));
1841 }
1842
1843 struct EventMailbox ev_m = { m };
1845 return 0;
1846}
+ 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 89 of file mx.c.

89 {
90 "mbox_type",
91 4,
92 (struct Mapping *) &MboxTypeMap,
93};
static const struct Mapping MboxTypeMap[]
Lookup table of mailbox types.
Definition mx.c:78
Mapping between user-readable string and a constant.
Definition mapping.h:33