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

IMAP network mailbox. More...

#include "config.h"
#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

void imap_init (void)
 Setup feature commands.
 
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.
 
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_init()

void imap_init ( void )

Setup feature commands.

Definition at line 102 of file imap.c.

103{
105}
bool commands_register(struct CommandArray *ca, const struct Command *cmds)
Add commands to Commands array.
Definition command.c:51
static const struct Command ImapCommands[]
Imap Commands.
Definition imap.c:84
Container for Accounts, Notifications.
Definition neomutt.h:43
struct CommandArray commands
NeoMutt commands.
Definition neomutt.h:51
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ 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 475 of file imap.c.

476{
477 if (imap_path_status(path, false) >= 0)
478 return 0;
479 return -1;
480}
int imap_path_status(const char *path, bool queue)
Refresh the number of total and new messages.
Definition imap.c:1194
+ 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 1052 of file imap.c.

1053{
1054 if (!m || !m->account)
1055 return MX_STATUS_ERROR;
1056
1058 struct ImapMboxData *mdata = imap_mdata_get(m);
1059 if (!adata || !mdata)
1060 return MX_STATUS_ERROR;
1061
1062 /* overload keyboard timeout to avoid many mailbox checks in a row.
1063 * Most users don't like having to wait exactly when they press a key. */
1064 int rc = 0;
1065
1066 /* try IDLE first, unless force is set */
1067 const bool c_imap_idle = cs_subset_bool(NeoMutt->sub, "imap_idle");
1068 const short c_imap_keep_alive = cs_subset_number(NeoMutt->sub, "imap_keep_alive");
1069 if (!force && c_imap_idle && (adata->capabilities & IMAP_CAP_IDLE) &&
1070 ((adata->state != IMAP_IDLE) || (mutt_date_now() >= adata->lastread + c_imap_keep_alive)))
1071 {
1072 if (imap_cmd_idle(adata) < 0)
1073 return MX_STATUS_ERROR;
1074 }
1075 if (adata->state == IMAP_IDLE)
1076 {
1077 while ((rc = mutt_socket_poll(adata->conn, 0)) > 0)
1078 {
1079 if (imap_cmd_step(adata) != IMAP_RES_CONTINUE)
1080 {
1081 mutt_debug(LL_DEBUG1, "Error reading IDLE response\n");
1082 return MX_STATUS_ERROR;
1083 }
1084 }
1085 if (rc < 0)
1086 {
1087 mutt_debug(LL_DEBUG1, "Poll failed, disabling IDLE\n");
1088 adata->capabilities &= ~IMAP_CAP_IDLE; // Clear the flag
1089 }
1090 }
1091
1092 const short c_timeout = cs_subset_number(NeoMutt->sub, "timeout");
1093 if ((force || ((adata->state != IMAP_IDLE) && (mutt_date_now() >= adata->lastread + c_timeout))) &&
1094 (imap_exec(adata, "NOOP", IMAP_CMD_POLL) != IMAP_EXEC_SUCCESS))
1095 {
1096 return MX_STATUS_ERROR;
1097 }
1098
1099 /* We call this even when we haven't run NOOP in case we have pending
1100 * changes to process, since we can reopen here. */
1101 imap_cmd_finish(adata);
1102
1103 enum MxStatus check = MX_STATUS_OK;
1104 if (mdata->check_status & IMAP_EXPUNGE_PENDING)
1105 check = MX_STATUS_REOPENED;
1106 else if (mdata->check_status & IMAP_NEWMAIL_PENDING)
1107 check = MX_STATUS_NEW_MAIL;
1108 else if (mdata->check_status & IMAP_FLAGS_PENDING)
1109 check = MX_STATUS_FLAGS;
1110 else if (rc < 0)
1111 check = MX_STATUS_ERROR;
1112
1113 mdata->check_status = IMAP_OPEN_NO_FLAGS;
1114
1115 if (force)
1116 m->last_checked = 0; // force a check on the next mx_mbox_check() call
1117 return check;
1118}
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:90
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition adata.c:123
int imap_cmd_idle(struct ImapAccountData *adata)
Enter the IDLE state.
Definition command.c:1455
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition command.c:1147
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:1322
void imap_cmd_finish(struct ImapAccountData *adata)
Attempt to perform cleanup.
Definition command.c:1388
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:56
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:44
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition date.c:455
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_FLAGS
Nondestructive flags change (IMAP)
Definition mxapi.h:66
@ MX_STATUS_REOPENED
Mailbox was reopened.
Definition mxapi.h:65
@ MX_STATUS_NEW_MAIL
New mail received in Mailbox.
Definition mxapi.h:63
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:105
void * mdata
Driver specific data.
Definition mailbox.h:132
struct Account * account
Account that owns this Mailbox.
Definition mailbox.h:127
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:47
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ 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 517 of file imap.c.

518{
519 char buf[PATH_MAX + 7];
520 char mbox[PATH_MAX] = { 0 };
521
523 if (!adata)
524 return -1;
525
526 struct Url *url = url_parse(path);
527 if (!url)
528 return -1;
529
530 imap_munge_mbox_name(adata->unicode, mbox, sizeof(mbox), url->path);
531 url_free(&url);
532 snprintf(buf, sizeof(buf), "DELETE %s", mbox);
534 return -1;
535
536 return 0;
537}
#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:960
#define PATH_MAX
Definition mutt.h:42
bool unicode
If true, we can send UTF-8, and the server will use UTF8 rather than mUTF7.
Definition adata.h:62
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:238
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition url.c:123
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ 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 1500 of file imap.c.

1501{
1502 if (!m)
1503 return -1;
1504
1505 struct Email **emails = NULL;
1506 int rc;
1507
1509 struct ImapMboxData *mdata = imap_mdata_get(m);
1510 if (!adata || !mdata)
1511 return MX_STATUS_ERROR;
1512
1513 if (adata->state < IMAP_SELECTED)
1514 {
1515 mutt_debug(LL_DEBUG2, "no mailbox selected\n");
1516 return -1;
1517 }
1518
1519 /* This function is only called when the calling code expects the context
1520 * to be changed. */
1522
1523 enum MxStatus check = imap_check_mailbox(m, false);
1524 if (check == MX_STATUS_ERROR)
1525 return check;
1526
1527 /* if we are expunging anyway, we can do deleted messages very quickly... */
1528 if (expunge && (m->rights & MUTT_ACL_DELETE))
1529 {
1530 struct UidArray uida = ARRAY_HEAD_INITIALIZER;
1531 select_email_uids(m->emails, m->msg_count, MUTT_DELETED, true, false, &uida);
1532 ARRAY_SORT(&uida, imap_sort_uid, NULL);
1533 rc = imap_exec_msg_set(adata, "UID STORE", "+FLAGS.SILENT (\\Deleted)", &uida);
1534 ARRAY_FREE(&uida);
1535 if (rc < 0)
1536 {
1537 mutt_error(_("Expunge failed"));
1538 return rc;
1539 }
1540
1541 if (rc > 0)
1542 {
1543 /* mark these messages as unchanged so second pass ignores them. Done
1544 * here so BOGUS UW-IMAP 4.7 SILENT FLAGS updates are ignored. */
1545 for (int i = 0; i < m->msg_count; i++)
1546 {
1547 struct Email *e = m->emails[i];
1548 if (!e)
1549 break;
1550 if (e->deleted && e->changed)
1551 e->active = false;
1552 }
1553 if (m->verbose)
1554 {
1555 mutt_message(ngettext("Marking %d message deleted...",
1556 "Marking %d messages deleted...", rc),
1557 rc);
1558 }
1559 }
1560 }
1561
1562#ifdef USE_HCACHE
1563 imap_hcache_open(adata, mdata, true);
1564#endif
1565
1566 /* save messages with real (non-flag) changes */
1567 for (int i = 0; i < m->msg_count; i++)
1568 {
1569 struct Email *e = m->emails[i];
1570 if (!e)
1571 break;
1572
1573 if (e->deleted)
1574 {
1575 imap_cache_del(m, e);
1576#ifdef USE_HCACHE
1577 imap_hcache_del(mdata, imap_edata_get(e)->uid);
1578#endif
1579 }
1580
1581 if (e->active && e->changed)
1582 {
1583#ifdef USE_HCACHE
1584 imap_hcache_put(mdata, e);
1585#endif
1586 /* if the message has been rethreaded or attachments have been deleted
1587 * we delete the message and reupload it.
1588 * This works better if we're expunging, of course. */
1589 if (e->env->changed || e->attach_del)
1590 {
1591 /* L10N: The plural is chosen by the last %d, i.e. the total number */
1592 if (m->verbose)
1593 {
1594 mutt_message(ngettext("Saving changed message... [%d/%d]",
1595 "Saving changed messages... [%d/%d]", m->msg_count),
1596 i + 1, m->msg_count);
1597 }
1598 bool save_append = m->append;
1599 m->append = true;
1601 m->append = save_append;
1602 e->env->changed = false;
1603 }
1604 }
1605 }
1606
1607#ifdef USE_HCACHE
1608 imap_hcache_close(mdata);
1609#endif
1610
1611 /* presort here to avoid doing 10 resorts in imap_exec_msg_set */
1612 emails = MUTT_MEM_MALLOC(m->msg_count, struct Email *);
1613 memcpy(emails, m->emails, m->msg_count * sizeof(struct Email *));
1614 mutt_qsort_r(emails, m->msg_count, sizeof(struct Email *), imap_sort_email_uid, NULL);
1615
1616 rc = sync_helper(m, emails, m->msg_count, MUTT_ACL_DELETE, MUTT_DELETED, "\\Deleted");
1617 if (rc >= 0)
1618 rc |= sync_helper(m, emails, m->msg_count, MUTT_ACL_WRITE, MUTT_FLAG, "\\Flagged");
1619 if (rc >= 0)
1620 rc |= sync_helper(m, emails, m->msg_count, MUTT_ACL_WRITE, MUTT_OLD, "Old");
1621 if (rc >= 0)
1622 rc |= sync_helper(m, emails, m->msg_count, MUTT_ACL_SEEN, MUTT_READ, "\\Seen");
1623 if (rc >= 0)
1624 rc |= sync_helper(m, emails, m->msg_count, MUTT_ACL_WRITE, MUTT_REPLIED, "\\Answered");
1625
1626 FREE(&emails);
1627
1628 /* Flush the queued flags if any were changed in sync_helper. */
1629 if (rc > 0)
1630 if (imap_exec(adata, NULL, IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS)
1631 rc = -1;
1632
1633 if (rc < 0)
1634 {
1635 if (close)
1636 {
1637 if (query_yesorno(_("Error saving flags. Close anyway?"), MUTT_NO) == MUTT_YES)
1638 {
1639 adata->state = IMAP_AUTHENTICATED;
1640 return 0;
1641 }
1642 }
1643 else
1644 {
1645 mutt_error(_("Error saving flags"));
1646 }
1647 return -1;
1648 }
1649
1650 /* Update local record of server state to reflect the synchronization just
1651 * completed. imap_read_headers always overwrites hcache-origin flags, so
1652 * there is no need to mutate the hcache after flag-only changes. */
1653 for (int i = 0; i < m->msg_count; i++)
1654 {
1655 struct Email *e = m->emails[i];
1656 if (!e)
1657 break;
1658 struct ImapEmailData *edata = imap_edata_get(e);
1659 edata->deleted = e->deleted;
1660 edata->flagged = e->flagged;
1661 edata->old = e->old;
1662 edata->read = e->read;
1663 edata->replied = e->replied;
1664 e->changed = false;
1665 }
1666 m->changed = false;
1667
1668 /* We must send an EXPUNGE command if we're not closing. */
1669 if (expunge && !close && (m->rights & MUTT_ACL_DELETE))
1670 {
1671 if (m->verbose)
1672 mutt_message(_("Expunging messages from server..."));
1673 /* Set expunge bit so we don't get spurious reopened messages */
1674 mdata->reopen |= IMAP_EXPUNGE_EXPECTED;
1675 if (imap_exec(adata, "EXPUNGE", IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS)
1676 {
1678 imap_error(_("imap_sync_mailbox: EXPUNGE failed"), adata->buf);
1679 return -1;
1680 }
1682 }
1683
1684 if (expunge && close)
1685 {
1686 adata->closing = true;
1687 imap_exec(adata, "CLOSE", IMAP_CMD_NO_FLAGS);
1688 adata->state = IMAP_AUTHENTICATED;
1689 }
1690
1691 const bool c_message_cache_clean = cs_subset_bool(NeoMutt->sub, "message_cache_clean");
1692 if (c_message_cache_clean)
1694
1695 return check;
1696}
#define ARRAY_SORT(head, fn, sdata)
Sort an array.
Definition array.h:335
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:204
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition array.h:58
#define MUTT_ACL_DELETE
Delete a message.
Definition mailbox.h:63
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition mailbox.h:71
#define MUTT_ACL_SEEN
Change the 'seen' status of a message.
Definition mailbox.h:70
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:740
@ 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:93
#define mutt_message(...)
Definition logging2.h:92
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:920
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:1907
int imap_cache_del(struct Mailbox *m, struct Email *e)
Delete an email from the body cache.
Definition message.c:1888
void imap_allow_reopen(struct Mailbox *m)
Allow re-opening a folder upon expunge.
Definition util.c:1067
@ 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:302
#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:383
void imap_error(const char *where, const char *msg)
Show an error and abort.
Definition util.c:660
void imap_hcache_close(struct ImapMboxData *mdata)
Close the header cache.
Definition util.c:343
int imap_hcache_del(struct ImapMboxData *mdata, unsigned int uid)
Delete an item from the header cache.
Definition util.c:401
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:310
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:240
enum MxStatus imap_check_mailbox(struct Mailbox *m, bool force)
Use the NOOP or IDLE command to poll for new mail.
Definition imap.c:1052
@ LL_DEBUG2
Log at debug level 2.
Definition logging2.h:45
#define FREE(x)
Definition memory.h:62
#define MUTT_MEM_MALLOC(n, type)
Definition memory.h:48
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:73
@ MUTT_OLD
Old messages.
Definition mutt.h:71
@ MUTT_FLAG
Flagged messages.
Definition mutt.h:79
@ MUTT_DELETED
Deleted messages.
Definition mutt.h:78
@ MUTT_REPLIED
Messages that have been replied to.
Definition mutt.h:72
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:67
@ 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:325
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
Definition adata.h:59
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:110
bool append
Mailbox is opened in append mode.
Definition mailbox.h:109
int msg_count
Total number of messages.
Definition mailbox.h:88
AclFlags rights
ACL bits, see AclFlags.
Definition mailbox.h:119
struct Email ** emails
Array of Emails.
Definition mailbox.h:96
bool verbose
Display status messages?
Definition mailbox.h:117
+ 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 1194 of file imap.c.

1195{
1196 struct Mailbox *m = mx_mbox_find2(path);
1197
1198 const bool is_temp = !m;
1199 if (is_temp)
1200 {
1201 m = mx_path_resolve(path);
1202 if (!mx_mbox_ac_link(m))
1203 {
1204 mailbox_free(&m);
1205 return 0;
1206 }
1207 }
1208
1209 int rc = imap_mailbox_status(m, queue);
1210
1211 if (is_temp)
1212 {
1213 mx_ac_remove(m, false);
1214 mailbox_free(&m);
1215 }
1216
1217 return rc;
1218}
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition mailbox.c:89
int imap_mailbox_status(struct Mailbox *m, bool queue)
Refresh the number of total and new messages.
Definition imap.c:1229
int mx_ac_remove(struct Mailbox *m, bool keep_account)
Remove a Mailbox from an Account and delete Account if empty.
Definition mx.c:1757
struct Mailbox * mx_mbox_find2(const char *path)
Find a Mailbox on an Account.
Definition mx.c:1618
bool mx_mbox_ac_link(struct Mailbox *m)
Link a Mailbox to an existing or new Account.
Definition mx.c:251
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition mx.c:1650
A mailbox.
Definition mailbox.h:79
+ 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 1229 of file imap.c.

1230{
1232 struct ImapMboxData *mdata = imap_mdata_get(m);
1233 if (!adata || !mdata)
1234 return -1;
1235 return imap_status(adata, mdata, queue);
1236}
static int imap_status(struct ImapAccountData *adata, struct ImapMboxData *mdata, bool queue)
Refresh the number of total and new messages.
Definition imap.c:1127
+ 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 1245 of file imap.c.

1246{
1247 struct ImapAccountData *adata = NULL;
1248 struct ImapMboxData *mdata = NULL;
1249
1250 if (imap_adata_find(path, &adata, &mdata) < 0)
1251 return -1;
1252
1253 if (subscribe)
1254 mutt_message(_("Subscribing to %s..."), mdata->name);
1255 else
1256 mutt_message(_("Unsubscribing from %s..."), mdata->name);
1257
1258 char buf[2048] = { 0 };
1259 snprintf(buf, sizeof(buf), "%sSUBSCRIBE %s", subscribe ? "" : "UN", mdata->munge_name);
1260
1261 if (imap_exec(adata, buf, IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS)
1262 {
1263 imap_mdata_free((void *) &mdata);
1264 return -1;
1265 }
1266
1267 const bool c_imap_check_subscribed = cs_subset_bool(NeoMutt->sub, "imap_check_subscribed");
1268 if (c_imap_check_subscribed)
1269 {
1270 struct Buffer *err = buf_pool_get();
1271 struct Buffer *mbox = buf_pool_get();
1272
1273 size_t len = buf_printf(mbox, "%smailboxes ", subscribe ? "" : "un");
1274 imap_quote_string(mbox->data + len, mbox->dsize - len, path, true);
1275
1276 if (parse_rc_line(mbox, err) != MUTT_CMD_SUCCESS)
1277 mutt_debug(LL_DEBUG1, "Error adding subscribed mailbox: %s\n", buf_string(err));
1278
1279 buf_pool_release(&mbox);
1280 buf_pool_release(&err);
1281 }
1282
1283 if (subscribe)
1284 mutt_message(_("Subscribed to %s"), mdata->name);
1285 else
1286 mutt_message(_("Unsubscribed from %s"), mdata->name);
1287 imap_mdata_free((void *) &mdata);
1288 return 0;
1289}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition command.h:38
void imap_mdata_free(void **ptr)
Free the private Mailbox data - Implements Mailbox::mdata_free() -.
Definition mdata.c:40
void imap_quote_string(char *dest, size_t dlen, const char *src, bool quote_backtick)
Quote string according to IMAP rules.
Definition util.c:886
int imap_adata_find(const char *path, struct ImapAccountData **adata, struct ImapMboxData **mdata)
Find the Account data for this path.
Definition util.c:71
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
enum CommandResult parse_rc_line(struct Buffer *line, struct Buffer *err)
Parse a line of user config.
Definition rc.c:45
String manipulation buffer.
Definition buffer.h:36
size_t dsize
Length of data.
Definition buffer.h:39
char * data
Pointer to data.
Definition buffer.h:37
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 1301 of file imap.c.

1302{
1303 struct ImapAccountData *adata = NULL;
1304 struct ImapMboxData *mdata = NULL;
1305 char tmp[2048] = { 0 };
1306 struct ImapList listresp = { 0 };
1307 struct Buffer *completion_buf = NULL;
1308 size_t clen;
1309 int completions = 0;
1310 int rc;
1311
1312 if (imap_adata_find(path, &adata, &mdata) < 0)
1313 {
1314 buf_strcpy(buf, path);
1315 return complete_hosts(buf);
1316 }
1317
1318 /* fire off command */
1319 const bool c_imap_list_subscribed = cs_subset_bool(NeoMutt->sub, "imap_list_subscribed");
1320 snprintf(tmp, sizeof(tmp), "%s \"\" \"%s%%\"",
1321 c_imap_list_subscribed ? "LSUB" : "LIST", mdata->real_name);
1322
1323 imap_cmd_start(adata, tmp);
1324
1325 /* and see what the results are */
1326 completion_buf = buf_pool_get();
1327 buf_strcpy(completion_buf, mdata->name);
1328 imap_mdata_free((void *) &mdata);
1329
1330 adata->cmdresult = &listresp;
1331 do
1332 {
1333 listresp.name = NULL;
1334 rc = imap_cmd_step(adata);
1335
1336 if ((rc == IMAP_RES_CONTINUE) && listresp.name)
1337 {
1338 /* if the folder isn't selectable, append delimiter to force browse
1339 * to enter it on second tab. */
1340 if (listresp.noselect)
1341 {
1342 clen = strlen(listresp.name);
1343 listresp.name[clen++] = listresp.delim;
1344 listresp.name[clen] = '\0';
1345 }
1346 /* copy in first word */
1347 if (!completions)
1348 {
1349 buf_strcpy(completion_buf, listresp.name);
1350 completions++;
1351 continue;
1352 }
1353
1354 longest_common_prefix(completion_buf, listresp.name, 0);
1355 completions++;
1356 }
1357 } while (rc == IMAP_RES_CONTINUE);
1358 adata->cmdresult = NULL;
1359
1360 if (completions)
1361 {
1362 /* reformat output */
1363 imap_buf_qualify_path(buf, &adata->conn->account, completion_buf->data);
1364 buf_pretty_mailbox(buf);
1365 buf_fix_dptr(buf);
1366 buf_pool_release(&completion_buf);
1367 return 0;
1368 }
1369
1370 buf_pool_release(&completion_buf);
1371 return -1;
1372}
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:1133
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:869
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:359
static int complete_hosts(struct Buffer *buf)
Look for completion matches for mailboxes.
Definition imap.c:382
void buf_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition muttlib.c:518
struct ConnAccount account
Account details: username, password, etc.
Definition connection.h:49
struct ImapList * cmdresult
Definition adata.h:66
Items in an IMAP browser.
Definition private.h:149
bool noselect
Definition private.h:152
char * name
Definition private.h:150
char delim
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 1382 of file imap.c.

1383{
1384 char prompt[1024] = { 0 };
1385 int rc = -1;
1386 bool triedcreate = false;
1387 enum QuadOption err_continue = MUTT_NO;
1388
1390 if (!adata)
1391 return -1;
1392
1393 struct ImapAccountData *dest_adata = NULL;
1394 struct ImapMboxData *dest_mdata = NULL;
1395
1396 if (imap_adata_find(dest, &dest_adata, &dest_mdata) < 0)
1397 return -1;
1398
1399 struct Buffer *sync_cmd = buf_pool_get();
1400
1401 /* check that the save-to folder is in the same account */
1402 if (!imap_account_match(&(adata->conn->account), &(dest_adata->conn->account)))
1403 {
1404 mutt_debug(LL_DEBUG3, "%s not same server as %s\n", dest, mailbox_path(m));
1405 goto out;
1406 }
1407
1408 for (int i = 0; i < m->msg_count; i++)
1409 {
1410 struct Email *e = m->emails[i];
1411 if (!e)
1412 break;
1413 if (e->active && e->changed && e->deleted && !e->purge)
1414 {
1415 rc = imap_sync_message_for_copy(m, e, sync_cmd, &err_continue);
1416 if (rc < 0)
1417 {
1418 mutt_debug(LL_DEBUG1, "could not sync\n");
1419 goto out;
1420 }
1421 }
1422 }
1423
1424 /* loop in case of TRYCREATE */
1425 do
1426 {
1427 struct UidArray uida = ARRAY_HEAD_INITIALIZER;
1428 select_email_uids(m->emails, m->msg_count, MUTT_TRASH, false, false, &uida);
1429 ARRAY_SORT(&uida, imap_sort_uid, NULL);
1430 rc = imap_exec_msg_set(adata, "UID COPY", dest_mdata->munge_name, &uida);
1431 if (rc == 0)
1432 {
1433 mutt_debug(LL_DEBUG1, "No messages to trash\n");
1434 rc = -1;
1435 goto out;
1436 }
1437 else if (rc < 0)
1438 {
1439 mutt_debug(LL_DEBUG1, "could not queue copy\n");
1440 goto out;
1441 }
1442 else if (m->verbose)
1443 {
1444 mutt_message(ngettext("Copying %d message to %s...", "Copying %d messages to %s...", rc),
1445 rc, dest_mdata->name);
1446 }
1447 ARRAY_FREE(&uida);
1448
1449 /* let's get it on */
1450 rc = imap_exec(adata, NULL, IMAP_CMD_NO_FLAGS);
1451 if (rc == IMAP_EXEC_ERROR)
1452 {
1453 if (triedcreate)
1454 {
1455 mutt_debug(LL_DEBUG1, "Already tried to create mailbox %s\n", dest_mdata->name);
1456 break;
1457 }
1458 /* bail out if command failed for reasons other than nonexistent target */
1459 if (!mutt_istr_startswith(imap_get_qualifier(adata->buf), "[TRYCREATE]"))
1460 break;
1461 mutt_debug(LL_DEBUG3, "server suggests TRYCREATE\n");
1462 snprintf(prompt, sizeof(prompt), _("Create %s?"), dest_mdata->name);
1463 const bool c_confirm_create = cs_subset_bool(NeoMutt->sub, "confirm_create");
1464 if (c_confirm_create &&
1465 (query_yesorno_help(prompt, MUTT_YES, NeoMutt->sub, "confirm_create") != MUTT_YES))
1466 {
1468 goto out;
1469 }
1470 if (imap_create_mailbox(adata, dest_mdata->name) < 0)
1471 break;
1472 triedcreate = true;
1473 }
1474 } while (rc == IMAP_EXEC_ERROR);
1475
1476 if (rc != IMAP_EXEC_SUCCESS)
1477 {
1478 imap_error("imap_fast_trash", adata->buf);
1479 goto out;
1480 }
1481
1482 rc = IMAP_EXEC_SUCCESS;
1483
1484out:
1485 buf_pool_release(&sync_cmd);
1486 imap_mdata_free((void *) &dest_mdata);
1487
1488 return ((rc == IMAP_EXEC_SUCCESS) ? 0 : -1);
1489}
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition mailbox.h:214
@ 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:1095
char * imap_get_qualifier(char *buf)
Get the qualifier from a tagged response.
Definition util.c:807
int imap_create_mailbox(struct ImapAccountData *adata, const char *mailbox)
Create a new mailbox.
Definition imap.c:448
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:946
@ LL_DEBUG3
Log at debug level 3.
Definition logging2.h:46
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition string.c:244
@ MUTT_TRASH
Trashed messages.
Definition mutt.h:85
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:353
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 668 of file imap.c.

669{
670 struct ImapMboxData *mdata = imap_mdata_get(m);
672
673 if (!mdata || !edata)
674 return;
675
676 imap_msn_remove(&mdata->msn, edata->msn - 1);
677 edata->msn = 0;
678}
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 197 of file browse.c.

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

395{
396 struct ImapAccountData *adata = NULL;
397 struct ImapMboxData *mdata = NULL;
398 struct Buffer *name = buf_pool_get();
399 int rc = -1;
400
401 if (imap_adata_find(path, &adata, &mdata) < 0)
402 {
403 mutt_debug(LL_DEBUG1, "Couldn't find open connection to %s\n", path);
404 goto done;
405 }
406
407 /* append a delimiter if necessary */
408 const size_t n = buf_strcpy(name, mdata->real_name);
409 if ((n != 0) && (buf_at(name, n - 1) != adata->delim))
410 {
411 buf_addch(name, adata->delim);
412 }
413
414 struct FileCompletionData cdata = { false, NULL, NULL, NULL, NULL };
415 if (mw_get_field(_("Create mailbox: "), name, MUTT_COMP_NO_FLAGS, HC_MAILBOX,
416 &CompleteMailboxOps, &cdata) != 0)
417 {
418 goto done;
419 }
420
421 if (buf_is_empty(name))
422 {
423 mutt_error(_("Mailbox must have a name"));
424 goto done;
425 }
426
427 if (imap_create_mailbox(adata, buf_string(name)) < 0)
428 goto done;
429
430 imap_mdata_free((void *) &mdata);
431 mutt_message(_("Mailbox created"));
432 mutt_sleep(0);
433 rc = 0;
434
435done:
436 imap_mdata_free((void *) &mdata);
437 buf_pool_release(&name);
438 return rc;
439}
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
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:272
@ HC_MAILBOX
Mailboxes.
Definition lib.h:60
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition mutt.h:56
void mutt_sleep(short s)
Sleep for a while.
Definition muttlib.c:841
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 449 of file browse.c.

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

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

574{
575 struct Account **ap = NULL;
577 {
578 struct Account *a = *ap;
579 if (a->type != MUTT_IMAP)
580 continue;
581
582 struct ImapAccountData *adata = a->adata;
583 if (!adata)
584 continue;
585
586 struct Connection *conn = adata->conn;
587 if (!conn || (conn->fd < 0))
588 continue;
589
590 mutt_message(_("Closing connection to %s..."), conn->account.host);
591 imap_logout(a->adata);
593 }
594}
static void imap_logout(struct ImapAccountData *adata)
Gracefully log out of server.
Definition imap.c:543
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:48
+ 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 477 of file util.c.

478{
479 static unsigned short ImapPort = 0;
480 static unsigned short ImapsPort = 0;
481
482 if (ImapPort == 0)
483 {
484 struct servent *service = getservbyname("imap", "tcp");
485 if (service)
486 ImapPort = ntohs(service->s_port);
487 else
488 ImapPort = IMAP_PORT;
489 mutt_debug(LL_DEBUG3, "Using default IMAP port %d\n", ImapPort);
490 }
491
492 if (ImapsPort == 0)
493 {
494 struct servent *service = getservbyname("imaps", "tcp");
495 if (service)
496 ImapsPort = ntohs(service->s_port);
497 else
498 ImapsPort = IMAP_SSL_PORT;
499 mutt_debug(LL_DEBUG3, "Using default IMAPS port %d\n", ImapsPort);
500 }
501
502 /* Defaults */
503 cac->port = ImapPort;
505 cac->service = "imap";
507
508 struct Url *url = url_parse(path);
509 if (!url)
510 return -1;
511
512 if ((url->scheme != U_IMAP) && (url->scheme != U_IMAPS))
513 {
514 url_free(&url);
515 return -1;
516 }
517
518 if ((account_from_url(cac, url) < 0) || (cac->host[0] == '\0'))
519 {
520 url_free(&url);
521 return -1;
522 }
523
524 if (url->scheme == U_IMAPS)
525 cac->flags |= MUTT_ACCT_SSL;
526
527 mutt_str_copy(mailbox, url->path, mailboxlen);
528
529 url_free(&url);
530
531 if ((cac->flags & MUTT_ACCT_SSL) && !(cac->flags & MUTT_ACCT_PORT))
532 cac->port = ImapsPort;
533
534 return 0;
535}
#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:207
#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 584 of file util.c.

585{
586 struct ConnAccount cac_target = { { 0 } };
587 struct ConnAccount cac_home = { { 0 } };
588 struct Url url = { 0 };
589 const char *delim = NULL;
590 int tlen;
591 int hlen = 0;
592 bool home_match = false;
593 char target_mailbox[1024] = { 0 };
594 char home_mailbox[1024] = { 0 };
595
596 if (imap_parse_path(path, &cac_target, target_mailbox, sizeof(target_mailbox)) < 0)
597 return;
598
599 if (imap_path_probe(folder, NULL) != MUTT_IMAP)
600 goto fallback;
601
602 if (imap_parse_path(folder, &cac_home, home_mailbox, sizeof(home_mailbox)) < 0)
603 goto fallback;
604
605 tlen = mutt_str_len(target_mailbox);
606 hlen = mutt_str_len(home_mailbox);
607
608 /* check whether we can do '+' substitution */
609 if (tlen && imap_account_match(&cac_home, &cac_target) &&
610 mutt_strn_equal(home_mailbox, target_mailbox, hlen))
611 {
612 const char *const c_imap_delim_chars = cs_subset_string(NeoMutt->sub, "imap_delim_chars");
613 if (hlen == 0)
614 {
615 home_match = true;
616 }
617 else if (c_imap_delim_chars)
618 {
619 for (delim = c_imap_delim_chars; *delim != '\0'; delim++)
620 if (target_mailbox[hlen] == *delim)
621 home_match = true;
622 }
623 }
624
625 /* do the '+' substitution */
626 if (home_match)
627 {
628 *path++ = '+';
629 /* copy remaining path, skipping delimiter */
630 if (hlen != 0)
631 hlen++;
632 memcpy(path, target_mailbox + hlen, tlen - hlen);
633 path[tlen - hlen] = '\0';
634 return;
635 }
636
637fallback:
638 account_to_url(&cac_target, &url);
639 url.path = target_mailbox;
640 url_tostring(&url, path, pathlen, U_NO_FLAGS);
641}
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:2382
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:427
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:422
#define U_NO_FLAGS
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:477
bool imap_account_match(const struct ConnAccount *a1, const struct ConnAccount *a2)
Compare two Accounts.
Definition util.c:1095
+ 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 548 of file util.c.

549{
550 char *b1 = NULL;
551 char *b2 = NULL;
552 int rc;
553
554 if (!mx1 || (*mx1 == '\0'))
555 mx1 = "INBOX";
556 if (!mx2 || (*mx2 == '\0'))
557 mx2 = "INBOX";
558 if (mutt_istr_equal(mx1, "INBOX") && mutt_istr_equal(mx2, "INBOX"))
559 {
560 return 0;
561 }
562
563 b1 = MUTT_MEM_MALLOC(strlen(mx1) + 1, char);
564 b2 = MUTT_MEM_MALLOC(strlen(mx2) + 1, char);
565
566 imap_fix_path(mx1, b1, strlen(mx1) + 1);
567 imap_fix_path(mx2, b2, strlen(mx2) + 1);
568
569 rc = mutt_str_cmp(b1, b2);
570 FREE(&b1);
571 FREE(&b2);
572
573 return rc;
574}
int mutt_str_cmp(const char *a, const char *b)
Compare two strings, safely.
Definition string.c:401
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:672
char * imap_fix_path(const char *mailbox, char *path, size_t plen)
Fix up the imap path.
Definition util.c:681
+ 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 1020 of file util.c.

1021{
1022 struct sigaction oldalrm = { 0 };
1023 struct sigaction act = { 0 };
1024 sigset_t oldmask = { 0 };
1025 int rc;
1026
1027 const bool c_imap_passive = cs_subset_bool(NeoMutt->sub, "imap_passive");
1028 cs_subset_str_native_set(NeoMutt->sub, "imap_passive", true, NULL);
1029 OptKeepQuiet = true;
1030
1031 sigprocmask(SIG_SETMASK, NULL, &oldmask);
1032
1033 sigemptyset(&act.sa_mask);
1034 act.sa_handler = mutt_sig_empty_handler;
1035#ifdef SA_INTERRUPT
1036 act.sa_flags = SA_INTERRUPT;
1037#else
1038 act.sa_flags = 0;
1039#endif
1040
1041 sigaction(SIGALRM, &act, &oldalrm);
1042
1043 const short c_imap_keep_alive = cs_subset_number(NeoMutt->sub, "imap_keep_alive");
1044 alarm(c_imap_keep_alive);
1045 while ((waitpid(pid, &rc, 0) < 0) && (errno == EINTR))
1046 {
1047 alarm(0); /* cancel a possibly pending alarm */
1049 alarm(c_imap_keep_alive);
1050 }
1051
1052 alarm(0); /* cancel a possibly pending alarm */
1053
1054 sigaction(SIGALRM, &oldalrm, NULL);
1055 sigprocmask(SIG_SETMASK, &oldmask, NULL);
1056
1057 OptKeepQuiet = false;
1058 cs_subset_str_native_set(NeoMutt->sub, "imap_passive", c_imap_passive, NULL);
1059
1060 return rc;
1061}
bool OptKeepQuiet
(pseudo) shut up the message and refresh functions while we are executing an external program
Definition globals.c:60
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:994
+ 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 994 of file util.c.

995{
996 time_t now = mutt_date_now();
997 const short c_imap_keep_alive = cs_subset_number(NeoMutt->sub, "imap_keep_alive");
998
999 struct Account **ap = NULL;
1001 {
1002 struct Account *a = *ap;
1003 if (a->type != MUTT_IMAP)
1004 continue;
1005
1006 struct ImapAccountData *adata = a->adata;
1007 if (!adata || !adata->mailbox)
1008 continue;
1009
1010 if ((adata->state >= IMAP_AUTHENTICATED) && (now >= (adata->lastread + c_imap_keep_alive)))
1011 imap_check_mailbox(adata->mailbox, true);
1012 }
1013}
+ 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 164 of file util.c.

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

192{
193 struct ImapAccountData *adata = NULL;
194 struct ImapMboxData *mdata = NULL;
195
196 if (imap_adata_find(path, &adata, &mdata) < 0)
197 return;
198
199 /* Returns a fully qualified IMAP url */
200 imap_qualify_path(path, plen, &adata->conn->account, mdata->name);
201 imap_mdata_free((void *) &mdata);
202}
+ 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: