NeoMutt  2025-12-11-694-ga89709
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
lib.h File Reference

IMAP network mailbox. More...

#include <stdbool.h>
#include <stddef.h>
#include <sys/types.h>
#include "core/lib.h"
#include "external.h"
+ Include dependency graph for lib.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

int imap_access (const char *path)
 Check permissions on an IMAP mailbox with a new connection.
 
enum MxStatus imap_check_mailbox (struct Mailbox *m, bool force)
 Use the NOOP or IDLE command to poll for new mail.
 
int imap_delete_mailbox (struct Mailbox *m, char *path)
 Delete a mailbox.
 
enum MxStatus imap_sync_mailbox (struct Mailbox *m, bool expunge, bool close)
 Sync all the changes to the server.
 
int imap_path_status (const char *path, bool queue)
 Refresh the number of total and new messages.
 
int imap_mailbox_status (struct Mailbox *m, bool queue)
 Refresh the number of total and new messages.
 
int imap_subscribe (const char *path, bool subscribe)
 Subscribe to a mailbox.
 
int imap_complete (struct Buffer *buf, const char *path)
 Try to complete an IMAP folder path.
 
int imap_fast_trash (struct Mailbox *m, const char *dest)
 Use server COPY command to copy deleted messages to trash.
 
enum MailboxType imap_path_probe (const char *path, const struct stat *st)
 Is this an IMAP Mailbox?
 
int imap_path_canon (struct Buffer *buf)
 Canonicalise a Mailbox path - Implements MxOps::path_canon() -.
 
void imap_notify_delete_email (struct Mailbox *m, struct Email *e)
 Inform IMAP that an Email has been deleted.
 
enum CommandResult parse_subscribe_to (const struct Command *cmd, struct Buffer *line, const struct ParseContext *pc, struct ParseError *pe)
 Parse the 'subscribe-to' command - Implements Command::parse() -.
 
enum CommandResult parse_unsubscribe_from (const struct Command *cmd, struct Buffer *line, const struct ParseContext *pc, struct ParseError *pe)
 Parse the 'unsubscribe-from' command - Implements Command::parse() -.
 
int imap_browse (const char *path, struct BrowserState *state)
 IMAP hook into the folder browser.
 
int imap_mailbox_create (const char *folder)
 Create a new IMAP mailbox.
 
int imap_mailbox_rename (const char *path)
 Rename a mailbox.
 
int imap_copy_messages (struct Mailbox *m, struct EmailArray *ea, const char *dest, enum MessageSaveOpt save_opt)
 Server COPY messages to another folder.
 
void imap_logout_all (void)
 Close all open connections.
 
int imap_parse_path (const char *path, struct ConnAccount *cac, char *mailbox, size_t mailboxlen)
 Parse an IMAP mailbox name into ConnAccount, name.
 
void imap_pretty_mailbox (char *path, size_t pathlen, const char *folder)
 Prettify an IMAP mailbox name.
 
int imap_mxcmp (const char *mx1, const char *mx2)
 Compare mailbox names, giving priority to INBOX.
 
int imap_wait_keep_alive (pid_t pid)
 Wait for a process to change state.
 
void imap_keep_alive (void)
 Poll the current folder to keep the connection alive.
 
void imap_get_parent_path (const char *path, char *buf, size_t buflen)
 Get the path of the parent folder.
 
void imap_clean_path (char *path, size_t plen)
 Cleans an IMAP path using imap_fix_path.
 
bool imap_search (struct Mailbox *m, const struct PatternList *pat)
 Find messages in mailbox matching a pattern.
 

Variables

const struct MxOps MxImapOps
 IMAP Mailbox - Implements MxOps -.
 

Detailed Description

IMAP network mailbox.

Authors
  • Richard Russon
  • Pietro Cerutti

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 lib.h.

Function Documentation

◆ imap_access()

int imap_access ( const char * path)

Check permissions on an IMAP mailbox with a new connection.

Parameters
pathMailbox path
Return values
0Success
<0Failure

TODO: ACL checks. Right now we assume if it exists we can mess with it. TODO: This method should take a Mailbox as parameter to be able to reuse the existing connection.

Definition at line 569 of file imap.c.

570{
571 if (imap_path_status(path, false) >= 0)
572 return 0;
573 return -1;
574}
int imap_path_status(const char *path, bool queue)
Refresh the number of total and new messages.
Definition imap.c:1354
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_check_mailbox()

enum MxStatus imap_check_mailbox ( struct Mailbox * m,
bool force )

Use the NOOP or IDLE command to poll for new mail.

Parameters
mMailbox
forceDon't wait
Return values
numMxStatus

Definition at line 1212 of file imap.c.

1213{
1214 if (!m || !m->account)
1215 return MX_STATUS_ERROR;
1216
1218 struct ImapMboxData *mdata = imap_mdata_get(m);
1219 if (!adata || !mdata)
1220 return MX_STATUS_ERROR;
1221
1222 /* overload keyboard timeout to avoid many mailbox checks in a row.
1223 * Most users don't like having to wait exactly when they press a key. */
1224 int rc = 0;
1225
1226 /* try IDLE first, unless force is set */
1227 const bool c_imap_idle = cs_subset_bool(NeoMutt->sub, "imap_idle");
1228 const short c_imap_keep_alive = cs_subset_number(NeoMutt->sub, "imap_keep_alive");
1229 if (!force && c_imap_idle && (adata->capabilities & IMAP_CAP_IDLE) &&
1230 ((adata->state != IMAP_IDLE) || (mutt_date_now() >= adata->lastread + c_imap_keep_alive)))
1231 {
1232 if (imap_cmd_idle(adata) < 0)
1233 return MX_STATUS_ERROR;
1234 }
1235 if (adata->state == IMAP_IDLE)
1236 {
1237 while ((rc = mutt_socket_poll(adata->conn, 0)) > 0)
1238 {
1239 if (imap_cmd_step(adata) != IMAP_RES_CONTINUE)
1240 {
1241 mutt_debug(LL_DEBUG1, "Error reading IDLE response\n");
1242 return MX_STATUS_ERROR;
1243 }
1244 }
1245 if (rc < 0)
1246 {
1247 mutt_debug(LL_DEBUG1, "Poll failed, disabling IDLE\n");
1248 adata->capabilities &= ~IMAP_CAP_IDLE; // Clear the flag
1249 }
1250 }
1251
1252 const short c_timeout = cs_subset_number(NeoMutt->sub, "timeout");
1253 if ((force || ((adata->state != IMAP_IDLE) && (mutt_date_now() >= adata->lastread + c_timeout))) &&
1254 (imap_exec(adata, "NOOP", IMAP_CMD_POLL) != IMAP_EXEC_SUCCESS))
1255 {
1256 return MX_STATUS_ERROR;
1257 }
1258
1259 /* We call this even when we haven't run NOOP in case we have pending
1260 * changes to process, since we can reopen here. */
1261 imap_cmd_finish(adata);
1262
1263 enum MxStatus check = MX_STATUS_OK;
1264 if (mdata->check_status & IMAP_EXPUNGE_PENDING)
1265 check = MX_STATUS_REOPENED;
1266 else if (mdata->check_status & IMAP_NEWMAIL_PENDING)
1267 check = MX_STATUS_NEW_MAIL;
1268 else if (mdata->check_status & IMAP_FLAGS_PENDING)
1269 check = MX_STATUS_FLAGS;
1270 else if (rc < 0)
1271 check = MX_STATUS_ERROR;
1272
1273 mdata->check_status = IMAP_OPEN_NO_FLAGS;
1274
1275 if (force)
1276 m->last_checked = 0; // force a check on the next mx_mbox_check() call
1277 return check;
1278}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition helpers.c:143
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition adata.c:158
int imap_cmd_idle(struct ImapAccountData *adata)
Enter the IDLE state.
Definition command.c:1573
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition command.c:1225
int imap_exec(struct ImapAccountData *adata, const char *cmdstr, ImapCmdFlags flags)
Execute a command and wait for the response from the server.
Definition command.c:1415
void imap_cmd_finish(struct ImapAccountData *adata)
Attempt to perform cleanup.
Definition command.c:1498
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition mdata.c:61
#define IMAP_CAP_IDLE
RFC2177: IDLE.
Definition private.h:133
@ IMAP_IDLE
Connection is idle.
Definition private.h:111
#define IMAP_EXPUNGE_PENDING
Messages on the server have been expunged.
Definition private.h:66
#define IMAP_OPEN_NO_FLAGS
No flags are set.
Definition private.h:63
#define IMAP_CMD_POLL
Poll the tcp connection before running the imap command.
Definition private.h:74
@ IMAP_EXEC_SUCCESS
Imap command executed or queued successfully.
Definition private.h:82
#define IMAP_NEWMAIL_PENDING
New mail is waiting on the server.
Definition private.h:67
#define IMAP_FLAGS_PENDING
Flags have changed on the server.
Definition private.h:68
#define IMAP_RES_CONTINUE
* ...
Definition private.h:55
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
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:59
@ MX_STATUS_ERROR
An error occurred.
Definition mxapi.h:60
@ MX_STATUS_OK
No changes.
Definition mxapi.h:61
@ MX_STATUS_FLAGS
Nondestructive flags change (IMAP)
Definition mxapi.h:65
@ MX_STATUS_REOPENED
Mailbox was reopened.
Definition mxapi.h:64
@ MX_STATUS_NEW_MAIL
New mail received in Mailbox.
Definition mxapi.h:62
int mutt_socket_poll(struct Connection *conn, time_t wait_secs)
Checks whether reads would block.
Definition socket.c:182
void * adata
Private data (for Mailbox backends)
Definition account.h:42
IMAP-specific Account data -.
Definition adata.h:40
time_t lastread
last time we read a command for the server
Definition adata.h:58
ImapCapFlags capabilities
Capability flags.
Definition adata.h:55
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition adata.h:44
struct Connection * conn
Connection to IMAP server.
Definition adata.h:41
IMAP-specific Mailbox data -.
Definition mdata.h:40
time_t last_checked
Last time we checked this mailbox for new mail.
Definition mailbox.h:104
void * mdata
Driver specific data.
Definition mailbox.h:131
struct Account * account
Account that owns this Mailbox.
Definition mailbox.h:126
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_delete_mailbox()

int imap_delete_mailbox ( struct Mailbox * m,
char * path )

Delete a mailbox.

Parameters
mMailbox
pathname of the mailbox to delete
Return values
0Success
-1Failure

Definition at line 611 of file imap.c.

612{
613 char buf[PATH_MAX + 7];
614 char mbox[PATH_MAX] = { 0 };
615
617 if (!adata)
618 return -1;
619
620 struct Url *url = url_parse(path);
621 if (!url)
622 return -1;
623
624 imap_munge_mbox_name(adata->unicode, mbox, sizeof(mbox), url->path);
625 url_free(&url);
626 snprintf(buf, sizeof(buf), "DELETE %s", mbox);
628 return -1;
629
630 return 0;
631}
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition private.h:71
void imap_munge_mbox_name(bool unicode, char *dest, size_t dlen, const char *src)
Quote awkward characters in a mailbox name.
Definition util.c:968
#define PATH_MAX
Definition mutt.h:49
bool unicode
If true, we can send UTF-8, and the server will use UTF8 rather than mUTF7.
Definition adata.h:63
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition url.h:69
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:

◆ imap_sync_mailbox()

enum MxStatus imap_sync_mailbox ( struct Mailbox * m,
bool expunge,
bool close )

Sync all the changes to the server.

Parameters
mMailbox
expungeif true do expunge
closeif true we move imap state to CLOSE
Return values
enumMxStatus
Note
The flag retvals come from a call to imap_check_mailbox()

Definition at line 1661 of file imap.c.

1662{
1663 if (!m)
1664 return -1;
1665
1666 struct Email **emails = NULL;
1667 int rc;
1668
1670 struct ImapMboxData *mdata = imap_mdata_get(m);
1671 if (!adata || !mdata)
1672 return MX_STATUS_ERROR;
1673
1674 if (adata->state < IMAP_SELECTED)
1675 {
1676 mutt_debug(LL_DEBUG2, "no mailbox selected\n");
1677 return -1;
1678 }
1679
1680 /* This function is only called when the calling code expects the context
1681 * to be changed. */
1683
1684 enum MxStatus check = imap_check_mailbox(m, false);
1685 if (check == MX_STATUS_ERROR)
1686 return check;
1687
1688 /* if we are expunging anyway, we can do deleted messages very quickly... */
1689 if (expunge && (m->rights & MUTT_ACL_DELETE))
1690 {
1691 struct UidArray uida = ARRAY_HEAD_INITIALIZER;
1692 select_email_uids(m->emails, m->msg_count, MUTT_DELETED, true, false, &uida);
1693 ARRAY_SORT(&uida, imap_sort_uid, NULL);
1694 rc = imap_exec_msg_set(adata, "UID STORE", "+FLAGS.SILENT (\\Deleted)", &uida);
1695 ARRAY_FREE(&uida);
1696 if (rc < 0)
1697 {
1698 mutt_error(_("Expunge failed"));
1699 return rc;
1700 }
1701
1702 if (rc > 0)
1703 {
1704 /* mark these messages as unchanged so second pass ignores them. Done
1705 * here so BOGUS UW-IMAP 4.7 SILENT FLAGS updates are ignored. */
1706 for (int i = 0; i < m->msg_count; i++)
1707 {
1708 struct Email *e = m->emails[i];
1709 if (!e)
1710 break;
1711 if (e->deleted && e->changed)
1712 e->active = false;
1713 }
1714 if (m->verbose)
1715 {
1716 mutt_message(ngettext("Marking %d message deleted...",
1717 "Marking %d messages deleted...", rc),
1718 rc);
1719 }
1720 }
1721 }
1722
1723#ifdef USE_HCACHE
1724 imap_hcache_open(adata, mdata, true);
1725#endif
1726
1727 /* save messages with real (non-flag) changes */
1728 for (int i = 0; i < m->msg_count; i++)
1729 {
1730 struct Email *e = m->emails[i];
1731 if (!e)
1732 break;
1733
1734 if (e->deleted)
1735 {
1736 imap_cache_del(m, e);
1737#ifdef USE_HCACHE
1738 imap_hcache_del(mdata, imap_edata_get(e)->uid);
1739#endif
1740 }
1741
1742 if (e->active && e->changed)
1743 {
1744#ifdef USE_HCACHE
1745 imap_hcache_put(mdata, e);
1746#endif
1747 /* if the message has been rethreaded or attachments have been deleted
1748 * we delete the message and reupload it.
1749 * This works better if we're expunging, of course. */
1750 if (e->env->changed || e->attach_del)
1751 {
1752 /* L10N: The plural is chosen by the last %d, i.e. the total number */
1753 if (m->verbose)
1754 {
1755 mutt_message(ngettext("Saving changed message... [%d/%d]",
1756 "Saving changed messages... [%d/%d]", m->msg_count),
1757 i + 1, m->msg_count);
1758 }
1759 bool save_append = m->append;
1760 m->append = true;
1762 m->append = save_append;
1763 e->env->changed = false;
1764 }
1765 }
1766 }
1767
1768#ifdef USE_HCACHE
1769 imap_hcache_close(mdata);
1770#endif
1771
1772 /* presort here to avoid doing 10 resorts in imap_exec_msg_set */
1773 emails = MUTT_MEM_MALLOC(m->msg_count, struct Email *);
1774 memcpy(emails, m->emails, m->msg_count * sizeof(struct Email *));
1775 mutt_qsort_r(emails, m->msg_count, sizeof(struct Email *), imap_sort_email_uid, NULL);
1776
1777 rc = sync_helper(m, emails, m->msg_count, MUTT_ACL_DELETE, MUTT_DELETED, "\\Deleted");
1778 if (rc >= 0)
1779 rc |= sync_helper(m, emails, m->msg_count, MUTT_ACL_WRITE, MUTT_FLAG, "\\Flagged");
1780 if (rc >= 0)
1781 rc |= sync_helper(m, emails, m->msg_count, MUTT_ACL_WRITE, MUTT_OLD, "Old");
1782 if (rc >= 0)
1783 rc |= sync_helper(m, emails, m->msg_count, MUTT_ACL_SEEN, MUTT_READ, "\\Seen");
1784 if (rc >= 0)
1785 rc |= sync_helper(m, emails, m->msg_count, MUTT_ACL_WRITE, MUTT_REPLIED, "\\Answered");
1786
1787 FREE(&emails);
1788
1789 /* Flush the queued flags if any were changed in sync_helper. */
1790 if (rc > 0)
1791 if (imap_exec(adata, NULL, IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS)
1792 rc = -1;
1793
1794 if (rc < 0)
1795 {
1796 if (close)
1797 {
1798 if (query_yesorno(_("Error saving flags. Close anyway?"), MUTT_NO) == MUTT_YES)
1799 {
1800 adata->state = IMAP_AUTHENTICATED;
1801 return 0;
1802 }
1803 }
1804 else
1805 {
1806 mutt_error(_("Error saving flags"));
1807 }
1808 return -1;
1809 }
1810
1811 /* Update local record of server state to reflect the synchronization just
1812 * completed. imap_read_headers always overwrites hcache-origin flags, so
1813 * there is no need to mutate the hcache after flag-only changes. */
1814 for (int i = 0; i < m->msg_count; i++)
1815 {
1816 struct Email *e = m->emails[i];
1817 if (!e)
1818 break;
1819 struct ImapEmailData *edata = imap_edata_get(e);
1820 edata->deleted = e->deleted;
1821 edata->flagged = e->flagged;
1822 edata->old = e->old;
1823 edata->read = e->read;
1824 edata->replied = e->replied;
1825 e->changed = false;
1826 }
1827 m->changed = false;
1828
1829 /* We must send an EXPUNGE command if we're not closing. */
1830 if (expunge && !close && (m->rights & MUTT_ACL_DELETE))
1831 {
1832 if (m->verbose)
1833 mutt_message(_("Expunging messages from server..."));
1834 /* Set expunge bit so we don't get spurious reopened messages */
1835 mdata->reopen |= IMAP_EXPUNGE_EXPECTED;
1836 if (imap_exec(adata, "EXPUNGE", IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS)
1837 {
1839 imap_error(_("imap_sync_mailbox: EXPUNGE failed"), adata->buf);
1840 return -1;
1841 }
1843 }
1844
1845 if (expunge && close)
1846 {
1847 adata->closing = true;
1848 imap_exec(adata, "CLOSE", IMAP_CMD_NO_FLAGS);
1849 adata->state = IMAP_AUTHENTICATED;
1850 }
1851
1852 const bool c_message_cache_clean = cs_subset_bool(NeoMutt->sub, "message_cache_clean");
1853 if (c_message_cache_clean)
1855
1856 return check;
1857}
#define ARRAY_SORT(head, fn, sdata)
Sort an array.
Definition array.h:373
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:209
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition array.h:58
#define MUTT_ACL_DELETE
Delete a message.
Definition mailbox.h:62
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition mailbox.h:70
#define MUTT_ACL_SEEN
Change the 'seen' status of a message.
Definition mailbox.h:69
int mutt_save_message_mbox(struct Mailbox *m_src, struct Email *e, enum MessageSaveOpt save_opt, enum MessageTransformOpt transform_opt, struct Mailbox *m_dst)
Save a message to a given mailbox.
Definition external.c:739
@ TRANSFORM_NONE
No transformation.
Definition external.h:43
@ SAVE_MOVE
Move message to another mailbox, removing the original.
Definition external.h:54
#define mutt_error(...)
Definition logging2.h:94
#define mutt_message(...)
Definition logging2.h:93
int imap_sort_uid(const void *a, const void *b, void *sdata)
Compare two UIDs - Implements sort_t -.
Definition msg_set.c:54
static int imap_sort_email_uid(const void *a, const void *b, void *sdata)
Compare two Emails by UID - Implements sort_t -.
Definition imap.c:1080
struct ImapEmailData * imap_edata_get(struct Email *e)
Get the private data for this Email.
Definition edata.c:66
int imap_cache_clean(struct Mailbox *m)
Delete all the entries in the message cache.
Definition message.c:1916
int imap_cache_del(struct Mailbox *m, struct Email *e)
Delete an email from the body cache.
Definition message.c:1897
void imap_allow_reopen(struct Mailbox *m)
Allow re-opening a folder upon expunge.
Definition util.c:1075
@ IMAP_AUTHENTICATED
Connection is authenticated.
Definition private.h:107
@ IMAP_SELECTED
Mailbox is selected.
Definition private.h:108
void imap_hcache_open(struct ImapAccountData *adata, struct ImapMboxData *mdata, bool create)
Open a header cache.
Definition util.c:304
#define IMAP_EXPUNGE_EXPECTED
Messages will be expunged from the server.
Definition private.h:65
int imap_hcache_put(struct ImapMboxData *mdata, struct Email *e)
Add an entry to the header cache.
Definition util.c:385
void imap_error(const char *where, const char *msg)
Show an error and abort.
Definition util.c:662
void imap_hcache_close(struct ImapMboxData *mdata)
Close the header cache.
Definition util.c:345
int imap_hcache_del(struct ImapMboxData *mdata, unsigned int uid)
Delete an item from the header cache.
Definition util.c:403
static int sync_helper(struct Mailbox *m, struct Email **emails, int num_emails, AclFlags right, enum MessageType flag, const char *name)
Sync flag changes to the server.
Definition imap.c:404
static int select_email_uids(struct Email **emails, int num_emails, enum MessageType flag, bool changed, bool invert, struct UidArray *uida)
Create a list of Email UIDs by type.
Definition imap.c:334
enum MxStatus imap_check_mailbox(struct Mailbox *m, bool force)
Use the NOOP or IDLE command to poll for new mail.
Definition imap.c:1212
@ LL_DEBUG2
Log at debug level 2.
Definition logging2.h:46
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
#define MUTT_MEM_MALLOC(n, type)
Definition memory.h:53
int imap_exec_msg_set(struct ImapAccountData *adata, const char *pre, const char *post, struct UidArray *uida)
Execute a command using a set of UIDs.
Definition msg_set.c:132
#define _(a)
Definition message.h:28
@ MUTT_READ
Messages that have been read.
Definition mutt.h:92
@ MUTT_OLD
Old messages.
Definition mutt.h:90
@ MUTT_FLAG
Flagged messages.
Definition mutt.h:98
@ MUTT_DELETED
Deleted messages.
Definition mutt.h:97
@ MUTT_REPLIED
Messages that have been replied to.
Definition mutt.h:91
void mutt_qsort_r(void *base, size_t nmemb, size_t size, sort_t compar, void *sdata)
Sort an array, where the comparator has access to opaque data rather than requiring global variables.
Definition qsort_r.c:72
@ 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_yesorno(const char *prompt, enum QuadOption def)
Ask the user a Yes/No question.
Definition question.c:329
The envelope/body of an email.
Definition email.h:39
bool read
Email is read.
Definition email.h:50
struct Envelope * env
Envelope information.
Definition email.h:68
void * edata
Driver-specific data.
Definition email.h:74
bool active
Message is not to be removed.
Definition email.h:76
bool old
Email is seen, but unread.
Definition email.h:49
bool changed
Email has been edited.
Definition email.h:77
bool attach_del
Has an attachment marked for deletion.
Definition email.h:99
bool flagged
Marked important?
Definition email.h:47
bool replied
Email has been replied to.
Definition email.h:51
bool deleted
Email is deleted.
Definition email.h:78
unsigned char changed
Changed fields, e.g. MUTT_ENV_CHANGED_SUBJECT.
Definition envelope.h:90
bool closing
If true, we are waiting for CLOSE completion.
Definition adata.h:43
char * buf
Command buffer.
Definition adata.h:60
IMAP-specific Email data -.
Definition edata.h:35
ImapOpenFlags reopen
Flags, e.g. IMAP_REOPEN_ALLOW.
Definition mdata.h:45
bool changed
Mailbox has been modified.
Definition mailbox.h:109
bool append
Mailbox is opened in append mode.
Definition mailbox.h:108
int msg_count
Total number of messages.
Definition mailbox.h:87
AclFlags rights
ACL bits, see AclFlags.
Definition mailbox.h:118
struct Email ** emails
Array of Emails.
Definition mailbox.h:95
bool verbose
Display status messages?
Definition mailbox.h:116
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_path_status()

int imap_path_status ( const char * path,
bool queue )

Refresh the number of total and new messages.

Parameters
pathMailbox path
queueQueue the STATUS command
Return values
numTotal number of messages

Definition at line 1354 of file imap.c.

1355{
1356 struct Mailbox *m = mx_mbox_find2(path);
1357
1358 const bool is_temp = !m;
1359 if (is_temp)
1360 {
1361 m = mx_path_resolve(path);
1362 if (!mx_mbox_ac_link(m))
1363 {
1364 mailbox_free(&m);
1365 return 0;
1366 }
1367 }
1368
1369 int rc = imap_mailbox_status(m, queue);
1370
1371 if (is_temp)
1372 {
1373 mx_ac_remove(m, false);
1374 mailbox_free(&m);
1375 }
1376
1377 return rc;
1378}
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition mailbox.c:90
int imap_mailbox_status(struct Mailbox *m, bool queue)
Refresh the number of total and new messages.
Definition imap.c:1389
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 Mailbox * mx_mbox_find2(const char *path)
Find a Mailbox on an Account.
Definition mx.c:1615
bool mx_mbox_ac_link(struct Mailbox *m)
Link a Mailbox to an existing or new Account.
Definition mx.c:248
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition mx.c:1647
A mailbox.
Definition mailbox.h:78
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_mailbox_status()

int imap_mailbox_status ( struct Mailbox * m,
bool queue )

Refresh the number of total and new messages.

Parameters
mMailbox
queueQueue the STATUS command
Return values
numTotal number of messages
-1Error
Note
Prepare the mailbox if we are not connected

Definition at line 1389 of file imap.c.

1390{
1392 struct ImapMboxData *mdata = imap_mdata_get(m);
1393 if (!adata || !mdata)
1394 return -1;
1395 return imap_status(adata, mdata, queue);
1396}
static int imap_status(struct ImapAccountData *adata, struct ImapMboxData *mdata, bool queue)
Refresh the number of total and new messages.
Definition imap.c:1287
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_subscribe()

int imap_subscribe ( const char * path,
bool subscribe )

Subscribe to a mailbox.

Parameters
pathMailbox path
subscribeTrue: subscribe, false: unsubscribe
Return values
0Success
-1Failure

Definition at line 1405 of file imap.c.

1406{
1407 struct ImapAccountData *adata = NULL;
1408 struct ImapMboxData *mdata = NULL;
1409
1410 if (imap_adata_find(path, &adata, &mdata) < 0)
1411 return -1;
1412
1413 if (subscribe)
1414 mutt_message(_("Subscribing to %s..."), mdata->name);
1415 else
1416 mutt_message(_("Unsubscribing from %s..."), mdata->name);
1417
1418 char buf[2048] = { 0 };
1419 snprintf(buf, sizeof(buf), "%sSUBSCRIBE %s", subscribe ? "" : "UN", mdata->munge_name);
1420
1421 if (imap_exec(adata, buf, IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS)
1422 {
1423 imap_mdata_free((void *) &mdata);
1424 return -1;
1425 }
1426
1427 const bool c_imap_check_subscribed = cs_subset_bool(NeoMutt->sub, "imap_check_subscribed");
1428 if (c_imap_check_subscribed)
1429 {
1430 if (subscribe)
1431 {
1432 struct Buffer *err = buf_pool_get();
1433 if (!mailbox_add_simple(path, err))
1434 mutt_debug(LL_DEBUG1, "Error adding subscribed mailbox: %s\n", buf_string(err));
1435 buf_pool_release(&err);
1436 }
1437 else
1438 {
1439 if (!mailbox_remove_simple(path))
1440 mutt_debug(LL_DEBUG1, "Error removing subscribed mailbox: %s\n", path);
1441 }
1442 }
1443
1444 if (subscribe)
1445 mutt_message(_("Subscribed to %s"), mdata->name);
1446 else
1447 mutt_message(_("Unsubscribed from %s"), mdata->name);
1448 imap_mdata_free((void *) &mdata);
1449 return 0;
1450}
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
void imap_mdata_free(void **ptr)
Free the private Mailbox data - Implements Mailbox::mdata_free() -.
Definition mdata.c:40
int imap_adata_find(const char *path, struct ImapAccountData **adata, struct ImapMboxData **mdata)
Find the Account data for this path.
Definition util.c:72
bool mailbox_remove_simple(const char *mailbox)
Remove a Mailbox.
Definition mailboxes.c:397
bool mailbox_add_simple(const char *mailbox, struct Buffer *err)
Add a new Mailbox.
Definition mailboxes.c:157
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
String manipulation buffer.
Definition buffer.h:36
char * name
Mailbox name.
Definition mdata.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_complete()

int imap_complete ( struct Buffer * buf,
const char * path )

Try to complete an IMAP folder path.

Parameters
bufBuffer for result
pathPartial mailbox name to complete
Return values
0Success
-1Failure

Given a partial IMAP folder path, return a string which adds as much to the path as is unique

Definition at line 1462 of file imap.c.

1463{
1464 struct ImapAccountData *adata = NULL;
1465 struct ImapMboxData *mdata = NULL;
1466 char tmp[2048] = { 0 };
1467 struct ImapList listresp = { 0 };
1468 struct Buffer *completion_buf = NULL;
1469 size_t clen;
1470 int completions = 0;
1471 int rc;
1472
1473 if (imap_adata_find(path, &adata, &mdata) < 0)
1474 {
1475 buf_strcpy(buf, path);
1476 return complete_hosts(buf);
1477 }
1478
1479 /* fire off command */
1480 const bool c_imap_list_subscribed = cs_subset_bool(NeoMutt->sub, "imap_list_subscribed");
1481 snprintf(tmp, sizeof(tmp), "%s \"\" \"%s%%\"",
1482 c_imap_list_subscribed ? "LSUB" : "LIST", mdata->real_name);
1483
1484 imap_cmd_start(adata, tmp);
1485
1486 /* and see what the results are */
1487 completion_buf = buf_pool_get();
1488 buf_strcpy(completion_buf, mdata->name);
1489 imap_mdata_free((void *) &mdata);
1490
1491 adata->cmdresult = &listresp;
1492 do
1493 {
1494 listresp.name = NULL;
1495 rc = imap_cmd_step(adata);
1496
1497 if ((rc == IMAP_RES_CONTINUE) && listresp.name)
1498 {
1499 /* if the folder isn't selectable, append delimiter to force browse
1500 * to enter it on second tab. */
1501 if (listresp.noselect)
1502 {
1503 clen = strlen(listresp.name);
1504 listresp.name[clen++] = listresp.delim;
1505 listresp.name[clen] = '\0';
1506 }
1507 /* copy in first word */
1508 if (!completions)
1509 {
1510 buf_strcpy(completion_buf, listresp.name);
1511 completions++;
1512 continue;
1513 }
1514
1515 longest_common_prefix(completion_buf, listresp.name, 0);
1516 completions++;
1517 }
1518 } while (rc == IMAP_RES_CONTINUE);
1519 adata->cmdresult = NULL;
1520
1521 if (completions)
1522 {
1523 /* reformat output */
1524 imap_buf_qualify_path(buf, &adata->conn->account, completion_buf->data);
1525 pretty_mailbox(buf);
1526 buf_fix_dptr(buf);
1527 buf_pool_release(&completion_buf);
1528 return 0;
1529 }
1530
1531 buf_pool_release(&completion_buf);
1532 return -1;
1533}
void buf_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition buffer.c:182
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
int imap_cmd_start(struct ImapAccountData *adata, const char *cmdstr)
Given an IMAP command, send it to the server.
Definition command.c:1211
void imap_buf_qualify_path(struct Buffer *buf, struct ConnAccount *conn_account, char *path)
Make an absolute IMAP folder target to a buffer.
Definition util.c:871
static size_t longest_common_prefix(struct Buffer *buf, const char *src, size_t start)
Find longest prefix common to two strings.
Definition imap.c:453
static int complete_hosts(struct Buffer *buf)
Look for completion matches for mailboxes.
Definition imap.c:476
void pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition muttlib.c:428
char * data
Pointer to data.
Definition buffer.h:37
struct ConnAccount account
Account details: username, password, etc.
Definition connection.h:49
struct ImapList * cmdresult
Resuls of complicated commands.
Definition adata.h:69
Items in an IMAP browser.
Definition private.h:149
bool noselect
Mailbox is not selectable.
Definition private.h:152
char * name
Mailbox name.
Definition private.h:150
char delim
Hierarchy delimiter.
Definition private.h:151
char * real_name
Original Mailbox name, e.g.: INBOX can be just \0.
Definition mdata.h:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_fast_trash()

int imap_fast_trash ( struct Mailbox * m,
const char * dest )

Use server COPY command to copy deleted messages to trash.

Parameters
mMailbox
destMailbox to move to
Return values
-1Error
0Success
1Non-fatal error - try fetch/append

Definition at line 1543 of file imap.c.

1544{
1545 char prompt[1024] = { 0 };
1546 int rc = -1;
1547 bool triedcreate = false;
1548 enum QuadOption err_continue = MUTT_NO;
1549
1551 if (!adata)
1552 return -1;
1553
1554 struct ImapAccountData *dest_adata = NULL;
1555 struct ImapMboxData *dest_mdata = NULL;
1556
1557 if (imap_adata_find(dest, &dest_adata, &dest_mdata) < 0)
1558 return -1;
1559
1560 struct Buffer *sync_cmd = buf_pool_get();
1561
1562 /* check that the save-to folder is in the same account */
1563 if (!imap_account_match(&(adata->conn->account), &(dest_adata->conn->account)))
1564 {
1565 mutt_debug(LL_DEBUG3, "%s not same server as %s\n", dest, mailbox_path(m));
1566 goto out;
1567 }
1568
1569 for (int i = 0; i < m->msg_count; i++)
1570 {
1571 struct Email *e = m->emails[i];
1572 if (!e)
1573 break;
1574 if (e->active && e->changed && e->deleted && !e->purge)
1575 {
1576 rc = imap_sync_message_for_copy(m, e, sync_cmd, &err_continue);
1577 if (rc < 0)
1578 {
1579 mutt_debug(LL_DEBUG1, "could not sync\n");
1580 goto out;
1581 }
1582 }
1583 }
1584
1585 /* loop in case of TRYCREATE */
1586 do
1587 {
1588 struct UidArray uida = ARRAY_HEAD_INITIALIZER;
1589 select_email_uids(m->emails, m->msg_count, MUTT_TRASH, false, false, &uida);
1590 ARRAY_SORT(&uida, imap_sort_uid, NULL);
1591 rc = imap_exec_msg_set(adata, "UID COPY", dest_mdata->munge_name, &uida);
1592 if (rc == 0)
1593 {
1594 mutt_debug(LL_DEBUG1, "No messages to trash\n");
1595 rc = -1;
1596 goto out;
1597 }
1598 else if (rc < 0)
1599 {
1600 mutt_debug(LL_DEBUG1, "could not queue copy\n");
1601 goto out;
1602 }
1603 else if (m->verbose)
1604 {
1605 mutt_message(ngettext("Copying %d message to %s...", "Copying %d messages to %s...", rc),
1606 rc, dest_mdata->name);
1607 }
1608 ARRAY_FREE(&uida);
1609
1610 /* let's get it on */
1611 rc = imap_exec(adata, NULL, IMAP_CMD_NO_FLAGS);
1612 if (rc == IMAP_EXEC_ERROR)
1613 {
1614 if (triedcreate)
1615 {
1616 mutt_debug(LL_DEBUG1, "Already tried to create mailbox %s\n", dest_mdata->name);
1617 break;
1618 }
1619 /* bail out if command failed for reasons other than nonexistent target */
1620 if (!mutt_istr_startswith(imap_get_qualifier(adata->buf), "[TRYCREATE]"))
1621 break;
1622 mutt_debug(LL_DEBUG3, "server suggests TRYCREATE\n");
1623 snprintf(prompt, sizeof(prompt), _("Create %s?"), dest_mdata->name);
1624 const bool c_confirm_create = cs_subset_bool(NeoMutt->sub, "confirm_create");
1625 if (c_confirm_create &&
1626 (query_yesorno_help(prompt, MUTT_YES, NeoMutt->sub, "confirm_create") != MUTT_YES))
1627 {
1629 goto out;
1630 }
1631 if (imap_create_mailbox(adata, dest_mdata->name) < 0)
1632 break;
1633 triedcreate = true;
1634 }
1635 } while (rc == IMAP_EXEC_ERROR);
1636
1637 if (rc != IMAP_EXEC_SUCCESS)
1638 {
1639 imap_error("imap_fast_trash", adata->buf);
1640 goto out;
1641 }
1642
1643 rc = IMAP_EXEC_SUCCESS;
1644
1645out:
1646 buf_pool_release(&sync_cmd);
1647 imap_mdata_free((void *) &dest_mdata);
1648
1649 return ((rc == IMAP_EXEC_SUCCESS) ? 0 : -1);
1650}
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition mailbox.h:213
@ IMAP_EXEC_ERROR
Imap command failure.
Definition private.h:83
bool imap_account_match(const struct ConnAccount *a1, const struct ConnAccount *a2)
Compare two Accounts.
Definition util.c:1103
char * imap_get_qualifier(char *buf)
Get the qualifier from a tagged response.
Definition util.c:809
int imap_create_mailbox(struct ImapAccountData *adata, const char *mailbox)
Create a new mailbox.
Definition imap.c:542
int imap_sync_message_for_copy(struct Mailbox *m, struct Email *e, struct Buffer *cmd, enum QuadOption *err_continue)
Update server to reflect the flags of a single message.
Definition imap.c:1106
@ LL_DEBUG3
Log at debug level 3.
Definition logging2.h:47
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition string.c:246
@ MUTT_TRASH
Trashed messages.
Definition mutt.h:104
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
QuadOption
Possible values for a quad-option.
Definition quad.h:36
enum QuadOption query_yesorno_help(const char *prompt, enum QuadOption def, struct ConfigSubset *sub, const char *name)
Ask the user a Yes/No question offering help.
Definition question.c:357
bool purge
Skip trash folder when deleting.
Definition email.h:79
char * munge_name
Munged version of the mailbox name.
Definition mdata.h:42
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_notify_delete_email()

void imap_notify_delete_email ( struct Mailbox * m,
struct Email * e )

Inform IMAP that an Email has been deleted.

Parameters
mMailbox
eEmail

Definition at line 828 of file imap.c.

829{
830 struct ImapMboxData *mdata = imap_mdata_get(m);
832
833 if (!mdata || !edata)
834 return;
835
836 imap_msn_remove(&mdata->msn, edata->msn - 1);
837 edata->msn = 0;
838}
void imap_msn_remove(struct MSNArray *msn, int idx)
Remove an entry from the cache.
Definition msn.c:116
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_browse()

int imap_browse ( const char * path,
struct BrowserState * state )

IMAP hook into the folder browser.

Parameters
pathCurrent folder
stateBrowserState to populate
Return values
0Success
-1Failure

Fill out browser_state, given a current folder to browse

Definition at line 196 of file browse.c.

197{
198 struct ImapAccountData *adata = NULL;
199 struct ImapList list = { 0 };
200 struct ConnAccount cac = { { 0 } };
201 char buf[PATH_MAX + 16];
202 char mbox[PATH_MAX] = { 0 };
203 char munged_mbox[PATH_MAX] = { 0 };
204 const char *list_cmd = NULL;
205 int len;
206 int n;
207 bool showparents = false;
208 int rc = -1;
209
210 if (imap_parse_path(path, &cac, buf, sizeof(buf)))
211 {
212 mutt_error(_("%s is an invalid IMAP path"), path);
213 return -1;
214 }
215
216 const bool c_imap_check_subscribed = cs_subset_bool(NeoMutt->sub, "imap_check_subscribed");
217 cs_subset_str_native_set(NeoMutt->sub, "imap_check_subscribed", false, NULL);
218
219 // Pick first mailbox connected to the same server
220 struct MailboxArray ma = neomutt_mailboxes_get(NeoMutt, MUTT_IMAP);
221 struct Mailbox **mp = NULL;
222 ARRAY_FOREACH(mp, &ma)
223 {
224 adata = imap_adata_get(*mp);
225 // Pick first mailbox connected on the same server
226 if (imap_account_match(&adata->conn->account, &cac))
227 break;
228 adata = NULL;
229 }
230 ARRAY_FREE(&ma); // Clean up the ARRAY, but not the Mailboxes
231
232 if (!adata)
233 goto fail;
234
235 const bool c_imap_list_subscribed = cs_subset_bool(NeoMutt->sub, "imap_list_subscribed");
236 if (c_imap_list_subscribed)
237 {
238 /* RFC3348 section 3 states LSUB is unreliable for hierarchy information.
239 * The newer LIST extensions are designed for this. */
241 list_cmd = "LIST (SUBSCRIBED RECURSIVEMATCH)";
242 else
243 list_cmd = "LSUB";
244 }
245 else
246 {
247 list_cmd = "LIST";
248 }
249
250 mutt_message(_("Getting folder list..."));
251
252 /* skip check for parents when at the root */
253 if (buf[0] == '\0')
254 {
255 mbox[0] = '\0';
256 n = 0;
257 }
258 else
259 {
260 imap_fix_path_with_delim(adata->delim, buf, mbox, sizeof(mbox));
261 n = mutt_str_len(mbox);
262 }
263
264 if (n > 0)
265 {
266 int rc_step;
267 mutt_debug(LL_DEBUG3, "mbox: %s\n", mbox);
268
269 /* if our target exists and has inferiors, enter it if we
270 * aren't already going to */
271 imap_munge_mbox_name(adata->unicode, munged_mbox, sizeof(munged_mbox), mbox);
272 len = snprintf(buf, sizeof(buf), "%s \"\" %s", list_cmd, munged_mbox);
274 snprintf(buf + len, sizeof(buf) - len, " RETURN (CHILDREN)");
275 imap_cmd_start(adata, buf);
276 adata->cmdresult = &list;
277 do
278 {
279 list.name = 0;
280 rc_step = imap_cmd_step(adata);
281 if ((rc_step == IMAP_RES_CONTINUE) && list.name)
282 {
283 if (!list.noinferiors && list.name[0] &&
284 (imap_mxcmp(list.name, mbox) == 0) && (n < sizeof(mbox) - 1))
285 {
286 mbox[n++] = list.delim;
287 mbox[n] = '\0';
288 }
289 }
290 } while (rc_step == IMAP_RES_CONTINUE);
291 adata->cmdresult = NULL;
292
293 /* if we're descending a folder, mark it as current in browser_state */
294 if (mbox[n - 1] == list.delim)
295 {
296 showparents = true;
297 imap_qualify_path(buf, sizeof(buf), &cac, mbox);
298 state->folder = mutt_str_dup(buf);
299 n--;
300 }
301
302 /* Find superiors to list
303 * Note: UW-IMAP servers return folder + delimiter when asked to list
304 * folder + delimiter. Cyrus servers don't. So we ask for folder,
305 * and tack on delimiter ourselves.
306 * Further note: UW-IMAP servers return nothing when asked for
307 * NAMESPACES without delimiters at the end. Argh! */
308 for (n--; n >= 0 && mbox[n] != list.delim; n--)
309 ; // do nothing
310
311 if (n > 0) /* "aaaa/bbbb/" -> "aaaa" */
312 {
313 /* forget the check, it is too delicate (see above). Have we ever
314 * had the parent not exist? */
315 char ctmp = mbox[n];
316 mbox[n] = '\0';
317
318 if (showparents)
319 {
320 mutt_debug(LL_DEBUG3, "adding parent %s\n", mbox);
321 add_folder(list.delim, mbox, true, false, state, true);
322 }
323
324 /* if our target isn't a folder, we are in our superior */
325 if (!state->folder)
326 {
327 /* store folder with delimiter */
328 mbox[n++] = ctmp;
329 ctmp = mbox[n];
330 mbox[n] = '\0';
331 imap_qualify_path(buf, sizeof(buf), &cac, mbox);
332 state->folder = mutt_str_dup(buf);
333 }
334 mbox[n] = ctmp;
335 }
336 else
337 {
338 /* "/bbbb/" -> add "/", "aaaa/" -> add "" */
339 char relpath[2] = { 0 };
340 /* folder may be "/" */
341 snprintf(relpath, sizeof(relpath), "%c", (n < 0) ? '\0' : adata->delim);
342 if (showparents)
343 add_folder(adata->delim, relpath, true, false, state, true);
344 if (!state->folder)
345 {
346 imap_qualify_path(buf, sizeof(buf), &cac, relpath);
347 state->folder = mutt_str_dup(buf);
348 }
349 }
350 }
351
352 /* no namespace, no folder: set folder to host only */
353 if (!state->folder)
354 {
355 imap_qualify_path(buf, sizeof(buf), &cac, NULL);
356 state->folder = mutt_str_dup(buf);
357 }
358
359 mutt_debug(LL_DEBUG3, "Quoting mailbox scan: %s -> ", mbox);
360 snprintf(buf, sizeof(buf), "%s%%", mbox);
361 imap_munge_mbox_name(adata->unicode, munged_mbox, sizeof(munged_mbox), buf);
362 mutt_debug(LL_DEBUG3, "%s\n", munged_mbox);
363 len = snprintf(buf, sizeof(buf), "%s \"\" %s", list_cmd, munged_mbox);
365 snprintf(buf + len, sizeof(buf) - len, " RETURN (CHILDREN)");
366 if (browse_add_list_result(adata, buf, state, false))
367 goto fail;
368
369 if (ARRAY_EMPTY(&state->entry))
370 {
371 // L10N: (%s) is the name / path of the folder we were trying to browse
372 mutt_error(_("No such folder: %s"), path);
373 goto fail;
374 }
375
377 rc = 0;
378
379fail:
380 cs_subset_str_native_set(NeoMutt->sub, "imap_check_subscribed",
381 c_imap_check_subscribed, NULL);
382 return rc;
383}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition array.h:74
static int browse_add_list_result(struct ImapAccountData *adata, const char *cmd, struct BrowserState *bstate, bool isparent)
Add entries to the folder browser.
Definition browse.c:154
static void add_folder(char delim, char *folder, bool noselect, bool noinferiors, struct BrowserState *state, bool isparent)
Format and add an IMAP folder to the browser.
Definition browse.c:68
@ MUTT_IMAP
'IMAP' Mailbox type
Definition mailbox.h:49
int imap_parse_path(const char *path, struct ConnAccount *cac, char *mailbox, size_t mailboxlen)
Parse an IMAP mailbox name into ConnAccount, name.
Definition util.c:479
int imap_mxcmp(const char *mx1, const char *mx2)
Compare mailbox names, giving priority to INBOX.
Definition util.c:550
void imap_qualify_path(char *buf, size_t buflen, struct ConnAccount *conn_account, char *path)
Make an absolute IMAP folder target.
Definition util.c:857
char * imap_fix_path_with_delim(char delim, const char *mailbox, char *path, size_t plen)
Fix up the imap path.
Definition util.c:715
#define IMAP_CAP_LIST_EXTENDED
RFC5258: IMAP4 LIST Command Extensions.
Definition private.h:138
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:503
struct MailboxArray neomutt_mailboxes_get(struct NeoMutt *n, enum MailboxType type)
Get an Array of matching Mailboxes.
Definition neomutt.c:526
char * folder
Folder name.
Definition lib.h:148
struct BrowserEntryArray entry
Array of files / dirs / mailboxes.
Definition lib.h:146
Login details for a remote server.
Definition connaccount.h:53
char delim
Path delimiter.
Definition adata.h:78
bool noinferiors
Mailbox has no children.
Definition private.h:153
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition subset.c:303
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_mailbox_create()

int imap_mailbox_create ( const char * path)

Create a new IMAP mailbox.

Parameters
pathMailbox to create
Return values
0Success
-1Failure

Prompt for a new mailbox name, and try to create it

Definition at line 393 of file browse.c.

394{
395 struct ImapAccountData *adata = NULL;
396 struct ImapMboxData *mdata = NULL;
397 struct Buffer *name = buf_pool_get();
398 int rc = -1;
399
400 if (imap_adata_find(path, &adata, &mdata) < 0)
401 {
402 mutt_debug(LL_DEBUG1, "Couldn't find open connection to %s\n", path);
403 goto done;
404 }
405
406 /* append a delimiter if necessary */
407 const size_t n = buf_strcpy(name, mdata->real_name);
408 if ((n != 0) && (buf_at(name, n - 1) != adata->delim))
409 {
410 buf_addch(name, adata->delim);
411 }
412
413 struct FileCompletionData cdata = { false, NULL, NULL, NULL, NULL };
414 if (mw_get_field(_("Create mailbox: "), name, MUTT_COMP_NO_FLAGS, HC_MAILBOX,
415 &CompleteMailboxOps, &cdata) != 0)
416 {
417 goto done;
418 }
419
420 if (buf_is_empty(name))
421 {
422 mutt_error(_("Mailbox must have a name"));
423 goto done;
424 }
425
426 if (imap_create_mailbox(adata, buf_string(name)) < 0)
427 goto done;
428
429 imap_mdata_free((void *) &mdata);
430 mutt_message(_("Mailbox created"));
431 mutt_sleep(0);
432 rc = 0;
433
434done:
435 imap_mdata_free((void *) &mdata);
436 buf_pool_release(&name);
437 return rc;
438}
const struct CompleteOps CompleteMailboxOps
Auto-Completion of Files / Mailboxes.
Definition complete.c:159
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:291
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
Definition buffer.c:668
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition buffer.c:241
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition wdata.h:42
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition window.c:463
@ HC_MAILBOX
Mailboxes.
Definition lib.h:61
void mutt_sleep(short s)
Sleep for a while.
Definition muttlib.c:787
Input for the file completion function.
Definition curs_lib.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_mailbox_rename()

int imap_mailbox_rename ( const char * path)

Rename a mailbox.

Parameters
pathMailbox to rename
Return values
0Success
-1Failure

The user will be prompted for a new name.

Definition at line 448 of file browse.c.

449{
450 struct ImapAccountData *adata = NULL;
451 struct ImapMboxData *mdata = NULL;
452 struct Buffer *buf = NULL;
453 struct Buffer *newname = NULL;
454 int rc = -1;
455
456 if (imap_adata_find(path, &adata, &mdata) < 0)
457 {
458 mutt_debug(LL_DEBUG1, "Couldn't find open connection to %s\n", path);
459 goto done;
460 }
461
462 if (mdata->real_name[0] == '\0')
463 {
464 mutt_error(_("Can't rename root folder"));
465 goto done;
466 }
467
468 buf = buf_pool_get();
469 newname = buf_pool_get();
470
471 buf_printf(buf, _("Rename mailbox %s to: "), mdata->name);
472 buf_strcpy(newname, mdata->name);
473
474 struct FileCompletionData cdata = { false, NULL, NULL, NULL, NULL };
476 &CompleteMailboxOps, &cdata) != 0)
477 {
478 goto done;
479 }
480
481 if (buf_is_empty(newname))
482 {
483 mutt_error(_("Mailbox must have a name"));
484 goto done;
485 }
486
487 imap_fix_path_with_delim(adata->delim, buf_string(newname), buf->data, buf->dsize);
488
489 if (imap_rename_mailbox(adata, mdata->name, buf_string(buf)) < 0)
490 {
491 mutt_error(_("Rename failed: %s"), imap_get_qualifier(adata->buf));
492 goto done;
493 }
494
495 mutt_message(_("Mailbox renamed"));
496 mutt_sleep(0);
497 rc = 0;
498
499done:
500 imap_mdata_free((void *) &mdata);
501 buf_pool_release(&buf);
502 buf_pool_release(&newname);
503
504 return rc;
505}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
int imap_rename_mailbox(struct ImapAccountData *adata, char *oldname, const char *newname)
Rename a mailbox.
Definition imap.c:584
size_t dsize
Length of data.
Definition buffer.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_copy_messages()

int imap_copy_messages ( struct Mailbox * m,
struct EmailArray * ea,
const char * dest,
enum MessageSaveOpt save_opt )

Server COPY messages to another folder.

Parameters
mMailbox
eaArray of Emails to copy
destDestination folder
save_optCopy or move, e.g. SAVE_MOVE
Return values
-1Error
0Success
1Non-fatal error - try fetch/append

Definition at line 1712 of file message.c.

1714{
1715 if (!m || !ea || ARRAY_EMPTY(ea) || !dest)
1716 return -1;
1717
1719 if (!adata)
1720 return -1;
1721
1722 char buf[PATH_MAX] = { 0 };
1723 char mbox[PATH_MAX] = { 0 };
1724 char mmbox[PATH_MAX] = { 0 };
1725 char prompt[PATH_MAX + 64];
1726 int rc;
1727 struct ConnAccount cac = { { 0 } };
1728 enum QuadOption err_continue = MUTT_NO;
1729 int triedcreate = 0;
1730 struct Email *e_cur = *ARRAY_GET(ea, 0);
1731 bool single = (ARRAY_SIZE(ea) == 1);
1732
1733 if (single && e_cur->attach_del)
1734 {
1735 mutt_debug(LL_DEBUG3, "#1 Message contains attachments to be deleted\n");
1736 return 1;
1737 }
1738
1739 if (imap_parse_path(dest, &cac, buf, sizeof(buf)))
1740 {
1741 mutt_debug(LL_DEBUG1, "bad destination %s\n", dest);
1742 return -1;
1743 }
1744
1745 /* check that the save-to folder is in the same account */
1746 if (!imap_account_match(&adata->conn->account, &cac))
1747 {
1748 mutt_debug(LL_DEBUG3, "%s not same server as %s\n", dest, mailbox_path(m));
1749 return 1;
1750 }
1751
1752 imap_fix_path_with_delim(adata->delim, buf, mbox, sizeof(mbox));
1753 if (*mbox == '\0')
1754 mutt_str_copy(mbox, "INBOX", sizeof(mbox));
1755 imap_munge_mbox_name(adata->unicode, mmbox, sizeof(mmbox), mbox);
1756
1757 /* loop in case of TRYCREATE */
1758 struct Buffer *cmd = buf_pool_get();
1759 struct Buffer *sync_cmd = buf_pool_get();
1760 do
1761 {
1762 buf_reset(sync_cmd);
1763 buf_reset(cmd);
1764
1765 if (single)
1766 {
1767 mutt_message(_("Copying message %d to %s..."), e_cur->index + 1, mbox);
1768 buf_add_printf(cmd, "UID COPY %u %s", imap_edata_get(e_cur)->uid, mmbox);
1769
1770 if (e_cur->active && e_cur->changed)
1771 {
1772 rc = imap_sync_message_for_copy(m, e_cur, sync_cmd, &err_continue);
1773 if (rc < 0)
1774 {
1775 mutt_debug(LL_DEBUG1, "#2 could not sync\n");
1776 goto out;
1777 }
1778 }
1779 rc = imap_exec(adata, buf_string(cmd), IMAP_CMD_QUEUE);
1780 if (rc != IMAP_EXEC_SUCCESS)
1781 {
1782 mutt_debug(LL_DEBUG1, "#2 could not queue copy\n");
1783 goto out;
1784 }
1785 }
1786 else /* copy tagged messages */
1787 {
1788 /* if any messages have attachments to delete, fall through to FETCH
1789 * and APPEND. TODO: Copy what we can with COPY, fall through for the
1790 * remainder. */
1791 struct Email **ep = NULL;
1792 ARRAY_FOREACH(ep, ea)
1793 {
1794 struct Email *e = *ep;
1795 if (e->attach_del)
1796 {
1797 mutt_debug(LL_DEBUG3, "#2 Message contains attachments to be deleted\n");
1798 rc = 1;
1799 goto out;
1800 }
1801
1802 if (e->active && e->changed)
1803 {
1804 rc = imap_sync_message_for_copy(m, e, sync_cmd, &err_continue);
1805 if (rc < 0)
1806 {
1807 mutt_debug(LL_DEBUG1, "#1 could not sync\n");
1808 goto out;
1809 }
1810 }
1811 }
1812
1813 struct UidArray uida = ARRAY_HEAD_INITIALIZER;
1814 emails_to_uid_array(ea, &uida);
1815 rc = imap_exec_msg_set(adata, "UID COPY", mmbox, &uida);
1816 ARRAY_FREE(&uida);
1817
1818 if (rc == 0)
1819 {
1820 mutt_debug(LL_DEBUG1, "No messages tagged\n");
1821 rc = -1;
1822 goto out;
1823 }
1824 else if (rc < 0)
1825 {
1826 mutt_debug(LL_DEBUG1, "#1 could not queue copy\n");
1827 goto out;
1828 }
1829 else
1830 {
1831 mutt_message(ngettext("Copying %d message to %s...", "Copying %d messages to %s...", rc),
1832 rc, mbox);
1833 }
1834 }
1835
1836 /* let's get it on */
1837 rc = imap_exec(adata, NULL, IMAP_CMD_NO_FLAGS);
1838 if (rc == IMAP_EXEC_ERROR)
1839 {
1840 if (triedcreate)
1841 {
1842 mutt_debug(LL_DEBUG1, "Already tried to create mailbox %s\n", mbox);
1843 break;
1844 }
1845 /* bail out if command failed for reasons other than nonexistent target */
1846 if (!mutt_istr_startswith(imap_get_qualifier(adata->buf), "[TRYCREATE]"))
1847 break;
1848 mutt_debug(LL_DEBUG3, "server suggests TRYCREATE\n");
1849 snprintf(prompt, sizeof(prompt), _("Create %s?"), mbox);
1850 const bool c_confirm_create = cs_subset_bool(NeoMutt->sub, "confirm_create");
1851 if (c_confirm_create &&
1852 (query_yesorno_help(prompt, MUTT_YES, NeoMutt->sub, "confirm_create") != MUTT_YES))
1853 {
1855 goto out;
1856 }
1857 if (imap_create_mailbox(adata, mbox) < 0)
1858 break;
1859 triedcreate = 1;
1860 }
1861 } while (rc == IMAP_EXEC_ERROR);
1862
1863 if (rc != 0)
1864 {
1865 imap_error("imap_copy_messages", adata->buf);
1866 goto out;
1867 }
1868
1869 /* cleanup */
1870 if (save_opt == SAVE_MOVE)
1871 {
1872 struct Email **ep = NULL;
1873 ARRAY_FOREACH(ep, ea)
1874 {
1875 struct Email *e = *ep;
1876 mutt_set_flag(m, e, MUTT_DELETE, true, true);
1877 mutt_set_flag(m, e, MUTT_PURGE, true, true);
1878 }
1879 }
1880
1881 rc = 0;
1882
1883out:
1884 buf_pool_release(&cmd);
1885 buf_pool_release(&sync_cmd);
1886
1887 return (rc < 0) ? -1 : rc;
1888}
#define ARRAY_SIZE(head)
The number of elements stored.
Definition array.h:87
#define ARRAY_GET(head, idx)
Return the element at index.
Definition array.h:109
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition buffer.c:204
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
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
static int emails_to_uid_array(struct EmailArray *ea, struct UidArray *uida)
Extract IMAP UIDs from Emails.
Definition message.c:1687
#define IMAP_CMD_QUEUE
Queue a command, do not execute.
Definition private.h:73
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition string.c:586
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition mutt.h:96
@ MUTT_DELETE
Messages to be deleted.
Definition mutt.h:94
int index
The absolute (unsorted) message number.
Definition email.h:110
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_logout_all()

void imap_logout_all ( void )

Close all open connections.

Quick and dirty until we can make sure we've got all the context we need.

Definition at line 667 of file imap.c.

668{
669 struct Account **ap = NULL;
671 {
672 struct Account *a = *ap;
673 if (a->type != MUTT_IMAP)
674 continue;
675
676 struct ImapAccountData *adata = a->adata;
677 if (!adata)
678 continue;
679
680 struct Connection *conn = adata->conn;
681 if (!conn || (conn->fd < 0))
682 continue;
683
684 mutt_message(_("Closing connection to %s..."), conn->account.host);
685 imap_logout(a->adata);
687 }
688}
static void imap_logout(struct ImapAccountData *adata)
Gracefully log out of server.
Definition imap.c:637
A group of associated Mailboxes.
Definition account.h:36
enum MailboxType type
Type of Mailboxes this Account contains.
Definition account.h:37
char host[128]
Server to login to.
Definition connaccount.h:54
int fd
Socket file descriptor.
Definition connection.h:53
struct AccountArray accounts
All Accounts.
Definition neomutt.h:50
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_parse_path()

int imap_parse_path ( const char * path,
struct ConnAccount * cac,
char * mailbox,
size_t mailboxlen )

Parse an IMAP mailbox name into ConnAccount, name.

Parameters
pathMailbox path to parse
cacAccount credentials
mailboxBuffer for mailbox name
mailboxlenLength of buffer
Return values
0Success
-1Failure

Given an IMAP mailbox name, return host, port and a path IMAP servers will recognize.

Definition at line 479 of file util.c.

480{
481 static unsigned short ImapPort = 0;
482 static unsigned short ImapsPort = 0;
483
484 if (ImapPort == 0)
485 {
486 struct servent *service = getservbyname("imap", "tcp");
487 if (service)
488 ImapPort = ntohs(service->s_port);
489 else
490 ImapPort = IMAP_PORT;
491 mutt_debug(LL_DEBUG3, "Using default IMAP port %d\n", ImapPort);
492 }
493
494 if (ImapsPort == 0)
495 {
496 struct servent *service = getservbyname("imaps", "tcp");
497 if (service)
498 ImapsPort = ntohs(service->s_port);
499 else
500 ImapsPort = IMAP_SSL_PORT;
501 mutt_debug(LL_DEBUG3, "Using default IMAPS port %d\n", ImapsPort);
502 }
503
504 /* Defaults */
505 cac->port = ImapPort;
507 cac->service = "imap";
509
510 struct Url *url = url_parse(path);
511 if (!url)
512 return -1;
513
514 if ((url->scheme != U_IMAP) && (url->scheme != U_IMAPS))
515 {
516 url_free(&url);
517 return -1;
518 }
519
520 if ((account_from_url(cac, url) < 0) || (cac->host[0] == '\0'))
521 {
522 url_free(&url);
523 return -1;
524 }
525
526 if (url->scheme == U_IMAPS)
527 cac->flags |= MUTT_ACCT_SSL;
528
529 mutt_str_copy(mailbox, url->path, mailboxlen);
530
531 url_free(&url);
532
533 if ((cac->flags & MUTT_ACCT_SSL) && !(cac->flags & MUTT_ACCT_PORT))
534 cac->port = ImapsPort;
535
536 return 0;
537}
#define MUTT_ACCT_SSL
Account uses SSL/TLS.
Definition connaccount.h:47
#define MUTT_ACCT_PORT
Port field has been set.
Definition connaccount.h:43
static const char * imap_get_field(enum ConnAccountField field, void *gf_data)
Get connection login credentials - Implements ConnAccount::get_field() -.
Definition util.c:208
#define IMAP_PORT
Default port for IMAP.
Definition private.h:44
#define IMAP_SSL_PORT
Port for IMAP over SSL/TLS.
Definition private.h:45
int account_from_url(struct ConnAccount *cac, const struct Url *url)
Fill ConnAccount with information from url.
@ MUTT_ACCT_TYPE_IMAP
Imap Account.
const char * service
Name of the service, e.g. "imap".
Definition connaccount.h:61
const char *(* get_field)(enum ConnAccountField field, void *gf_data)
Definition connaccount.h:70
unsigned char type
Connection type, e.g. MUTT_ACCT_TYPE_IMAP.
Definition connaccount.h:59
MuttAccountFlags flags
Which fields are initialised, e.g. MUTT_ACCT_USER.
Definition connaccount.h:60
unsigned short port
Port to connect to.
Definition connaccount.h:58
enum UrlScheme scheme
Scheme, e.g. U_SMTPS.
Definition url.h:70
@ U_IMAP
Url is imap://.
Definition url.h:39
@ U_IMAPS
Url is imaps://.
Definition url.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_pretty_mailbox()

void imap_pretty_mailbox ( char * path,
size_t pathlen,
const char * folder )

Prettify an IMAP mailbox name.

Parameters
pathMailbox name to be tidied
pathlenLength of path
folderPath to use for '+' abbreviations

Called by mutt_pretty_mailbox() to make IMAP paths look nice.

Definition at line 586 of file util.c.

587{
588 struct ConnAccount cac_target = { { 0 } };
589 struct ConnAccount cac_home = { { 0 } };
590 struct Url url = { 0 };
591 const char *delim = NULL;
592 int tlen;
593 int hlen = 0;
594 bool home_match = false;
595 char target_mailbox[1024] = { 0 };
596 char home_mailbox[1024] = { 0 };
597
598 if (imap_parse_path(path, &cac_target, target_mailbox, sizeof(target_mailbox)) < 0)
599 return;
600
601 if (imap_path_probe(folder, NULL) != MUTT_IMAP)
602 goto fallback;
603
604 if (imap_parse_path(folder, &cac_home, home_mailbox, sizeof(home_mailbox)) < 0)
605 goto fallback;
606
607 tlen = mutt_str_len(target_mailbox);
608 hlen = mutt_str_len(home_mailbox);
609
610 /* check whether we can do '+' substitution */
611 if (tlen && imap_account_match(&cac_home, &cac_target) &&
612 mutt_strn_equal(home_mailbox, target_mailbox, hlen))
613 {
614 const char *const c_imap_delim_chars = cs_subset_string(NeoMutt->sub, "imap_delim_chars");
615 if (hlen == 0)
616 {
617 home_match = true;
618 }
619 else if (c_imap_delim_chars)
620 {
621 for (delim = c_imap_delim_chars; *delim != '\0'; delim++)
622 if (target_mailbox[hlen] == *delim)
623 home_match = true;
624 }
625 }
626
627 /* do the '+' substitution */
628 if (home_match)
629 {
630 *path++ = '+';
631 /* copy remaining path, skipping delimiter */
632 if (hlen != 0)
633 hlen++;
634 memcpy(path, target_mailbox + hlen, tlen - hlen);
635 path[tlen - hlen] = '\0';
636 return;
637 }
638
639fallback:
640 account_to_url(&cac_target, &url);
641 url.path = target_mailbox;
642 url_tostring(&url, path, pathlen, U_NO_FLAGS);
643}
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox?
Definition imap.c:2546
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition string.c:429
void account_to_url(struct ConnAccount *cac, struct Url *url)
Fill URL with info from account.
int url_tostring(const struct Url *url, char *dest, size_t len, uint8_t flags)
Output the URL string for a given Url object.
Definition url.c:423
#define U_NO_FLAGS
No flags are set for URL parsing.
Definition url.h:49
int imap_parse_path(const char *path, struct ConnAccount *cac, char *mailbox, size_t mailboxlen)
Parse an IMAP mailbox name into ConnAccount, name.
Definition util.c:479
bool imap_account_match(const struct ConnAccount *a1, const struct ConnAccount *a2)
Compare two Accounts.
Definition util.c:1103
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_mxcmp()

int imap_mxcmp ( const char * mx1,
const char * mx2 )

Compare mailbox names, giving priority to INBOX.

Parameters
mx1First mailbox name
mx2Second mailbox name
Return values
<0First mailbox precedes Second mailbox
0Mailboxes are the same
>0Second mailbox precedes First mailbox

Like a normal sort function except that "INBOX" will be sorted to the beginning of the list.

Definition at line 550 of file util.c.

551{
552 char *b1 = NULL;
553 char *b2 = NULL;
554 int rc;
555
556 if (!mx1 || (*mx1 == '\0'))
557 mx1 = "INBOX";
558 if (!mx2 || (*mx2 == '\0'))
559 mx2 = "INBOX";
560 if (mutt_istr_equal(mx1, "INBOX") && mutt_istr_equal(mx2, "INBOX"))
561 {
562 return 0;
563 }
564
565 b1 = MUTT_MEM_MALLOC(strlen(mx1) + 1, char);
566 b2 = MUTT_MEM_MALLOC(strlen(mx2) + 1, char);
567
568 imap_fix_path(mx1, b1, strlen(mx1) + 1);
569 imap_fix_path(mx2, b2, strlen(mx2) + 1);
570
571 rc = mutt_str_cmp(b1, b2);
572 FREE(&b1);
573 FREE(&b2);
574
575 return rc;
576}
int mutt_str_cmp(const char *a, const char *b)
Compare two strings, safely.
Definition string.c:403
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:677
char * imap_fix_path(const char *mailbox, char *path, size_t plen)
Fix up the imap path.
Definition util.c:683
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_wait_keep_alive()

int imap_wait_keep_alive ( pid_t pid)

Wait for a process to change state.

Parameters
pidProcess ID to listen to
Return values
num'wstatus' from waitpid()

Definition at line 1028 of file util.c.

1029{
1030 struct sigaction oldalrm = { 0 };
1031 struct sigaction act = { 0 };
1032 sigset_t oldmask = { 0 };
1033 int rc;
1034
1035 const bool c_imap_passive = cs_subset_bool(NeoMutt->sub, "imap_passive");
1036 cs_subset_str_native_set(NeoMutt->sub, "imap_passive", true, NULL);
1037 OptKeepQuiet = true;
1038
1039 sigprocmask(SIG_SETMASK, NULL, &oldmask);
1040
1041 sigemptyset(&act.sa_mask);
1042 act.sa_handler = mutt_sig_empty_handler;
1043#ifdef SA_INTERRUPT
1044 act.sa_flags = SA_INTERRUPT;
1045#else
1046 act.sa_flags = 0;
1047#endif
1048
1049 sigaction(SIGALRM, &act, &oldalrm);
1050
1051 const short c_imap_keep_alive = cs_subset_number(NeoMutt->sub, "imap_keep_alive");
1052 alarm(c_imap_keep_alive);
1053 while ((waitpid(pid, &rc, 0) < 0) && (errno == EINTR))
1054 {
1055 alarm(0); /* cancel a possibly pending alarm */
1057 alarm(c_imap_keep_alive);
1058 }
1059
1060 alarm(0); /* cancel a possibly pending alarm */
1061
1062 sigaction(SIGALRM, &oldalrm, NULL);
1063 sigprocmask(SIG_SETMASK, &oldmask, NULL);
1064
1065 OptKeepQuiet = false;
1066 cs_subset_str_native_set(NeoMutt->sub, "imap_passive", c_imap_passive, NULL);
1067
1068 return rc;
1069}
bool OptKeepQuiet
(pseudo) shut up the message and refresh functions while we are executing an external program
Definition globals.c:49
void mutt_sig_empty_handler(int sig)
Dummy signal handler.
Definition signal.c:130
void imap_keep_alive(void)
Poll the current folder to keep the connection alive.
Definition util.c:1002
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_keep_alive()

void imap_keep_alive ( void )

Poll the current folder to keep the connection alive.

Definition at line 1002 of file util.c.

1003{
1004 time_t now = mutt_date_now();
1005 const short c_imap_keep_alive = cs_subset_number(NeoMutt->sub, "imap_keep_alive");
1006
1007 struct Account **ap = NULL;
1009 {
1010 struct Account *a = *ap;
1011 if (a->type != MUTT_IMAP)
1012 continue;
1013
1014 struct ImapAccountData *adata = a->adata;
1015 if (!adata || !adata->mailbox)
1016 continue;
1017
1018 if ((adata->state >= IMAP_AUTHENTICATED) && (now >= (adata->lastread + c_imap_keep_alive)))
1019 imap_check_mailbox(adata->mailbox, true);
1020 }
1021}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_get_parent_path()

void imap_get_parent_path ( const char * path,
char * buf,
size_t buflen )

Get the path of the parent folder.

Parameters
pathMailbox whose parent is to be determined
bufBuffer for the result
buflenLength of the buffer

Provided an imap path, returns in buf the parent directory if existent. Else returns the same path.

Definition at line 165 of file util.c.

166{
167 struct ImapAccountData *adata = NULL;
168 struct ImapMboxData *mdata = NULL;
169 char mbox[1024] = { 0 };
170
171 if (imap_adata_find(path, &adata, &mdata) < 0)
172 {
173 mutt_str_copy(buf, path, buflen);
174 return;
175 }
176
177 /* Gets the parent mbox in mbox */
178 imap_get_parent(mdata->name, adata->delim, mbox, sizeof(mbox));
179
180 /* Returns a fully qualified IMAP url */
181 imap_qualify_path(buf, buflen, &adata->conn->account, mbox);
182 imap_mdata_free((void *) &mdata);
183}
void imap_qualify_path(char *buf, size_t buflen, struct ConnAccount *cac, char *path)
Make an absolute IMAP folder target.
Definition util.c:857
void imap_get_parent(const char *mbox, char delim, char *buf, size_t buflen)
Get an IMAP folder's parent.
Definition util.c:124
int imap_adata_find(const char *path, struct ImapAccountData **adata, struct ImapMboxData **mdata)
Find the Account data for this path.
Definition util.c:72
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_clean_path()

void imap_clean_path ( char * path,
size_t plen )

Cleans an IMAP path using imap_fix_path.

Parameters
pathPath to be cleaned
plenLength of the buffer

Does it in place.

Definition at line 192 of file util.c.

193{
194 struct ImapAccountData *adata = NULL;
195 struct ImapMboxData *mdata = NULL;
196
197 if (imap_adata_find(path, &adata, &mdata) < 0)
198 return;
199
200 /* Returns a fully qualified IMAP url */
201 imap_qualify_path(path, plen, &adata->conn->account, mdata->name);
202 imap_mdata_free((void *) &mdata);
203}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_search()

bool imap_search ( struct Mailbox * m,
const struct PatternList * pat )

Find messages in mailbox matching a pattern.

Parameters
mMailbox
patPattern to match
Return values
trueSuccess
falseFailure

Definition at line 227 of file search.c.

228{
229 for (int i = 0; i < m->msg_count; i++)
230 {
231 struct Email *e = m->emails[i];
232 if (!e)
233 break;
234 e->matched = false;
235 }
236
237 if (check_pattern_list(pat) == 0)
238 return true;
239
240 struct Buffer *buf = buf_pool_get();
241 buf_addstr(buf, "UID SEARCH ");
242
244 if (!adata)
245 return false;
246
247 const bool ok = compile_search(adata, SLIST_FIRST(pat), buf) &&
249
251 return ok;
252}
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:226
#define SLIST_FIRST(head)
Definition queue.h:227
static bool compile_search(const struct ImapAccountData *adata, const struct Pattern *pat, struct Buffer *buf)
Convert NeoMutt pattern to IMAP search.
Definition search.c:207
static int check_pattern_list(const struct PatternList *patterns)
Check how many patterns in a list can be searched server-side.
Definition search.c:81
bool matched
Search matches this Email.
Definition email.h:102
+ Here is the call graph for this function:
+ Here is the caller graph for this function: