NeoMutt  2020-06-26-250-g349c94
Teaching an old dog new tricks
DOXYGEN
imap.c File Reference

IMAP network mailbox. More...

#include "config.h"
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "private.h"
#include "mutt/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "conn/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "lib.h"
#include "auth.h"
#include "commands.h"
#include "hook.h"
#include "init.h"
#include "message.h"
#include "mutt_globals.h"
#include "mutt_logging.h"
#include "mutt_socket.h"
#include "muttlib.h"
#include "mx.h"
#include "progress.h"
#include "sort.h"
#include "bcache/lib.h"
#include "pattern/lib.h"
#include <libintl.h>
+ Include dependency graph for imap.c:

Go to the source code of this file.

Functions

static int check_capabilities (struct ImapAccountData *adata)
 Make sure we can log in to this server. More...
 
static char * get_flags (struct ListHead *hflags, char *s)
 Make a simple list out of a FLAGS response. More...
 
static void set_flag (struct Mailbox *m, AclFlags aclflag, int flag, const char *str, char *flags, size_t flsize)
 append str to flags if we currently have permission according to aclflag More...
 
static int make_msg_set (struct Mailbox *m, struct Buffer *buf, int flag, bool changed, bool invert, int *pos)
 Make a message set. More...
 
static bool compare_flags_for_copy (struct Email *e)
 Compare local flags against the server. More...
 
static int sync_helper (struct Mailbox *m, AclFlags right, int flag, const char *name)
 Sync flag changes to the server. More...
 
static size_t longest_common_prefix (char *dest, const char *src, size_t start, size_t dlen)
 Find longest prefix common to two strings. More...
 
static int complete_hosts (char *buf, size_t buflen)
 Look for completion matches for mailboxes. More...
 
int imap_create_mailbox (struct ImapAccountData *adata, char *mailbox)
 Create a new mailbox. More...
 
int imap_access (const char *path)
 Check permissions on an IMAP mailbox with a new connection. More...
 
int imap_rename_mailbox (struct ImapAccountData *adata, char *oldname, const char *newname)
 Rename a mailbox. More...
 
int imap_delete_mailbox (struct Mailbox *m, char *path)
 Delete a mailbox. More...
 
static void imap_logout (struct ImapAccountData *adata)
 Gracefully log out of server. More...
 
void imap_logout_all (void)
 close all open connections More...
 
int imap_read_literal (FILE *fp, struct ImapAccountData *adata, unsigned long bytes, struct Progress *pbar)
 Read bytes bytes from server into file. More...
 
void imap_expunge_mailbox (struct Mailbox *m)
 Purge messages from the server. More...
 
int imap_open_connection (struct ImapAccountData *adata)
 Open an IMAP connection. More...
 
void imap_close_connection (struct ImapAccountData *adata)
 Close an IMAP connection. More...
 
bool imap_has_flag (struct ListHead *flag_list, const char *flag)
 Does the flag exist in the list. More...
 
static int compare_uid (const void *a, const void *b)
 Compare two Emails by UID - Implements sort_t. More...
 
int imap_exec_msgset (struct Mailbox *m, const char *pre, const char *post, int flag, bool changed, bool invert)
 Prepare commands for all messages matching conditions. More...
 
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. More...
 
int imap_check_mailbox (struct Mailbox *m, bool force)
 use the NOOP or IDLE command to poll for new mail More...
 
static int imap_status (struct ImapAccountData *adata, struct ImapMboxData *mdata, bool queue)
 Refresh the number of total and new messages. More...
 
static int imap_mbox_check_stats (struct Mailbox *m, int flags)
 Check the Mailbox statistics - Implements MxOps::mbox_check_stats() More...
 
int imap_path_status (const char *path, bool queue)
 Refresh the number of total and new messages. More...
 
int imap_mailbox_status (struct Mailbox *m, bool queue)
 Refresh the number of total and new messages. More...
 
int imap_subscribe (char *path, bool subscribe)
 Subscribe to a mailbox. More...
 
int imap_complete (char *buf, size_t buflen, const char *path)
 Try to complete an IMAP folder path. More...
 
int imap_fast_trash (struct Mailbox *m, char *dest)
 Use server COPY command to copy deleted messages to trash. More...
 
int imap_sync_mailbox (struct Mailbox *m, bool expunge, bool close)
 Sync all the changes to the server. More...
 
static struct Accountimap_ac_find (struct Account *a, const char *path)
 Find an Account that matches a Mailbox path - Implements MxOps::ac_find() More...
 
static int imap_ac_add (struct Account *a, struct Mailbox *m)
 Add a Mailbox to an Account - Implements MxOps::ac_add() More...
 
static void imap_mbox_select (struct Mailbox *m)
 Select a Mailbox. More...
 
int imap_login (struct ImapAccountData *adata)
 Open an IMAP connection. More...
 
static int imap_mbox_open (struct Mailbox *m)
 Open a mailbox - Implements MxOps::mbox_open() More...
 
static int imap_mbox_open_append (struct Mailbox *m, OpenMailboxFlags flags)
 Open a Mailbox for appending - Implements MxOps::mbox_open_append() More...
 
static int imap_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() More...
 
static int imap_mbox_close (struct Mailbox *m)
 Close a Mailbox - Implements MxOps::mbox_close() More...
 
static int imap_msg_open_new (struct Mailbox *m, struct Message *msg, struct Email *e)
 Open a new message in a Mailbox - Implements MxOps::msg_open_new() More...
 
static int imap_tags_edit (struct Mailbox *m, const char *tags, char *buf, size_t buflen)
 Prompt and validate new messages tags - Implements MxOps::tags_edit() More...
 
static int imap_tags_commit (struct Mailbox *m, struct Email *e, char *buf)
 Save the tags to a message - Implements MxOps::tags_commit() More...
 
enum MailboxType imap_path_probe (const char *path, const struct stat *st)
 Is this an IMAP Mailbox? - Implements MxOps::path_probe() More...
 
int imap_path_canon (char *buf, size_t buflen)
 Canonicalise a Mailbox path - Implements MxOps::path_canon() More...
 
int imap_expand_path (struct Buffer *buf)
 Buffer wrapper around imap_path_canon() More...
 
static int imap_path_pretty (char *buf, size_t buflen, const char *folder)
 Abbreviate a Mailbox path - Implements MxOps::path_pretty() More...
 
static int imap_path_parent (char *buf, size_t buflen)
 Find the parent of a Mailbox path - Implements MxOps::path_parent() More...
 

Variables

struct MxOps MxImapOps
 IMAP Mailbox - Implements MxOps. More...
 

Detailed Description

IMAP network mailbox.

Authors
  • Michael R. Elkins
  • Brandon Long
  • Brendan Cully
  • Richard Russon

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file imap.c.

Function Documentation

◆ check_capabilities()

static int check_capabilities ( struct ImapAccountData adata)
static

Make sure we can log in to this server.

Parameters
adataImap Account data
Return values
0Success
-1Failure

Definition at line 73 of file imap.c.

74 {
75  if (imap_exec(adata, "CAPABILITY", IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS)
76  {
77  imap_error("check_capabilities", adata->buf);
78  return -1;
79  }
80 
81  if (!((adata->capabilities & IMAP_CAP_IMAP4) || (adata->capabilities & IMAP_CAP_IMAP4REV1)))
82  {
83  mutt_error(
84  _("This IMAP server is ancient. NeoMutt does not work with it."));
85  return -1;
86  }
87 
88  return 0;
89 }
#define IMAP_CAP_IMAP4
Server supports IMAP4.
Definition: private.h:122
#define _(a)
Definition: message.h:28
Imap command executed or queued successfully.
Definition: private.h:83
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:1247
void imap_error(const char *where, const char *msg)
show an error and abort
Definition: util.c:798
#define IMAP_CAP_IMAP4REV1
Server supports IMAP4rev1.
Definition: private.h:123
ImapCapFlags capabilities
Definition: private.h:185
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:72
char * buf
Definition: private.h:189
#define mutt_error(...)
Definition: logging.h:84
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_flags()

static char* get_flags ( struct ListHead *  hflags,
char *  s 
)
static

Make a simple list out of a FLAGS response.

Parameters
hflagsList to store flags
sString containing flags
Return values
ptrEnd of the flags
NULLFailure

return stream following FLAGS response

Definition at line 100 of file imap.c.

101 {
102  /* sanity-check string */
103  const size_t plen = mutt_istr_startswith(s, "FLAGS");
104  if (plen == 0)
105  {
106  mutt_debug(LL_DEBUG1, "not a FLAGS response: %s\n", s);
107  return NULL;
108  }
109  s += plen;
110  SKIPWS(s);
111  if (*s != '(')
112  {
113  mutt_debug(LL_DEBUG1, "bogus FLAGS response: %s\n", s);
114  return NULL;
115  }
116 
117  /* update caller's flags handle */
118  while (*s && (*s != ')'))
119  {
120  s++;
121  SKIPWS(s);
122  const char *flag_word = s;
123  while (*s && (*s != ')') && !IS_SPACE(*s))
124  s++;
125  const char ctmp = *s;
126  *s = '\0';
127  if (*flag_word)
128  mutt_list_insert_tail(hflags, mutt_str_dup(flag_word));
129  *s = ctmp;
130  }
131 
132  /* note bad flags response */
133  if (*s != ')')
134  {
135  mutt_debug(LL_DEBUG1, "Unterminated FLAGS response: %s\n", s);
136  mutt_list_free(hflags);
137 
138  return NULL;
139  }
140 
141  s++;
142 
143  return s;
144 }
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
#define SKIPWS(ch)
Definition: string2.h:46
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:177
#define IS_SPACE(ch)
Definition: string2.h:38
Log at debug level 1.
Definition: logging.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ set_flag()

static void set_flag ( struct Mailbox m,
AclFlags  aclflag,
int  flag,
const char *  str,
char *  flags,
size_t  flsize 
)
static

append str to flags if we currently have permission according to aclflag

Parameters
[in]mSelected Imap Mailbox
[in]aclflagPermissions, see AclFlags
[in]flagDoes the email have the flag set?
[in]strServer flag name
[out]flagsBuffer for server command
[in]flsizeLength of buffer

Definition at line 155 of file imap.c.

157 {
158  if (m->rights & aclflag)
159  if (flag && imap_has_flag(&imap_mdata_get(m)->flags, str))
160  mutt_str_cat(flags, flsize, str);
161 }
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: util.c:245
bool imap_has_flag(struct ListHead *flag_list, const char *flag)
Does the flag exist in the list.
Definition: imap.c:832
struct ListHead flags
Definition: private.h:227
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:121
char * mutt_str_cat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
Definition: string.c:390
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ make_msg_set()

static int make_msg_set ( struct Mailbox m,
struct Buffer buf,
int  flag,
bool  changed,
bool  invert,
int *  pos 
)
static

Make a message set.

Parameters
[in]mSelected Imap Mailbox
[in]bufBuffer to store message set
[in]flagFlags to match, e.g. MUTT_DELETED
[in]changedMatched messages that have been altered
[in]invertFlag matches should be inverted
[out]posCursor used for multiple calls to this function
Return values
numMessages in the set
Note
Headers must be in SORT_ORDER. See imap_exec_msgset() for args. Pos is an opaque pointer a la strtok(). It should be 0 at first call.

Definition at line 176 of file imap.c.

178 {
179  int count = 0; /* number of messages in message set */
180  unsigned int setstart = 0; /* start of current message range */
181  int n;
182  bool started = false;
183 
184  struct ImapAccountData *adata = imap_adata_get(m);
185  if (!adata || (adata->mailbox != m))
186  return -1;
187 
188  for (n = *pos; (n < m->msg_count) && (mutt_buffer_len(buf) < IMAP_MAX_CMDLEN); n++)
189  {
190  struct Email *e = m->emails[n];
191  if (!e)
192  break;
193  bool match = false; /* whether current message matches flag condition */
194  /* don't include pending expunged messages.
195  *
196  * TODO: can we unset active in cmd_parse_expunge() and
197  * cmd_parse_vanished() instead of checking for index != INT_MAX. */
198  if (e->active && (e->index != INT_MAX))
199  {
200  switch (flag)
201  {
202  case MUTT_DELETED:
203  if (e->deleted != imap_edata_get(e)->deleted)
204  match = invert ^ e->deleted;
205  break;
206  case MUTT_FLAG:
207  if (e->flagged != imap_edata_get(e)->flagged)
208  match = invert ^ e->flagged;
209  break;
210  case MUTT_OLD:
211  if (e->old != imap_edata_get(e)->old)
212  match = invert ^ e->old;
213  break;
214  case MUTT_READ:
215  if (e->read != imap_edata_get(e)->read)
216  match = invert ^ e->read;
217  break;
218  case MUTT_REPLIED:
219  if (e->replied != imap_edata_get(e)->replied)
220  match = invert ^ e->replied;
221  break;
222  case MUTT_TAG:
223  if (e->tagged)
224  match = true;
225  break;
226  case MUTT_TRASH:
227  if (e->deleted && !e->purge)
228  match = true;
229  break;
230  }
231  }
232 
233  if (match && (!changed || e->changed))
234  {
235  count++;
236  if (setstart == 0)
237  {
238  setstart = imap_edata_get(e)->uid;
239  if (started)
240  {
241  mutt_buffer_add_printf(buf, ",%u", imap_edata_get(e)->uid);
242  }
243  else
244  {
245  mutt_buffer_add_printf(buf, "%u", imap_edata_get(e)->uid);
246  started = true;
247  }
248  }
249  /* tie up if the last message also matches */
250  else if (n == (m->msg_count - 1))
251  mutt_buffer_add_printf(buf, ":%u", imap_edata_get(e)->uid);
252  }
253  /* End current set if message doesn't match or we've reached the end
254  * of the mailbox via inactive messages following the last match. */
255  else if (setstart && (e->active || (n == adata->mailbox->msg_count - 1)))
256  {
257  if (imap_edata_get(m->emails[n - 1])->uid > setstart)
258  mutt_buffer_add_printf(buf, ":%u", imap_edata_get(m->emails[n - 1])->uid);
259  setstart = 0;
260  }
261  }
262 
263  *pos = n;
264 
265  return count;
266 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
Deleted messages.
Definition: mutt.h:101
struct ImapEmailData * imap_edata_get(struct Email *e)
Get the private data for this Email.
Definition: message.c:98
int msg_count
Total number of messages.
Definition: mailbox.h:91
The envelope/body of an email.
Definition: email.h:37
if(!test_colorize_)
Definition: acutest.h:499
Flagged messages.
Definition: mutt.h:102
struct Mailbox * mailbox
Current selected mailbox.
Definition: private.h:206
bool changed
Email has been edited.
Definition: email.h:48
Messages that have been replied to.
Definition: mutt.h:95
#define IMAP_MAX_CMDLEN
Maximum length of command lines before they must be split (for lazy servers)
Definition: private.h:61
bool flagged
Definition: message.h:39
bool deleted
Definition: message.h:38
bool tagged
Email is tagged.
Definition: email.h:44
bool read
Email is read.
Definition: email.h:51
bool old
Email is seen, but unread.
Definition: email.h:50
int mutt_buffer_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:203
Old messages.
Definition: mutt.h:94
bool active
Message is not to be removed.
Definition: email.h:59
unsigned int uid
32-bit Message UID
Definition: message.h:44
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:356
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
Tagged messages.
Definition: mutt.h:103
Messages that have been read.
Definition: mutt.h:96
bool replied
Definition: message.h:40
bool old
Definition: message.h:37
bool purge
Skip trash folder when deleting.
Definition: email.h:46
IMAP-specific Account data -.
Definition: private.h:169
int n
Definition: acutest.h:492
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:113
bool flagged
Marked important?
Definition: email.h:43
bool deleted
Email is deleted.
Definition: email.h:45
bool replied
Email has been replied to.
Definition: email.h:54
int index
The absolute (unsorted) message number.
Definition: email.h:86
bool read
Definition: message.h:36
Trashed messages.
Definition: mutt.h:108
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compare_flags_for_copy()

static bool compare_flags_for_copy ( struct Email e)
static

Compare local flags against the server.

Parameters
eEmail
Return values
trueFlags have changed
falseFlags match cached server flags

The comparison of flags EXCLUDES the deleted flag.

Definition at line 276 of file imap.c.

277 {
278  struct ImapEmailData *edata = e->edata;
279 
280  if (e->read != edata->read)
281  return true;
282  if (e->old != edata->old)
283  return true;
284  if (e->flagged != edata->flagged)
285  return true;
286  if (e->replied != edata->replied)
287  return true;
288 
289  return false;
290 }
bool flagged
Definition: message.h:39
bool read
Email is read.
Definition: email.h:51
bool old
Email is seen, but unread.
Definition: email.h:50
bool replied
Definition: message.h:40
bool old
Definition: message.h:37
bool flagged
Marked important?
Definition: email.h:43
void * edata
Driver-specific data.
Definition: email.h:109
bool replied
Email has been replied to.
Definition: email.h:54
bool read
Definition: message.h:36
IMAP-specific Email data -.
Definition: message.h:33
+ Here is the caller graph for this function:

◆ sync_helper()

static int sync_helper ( struct Mailbox m,
AclFlags  right,
int  flag,
const char *  name 
)
static

Sync flag changes to the server.

Parameters
mSelected Imap Mailbox
rightACL, see AclFlags
flagNeoMutt flag, e.g. MUTT_DELETED
nameName of server flag
Return values
>=0Success, number of messages
-1Failure

Definition at line 301 of file imap.c.

302 {
303  int count = 0;
304  int rc;
305  char buf[1024];
306 
307  if (!m)
308  return -1;
309 
310  if ((m->rights & right) == 0)
311  return 0;
312 
313  if ((right == MUTT_ACL_WRITE) && !imap_has_flag(&imap_mdata_get(m)->flags, name))
314  return 0;
315 
316  snprintf(buf, sizeof(buf), "+FLAGS.SILENT (%s)", name);
317  rc = imap_exec_msgset(m, "UID STORE", buf, flag, true, false);
318  if (rc < 0)
319  return rc;
320  count += rc;
321 
322  buf[0] = '-';
323  rc = imap_exec_msgset(m, "UID STORE", buf, flag, true, true);
324  if (rc < 0)
325  return rc;
326  count += rc;
327 
328  return count;
329 }
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: util.c:245
bool imap_has_flag(struct ListHead *flag_list, const char *flag)
Does the flag exist in the list.
Definition: imap.c:832
int imap_exec_msgset(struct Mailbox *m, const char *pre, const char *post, int flag, bool changed, bool invert)
Prepare commands for all messages matching conditions.
Definition: imap.c:881
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:74
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:121
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ longest_common_prefix()

static size_t longest_common_prefix ( char *  dest,
const char *  src,
size_t  start,
size_t  dlen 
)
static

Find longest prefix common to two strings.

Parameters
destDestination buffer
srcSource buffer
startStarting offset into string
dlenDestination buffer length
Return values
numLength of the common string

Trim dest to the length of the longest prefix it shares with src.

Definition at line 341 of file imap.c.

342 {
343  size_t pos = start;
344 
345  while ((pos < dlen) && dest[pos] && (dest[pos] == src[pos]))
346  pos++;
347  dest[pos] = '\0';
348 
349  return pos;
350 }
+ Here is the caller graph for this function:

◆ complete_hosts()

static int complete_hosts ( char *  buf,
size_t  buflen 
)
static

Look for completion matches for mailboxes.

Parameters
bufPartial mailbox name to complete
buflenLength of buffer
Return values
0Success
-1Failure

look for IMAP URLs to complete from defined mailboxes. Could be extended to complete over open connections and account/folder hooks too.

Definition at line 362 of file imap.c.

363 {
364  // struct Connection *conn = NULL;
365  int rc = -1;
366  size_t matchlen;
367 
368  matchlen = mutt_str_len(buf);
369  struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
371  struct MailboxNode *np = NULL;
372  STAILQ_FOREACH(np, &ml, entries)
373  {
374  if (!mutt_str_startswith(mailbox_path(np->mailbox), buf))
375  continue;
376 
377  if (rc)
378  {
379  mutt_str_copy(buf, mailbox_path(np->mailbox), buflen);
380  rc = 0;
381  }
382  else
383  longest_common_prefix(buf, mailbox_path(np->mailbox), matchlen, buflen);
384  }
386 
387 #if 0
388  TAILQ_FOREACH(conn, mutt_socket_head(), entries)
389  {
390  struct Url url = { 0 };
391  char urlstr[1024];
392 
393  if (conn->account.type != MUTT_ACCT_TYPE_IMAP)
394  continue;
395 
396  mutt_account_tourl(&conn->account, &url);
397  /* FIXME: how to handle multiple users on the same host? */
398  url.user = NULL;
399  url.path = NULL;
400  url_tostring(&url, urlstr, sizeof(urlstr), 0);
401  if (mutt_strn_equal(buf, urlstr, matchlen))
402  {
403  if (rc)
404  {
405  mutt_str_copy(buf, urlstr, buflen);
406  rc = 0;
407  }
408  else
409  longest_common_prefix(buf, urlstr, matchlen, buflen);
410  }
411  }
412 #endif
413 
414  return rc;
415 }
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:201
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:66
void neomutt_mailboxlist_clear(struct MailboxList *ml)
Free a Mailbox List.
Definition: neomutt.c:137
Match any Mailbox type.
Definition: mailbox.h:45
size_t neomutt_mailboxlist_get_all(struct MailboxList *head, struct NeoMutt *n, enum MailboxType type)
Get a List of all Mailboxes.
Definition: neomutt.c:160
Container for Accounts, Notifications.
Definition: neomutt.h:36
void mutt_account_tourl(struct ConnAccount *cac, struct Url *url)
Fill URL with info from account.
Definition: mutt_account.c:79
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:165
char * user
Username.
Definition: url.h:69
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
Imap Account.
Definition: mutt_account.h:37
char * path
Path.
Definition: url.h:73
bool mutt_strn_equal(const char *a, const char *b, size_t l)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:598
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:636
static size_t longest_common_prefix(char *dest, const char *src, size_t start, size_t dlen)
Find longest prefix common to two strings.
Definition: imap.c:341
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:721
int url_tostring(struct Url *url, char *dest, size_t len, int flags)
Output the URL string for a given Url object.
Definition: url.c:418
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:321
List of Mailboxes.
Definition: mailbox.h:150
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:152
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_create_mailbox()

int imap_create_mailbox ( struct ImapAccountData adata,
char *  mailbox 
)

Create a new mailbox.

Parameters
adataImap Account data
mailboxMailbox to create
Return values
0Success
-1Failure

Definition at line 424 of file imap.c.

425 {
426  char buf[2048], mbox[1024];
427 
428  imap_munge_mbox_name(adata->unicode, mbox, sizeof(mbox), mailbox);
429  snprintf(buf, sizeof(buf), "CREATE %s", mbox);
430 
431  if (imap_exec(adata, buf, IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS)
432  {
433  mutt_error(_("CREATE failed: %s"), imap_cmd_trailer(adata));
434  return -1;
435  }
436 
437  return 0;
438 }
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:1045
#define _(a)
Definition: message.h:28
const char * imap_cmd_trailer(struct ImapAccountData *adata)
Extra information after tagged command response if any.
Definition: command.c:1210
Imap command executed or queued successfully.
Definition: private.h:83
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:1247
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:72
#define mutt_error(...)
Definition: logging.h:84
bool unicode
If true, we can send UTF-8, and the server will use UTF8 rather than mUTF7.
Definition: private.h:192
+ 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 450 of file imap.c.

451 {
452  if (imap_path_status(path, false) >= 0)
453  return 0;
454  return -1;
455 }
int imap_path_status(const char *path, bool queue)
Refresh the number of total and new messages.
Definition: imap.c:1181
char * path
Path.
Definition: url.h:73
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_rename_mailbox()

int imap_rename_mailbox ( struct ImapAccountData adata,
char *  oldname,
const char *  newname 
)

Rename a mailbox.

Parameters
adataImap Account data
oldnameExisting mailbox
newnameNew name for mailbox
Return values
0Success
-1Failure

Definition at line 465 of file imap.c.

466 {
467  char oldmbox[1024];
468  char newmbox[1024];
469  int rc = 0;
470 
471  imap_munge_mbox_name(adata->unicode, oldmbox, sizeof(oldmbox), oldname);
472  imap_munge_mbox_name(adata->unicode, newmbox, sizeof(newmbox), newname);
473 
474  struct Buffer *buf = mutt_buffer_pool_get();
475  mutt_buffer_printf(buf, "RENAME %s %s", oldmbox, newmbox);
476 
478  rc = -1;
479 
481 
482  return rc;
483 }
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
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:1045
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
Imap command executed or queued successfully.
Definition: private.h:83
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:1247
#define mutt_b2s(buf)
Definition: buffer.h:41
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:72
bool unicode
If true, we can send UTF-8, and the server will use UTF8 rather than mUTF7.
Definition: private.h:192
+ 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 492 of file imap.c.

493 {
494  char buf[PATH_MAX + 7];
495  char mbox[PATH_MAX];
496  struct Url *url = url_parse(path);
497 
498  struct ImapAccountData *adata = imap_adata_get(m);
499  imap_munge_mbox_name(adata->unicode, mbox, sizeof(mbox), url->path);
500  url_free(&url);
501  snprintf(buf, sizeof(buf), "DELETE %s", mbox);
503  return -1;
504 
505  return 0;
506 }
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:66
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:1045
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition: url.c:123
Imap command executed or queued successfully.
Definition: private.h:83
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:1247
#define PATH_MAX
Definition: mutt.h:44
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:72
char * path
Path.
Definition: url.h:73
IMAP-specific Account data -.
Definition: private.h:169
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:131
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:113
bool unicode
If true, we can send UTF-8, and the server will use UTF8 rather than mUTF7.
Definition: private.h:192
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:234
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_logout()

static void imap_logout ( struct ImapAccountData adata)
static

Gracefully log out of server.

Parameters
adataImap Account data

Definition at line 512 of file imap.c.

513 {
514  /* we set status here to let imap_handle_untagged know we _expect_ to
515  * receive a bye response (so it doesn't freak out and close the conn) */
516  if (adata->state == IMAP_DISCONNECTED)
517  {
518  return;
519  }
520 
521  adata->status = IMAP_BYE;
522  imap_cmd_start(adata, "LOGOUT");
523  if ((C_ImapPollTimeout <= 0) || (mutt_socket_poll(adata->conn, C_ImapPollTimeout) != 0))
524  {
525  while (imap_cmd_step(adata) == IMAP_RES_CONTINUE)
526  ; // do nothing
527  }
528  mutt_socket_close(adata->conn);
529  adata->state = IMAP_DISCONNECTED;
530 }
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1076
Logged out from server.
Definition: private.h:97
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: private.h:174
int imap_cmd_start(struct ImapAccountData *adata, const char *cmdstr)
Given an IMAP command, send it to the server.
Definition: command.c:1062
int mutt_socket_poll(struct Connection *conn, time_t wait_secs)
Checks whether reads would block.
Definition: socket.c:191
Disconnected from server.
Definition: private.h:106
short C_ImapPollTimeout
Config: (imap) Maximum time to wait for a server response.
Definition: config.c:54
unsigned char status
ImapFlags, e.g. IMAP_FATAL.
Definition: private.h:175
int mutt_socket_close(struct Connection *conn)
Close a socket.
Definition: socket.c:96
#define IMAP_RES_CONTINUE
* ...
Definition: private.h:56
struct Connection * conn
Definition: private.h:171
+ 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 537 of file imap.c.

538 {
539  struct Account *np = NULL;
540  TAILQ_FOREACH(np, &NeoMutt->accounts, entries)
541  {
542  if (np->type != MUTT_IMAP)
543  continue;
544 
545  struct ImapAccountData *adata = np->adata;
546  if (!adata)
547  continue;
548 
549  struct Connection *conn = adata->conn;
550  if (!conn || (conn->fd < 0))
551  continue;
552 
553  mutt_message(_("Closing connection to %s..."), conn->account.host);
554  imap_logout(np->adata);
556  }
557 }
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:36
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
#define mutt_message(...)
Definition: logging.h:83
struct AccountList accounts
List of all Accounts.
Definition: neomutt.h:40
A group of associated Mailboxes.
Definition: account.h:36
An open network connection (socket)
Definition: connection.h:34
static void imap_logout(struct ImapAccountData *adata)
Gracefully log out of server.
Definition: imap.c:512
#define _(a)
Definition: message.h:28
enum MailboxType type
Type of Mailboxes this Account contains.
Definition: account.h:38
Container for Accounts, Notifications.
Definition: neomutt.h:36
char host[128]
Server to login to.
Definition: connaccount.h:53
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
int fd
Socket file descriptor.
Definition: connection.h:40
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
IMAP-specific Account data -.
Definition: private.h:169
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
struct Connection * conn
Definition: private.h:171
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_read_literal()

int imap_read_literal ( FILE *  fp,
struct ImapAccountData adata,
unsigned long  bytes,
struct Progress pbar 
)

Read bytes bytes from server into file.

Parameters
fpFile handle for email file
adataImap Account data
bytesNumber of bytes to read
pbarProgress bar
Return values
0Success
-1Failure

Not explicitly buffered, relies on FILE buffering.

Note
Strips \r from \r\n. Apparently even literals use \r\n-terminated strings ?!

Definition at line 573 of file imap.c.

575 {
576  char c;
577  bool r = false;
578  struct Buffer buf = { 0 }; // Do not allocate, maybe it won't be used
579 
581  mutt_buffer_alloc(&buf, bytes + 10);
582 
583  mutt_debug(LL_DEBUG2, "reading %ld bytes\n", bytes);
584 
585  for (unsigned long pos = 0; pos < bytes; pos++)
586  {
587  if (mutt_socket_readchar(adata->conn, &c) != 1)
588  {
589  mutt_debug(LL_DEBUG1, "error during read, %ld bytes read\n", pos);
590  adata->status = IMAP_FATAL;
591 
592  mutt_buffer_dealloc(&buf);
593  return -1;
594  }
595 
596  if (r && (c != '\n'))
597  fputc('\r', fp);
598 
599  if (c == '\r')
600  {
601  r = true;
602  continue;
603  }
604  else
605  r = false;
606 
607  fputc(c, fp);
608 
609  if (pbar && !(pos % 1024))
610  mutt_progress_update(pbar, pos, -1);
612  mutt_buffer_addch(&buf, c);
613  }
614 
616  {
617  mutt_debug(IMAP_LOG_LTRL, "\n%s", buf.data);
618  mutt_buffer_dealloc(&buf);
619  }
620  return 0;
621 }
Unrecoverable error occurred.
Definition: private.h:96
String manipulation buffer.
Definition: buffer.h:33
int mutt_socket_readchar(struct Connection *conn, char *c)
simple read buffering to speed things up
Definition: socket.c:209
void mutt_progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:212
Log at debug level 2.
Definition: logging.h:41
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
short C_DebugLevel
Config: Logging level for debug logs.
Definition: mutt_logging.c:48
unsigned char status
ImapFlags, e.g. IMAP_FATAL.
Definition: private.h:175
char * data
Pointer to data.
Definition: buffer.h:35
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
Log at debug level 1.
Definition: logging.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
#define IMAP_LOG_LTRL
Definition: private.h:49
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:265
struct Connection * conn
Definition: private.h:171
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_expunge_mailbox()

void imap_expunge_mailbox ( struct Mailbox m)

Purge messages from the server.

Parameters
mMailbox

Purge IMAP portion of expunged messages from the context. Must not be done while something has a handle on any headers (eg inside pager or editor). That is, check IMAP_REOPEN_ALLOW.

Definition at line 631 of file imap.c.

632 {
633  struct ImapAccountData *adata = imap_adata_get(m);
634  struct ImapMboxData *mdata = imap_mdata_get(m);
635  if (!adata || !mdata)
636  return;
637 
638  struct Email *e = NULL;
639 
640 #ifdef USE_HCACHE
641  imap_hcache_open(adata, mdata);
642 #endif
643 
644  for (int i = 0; i < m->msg_count; i++)
645  {
646  e = m->emails[i];
647  if (!e)
648  break;
649 
650  if (e->index == INT_MAX)
651  {
652  mutt_debug(LL_DEBUG2, "Expunging message UID %u\n", imap_edata_get(e)->uid);
653 
654  e->deleted = true;
655 
656  imap_cache_del(m, e);
657 #ifdef USE_HCACHE
658  imap_hcache_del(mdata, imap_edata_get(e)->uid);
659 #endif
660 
661  mutt_hash_int_delete(mdata->uid_hash, imap_edata_get(e)->uid, e);
662 
663  imap_edata_free((void **) &e->edata);
664  }
665  else
666  {
667  e->index = i;
668  /* NeoMutt has several places where it turns off e->active as a
669  * hack. For example to avoid FLAG updates, or to exclude from
670  * imap_exec_msgset.
671  *
672  * Unfortunately, when a reopen is allowed and the IMAP_EXPUNGE_PENDING
673  * flag becomes set (e.g. a flag update to a modified header),
674  * this function will be called by imap_cmd_finish().
675  *
676  * The ctx_update_tables() will free and remove these "inactive" headers,
677  * despite that an EXPUNGE was not received for them.
678  * This would result in memory leaks and segfaults due to dangling
679  * pointers in the msn_index and uid_hash.
680  *
681  * So this is another hack to work around the hacks. We don't want to
682  * remove the messages, so make sure active is on. */
683  e->active = true;
684  }
685  }
686 
687 #ifdef USE_HCACHE
688  imap_hcache_close(mdata);
689 #endif
690 
693 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
struct ImapEmailData * imap_edata_get(struct Email *e)
Get the private data for this Email.
Definition: message.c:98
int msg_count
Total number of messages.
Definition: mailbox.h:91
The envelope/body of an email.
Definition: email.h:37
Update internal tables.
Definition: mailbox.h:174
int imap_hcache_del(struct ImapMboxData *mdata, unsigned int uid)
Delete an item from the header cache.
Definition: util.c:534
int imap_cache_del(struct Mailbox *m, struct Email *e)
Delete an email from the body cache.
Definition: message.c:1773
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: util.c:245
void imap_hcache_close(struct ImapMboxData *mdata)
Close the header cache.
Definition: util.c:475
Log at debug level 2.
Definition: logging.h:41
void imap_edata_free(void **ptr)
Free the private Email data - Implements Email::edata_free()
Definition: message.c:72
void * mdata
Driver specific data.
Definition: mailbox.h:136
struct HashTable * uid_hash
Definition: private.h:236
Email list needs resorting.
Definition: mailbox.h:172
bool active
Message is not to be removed.
Definition: email.h:59
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
void mutt_hash_int_delete(struct HashTable *table, unsigned int intkey, const void *data)
Remove an element from a Hash Table.
Definition: hash.c:434
IMAP-specific Account data -.
Definition: private.h:169
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:113
IMAP-specific Mailbox data -.
Definition: private.h:216
bool deleted
Email is deleted.
Definition: email.h:45
void * edata
Driver-specific data.
Definition: email.h:109
int index
The absolute (unsorted) message number.
Definition: email.h:86
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
void imap_hcache_open(struct ImapAccountData *adata, struct ImapMboxData *mdata)
Open a header cache.
Definition: util.c:435
void mailbox_changed(struct Mailbox *m, enum NotifyMailbox action)
Notify observers of a change to a Mailbox.
Definition: mailbox.c:174
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_open_connection()

int imap_open_connection ( struct ImapAccountData adata)

Open an IMAP connection.

Parameters
adataImap Account data
Return values
0Success
-1Failure

Definition at line 701 of file imap.c.

702 {
703  if (mutt_socket_open(adata->conn) < 0)
704  return -1;
705 
706  adata->state = IMAP_CONNECTED;
707 
708  if (imap_cmd_step(adata) != IMAP_RES_OK)
709  {
710  imap_close_connection(adata);
711  return -1;
712  }
713 
714  if (mutt_istr_startswith(adata->buf, "* OK"))
715  {
716  if (!mutt_istr_startswith(adata->buf, "* OK [CAPABILITY") && check_capabilities(adata))
717  {
718  goto bail;
719  }
720 #ifdef USE_SSL
721  /* Attempt STARTTLS if available and desired. */
722  if ((adata->conn->ssf == 0) && (C_SslForceTls || (adata->capabilities & IMAP_CAP_STARTTLS)))
723  {
724  enum QuadOption ans;
725 
726  if (C_SslForceTls)
727  ans = MUTT_YES;
728  else if ((ans = query_quadoption(C_SslStarttls,
729  _("Secure connection with TLS?"))) == MUTT_ABORT)
730  {
731  goto err_close_conn;
732  }
733  if (ans == MUTT_YES)
734  {
735  enum ImapExecResult rc = imap_exec(adata, "STARTTLS", IMAP_CMD_SINGLE);
736  // Clear any data after the STARTTLS acknowledgement
737  mutt_socket_empty(adata->conn);
738 
739  if (rc == IMAP_EXEC_FATAL)
740  goto bail;
741  if (rc != IMAP_EXEC_ERROR)
742  {
743  if (mutt_ssl_starttls(adata->conn))
744  {
745  mutt_error(_("Could not negotiate TLS connection"));
746  goto err_close_conn;
747  }
748  else
749  {
750  /* RFC2595 demands we recheck CAPABILITY after TLS completes. */
751  if (imap_exec(adata, "CAPABILITY", IMAP_CMD_NO_FLAGS))
752  goto bail;
753  }
754  }
755  }
756  }
757 
758  if (C_SslForceTls && (adata->conn->ssf == 0))
759  {
760  mutt_error(_("Encrypted connection unavailable"));
761  goto err_close_conn;
762  }
763 #endif
764  }
765  else if (mutt_istr_startswith(adata->buf, "* PREAUTH"))
766  {
767 #ifdef USE_SSL
768  /* Unless using a secure $tunnel, an unencrypted PREAUTH response may be a
769  * MITM attack. The only way to stop "STARTTLS" MITM attacks is via
770  * $ssl_force_tls: an attacker can easily spoof "* OK" and strip the
771  * STARTTLS capability. So consult $ssl_force_tls, not $ssl_starttls, to
772  * decide whether to abort. Note that if using $tunnel and
773  * $tunnel_is_secure, adata->conn->ssf will be set to 1. */
774  if ((adata->conn->ssf == 0) && C_SslForceTls)
775  {
776  mutt_error(_("Encrypted connection unavailable"));
777  goto err_close_conn;
778  }
779 #endif
780 
781  adata->state = IMAP_AUTHENTICATED;
782  if (check_capabilities(adata) != 0)
783  goto bail;
784  FREE(&adata->capstr);
785  }
786  else
787  {
788  imap_error("imap_open_connection()", adata->buf);
789  goto bail;
790  }
791 
792  return 0;
793 
794 #ifdef USE_SSL
795 err_close_conn:
796  imap_close_connection(adata);
797 #endif
798 bail:
799  FREE(&adata->capstr);
800  return -1;
801 }
#define IMAP_RES_OK
<tag> OK ...
Definition: private.h:55
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1076
Imap connection failure.
Definition: private.h:85
unsigned int ssf
Security strength factor, in bits (see below)
Definition: connection.h:37
Connection is authenticated.
Definition: private.h:108
User aborted the question (with Ctrl-G)
Definition: quad.h:38
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: private.h:174
#define _(a)
Definition: message.h:28
void imap_close_connection(struct ImapAccountData *adata)
Close an IMAP connection.
Definition: imap.c:807
char * capstr
Definition: private.h:184
ImapExecResult
imap_exec return code
Definition: private.h:81
#define IMAP_CAP_STARTTLS
RFC2595: STARTTLS.
Definition: private.h:131
int mutt_socket_open(struct Connection *conn)
Simple wrapper.
Definition: socket.c:75
Connected to server.
Definition: private.h:107
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:1247
void imap_error(const char *where, const char *msg)
show an error and abort
Definition: util.c:798
unsigned char C_SslStarttls
Config: (ssl) Use STARTTLS on servers advertising the capability.
Definition: config.c: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:177
ImapCapFlags capabilities
Definition: private.h:185
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:72
bool C_SslForceTls
Config: (ssl) Require TLS encryption for all connections.
Definition: config.c:45
Imap command failure.
Definition: private.h:84
void mutt_socket_empty(struct Connection *conn)
Clear out any queued data.
Definition: socket.c:312
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: curs_lib.c:516
char * buf
Definition: private.h:189
#define mutt_error(...)
Definition: logging.h:84
#define FREE(x)
Definition: memory.h:40
static int check_capabilities(struct ImapAccountData *adata)
Make sure we can log in to this server.
Definition: imap.c:73
#define IMAP_CMD_SINGLE
Run a single command.
Definition: private.h:76
int mutt_ssl_starttls(struct Connection *conn)
Negotiate TLS over an already opened connection.
Definition: gnutls.c:1136
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
struct Connection * conn
Definition: private.h:171
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_close_connection()

void imap_close_connection ( struct ImapAccountData adata)

Close an IMAP connection.

Parameters
adataImap Account data

Definition at line 807 of file imap.c.

808 {
809  if (adata->state != IMAP_DISCONNECTED)
810  {
811  mutt_socket_close(adata->conn);
812  adata->state = IMAP_DISCONNECTED;
813  }
814  adata->seqno = 0;
815  adata->nextcmd = 0;
816  adata->lastcmd = 0;
817  adata->status = 0;
818  memset(adata->cmds, 0, sizeof(struct ImapCommand) * adata->cmdslots);
819 }
struct ImapCommand * cmds
Definition: private.h:199
unsigned int seqno
tag sequence number, e.g. &#39;{seqid}0001&#39;
Definition: private.h:187
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: private.h:174
Disconnected from server.
Definition: private.h:106
IMAP command structure.
Definition: private.h:158
unsigned char status
ImapFlags, e.g. IMAP_FATAL.
Definition: private.h:175
int mutt_socket_close(struct Connection *conn)
Close a socket.
Definition: socket.c:96
struct Connection * conn
Definition: private.h:171
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_has_flag()

bool imap_has_flag ( struct ListHead *  flag_list,
const char *  flag 
)

Does the flag exist in the list.

Parameters
flag_listList of server flags
flagFlag to find
Return values
trueFlag exists

Do a caseless comparison of the flag against a flag list, return true if found or flag list has '*'. Note that "flag" might contain additional whitespace at the end, so we really need to compare up to the length of each element in "flag_list".

Definition at line 832 of file imap.c.

833 {
834  if (STAILQ_EMPTY(flag_list))
835  return false;
836 
837  const size_t flaglen = mutt_str_len(flag);
838  struct ListNode *np = NULL;
839  STAILQ_FOREACH(np, flag_list, entries)
840  {
841  const size_t nplen = strlen(np->data);
842  if ((flaglen >= nplen) && ((flag[nplen] == '\0') || (flag[nplen] == ' ')) &&
843  mutt_istrn_equal(np->data, flag, nplen))
844  {
845  return true;
846  }
847 
848  if (mutt_str_equal(np->data, "\\*"))
849  return true;
850  }
851 
852  return false;
853 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:876
bool mutt_istrn_equal(const char *a, const char *b, size_t l)
Check for equality of two strings ignoring case (to a maximum), safely.
Definition: string.c:626
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:636
char * data
String.
Definition: list.h:36
#define STAILQ_EMPTY(head)
Definition: queue.h:345
A List node for strings.
Definition: list.h:34
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compare_uid()

static int compare_uid ( const void *  a,
const void *  b 
)
static

Compare two Emails by UID - Implements sort_t.

Definition at line 858 of file imap.c.

859 {
860  const struct Email *ea = *(struct Email const *const *) a;
861  const struct Email *eb = *(struct Email const *const *) b;
862  return imap_edata_get((struct Email *) ea)->uid -
863  imap_edata_get((struct Email *) eb)->uid;
864 }
struct ImapEmailData * imap_edata_get(struct Email *e)
Get the private data for this Email.
Definition: message.c:98
The envelope/body of an email.
Definition: email.h:37
unsigned int uid
32-bit Message UID
Definition: message.h:44
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_exec_msgset()

int imap_exec_msgset ( struct Mailbox m,
const char *  pre,
const char *  post,
int  flag,
bool  changed,
bool  invert 
)

Prepare commands for all messages matching conditions.

Parameters
mSelected Imap Mailbox
preprefix commands
postpostfix commands
flagflag type on which to filter, e.g. MUTT_REPLIED
changedinclude only changed messages in message set
invertinvert sense of flag, eg MUTT_READ matches unread messages
Return values
numMatched messages
-1Failure

pre/post: commands are of the form "%s %s %s %s", tag, pre, message set, post Prepares commands for all messages matching conditions (must be flushed with imap_exec)

Definition at line 881 of file imap.c.

883 {
884  struct ImapAccountData *adata = imap_adata_get(m);
885  if (!adata || (adata->mailbox != m))
886  return -1;
887 
888  struct Email **emails = NULL;
889  short oldsort;
890  int pos;
891  int rc;
892  int count = 0;
893 
894  struct Buffer cmd = mutt_buffer_make(0);
895 
896  /* We make a copy of the headers just in case resorting doesn't give
897  exactly the original order (duplicate messages?), because other parts of
898  the ctx are tied to the header order. This may be overkill. */
899  oldsort = C_Sort;
900  if (C_Sort != SORT_ORDER)
901  {
902  emails = m->emails;
903  // We overcommit here, just in case new mail arrives whilst we're sync-ing
904  m->emails = mutt_mem_malloc(m->email_max * sizeof(struct Email *));
905  memcpy(m->emails, emails, m->email_max * sizeof(struct Email *));
906 
907  C_Sort = SORT_ORDER;
908  qsort(m->emails, m->msg_count, sizeof(struct Email *), compare_uid);
909  }
910 
911  pos = 0;
912 
913  do
914  {
915  mutt_buffer_reset(&cmd);
916  mutt_buffer_add_printf(&cmd, "%s ", pre);
917  rc = make_msg_set(m, &cmd, flag, changed, invert, &pos);
918  if (rc > 0)
919  {
920  mutt_buffer_add_printf(&cmd, " %s", post);
921  if (imap_exec(adata, cmd.data, IMAP_CMD_QUEUE) != IMAP_EXEC_SUCCESS)
922  {
923  rc = -1;
924  goto out;
925  }
926  count += rc;
927  }
928  } while (rc > 0);
929 
930  rc = count;
931 
932 out:
933  mutt_buffer_dealloc(&cmd);
934  if (oldsort != C_Sort)
935  {
936  C_Sort = oldsort;
937  FREE(&m->emails);
938  m->emails = emails;
939  }
940 
941  return rc;
942 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
int msg_count
Total number of messages.
Definition: mailbox.h:91
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
The envelope/body of an email.
Definition: email.h:37
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
static int make_msg_set(struct Mailbox *m, struct Buffer *buf, int flag, bool changed, bool invert, int *pos)
Make a message set.
Definition: imap.c:176
struct Mailbox * mailbox
Current selected mailbox.
Definition: private.h:206
Imap command executed or queued successfully.
Definition: private.h:83
Sort by the order the messages appear in the mailbox.
Definition: sort2.h:55
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
int mutt_buffer_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:203
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:58
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:1247
int email_max
Number of pointers in emails.
Definition: mailbox.h:100
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
char * data
Pointer to data.
Definition: buffer.h:35
IMAP-specific Account data -.
Definition: private.h:169
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:113
#define FREE(x)
Definition: memory.h:40
#define IMAP_CMD_QUEUE
Queue a command, do not execute.
Definition: private.h:74
static int compare_uid(const void *a, const void *b)
Compare two Emails by UID - Implements sort_t.
Definition: imap.c:858
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_sync_message_for_copy()

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.

Parameters
[in]mMailbox
[in]eEmail
[in]cmdBuffer for the command string
[out]err_continueDid the user force a continue?
Return values
0Success
-1Failure

Update the IMAP server to reflect the flags for a single message before performing a "UID COPY".

Note
This does not sync the "deleted" flag state, because it is not desirable to propagate that flag into the copy.

Definition at line 959 of file imap.c.

961 {
962  struct ImapAccountData *adata = imap_adata_get(m);
963  if (!adata || (adata->mailbox != m))
964  return -1;
965 
966  char flags[1024];
967  char *tags = NULL;
968  char uid[11];
969 
970  if (!compare_flags_for_copy(e))
971  {
972  if (e->deleted == imap_edata_get(e)->deleted)
973  e->changed = false;
974  return 0;
975  }
976 
977  snprintf(uid, sizeof(uid), "%u", imap_edata_get(e)->uid);
978  mutt_buffer_reset(cmd);
979  mutt_buffer_addstr(cmd, "UID STORE ");
980  mutt_buffer_addstr(cmd, uid);
981 
982  flags[0] = '\0';
983 
984  set_flag(m, MUTT_ACL_SEEN, e->read, "\\Seen ", flags, sizeof(flags));
985  set_flag(m, MUTT_ACL_WRITE, e->old, "Old ", flags, sizeof(flags));
986  set_flag(m, MUTT_ACL_WRITE, e->flagged, "\\Flagged ", flags, sizeof(flags));
987  set_flag(m, MUTT_ACL_WRITE, e->replied, "\\Answered ", flags, sizeof(flags));
988  set_flag(m, MUTT_ACL_DELETE, imap_edata_get(e)->deleted, "\\Deleted ", flags,
989  sizeof(flags));
990 
991  if (m->rights & MUTT_ACL_WRITE)
992  {
993  /* restore system flags */
994  if (imap_edata_get(e)->flags_system)
995  mutt_str_cat(flags, sizeof(flags), imap_edata_get(e)->flags_system);
996  /* set custom flags */
997  tags = driver_tags_get_with_hidden(&e->tags);
998  if (tags)
999  {
1000  mutt_str_cat(flags, sizeof(flags), tags);
1001  FREE(&tags);
1002  }
1003  }
1004 
1006 
1007  /* UW-IMAP is OK with null flags, Cyrus isn't. The only solution is to
1008  * explicitly revoke all system flags (if we have permission) */
1009  if (*flags == '\0')
1010  {
1011  set_flag(m, MUTT_ACL_SEEN, 1, "\\Seen ", flags, sizeof(flags));
1012  set_flag(m, MUTT_ACL_WRITE, 1, "Old ", flags, sizeof(flags));
1013  set_flag(m, MUTT_ACL_WRITE, 1, "\\Flagged ", flags, sizeof(flags));
1014  set_flag(m, MUTT_ACL_WRITE, 1, "\\Answered ", flags, sizeof(flags));
1015  set_flag(m, MUTT_ACL_DELETE, !imap_edata_get(e)->deleted, "\\Deleted ",
1016  flags, sizeof(flags));
1017 
1018  /* erase custom flags */
1019  if ((m->rights & MUTT_ACL_WRITE) && imap_edata_get(e)->flags_remote)
1020  mutt_str_cat(flags, sizeof(flags), imap_edata_get(e)->flags_remote);
1021 
1023 
1024  mutt_buffer_addstr(cmd, " -FLAGS.SILENT (");
1025  }
1026  else
1027  mutt_buffer_addstr(cmd, " FLAGS.SILENT (");
1028 
1029  mutt_buffer_addstr(cmd, flags);
1030  mutt_buffer_addstr(cmd, ")");
1031 
1032  /* after all this it's still possible to have no flags, if you
1033  * have no ACL rights */
1034  if (*flags && (imap_exec(adata, cmd->data, IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS) &&
1035  err_continue && (*err_continue != MUTT_YES))
1036  {
1037  *err_continue = imap_continue("imap_sync_message: STORE failed", adata->buf);
1038  if (*err_continue != MUTT_YES)
1039  return -1;
1040  }
1041 
1042  /* server have now the updated flags */
1043  FREE(&imap_edata_get(e)->flags_remote);
1045 
1046  if (e->deleted == imap_edata_get(e)->deleted)
1047  e->changed = false;
1048 
1049  return 0;
1050 }
enum QuadOption imap_continue(const char *msg, const char *resp)
display a message and ask the user if they want to go on
Definition: util.c:787
struct ImapEmailData * imap_edata_get(struct Email *e)
Get the private data for this Email.
Definition: message.c:98
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
struct Mailbox * mailbox
Current selected mailbox.
Definition: private.h:206
bool changed
Email has been edited.
Definition: email.h:48
#define MUTT_ACL_DELETE
Delete a message.
Definition: mailbox.h:66
Imap command executed or queued successfully.
Definition: private.h:83
bool read
Email is read.
Definition: email.h:51
bool old
Email is seen, but unread.
Definition: email.h:50
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:74
struct TagList tags
For drivers that support server tagging.
Definition: email.h:107
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:1247
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
char * flags_remote
Definition: message.h:48
void mutt_str_remove_trailing_ws(char *s)
Trim trailing whitespace from a string.
Definition: string.c:705
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
char * data
Pointer to data.
Definition: buffer.h:35
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:121
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:72
char * mutt_str_cat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
Definition: string.c:390
IMAP-specific Account data -.
Definition: private.h:169
char * driver_tags_get_with_hidden(struct TagList *list)
Get tags with hiddens.
Definition: tags.c:155
static bool compare_flags_for_copy(struct Email *e)
Compare local flags against the server.
Definition: imap.c:276
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:113
bool flagged
Marked important?
Definition: email.h:43
char * buf
Definition: private.h:189
bool deleted
Email is deleted.
Definition: email.h:45
bool replied
Email has been replied to.
Definition: email.h:54
#define FREE(x)
Definition: memory.h:40
#define MUTT_ACL_SEEN
Change the &#39;seen&#39; status of a message.
Definition: mailbox.h:73
static void set_flag(struct Mailbox *m, AclFlags aclflag, int flag, const char *str, char *flags, size_t flsize)
append str to flags if we currently have permission according to aclflag
Definition: imap.c:155
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_check_mailbox()

int 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
MUTT_REOPENEDmailbox has been externally modified
MUTT_NEW_MAILnew mail has arrived
0no change
-1error

Definition at line 1061 of file imap.c.

1062 {
1063  if (!m || !m->account)
1064  return -1;
1065 
1066  struct ImapAccountData *adata = imap_adata_get(m);
1067  struct ImapMboxData *mdata = imap_mdata_get(m);
1068 
1069  /* overload keyboard timeout to avoid many mailbox checks in a row.
1070  * Most users don't like having to wait exactly when they press a key. */
1071  int rc = 0;
1072 
1073  /* try IDLE first, unless force is set */
1074  if (!force && C_ImapIdle && (adata->capabilities & IMAP_CAP_IDLE) &&
1075  ((adata->state != IMAP_IDLE) || (mutt_date_epoch() >= adata->lastread + C_ImapKeepalive)))
1076  {
1077  if (imap_cmd_idle(adata) < 0)
1078  return -1;
1079  }
1080  if (adata->state == IMAP_IDLE)
1081  {
1082  while ((rc = mutt_socket_poll(adata->conn, 0)) > 0)
1083  {
1084  if (imap_cmd_step(adata) != IMAP_RES_CONTINUE)
1085  {
1086  mutt_debug(LL_DEBUG1, "Error reading IDLE response\n");
1087  return -1;
1088  }
1089  }
1090  if (rc < 0)
1091  {
1092  mutt_debug(LL_DEBUG1, "Poll failed, disabling IDLE\n");
1093  adata->capabilities &= ~IMAP_CAP_IDLE; // Clear the flag
1094  }
1095  }
1096 
1097  if ((force || ((adata->state != IMAP_IDLE) &&
1098  (mutt_date_epoch() >= adata->lastread + C_Timeout))) &&
1099  (imap_exec(adata, "NOOP", IMAP_CMD_POLL) != IMAP_EXEC_SUCCESS))
1100  {
1101  return -1;
1102  }
1103 
1104  /* We call this even when we haven't run NOOP in case we have pending
1105  * changes to process, since we can reopen here. */
1106  imap_cmd_finish(adata);
1107 
1108  if (mdata->check_status & IMAP_EXPUNGE_PENDING)
1109  rc = MUTT_REOPENED;
1110  else if (mdata->check_status & IMAP_NEWMAIL_PENDING)
1111  rc = MUTT_NEW_MAIL;
1112  else if (mdata->check_status & IMAP_FLAGS_PENDING)
1113  rc = MUTT_FLAGS;
1114 
1116 
1117  return rc;
1118 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:416
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1076
WHERE short C_Timeout
Config: Time to wait for user input in menus.
Definition: mutt_globals.h:116
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: private.h:174
#define IMAP_FLAGS_PENDING
Flags have changed on the server.
Definition: private.h:69
#define IMAP_CMD_POLL
Poll the tcp connection before running the imap command.
Definition: private.h:75
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: util.c:245
Imap command executed or queued successfully.
Definition: private.h:83
int mutt_socket_poll(struct Connection *conn, time_t wait_secs)
Checks whether reads would block.
Definition: socket.c:191
int imap_cmd_idle(struct ImapAccountData *adata)
Enter the IDLE state.
Definition: command.c:1374
ImapOpenFlags check_status
Flags, e.g. IMAP_NEWMAIL_PENDING.
Definition: private.h:223
void * mdata
Driver specific data.
Definition: mailbox.h:136
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:1247
Nondestructive flags change (IMAP)
Definition: mx.h:77
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
void imap_cmd_finish(struct ImapAccountData *adata)
Attempt to perform cleanup.
Definition: command.c:1311
ImapCapFlags capabilities
Definition: private.h:185
#define IMAP_OPEN_NO_FLAGS
No flags are set.
Definition: private.h:64
time_t lastread
last time we read a command for the server
Definition: private.h:188
Connection is idle.
Definition: private.h:112
short C_ImapKeepalive
Config: (imap) Time to wait before polling an open IMAP connection.
Definition: config.c:46
IMAP-specific Account data -.
Definition: private.h:169
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:131
Log at debug level 1.
Definition: logging.h:40
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:113
IMAP-specific Mailbox data -.
Definition: private.h:216
#define IMAP_NEWMAIL_PENDING
New mail is waiting on the server.
Definition: private.h:68
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
New mail received in Mailbox.
Definition: mx.h:74
#define IMAP_RES_CONTINUE
* ...
Definition: private.h:56
Mailbox was reopened.
Definition: mx.h:76
bool C_ImapIdle
Config: (imap) Use the IMAP IDLE extension to check for new mail.
Definition: config.c:45
#define IMAP_CAP_IDLE
RFC2177: IDLE.
Definition: private.h:133
#define IMAP_EXPUNGE_PENDING
Messages on the server have been expunged.
Definition: private.h:67
struct Connection * conn
Definition: private.h:171
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_status()

static int imap_status ( struct ImapAccountData adata,
struct ImapMboxData mdata,
bool  queue 
)
static

Refresh the number of total and new messages.

Parameters
adataIMAP Account data
mdataIMAP Mailbox data
queueQueue the STATUS command
Return values
numTotal number of messages

Definition at line 1127 of file imap.c.

1128 {
1129  char *uidvalidity_flag = NULL;
1130  char cmd[2048];
1131 
1132  if (!adata || !mdata)
1133  return -1;
1134 
1135  /* Don't issue STATUS on the selected mailbox, it will be NOOPed or
1136  * IDLEd elsewhere.
1137  * adata->mailbox may be NULL for connections other than the current
1138  * mailbox's. */
1139  if (adata->mailbox && (adata->mailbox->mdata == mdata))
1140  {
1141  adata->mailbox->has_new = false;
1142  return mdata->messages;
1143  }
1144 
1145  if (adata->capabilities & IMAP_CAP_IMAP4REV1)
1146  uidvalidity_flag = "UIDVALIDITY";
1147  else if (adata->capabilities & IMAP_CAP_STATUS)
1148  uidvalidity_flag = "UID-VALIDITY";
1149  else
1150  {
1151  mutt_debug(LL_DEBUG2, "Server doesn't support STATUS\n");
1152  return -1;
1153  }
1154 
1155  snprintf(cmd, sizeof(cmd), "STATUS %s (UIDNEXT %s UNSEEN RECENT MESSAGES)",
1156  mdata->munge_name, uidvalidity_flag);
1157 
1158  int rc = imap_exec(adata, cmd, queue ? IMAP_CMD_QUEUE : IMAP_CMD_NO_FLAGS | IMAP_CMD_POLL);
1159  if (rc < 0)
1160  {
1161  mutt_debug(LL_DEBUG1, "Error queueing command\n");
1162  return rc;
1163  }
1164  return mdata->messages;
1165 }
#define IMAP_CMD_POLL
Poll the tcp connection before running the imap command.
Definition: private.h:75
struct Mailbox * mailbox
Current selected mailbox.
Definition: private.h:206
bool has_new
Mailbox has new mail.
Definition: mailbox.h:88
Log at debug level 2.
Definition: logging.h:41
void * mdata
Driver specific data.
Definition: mailbox.h:136
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:1247
#define IMAP_CAP_IMAP4REV1
Server supports IMAP4rev1.
Definition: private.h:123
#define IMAP_CAP_STATUS
Server supports STATUS command.
Definition: private.h:124
ImapCapFlags capabilities
Definition: private.h:185
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:72
Log at debug level 1.
Definition: logging.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
#define IMAP_CMD_QUEUE
Queue a command, do not execute.
Definition: private.h:74
char * munge_name
Munged version of the mailbox name.
Definition: private.h:219
unsigned int messages
Definition: private.h:231
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_mbox_check_stats()

static int imap_mbox_check_stats ( struct Mailbox m,
int  flags 
)
static

Check the Mailbox statistics - Implements MxOps::mbox_check_stats()

Definition at line 1170 of file imap.c.

1171 {
1172  return imap_mailbox_status(m, true);
1173 }
int imap_mailbox_status(struct Mailbox *m, bool queue)
Refresh the number of total and new messages.
Definition: imap.c:1215
+ Here is the call 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 1181 of file imap.c.

1182 {
1183  struct Mailbox *m = mx_mbox_find2(path);
1184 
1185  const bool is_temp = !m;
1186  if (is_temp)
1187  {
1188  m = mx_path_resolve(path);
1189  if (!mx_mbox_ac_link(m))
1190  {
1191  mailbox_free(&m);
1192  return 0;
1193  }
1194  }
1195 
1196  int rc = imap_mailbox_status(m, queue);
1197 
1198  if (is_temp)
1199  {
1200  mx_ac_remove(m);
1201  }
1202 
1203  return rc;
1204 }
struct Mailbox * mx_mbox_find2(const char *path)
Find a Mailbox on an Account.
Definition: mx.c:1670
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:60
A mailbox.
Definition: mailbox.h:81
int imap_mailbox_status(struct Mailbox *m, bool queue)
Refresh the number of total and new messages.
Definition: imap.c:1215
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1697
bool mx_mbox_ac_link(struct Mailbox *m)
Link a Mailbox to an existing or new Account.
Definition: mx.c:266
int mx_ac_remove(struct Mailbox *m)
Remove a Mailbox from an Account and delete Account if empty.
Definition: mx.c:1800
+ 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 1215 of file imap.c.

1216 {
1217  struct ImapAccountData *adata = imap_adata_get(m);
1218  struct ImapMboxData *mdata = imap_mdata_get(m);
1219  if (!adata || !mdata)
1220  return -1;
1221  return imap_status(adata, mdata, queue);
1222 }
static int imap_status(struct ImapAccountData *adata, struct ImapMboxData *mdata, bool queue)
Refresh the number of total and new messages.
Definition: imap.c:1127
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: util.c:245
void * mdata
Driver specific data.
Definition: mailbox.h:136
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
IMAP-specific Account data -.
Definition: private.h:169
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:113
IMAP-specific Mailbox data -.
Definition: private.h:216
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_subscribe()

int imap_subscribe ( char *  path,
bool  subscribe 
)

Subscribe to a mailbox.

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

Definition at line 1231 of file imap.c.

1232 {
1233  struct ImapAccountData *adata = NULL;
1234  struct ImapMboxData *mdata = NULL;
1235  char buf[2048];
1236  struct Buffer err;
1237 
1238  if (imap_adata_find(path, &adata, &mdata) < 0)
1239  return -1;
1240 
1242  {
1243  char mbox[1024];
1244  mutt_buffer_init(&err);
1245  err.dsize = 256;
1246  err.data = mutt_mem_malloc(err.dsize);
1247  size_t len = snprintf(mbox, sizeof(mbox), "%smailboxes ", subscribe ? "" : "un");
1248  imap_quote_string(mbox + len, sizeof(mbox) - len, path, true);
1249  if (mutt_parse_rc_line(mbox, &err))
1250  mutt_debug(LL_DEBUG1, "Error adding subscribed mailbox: %s\n", err.data);
1251  FREE(&err.data);
1252  }
1253 
1254  if (subscribe)
1255  mutt_message(_("Subscribing to %s..."), mdata->name);
1256  else
1257  mutt_message(_("Unsubscribing from %s..."), mdata->name);
1258 
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  if (subscribe)
1268  mutt_message(_("Subscribed to %s"), mdata->name);
1269  else
1270  mutt_message(_("Unsubscribed from %s"), mdata->name);
1271  imap_mdata_free((void *) &mdata);
1272  return 0;
1273 }
void imap_mdata_free(void **ptr)
Free the private Mailbox data - Implements Mailbox::mdata_free()
Definition: util.c:226
#define mutt_message(...)
Definition: logging.h:83
String manipulation buffer.
Definition: buffer.h:33
enum CommandResult mutt_parse_rc_line(const char *line, struct Buffer *err)
Parse a line of user config.
Definition: init.c:1041
#define _(a)
Definition: message.h:28
Imap command executed or queued successfully.
Definition: private.h:83
int imap_adata_find(const char *path, struct ImapAccountData **adata, struct ImapMboxData **mdata)
Find the Account data for this path.
Definition: util.c:128
void * mdata
Driver specific data.
Definition: mailbox.h:136
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:1247
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
char * name
Mailbox name.
Definition: private.h:218
bool C_ImapCheckSubscribed
Config: (imap) When opening a mailbox, ask the server for a list of subscribed folders.
Definition: config.c:37
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:72
IMAP-specific Account data -.
Definition: private.h:169
Log at debug level 1.
Definition: logging.h:40
IMAP-specific Mailbox data -.
Definition: private.h:216
#define FREE(x)
Definition: memory.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:46
char * munge_name
Munged version of the mailbox name.
Definition: private.h:219
void imap_quote_string(char *dest, size_t dlen, const char *src, bool quote_backtick)
quote string according to IMAP rules
Definition: util.c:971
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_complete()

int imap_complete ( char *  buf,
size_t  buflen,
const char *  path 
)

Try to complete an IMAP folder path.

Parameters
bufBuffer for result
buflenLength of buffer
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 1286 of file imap.c.

1287 {
1288  struct ImapAccountData *adata = NULL;
1289  struct ImapMboxData *mdata = NULL;
1290  char tmp[2048];
1291  struct ImapList listresp = { 0 };
1292  char completion[1024];
1293  int clen;
1294  size_t matchlen = 0;
1295  int completions = 0;
1296  int rc;
1297 
1298  if (imap_adata_find(path, &adata, &mdata) < 0)
1299  {
1300  mutt_str_copy(buf, path, buflen);
1301  return complete_hosts(buf, buflen);
1302  }
1303 
1304  /* fire off command */
1305  snprintf(tmp, sizeof(tmp), "%s \"\" \"%s%%\"",
1306  C_ImapListSubscribed ? "LSUB" : "LIST", mdata->real_name);
1307 
1308  imap_cmd_start(adata, tmp);
1309 
1310  /* and see what the results are */
1311  mutt_str_copy(completion, mdata->name, sizeof(completion));
1312  imap_mdata_free((void *) &mdata);
1313 
1314  adata->cmdresult = &listresp;
1315  do
1316  {
1317  listresp.name = NULL;
1318  rc = imap_cmd_step(adata);
1319 
1320  if ((rc == IMAP_RES_CONTINUE) && listresp.name)
1321  {
1322  /* if the folder isn't selectable, append delimiter to force browse
1323  * to enter it on second tab. */
1324  if (listresp.noselect)
1325  {
1326  clen = strlen(listresp.name);
1327  listresp.name[clen++] = listresp.delim;
1328  listresp.name[clen] = '\0';
1329  }
1330  /* copy in first word */
1331  if (!completions)
1332  {
1333  mutt_str_copy(completion, listresp.name, sizeof(completion));
1334  matchlen = strlen(completion);
1335  completions++;
1336  continue;
1337  }
1338 
1339  matchlen = longest_common_prefix(completion, listresp.name, 0, matchlen);
1340  completions++;
1341  }
1342  } while (rc == IMAP_RES_CONTINUE);
1343  adata->cmdresult = NULL;
1344 
1345  if (completions)
1346  {
1347  /* reformat output */
1348  imap_qualify_path(buf, buflen, &adata->conn->account, completion);
1349  mutt_pretty_mailbox(buf, buflen);
1350  return 0;
1351  }
1352 
1353  return -1;
1354 }
void imap_mdata_free(void **ptr)
Free the private Mailbox data - Implements Mailbox::mdata_free()
Definition: util.c:226
void imap_qualify_path(char *buf, size_t buflen, struct ConnAccount *conn_account, char *path)
Make an absolute IMAP folder target.
Definition: util.c:954
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1076
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:36
Items in an IMAP browser.
Definition: private.h:147
int imap_cmd_start(struct ImapAccountData *adata, const char *cmdstr)
Given an IMAP command, send it to the server.
Definition: command.c:1062
char delim
Definition: private.h:150
int imap_adata_find(const char *path, struct ImapAccountData **adata, struct ImapMboxData **mdata)
Find the Account data for this path.
Definition: util.c:128
bool C_ImapListSubscribed
Config: (imap) When browsing a mailbox, only display subscribed folders.
Definition: config.c:47
static int complete_hosts(char *buf, size_t buflen)
Look for completion matches for mailboxes.
Definition: imap.c:362
void * mdata
Driver specific data.
Definition: mailbox.h:136
char * name
Definition: private.h:149
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
char * name
Mailbox name.
Definition: private.h:218
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:522
char * real_name
Original Mailbox name, e.g.: INBOX can be just \0.
Definition: private.h:220
IMAP-specific Account data -.
Definition: private.h:169
static size_t longest_common_prefix(char *dest, const char *src, size_t start, size_t dlen)
Find longest prefix common to two strings.
Definition: imap.c:341
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:721
IMAP-specific Mailbox data -.
Definition: private.h:216
struct ImapList * cmdresult
Definition: private.h:196
#define IMAP_RES_CONTINUE
* ...
Definition: private.h:56
bool noselect
Definition: private.h:151
struct Connection * conn
Definition: private.h:171
+ 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,
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 1364 of file imap.c.

1365 {
1366  char prompt[1024];
1367  int rc = -1;
1368  bool triedcreate = false;
1369  enum QuadOption err_continue = MUTT_NO;
1370 
1371  struct ImapAccountData *adata = imap_adata_get(m);
1372  struct ImapAccountData *dest_adata = NULL;
1373  struct ImapMboxData *dest_mdata = NULL;
1374 
1375  if (imap_adata_find(dest, &dest_adata, &dest_mdata) < 0)
1376  return -1;
1377 
1378  struct Buffer sync_cmd = mutt_buffer_make(0);
1379 
1380  /* check that the save-to folder is in the same account */
1381  if (!imap_account_match(&(adata->conn->account), &(dest_adata->conn->account)))
1382  {
1383  mutt_debug(LL_DEBUG3, "%s not same server as %s\n", dest, mailbox_path(m));
1384  goto out;
1385  }
1386 
1387  for (int i = 0; i < m->msg_count; i++)
1388  {
1389  struct Email *e = m->emails[i];
1390  if (!e)
1391  break;
1392  if (e->active && e->changed && e->deleted && !e->purge)
1393  {
1394  rc = imap_sync_message_for_copy(m, e, &sync_cmd, &err_continue);
1395  if (rc < 0)
1396  {
1397  mutt_debug(LL_DEBUG1, "could not sync\n");
1398  goto out;
1399  }
1400  }
1401  }
1402 
1403  /* loop in case of TRYCREATE */
1404  do
1405  {
1406  rc = imap_exec_msgset(m, "UID COPY", dest_mdata->munge_name, MUTT_TRASH, false, false);
1407  if (rc == 0)
1408  {
1409  mutt_debug(LL_DEBUG1, "No messages to trash\n");
1410  rc = -1;
1411  goto out;
1412  }
1413  else if (rc < 0)
1414  {
1415  mutt_debug(LL_DEBUG1, "could not queue copy\n");
1416  goto out;
1417  }
1418  else if (m->verbose)
1419  {
1420  mutt_message(ngettext("Copying %d message to %s...", "Copying %d messages to %s...", rc),
1421  rc, dest_mdata->name);
1422  }
1423 
1424  /* let's get it on */
1425  rc = imap_exec(adata, NULL, IMAP_CMD_NO_FLAGS);
1426  if (rc == IMAP_EXEC_ERROR)
1427  {
1428  if (triedcreate)
1429  {
1430  mutt_debug(LL_DEBUG1, "Already tried to create mailbox %s\n", dest_mdata->name);
1431  break;
1432  }
1433  /* bail out if command failed for reasons other than nonexistent target */
1434  if (!mutt_istr_startswith(imap_get_qualifier(adata->buf), "[TRYCREATE]"))
1435  break;
1436  mutt_debug(LL_DEBUG3, "server suggests TRYCREATE\n");
1437  snprintf(prompt, sizeof(prompt), _("Create %s?"), dest_mdata->name);
1438  if (C_Confirmcreate && (mutt_yesorno(prompt, MUTT_YES) != MUTT_YES))
1439  {
1440  mutt_clear_error();
1441  goto out;
1442  }
1443  if (imap_create_mailbox(adata, dest_mdata->name) < 0)
1444  break;
1445  triedcreate = true;
1446  }
1447  } while (rc == IMAP_EXEC_ERROR);
1448 
1449  if (rc != IMAP_EXEC_SUCCESS)
1450  {
1451  imap_error("imap_fast_trash", adata->buf);
1452  goto out;
1453  }
1454 
1455  rc = IMAP_EXEC_SUCCESS;
1456 
1457 out:
1458  mutt_buffer_dealloc(&sync_cmd);
1459  imap_mdata_free((void *) &dest_mdata);
1460 
1461  return ((rc == IMAP_EXEC_SUCCESS) ? 0 : -1);
1462 }
void imap_mdata_free(void **ptr)
Free the private Mailbox data - Implements Mailbox::mdata_free()
Definition: util.c:226
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:201
int msg_count
Total number of messages.
Definition: mailbox.h:91
The envelope/body of an email.
Definition: email.h:37
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:36
#define mutt_message(...)
Definition: logging.h:83
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
bool changed
Email has been edited.
Definition: email.h:48
bool imap_account_match(const struct ConnAccount *a1, const struct ConnAccount *a2)
Compare two Accounts.
Definition: util.c:1178
Imap command executed or queued successfully.
Definition: private.h:83
int imap_adata_find(const char *path, struct ImapAccountData **adata, struct ImapMboxData **mdata)
Find the Account data for this path.
Definition: util.c:128
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:378
int imap_exec_msgset(struct Mailbox *m, const char *pre, const char *post, int flag, bool changed, bool invert)
Prepare commands for all messages matching conditions.
Definition: imap.c:881
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
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:1247
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:959
void imap_error(const char *where, const char *msg)
show an error and abort
Definition: util.c:798
bool active
Message is not to be removed.
Definition: email.h:59
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:39
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
char * name
Mailbox name.
Definition: private.h:218
bool verbose
Display status messages?
Definition: mailbox.h:118
bool purge
Skip trash folder when deleting.
Definition: email.h:46
WHERE bool C_Confirmcreate
Config: Confirm before creating a new mailbox.
Definition: mutt_globals.h:144
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:177
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:72
int imap_create_mailbox(struct ImapAccountData *adata, char *mailbox)
Create a new mailbox.
Definition: imap.c:424
Imap command failure.
Definition: private.h:84
IMAP-specific Account data -.
Definition: private.h:169
char * imap_get_qualifier(char *buf)
Get the qualifier from a tagged response.
Definition: util.c:906
Log at debug level 1.
Definition: logging.h:40
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:113
IMAP-specific Mailbox data -.
Definition: private.h:216
char * buf
Definition: private.h:189
bool deleted
Email is deleted.
Definition: email.h:45
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
char * munge_name
Munged version of the mailbox name.
Definition: private.h:219
Trashed messages.
Definition: mutt.h:108
Log at debug level 3.
Definition: logging.h:42
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
struct Connection * conn
Definition: private.h:171
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_sync_mailbox()

int 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
MUTT_REOPENEDmailbox has been externally modified
MUTT_NEW_MAILnew mail has arrived
0Success
-1Error
Note
The flag retvals come from a call to imap_check_mailbox()

Definition at line 1476 of file imap.c.

1477 {
1478  if (!m)
1479  return -1;
1480 
1481  struct Email **emails = NULL;
1482  int oldsort;
1483  int rc;
1484  int check;
1485 
1486  struct ImapAccountData *adata = imap_adata_get(m);
1487  struct ImapMboxData *mdata = imap_mdata_get(m);
1488 
1489  if (adata->state < IMAP_SELECTED)
1490  {
1491  mutt_debug(LL_DEBUG2, "no mailbox selected\n");
1492  return -1;
1493  }
1494 
1495  /* This function is only called when the calling code expects the context
1496  * to be changed. */
1497  imap_allow_reopen(m);
1498 
1499  check = imap_check_mailbox(m, false);
1500  if (check < 0)
1501  return check;
1502 
1503  /* if we are expunging anyway, we can do deleted messages very quickly... */
1504  if (expunge && (m->rights & MUTT_ACL_DELETE))
1505  {
1506  rc = imap_exec_msgset(m, "UID STORE", "+FLAGS.SILENT (\\Deleted)",
1507  MUTT_DELETED, true, false);
1508  if (rc < 0)
1509  {
1510  mutt_error(_("Expunge failed"));
1511  return rc;
1512  }
1513 
1514  if (rc > 0)
1515  {
1516  /* mark these messages as unchanged so second pass ignores them. Done
1517  * here so BOGUS UW-IMAP 4.7 SILENT FLAGS updates are ignored. */
1518  for (int i = 0; i < m->msg_count; i++)
1519  {
1520  struct Email *e = m->emails[i];
1521  if (!e)
1522  break;
1523  if (e->deleted && e->changed)
1524  e->active = false;
1525  }
1526  if (m->verbose)
1527  {
1528  mutt_message(ngettext("Marking %d message deleted...",
1529  "Marking %d messages deleted...", rc),
1530  rc);
1531  }
1532  }
1533  }
1534 
1535 #ifdef USE_HCACHE
1536  imap_hcache_open(adata, mdata);
1537 #endif
1538 
1539  /* save messages with real (non-flag) changes */
1540  for (int i = 0; i < m->msg_count; i++)
1541  {
1542  struct Email *e = m->emails[i];
1543  if (!e)
1544  break;
1545 
1546  if (e->deleted)
1547  {
1548  imap_cache_del(m, e);
1549 #ifdef USE_HCACHE
1550  imap_hcache_del(mdata, imap_edata_get(e)->uid);
1551 #endif
1552  }
1553 
1554  if (e->active && e->changed)
1555  {
1556 #ifdef USE_HCACHE
1557  imap_hcache_put(mdata, e);
1558 #endif
1559  /* if the message has been rethreaded or attachments have been deleted
1560  * we delete the message and reupload it.
1561  * This works better if we're expunging, of course. */
1562  /* TODO: why the e->env check? */
1563  if ((e->env && e->env->changed) || e->attach_del)
1564  {
1565  /* L10N: The plural is chosen by the last %d, i.e. the total number */
1566  if (m->verbose)
1567  {
1568  mutt_message(ngettext("Saving changed message... [%d/%d]",
1569  "Saving changed messages... [%d/%d]", m->msg_count),
1570  i + 1, m->msg_count);
1571  }
1572  bool save_append = m->append;
1573  m->append = true;
1574  mutt_save_message_ctx(e, true, false, false, m);
1575  m->append = save_append;
1576  /* TODO: why the check for h->env? Is this possible? */
1577  if (e->env)
1578  e->env->changed = 0;
1579  }
1580  }
1581  }
1582 
1583 #ifdef USE_HCACHE
1584  imap_hcache_close(mdata);
1585 #endif
1586 
1587  /* presort here to avoid doing 10 resorts in imap_exec_msgset */
1588  oldsort = C_Sort;
1589  if (C_Sort != SORT_ORDER)
1590  {
1591  emails = m->emails;
1592  m->emails = mutt_mem_malloc(m->msg_count * sizeof(struct Email *));
1593  memcpy(m->emails, emails, m->msg_count * sizeof(struct Email *));
1594 
1595  C_Sort = SORT_ORDER;
1596  qsort(m->emails, m->msg_count, sizeof(struct Email *), mutt_get_sort_func(SORT_ORDER));
1597  }
1598 
1599  rc = sync_helper(m, MUTT_ACL_DELETE, MUTT_DELETED, "\\Deleted");
1600  if (rc >= 0)
1601  rc |= sync_helper(m, MUTT_ACL_WRITE, MUTT_FLAG, "\\Flagged");
1602  if (rc >= 0)
1603  rc |= sync_helper(m, MUTT_ACL_WRITE, MUTT_OLD, "Old");
1604  if (rc >= 0)
1605  rc |= sync_helper(m, MUTT_ACL_SEEN, MUTT_READ, "\\Seen");
1606  if (rc >= 0)
1607  rc |= sync_helper(m, MUTT_ACL_WRITE, MUTT_REPLIED, "\\Answered");
1608 
1609  if (oldsort != C_Sort)
1610  {
1611  C_Sort = oldsort;
1612  FREE(&m->emails);
1613  m->emails = emails;
1614  }
1615 
1616  /* Flush the queued flags if any were changed in sync_helper. */
1617  if (rc > 0)
1618  if (imap_exec(adata, NULL, IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS)
1619  rc = -1;
1620 
1621  if (rc < 0)
1622  {
1623  if (close)
1624  {
1625  if (mutt_yesorno(_("Error saving flags. Close anyway?"), MUTT_NO) == MUTT_YES)
1626  {
1627  adata->state = IMAP_AUTHENTICATED;
1628  return 0;
1629  }
1630  }
1631  else
1632  mutt_error(_("Error saving flags"));
1633  return -1;
1634  }
1635 
1636  /* Update local record of server state to reflect the synchronization just
1637  * completed. imap_read_headers always overwrites hcache-origin flags, so
1638  * there is no need to mutate the hcache after flag-only changes. */
1639  for (int i = 0; i < m->msg_count; i++)
1640  {
1641  struct Email *e = m->emails[i];
1642  if (!e)
1643  break;
1644  struct ImapEmailData *edata = imap_edata_get(e);
1645  edata->deleted = e->deleted;
1646  edata->flagged = e->flagged;
1647  edata->old = e->old;
1648  edata->read = e->read;
1649  edata->replied = e->replied;
1650  e->changed = false;
1651  }
1652  m->changed = false;
1653 
1654  /* We must send an EXPUNGE command if we're not closing. */
1655  if (expunge && !close && (m->rights & MUTT_ACL_DELETE))
1656  {
1657  if (m->verbose)
1658  mutt_message(_("Expunging messages from server..."));
1659  /* Set expunge bit so we don't get spurious reopened messages */
1660  mdata->reopen |= IMAP_EXPUNGE_EXPECTED;
1661  if (imap_exec(adata, "EXPUNGE", IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS)
1662  {
1663  mdata->reopen &= ~IMAP_EXPUNGE_EXPECTED;
1664  imap_error(_("imap_sync_mailbox: EXPUNGE failed"), adata->buf);
1665  return -1;
1666  }
1667  mdata->reopen &= ~IMAP_EXPUNGE_EXPECTED;
1668  }
1669 
1670  if (expunge && close)
1671  {
1672  adata->closing = true;
1673  imap_exec(adata, "CLOSE", IMAP_CMD_QUEUE);
1674  adata->state = IMAP_AUTHENTICATED;
1675  }
1676 
1677  if (C_MessageCacheClean)
1678  imap_cache_clean(m);
1679 
1680  return check;
1681 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
int mutt_save_message_ctx(struct Email *e, bool delete_original, bool decode, bool decrypt, struct Mailbox *m)
Save a message to a given mailbox.
Definition: commands.c:998
Deleted messages.
Definition: mutt.h:101
struct ImapEmailData * imap_edata_get(struct Email *e)
Get the private data for this Email.
Definition: message.c:98
int msg_count
Total number of messages.
Definition: mailbox.h:91
The envelope/body of an email.
Definition: email.h:37
bool C_MessageCacheClean
Config: (imap/pop) Clean out obsolete entries from the message cache.
Definition: bcache.c:44
Connection is authenticated.
Definition: private.h:108
#define mutt_message(...)
Definition: logging.h:83
static int sync_helper(struct Mailbox *m, AclFlags right, int flag, const char *name)
Sync flag changes to the server.
Definition: imap.c:301
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
int imap_hcache_put(struct ImapMboxData *mdata, struct Email *e)
Add an entry to the header cache.
Definition: util.c:516
int imap_hcache_del(struct ImapMboxData *mdata, unsigned int uid)
Delete an item from the header cache.
Definition: util.c:534
bool attach_del
Has an attachment marked for deletion.
Definition: email.h:49
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: private.h:174
ImapOpenFlags reopen
Flags, e.g. IMAP_REOPEN_ALLOW.
Definition: private.h:222
int imap_cache_del(struct Mailbox *m, struct Email *e)
Delete an email from the body cache.
Definition: message.c:1773
Flagged messages.
Definition: mutt.h:102
#define _(a)
Definition: message.h:28
bool changed
Email has been edited.
Definition: email.h:48
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: util.c:245
#define MUTT_ACL_DELETE
Delete a message.
Definition: mailbox.h:66
Messages that have been replied to.
Definition: mutt.h:95
Imap command executed or queued successfully.
Definition: private.h:83
bool flagged
Definition: message.h:39
unsigned char changed
Changed fields, e.g. MUTT_ENV_CHANGED_SUBJECT.
Definition: envelope.h:88
bool deleted
Definition: message.h:38
bool read
Email is read.
Definition: email.h:51
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:378
void imap_hcache_close(struct ImapMboxData *mdata)
Close the header cache.
Definition: util.c:475
Log at debug level 2.
Definition: logging.h:41
bool old
Email is seen, but unread.
Definition: email.h:50
Sort by the order the messages appear in the mailbox.
Definition: sort2.h:55
struct Envelope * env
Envelope information.
Definition: email.h:90
int imap_exec_msgset(struct Mailbox *m, const char *pre, const char *post, int flag, bool changed, bool invert)
Prepare commands for all messages matching conditions.
Definition: imap.c:881
Mailbox is selected.
Definition: private.h:109
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:58
void * mdata
Driver specific data.
Definition: mailbox.h:136
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:74
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:1247
Old messages.
Definition: mutt.h:94
bool closing
If true, we are waiting for CLOSE completion.
Definition: private.h:173
void imap_error(const char *where, const char *msg)
show an error and abort
Definition: util.c:798
bool active
Message is not to be removed.
Definition: email.h:59
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:39
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
#define IMAP_EXPUNGE_EXPECTED
Messages will be expunged from the server.
Definition: private.h:66
Messages that have been read.
Definition: mutt.h:96
bool replied
Definition: message.h:40
bool old
Definition: message.h:37
bool append
Mailbox is opened in append mode.
Definition: mailbox.h:113
bool verbose
Display status messages?
Definition: mailbox.h:118
void imap_allow_reopen(struct Mailbox *m)
Allow re-opening a folder upon expunge.
Definition: util.c:1150
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:121
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:72
int imap_cache_clean(struct Mailbox *m)
Delete all the entries in the message cache.
Definition: message.c:1792
int imap_check_mailbox(struct Mailbox *m, bool force)
use the NOOP or IDLE command to poll for new mail
Definition: imap.c:1061
IMAP-specific Account data -.
Definition: private.h:169
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:113
bool flagged
Marked important?
Definition: email.h:43
IMAP-specific Mailbox data -.
Definition: private.h:216
char * buf
Definition: private.h:189
bool deleted
Email is deleted.
Definition: email.h:45
void * edata
Driver-specific data.
Definition: email.h:109
#define mutt_error(...)
Definition: logging.h:84
bool replied
Email has been replied to.
Definition: email.h:54
#define FREE(x)
Definition: memory.h:40
bool read
Definition: message.h:36
#define MUTT_ACL_SEEN
Change the &#39;seen&#39; status of a message.
Definition: mailbox.h:73
bool changed
Mailbox has been modified.
Definition: mailbox.h:114
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
#define IMAP_CMD_QUEUE
Queue a command, do not execute.
Definition: private.h:74
IMAP-specific Email data -.
Definition: message.h:33
sort_t mutt_get_sort_func(enum SortType method)
Get the sort function for a given sort id.
Definition: sort.c:324
void imap_hcache_open(struct ImapAccountData *adata, struct ImapMboxData *mdata)
Open a header cache.
Definition: util.c:435
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_ac_find()

static struct Account* imap_ac_find ( struct Account a,
const char *  path 
)
static

Find an Account that matches a Mailbox path - Implements MxOps::ac_find()

Definition at line 1686 of file imap.c.

1687 {
1688  if (!a || (a->type != MUTT_IMAP) || !path)
1689  return NULL;
1690 
1691  struct Url *url = url_parse(path);
1692  if (!url)
1693  return NULL;
1694 
1695  struct ImapAccountData *adata = a->adata;
1696  struct ConnAccount *cac = &adata->conn->account;
1697 
1698  if (!mutt_istr_equal(url->host, cac->host))
1699  a = NULL;
1700  else if (url->user && !mutt_istr_equal(url->user, cac->user))
1701  a = NULL;
1702 
1703  url_free(&url);
1704  return a;
1705 }
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:36
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:66
char user[128]
Username.
Definition: connaccount.h:55
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition: url.c:123
enum MailboxType type
Type of Mailboxes this Account contains.
Definition: account.h:38
char host[128]
Server to login to.
Definition: connaccount.h:53
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
char * user
Username.
Definition: url.h:69
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
char * host
Host.
Definition: url.h:71
Login details for a remote server.
Definition: connaccount.h:51
char * path
Path.
Definition: url.h:73
IMAP-specific Account data -.
Definition: private.h:169
char * path
Path of Email (for local Mailboxes)
Definition: email.h:92
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
struct Connection * conn
Definition: private.h:171
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:234
+ Here is the call graph for this function:

◆ imap_ac_add()

static int imap_ac_add ( struct Account a,
struct Mailbox m 
)
static

Add a Mailbox to an Account - Implements MxOps::ac_add()

Definition at line 1710 of file imap.c.

1711 {
1712  if (!a || !m || (m->type != MUTT_IMAP))
1713  return -1;
1714 
1715  struct ImapAccountData *adata = a->adata;
1716 
1717  if (!adata)
1718  {
1719  struct ConnAccount cac = { { 0 } };
1720  char mailbox[PATH_MAX];
1721 
1722  if (imap_parse_path(mailbox_path(m), &cac, mailbox, sizeof(mailbox)) < 0)
1723  return -1;
1724 
1725  adata = imap_adata_new(a);
1726  adata->conn = mutt_conn_new(&cac);
1727  if (!adata->conn)
1728  {
1729  imap_adata_free((void **) &adata);
1730  return -1;
1731  }
1732 
1734 
1735  if (imap_login(adata) < 0)
1736  {
1737  imap_adata_free((void **) &adata);
1738  return -1;
1739  }
1740 
1741  a->adata = adata;
1743  }
1744 
1745  if (!m->mdata)
1746  {
1747  struct Url *url = url_parse(mailbox_path(m));
1748  struct ImapMboxData *mdata = imap_mdata_new(adata, url->path);
1749 
1750  /* fixup path and realpath, mainly to replace / by /INBOX */
1751  char buf[1024];
1752  imap_qualify_path(buf, sizeof(buf), &adata->conn->account, mdata->name);
1753  mutt_buffer_strcpy(&m->pathbuf, buf);
1755 
1756  m->mdata = mdata;
1758  url_free(&url);
1759  }
1760  return 0;
1761 }
void imap_mdata_free(void **ptr)
Free the private Mailbox data - Implements Mailbox::mdata_free()
Definition: util.c:226
void imap_adata_free(void **ptr)
Free the private Account data - Implements Account::adata_free()
Definition: util.c:65
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:201
void imap_qualify_path(char *buf, size_t buflen, struct ConnAccount *conn_account, char *path)
Make an absolute IMAP folder target.
Definition: util.c:954
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:36
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:66
int imap_login(struct ImapAccountData *adata)
Open an IMAP connection.
Definition: imap.c:1799
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:618
struct ImapAccountData * imap_adata_new(struct Account *a)
Allocate and initialise a new ImapAccountData structure.
Definition: util.c:91
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition: url.c:123
void(* mdata_free)(void **ptr)
Free the private data attached to the Mailbox.
Definition: mailbox.h:142
void(* adata_free)(void **ptr)
Free the private data attached to the Account.
Definition: account.h:49
struct ImapMboxData * imap_mdata_new(struct ImapAccountData *adata, const char *name)
Allocate and initialise a new ImapMboxData structure.
Definition: util.c:164
void * mdata
Driver specific data.
Definition: mailbox.h:136
struct Connection * mutt_conn_new(const struct ConnAccount *cac)
Create a new Connection.
Definition: mutt_socket.c:46
void mutt_account_hook(const char *url)
Perform an account hook.
Definition: hook.c:754
#define PATH_MAX
Definition: mutt.h:44
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
char * name
Mailbox name.
Definition: private.h:218
Login details for a remote server.
Definition: connaccount.h:51
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
char * path
Path.
Definition: url.h:73
IMAP-specific Account data -.
Definition: private.h:169
IMAP-specific Mailbox data -.
Definition: private.h:216
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:451
struct Buffer pathbuf
Definition: mailbox.h:83
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
struct Connection * conn
Definition: private.h:171
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:234
+ Here is the call graph for this function:

◆ imap_mbox_select()

static void imap_mbox_select ( struct Mailbox m)
static

Select a Mailbox.

Parameters
mMailbox

Definition at line 1767 of file imap.c.

1768 {
1769  struct ImapAccountData *adata = imap_adata_get(m);
1770  struct ImapMboxData *mdata = imap_mdata_get(m);
1771  if (!adata || !mdata)
1772  return;
1773 
1774  const char *condstore = NULL;
1775 #ifdef USE_HCACHE
1777  condstore = " (CONDSTORE)";
1778  else
1779 #endif
1780  condstore = "";
1781 
1782  char buf[PATH_MAX];
1783  snprintf(buf, sizeof(buf), "%s %s%s", m->readonly ? "EXAMINE" : "SELECT",
1784  mdata->munge_name, condstore);
1785 
1786  adata->state = IMAP_SELECTED;
1787 
1788  imap_cmd_start(adata, buf);
1789 }
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: private.h:174
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: util.c:245
int imap_cmd_start(struct ImapAccountData *adata, const char *cmdstr)
Given an IMAP command, send it to the server.
Definition: command.c:1062
bool C_ImapCondstore
Config: (imap) Enable the CONDSTORE extension.
Definition: config.c:38
bool readonly
Don&#39;t allow changes to the mailbox.
Definition: mailbox.h:119
Mailbox is selected.
Definition: private.h:109
void * mdata
Driver specific data.
Definition: mailbox.h:136
#define PATH_MAX
Definition: mutt.h:44
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
ImapCapFlags capabilities
Definition: private.h:185
IMAP-specific Account data -.
Definition: private.h:169
#define IMAP_CAP_CONDSTORE
RFC7162.
Definition: private.h:136
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:113
IMAP-specific Mailbox data -.
Definition: private.h:216
char * munge_name
Munged version of the mailbox name.
Definition: private.h:219
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_login()

int imap_login ( struct ImapAccountData adata)

Open an IMAP connection.

Parameters
adataImap Account data
Return values
0Success
-1Failure

Ensure ImapAccountData is connected and logged into the imap server.

Definition at line 1799 of file imap.c.

1800 {
1801  if (!adata)
1802  return -1;
1803 
1804  if (adata->state == IMAP_DISCONNECTED)
1805  {
1806  mutt_buffer_reset(&adata->cmdbuf); // purge outstanding queued commands
1807  imap_open_connection(adata);
1808  }
1809  if (adata->state == IMAP_CONNECTED)
1810  {
1811  if (imap_authenticate(adata) == IMAP_AUTH_SUCCESS)
1812  {
1813  adata->state = IMAP_AUTHENTICATED;
1814  FREE(&adata->capstr);
1815  if (adata->conn->ssf != 0)
1816  {
1817  mutt_debug(LL_DEBUG2, "Communication encrypted at %d bits\n",
1818  adata->conn->ssf);
1819  }
1820  }
1821  else
1823  }
1824  if (adata->state == IMAP_AUTHENTICATED)
1825  {
1826  /* capabilities may have changed */
1827  imap_exec(adata, "CAPABILITY", IMAP_CMD_PASS);
1828 
1829 #ifdef USE_ZLIB
1830  /* RFC4978 */
1831  if ((adata->capabilities & IMAP_CAP_COMPRESS) && C_ImapDeflate &&
1832  (imap_exec(adata, "COMPRESS DEFLATE", IMAP_CMD_PASS) == IMAP_EXEC_SUCCESS))
1833  {
1834  mutt_debug(LL_DEBUG2, "IMAP compression is enabled on connection to %s\n",
1835  adata->conn->account.host);
1836  mutt_zstrm_wrap_conn(adata->conn);
1837  }
1838 #endif
1839 
1840  /* enable RFC6855, if the server supports that */
1841  if (C_ImapRfc5161 && (adata->capabilities & IMAP_CAP_ENABLE))
1842  imap_exec(adata, "ENABLE UTF8=ACCEPT", IMAP_CMD_QUEUE);
1843 
1844  /* enable QRESYNC. Advertising QRESYNC also means CONDSTORE
1845  * is supported (even if not advertised), so flip that bit. */
1846  if (adata->capabilities & IMAP_CAP_QRESYNC)
1847  {
1848  adata->capabilities |= IMAP_CAP_CONDSTORE;
1850  imap_exec(adata, "ENABLE QRESYNC", IMAP_CMD_QUEUE);
1851  }
1852 
1853  /* get root delimiter, '/' as default */
1854  adata->delim = '/';
1855  imap_exec(adata, "LIST \"\" \"\"", IMAP_CMD_QUEUE);
1856 
1857  /* we may need the root delimiter before we open a mailbox */
1858  imap_exec(adata, NULL, IMAP_CMD_NO_FLAGS);
1859 
1860  /* select the mailbox that used to be open before disconnect */
1861  if (adata->mailbox)
1862  {
1863  imap_mbox_select(adata->mailbox);
1864  }
1865  }
1866 
1867  if (adata->state < IMAP_AUTHENTICATED)
1868  return -1;
1869 
1870  return 0;
1871 }
#define IMAP_CAP_COMPRESS
RFC4978: COMPRESS=DEFLATE.
Definition: private.h:139
void mutt_zstrm_wrap_conn(struct Connection *conn)
Wrap a compression layer around a Connection.
Definition: zstrm.c:288
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:36
unsigned int ssf
Security strength factor, in bits (see below)
Definition: connection.h:37
int imap_open_connection(struct ImapAccountData *adata)
Open an IMAP connection.
Definition: imap.c:701
Connection is authenticated.
Definition: private.h:108
#define IMAP_CAP_ENABLE
RFC5161.
Definition: private.h:135
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: private.h:174
bool C_ImapRfc5161
Config: (imap) Use the IMAP ENABLE extension to select capabilities.
Definition: config.c:56
struct Mailbox * mailbox
Current selected mailbox.
Definition: private.h:206
char * capstr
Definition: private.h:184
Imap command executed or queued successfully.
Definition: private.h:83
char host[128]
Server to login to.
Definition: connaccount.h:53
Disconnected from server.
Definition: private.h:106
Log at debug level 2.
Definition: logging.h:41
struct Buffer cmdbuf
Definition: private.h:203
bool C_ImapQresync
Config: (imap) Enable the QRESYNC extension.
Definition: config.c:55
Connected to server.
Definition: private.h:107
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:1247
void mutt_account_unsetpass(struct ConnAccount *cac)
Unset ConnAccount&#39;s password.
Definition: connaccount.c:141
#define IMAP_CMD_PASS
Command contains a password. Suppress logging.
Definition: private.h:73
ImapCapFlags capabilities
Definition: private.h:185
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:72
static void imap_mbox_select(struct Mailbox *m)
Select a Mailbox.
Definition: imap.c:1767
#define IMAP_CAP_CONDSTORE
RFC7162.
Definition: private.h:136
bool C_ImapDeflate
Config: (imap) Compress network traffic.
Definition: config.c:40
#define IMAP_CAP_QRESYNC
RFC7162.
Definition: private.h:137
#define FREE(x)
Definition: memory.h:40
int imap_authenticate(struct ImapAccountData *adata)
Authenticate to an IMAP server.
Definition: auth.c:82
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
#define IMAP_CMD_QUEUE
Queue a command, do not execute.
Definition: private.h:74
Authentication successful.
Definition: auth.h:38
struct Connection * conn
Definition: private.h:171
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_mbox_open()

static int imap_mbox_open ( struct Mailbox m)
static

Open a mailbox - Implements MxOps::mbox_open()

Definition at line 1876 of file imap.c.

1877 {
1878  if (!m || !m->account || !m->mdata)
1879  return -1;
1880 
1881  char buf[PATH_MAX];
1882  int count = 0;
1883  int rc;
1884 
1885  struct ImapAccountData *adata = imap_adata_get(m);
1886  struct ImapMboxData *mdata = imap_mdata_get(m);
1887 
1888  mutt_debug(LL_DEBUG3, "opening %s, saving %s\n", m->pathbuf.data,
1889  (adata->mailbox ? adata->mailbox->pathbuf.data : "(none)"));
1890  adata->prev_mailbox = adata->mailbox;
1891  adata->mailbox = m;
1892 
1893  /* clear mailbox status */
1894  adata->status = 0;
1895  m->rights = 0;
1896  mdata->new_mail_count = 0;
1897 
1898  if (m->verbose)
1899  mutt_message(_("Selecting %s..."), mdata->name);
1900 
1901  /* pipeline ACL test */
1902  if (adata->capabilities & IMAP_CAP_ACL)
1903  {
1904  snprintf(buf, sizeof(buf), "MYRIGHTS %s", mdata->munge_name);
1905  imap_exec(adata, buf, IMAP_CMD_QUEUE);
1906  }
1907  /* assume we have all rights if ACL is unavailable */
1908  else
1909  {
1912  }
1913 
1914  /* pipeline the postponed count if possible */
1915  struct Mailbox *m_postponed = mx_mbox_find2(C_Postponed);
1916  struct ImapAccountData *postponed_adata = imap_adata_get(m_postponed);
1917  if (postponed_adata &&
1918  imap_account_match(&postponed_adata->conn->account, &adata->conn->account))
1919  {
1920  imap_mailbox_status(m_postponed, true);
1921  }
1922 
1924  imap_exec(adata, "LSUB \"\" \"*\"", IMAP_CMD_QUEUE);
1925 
1926  imap_mbox_select(m);
1927 
1928  do
1929  {
1930  char *pc = NULL;
1931 
1932  rc = imap_cmd_step(adata);
1933  if (rc != IMAP_RES_CONTINUE)
1934  break;
1935 
1936  pc = adata->buf + 2;
1937 
1938  /* Obtain list of available flags here, may be overridden by a
1939  * PERMANENTFLAGS tag in the OK response */
1940  if (mutt_istr_startswith(pc, "FLAGS"))
1941  {
1942  /* don't override PERMANENTFLAGS */
1943  if (STAILQ_EMPTY(&mdata->flags))
1944  {
1945  mutt_debug(LL_DEBUG3, "Getting mailbox FLAGS\n");
1946  pc = get_flags(&mdata->flags, pc);
1947  if (!pc)
1948  goto fail;
1949  }
1950  }
1951  /* PERMANENTFLAGS are massaged to look like FLAGS, then override FLAGS */
1952  else if (mutt_istr_startswith(pc, "OK [PERMANENTFLAGS"))
1953  {
1954  mutt_debug(LL_DEBUG3, "Getting mailbox PERMANENTFLAGS\n");
1955  /* safe to call on NULL */
1956  mutt_list_free(&mdata->flags);
1957  /* skip "OK [PERMANENT" so syntax is the same as FLAGS */
1958  pc += 13;
1959  pc = get_flags(&(mdata->flags), pc);
1960  if (!pc)
1961  goto fail;
1962  }
1963  /* save UIDVALIDITY for the header cache */
1964  else if (mutt_istr_startswith(pc, "OK [UIDVALIDITY"))
1965  {
1966  mutt_debug(LL_DEBUG3, "Getting mailbox UIDVALIDITY\n");
1967  pc += 3;
1968  pc = imap_next_word(pc);
1969  if (mutt_str_atoui(pc, &mdata->uidvalidity) < 0)
1970  goto fail;
1971  }
1972  else if (mutt_istr_startswith(pc, "OK [UIDNEXT"))
1973  {
1974  mutt_debug(LL_DEBUG3, "Getting mailbox UIDNEXT\n");
1975  pc += 3;
1976  pc = imap_next_word(pc);
1977  if (mutt_str_atoui(pc, &mdata->uid_next) < 0)
1978  goto fail;
1979  }
1980  else if (mutt_istr_startswith(pc, "OK [HIGHESTMODSEQ"))
1981  {
1982  mutt_debug(LL_DEBUG3, "Getting mailbox HIGHESTMODSEQ\n");
1983  pc += 3;
1984  pc = imap_next_word(pc);
1985  if (mutt_str_atoull(pc, &mdata->modseq) < 0)
1986  goto fail;
1987  }
1988  else if (mutt_istr_startswith(pc, "OK [NOMODSEQ"))
1989  {
1990  mutt_debug(LL_DEBUG3, "Mailbox has NOMODSEQ set\n");
1991  mdata->modseq = 0;
1992  }
1993  else
1994  {
1995  pc = imap_next_word(pc);
1996  if (mutt_istr_startswith(pc, "EXISTS"))
1997  {
1998  count = mdata->new_mail_count;
1999  mdata->new_mail_count = 0;
2000  }
2001  }
2002  } while (rc == IMAP_RES_CONTINUE);
2003 
2004  if (rc == IMAP_RES_NO)
2005  {
2006  char *s = imap_next_word(adata->buf); /* skip seq */
2007  s = imap_next_word(s); /* Skip response */
2008  mutt_error("%s", s);
2009  goto fail;
2010  }
2011 
2012  if (rc != IMAP_RES_OK)
2013  goto fail;
2014 
2015  /* check for READ-ONLY notification */
2016  if (mutt_istr_startswith(imap_get_qualifier(adata->buf), "[READ-ONLY]") &&
2017  !(adata->capabilities & IMAP_CAP_ACL))
2018  {
2019  mutt_debug(LL_DEBUG2, "Mailbox is read-only\n");
2020  m->readonly = true;
2021  }
2022 
2023  /* dump the mailbox flags we've found */
2024  if (C_DebugLevel > LL_DEBUG2)
2025  {
2026  if (STAILQ_EMPTY(&mdata->flags))
2027  mutt_debug(LL_DEBUG3, "No folder flags found\n");
2028  else
2029  {
2030  struct ListNode *np = NULL;
2031  struct Buffer flag_buffer;
2032  mutt_buffer_init(&flag_buffer);
2033  mutt_buffer_printf(&flag_buffer, "Mailbox flags: ");
2034  STAILQ_FOREACH(np, &mdata->flags, entries)
2035  {
2036  mutt_buffer_add_printf(&flag_buffer, "[%s] ", np->data);
2037  }
2038  mutt_debug(LL_DEBUG3, "%s\n", flag_buffer.data);
2039  FREE(&flag_buffer.data);
2040  }
2041  }
2042 
2043  if (!((m->rights & MUTT_ACL_DELETE) || (m->rights & MUTT_ACL_SEEN) ||
2044  (m->rights & MUTT_ACL_WRITE) || (m->rights & MUTT_ACL_INSERT)))
2045  {
2046  m->readonly = true;
2047  }
2048 
2049  while (m->email_max < count)
2050  mx_alloc_memory(m);
2051 
2052  m->msg_count = 0;
2053  m->msg_unread = 0;
2054  m->msg_flagged = 0;
2055  m->msg_new = 0;
2056  m->msg_deleted = 0;
2057  m->size = 0;
2058  m->vcount = 0;
2059 
2060  if (count && (imap_read_headers(m, 1, count, true) < 0))
2061  {
2062  mutt_error(_("Error opening mailbox"));
2063  goto fail;
2064  }
2065 
2066  mutt_debug(LL_DEBUG2, "msg_count is %d\n", m->msg_count);
2067  return 0;
2068 
2069 fail:
2070  if (adata->state == IMAP_SELECTED)
2071  adata->state = IMAP_AUTHENTICATED;
2072  return -1;
2073 }
int msg_count
Total number of messages.
Definition: mailbox.h:91
off_t size
Size of the Mailbox.
Definition: mailbox.h:87
#define IMAP_RES_OK
<tag> OK ...
Definition: private.h:55
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1076
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:36
uint32_t uidvalidity
Definition: private.h:228
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:96
int msg_unread
Number of unread messages.
Definition: mailbox.h:92
#define MUTT_ACL_READ
Read the mailbox.
Definition: mailbox.h:72
Connection is authenticated.
Definition: private.h:108
#define mutt_message(...)
Definition: logging.h:83
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:93
#define MUTT_ACL_CREATE
Create a mailbox.
Definition: mailbox.h:65
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: private.h:174
String manipulation buffer.
Definition: buffer.h:33
#define MUTT_ACL_INSERT
Add/copy into the mailbox (used when editing a message)
Definition: mailbox.h:69
void mx_alloc_memory(struct Mailbox *m)
Create storage for the emails.
Definition: mx.c:1233
#define _(a)
Definition: message.h:28
struct Mailbox * mailbox
Current selected mailbox.
Definition: private.h:206
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: util.c:245
bool imap_account_match(const struct ConnAccount *a1, const struct ConnAccount *a2)
Compare two Accounts.
Definition: util.c:1178
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
struct Mailbox * mx_mbox_find2(const char *path)
Find a Mailbox on an Account.
Definition: mx.c:1670
#define MUTT_ACL_DELETE
Delete a message.
Definition: mailbox.h:66
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
static char * get_flags(struct ListHead *hflags, char *s)
Make a simple list out of a FLAGS response.
Definition: imap.c:100
int vcount
The number of virtual messages.
Definition: mailbox.h:102
unsigned int new_mail_count
Set when EXISTS notifies of new mail.
Definition: private.h:224
char * imap_next_word(char *s)
Find where the next IMAP word begins.
Definition: util.c:923
Log at debug level 2.
Definition: logging.h:41
bool readonly
Don&#39;t allow changes to the mailbox.
Definition: mailbox.h:119
int imap_read_headers(struct Mailbox *m, unsigned int msn_begin, unsigned int msn_end, bool initial_download)
Read headers from the server.
Definition: message.c:1284
Mailbox is selected.
Definition: private.h:109
struct Mailbox * prev_mailbox
Previously selected mailbox.
Definition: private.h:207
int mutt_buffer_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:203
#define MUTT_ACL_POST
Post (submit messages to the server)
Definition: mailbox.h:71
void * mdata
Driver specific data.
Definition: mailbox.h:136
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:74
unsigned long long modseq
Definition: private.h:230
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:1247
short C_DebugLevel
Config: Logging level for debug logs.
Definition: mutt_logging.c:48
int email_max
Number of pointers in emails.
Definition: mailbox.h:100
A mailbox.
Definition: mailbox.h:81
#define PATH_MAX
Definition: mutt.h:44
struct ListHead flags
Definition: private.h:227
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
unsigned char status
ImapFlags, e.g. IMAP_FATAL.
Definition: private.h:175
char * data
Pointer to data.
Definition: buffer.h:35
char * name
Mailbox name.
Definition: private.h:218
int mutt_str_atoui(const char *str, unsigned int *dst)
Convert ASCII string to an unsigned integer.
Definition: string.c:287
bool verbose
Display status messages?
Definition: mailbox.h:118
int mutt_str_atoull(const char *str, unsigned long long *dst)
Convert ASCII string to an unsigned long long.
Definition: string.c:348
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:177
int imap_mailbox_status(struct Mailbox *m, bool queue)
Refresh the number of total and new messages.
Definition: imap.c:1215
bool C_ImapCheckSubscribed
Config: (imap) When opening a mailbox, ask the server for a list of subscribed folders.
Definition: config.c:37
ImapCapFlags capabilities
Definition: private.h:185
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:121
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
#define IMAP_RES_NO
<tag> NO ...
Definition: private.h:53
static void imap_mbox_select(struct Mailbox *m)
Select a Mailbox.
Definition: imap.c:1767
IMAP-specific Account data -.
Definition: private.h:169
unsigned int uid_next
Definition: private.h:229
char * imap_get_qualifier(char *buf)
Get the qualifier from a tagged response.
Definition: util.c:906
char * data
String.
Definition: list.h:36
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:131
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:113
IMAP-specific Mailbox data -.
Definition: private.h:216
char * buf
Definition: private.h:189
int msg_new
Number of new messages.
Definition: mailbox.h:95
#define mutt_error(...)
Definition: logging.h:84
#define FREE(x)
Definition: memory.h:40
#define MUTT_ACL_SEEN
Change the &#39;seen&#39; status of a message.
Definition: mailbox.h:73
#define STAILQ_EMPTY(head)
Definition: queue.h:345
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
#define IMAP_CMD_QUEUE
Queue a command, do not execute.
Definition: private.h:74
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:46
struct Buffer pathbuf
Definition: mailbox.h:83
A List node for strings.
Definition: list.h:34
#define IMAP_RES_CONTINUE
* ...
Definition: private.h:56
char * munge_name
Munged version of the mailbox name.
Definition: private.h:219
#define IMAP_CAP_ACL
RFC2086: IMAP4 ACL extension.
Definition: private.h:125
Log at debug level 3.
Definition: logging.h:42
WHERE char * C_Postponed
Config: Folder to store postponed messages.
Definition: mutt_globals.h:102
#define MUTT_ACL_LOOKUP
Lookup mailbox (visible to &#39;list&#39;)
Definition: mailbox.h:70
struct Connection * conn
Definition: private.h:171
+ Here is the call graph for this function:

◆ imap_mbox_open_append()

static int imap_mbox_open_append ( struct Mailbox m,
OpenMailboxFlags  flags 
)
static

Open a Mailbox for appending - Implements MxOps::mbox_open_append()

Definition at line 2078 of file imap.c.

2079 {
2080  if (!m || !m->account)
2081  return -1;
2082 
2083  /* in APPEND mode, we appear to hijack an existing IMAP connection -
2084  * ctx is brand new and mostly empty */
2085  struct ImapAccountData *adata = imap_adata_get(m);
2086  struct ImapMboxData *mdata = imap_mdata_get(m);
2087 
2088  int rc = imap_mailbox_status(m, false);
2089  if (rc >= 0)
2090  return 0;
2091  if (rc == -1)
2092  return -1;
2093 
2094  char buf[PATH_MAX + 64];
2095  snprintf(buf, sizeof(buf), _("Create %s?"), mdata->name);
2096  if (C_Confirmcreate && (mutt_yesorno(buf, MUTT_YES) != MUTT_YES))
2097  return -1;
2098 
2099  if (imap_create_mailbox(adata, mdata->name) < 0)
2100  return -1;
2101 
2102  return 0;
2103 }
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
#define _(a)
Definition: message.h:28
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: util.c:245
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:378
void * mdata
Driver specific data.
Definition: mailbox.h:136
#define PATH_MAX
Definition: mutt.h:44
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
char * name
Mailbox name.
Definition: private.h:218
WHERE bool C_Confirmcreate
Config: Confirm before creating a new mailbox.
Definition: mutt_globals.h:144
int imap_mailbox_status(struct Mailbox *m, bool queue)
Refresh the number of total and new messages.
Definition: imap.c:1215
int imap_create_mailbox(struct ImapAccountData *adata, char *mailbox)
Create a new mailbox.
Definition: imap.c:424
IMAP-specific Account data -.
Definition: private.h:169
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:131
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:113
IMAP-specific Mailbox data -.
Definition: private.h:216
+ Here is the call graph for this function:

◆ imap_mbox_check()

static int imap_mbox_check ( struct Mailbox m)
static

Check for new mail - Implements MxOps::mbox_check()

Parameters
mMailbox
Return values
>0Success, e.g. MUTT_REOPENED
-1Failure

Definition at line 2111 of file imap.c.

2112 {
2113  if (!m)
2114  return -1;
2115 
2116  imap_allow_reopen(m);
2117  int rc = imap_check_mailbox(m, false);
2118  /* NOTE - ctx might have been changed at this point. In particular,
2119  * m could be NULL. Beware. */
2121 
2122  return rc;
2123 }
void imap_disallow_reopen(struct Mailbox *m)
Disallow re-opening a folder upon expunge.
Definition: util.c:1163
void imap_allow_reopen(struct Mailbox *m)
Allow re-opening a folder upon expunge.
Definition: util.c:1150
int imap_check_mailbox(struct Mailbox *m, bool force)
use the NOOP or IDLE command to poll for new mail
Definition: imap.c:1061
+ Here is the call graph for this function:

◆ imap_mbox_close()

static int imap_mbox_close ( struct Mailbox m)
static

Close a Mailbox - Implements MxOps::mbox_close()

Definition at line 2128 of file imap.c.

2129 {
2130  if (!m)
2131  return -1;
2132 
2133  struct ImapAccountData *adata = imap_adata_get(m);
2134  struct ImapMboxData *mdata = imap_mdata_get(m);
2135 
2136  /* Check to see if the mailbox is actually open */
2137  if (!adata || !mdata)
2138  return 0;
2139 
2140  /* imap_mbox_open_append() borrows the struct ImapAccountData temporarily,
2141  * just for the connection.
2142  *
2143  * So when these are equal, it means we are actually closing the
2144  * mailbox and should clean up adata. Otherwise, we don't want to
2145  * touch adata - it's still being used. */
2146  if (m == adata->mailbox)
2147  {
2148  if ((adata->status != IMAP_FATAL) && (adata->state >= IMAP_SELECTED))
2149  {
2150  /* mx_mbox_close won't sync if there are no deleted messages
2151  * and the mailbox is unchanged, so we may have to close here */
2152  if (m->msg_deleted == 0)
2153  {
2154  adata->closing = true;
2155  imap_exec(adata, "CLOSE", IMAP_CMD_QUEUE);
2156  }
2157  adata->state = IMAP_AUTHENTICATED;
2158  }
2159 
2160  mutt_debug(LL_DEBUG3, "closing %s, restoring %s\n", m->pathbuf.data,
2161  (adata->prev_mailbox ? adata->prev_mailbox->pathbuf.data : "(none)"));
2162  adata->mailbox = adata->prev_mailbox;
2165  }
2166 
2167  return 0;
2168 }
void imap_mdata_cache_reset(struct ImapMboxData *mdata)
Release and clear cache data of ImapMboxData structure.
Definition: util.c:214
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:96
Connection is authenticated.
Definition: private.h:108
Unrecoverable error occurred.
Definition: private.h:96
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: private.h:174
struct Mailbox * mailbox
Current selected mailbox.
Definition: private.h:206
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: util.c:245
Mailbox is selected.
Definition: private.h:109
struct Mailbox * prev_mailbox
Previously selected mailbox.
Definition: private.h:207
void * mdata
Driver specific data.
Definition: mailbox.h:136
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:1247
bool closing
If true, we are waiting for CLOSE completion.
Definition: private.h:173
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
unsigned char status
ImapFlags, e.g. IMAP_FATAL.
Definition: private.h:175
char * data
Pointer to data.
Definition: buffer.h:35
static void imap_mbox_select(struct Mailbox *m)
Select a Mailbox.
Definition: imap.c:1767
IMAP-specific Account data -.
Definition: private.h:169
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:113
IMAP-specific Mailbox data -.
Definition: private.h:216
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
#define IMAP_CMD_QUEUE
Queue a command, do not execute.
Definition: private.h:74
struct Buffer pathbuf
Definition: mailbox.h:83
Log at debug level 3.
Definition: logging.h:42
+ Here is the call graph for this function:

◆ imap_msg_open_new()

static int imap_msg_open_new ( struct Mailbox m,
struct Message msg,
struct Email e 
)
static

Open a new message in a Mailbox - Implements MxOps::msg_open_new()

Definition at line 2173 of file imap.c.

2174 {
2175  int rc = -1;
2176 
2177  struct Buffer *tmp = mutt_buffer_pool_get();
2178  mutt_buffer_mktemp(tmp);
2179 
2180  msg->fp = mutt_file_fopen(mutt_b2s(tmp), "w");
2181  if (!msg->fp)
2182  {
2183  mutt_perror(mutt_b2s(tmp));
2184  goto cleanup;
2185  }
2186 
2187  msg->path = mutt_buffer_strdup(tmp);
2188  rc = 0;
2189 
2190 cleanup:
2192  return rc;
2193 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
char * mutt_buffer_strdup(struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
String manipulation buffer.
Definition: buffer.h:33
#define mutt_b2s(buf)
Definition: buffer.h:41
FILE * fp
pointer to the message data
Definition: mx.h:85
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
char * path
path to temp file
Definition: mx.h:86
+ Here is the call graph for this function:

◆ imap_tags_edit()

static int imap_tags_edit ( struct Mailbox m,
const char *  tags,
char *  buf,
size_t  buflen 
)
static

Prompt and validate new messages tags - Implements MxOps::tags_edit()

Definition at line 2198 of file imap.c.

2199 {
2200  struct ImapMboxData *mdata = imap_mdata_get(m);
2201  if (!mdata)
2202  return -1;
2203 
2204  char *new_tag = NULL;
2205  char *checker = NULL;
2206 
2207  /* Check for \* flags capability */
2208  if (!imap_has_flag(&mdata->flags, NULL))
2209  {
2210  mutt_error(_("IMAP server doesn't support custom flags"));
2211  return -1;
2212  }
2213 
2214  *buf = '\0';
2215  if (tags)
2216  mutt_str_copy(buf, tags, buflen);
2217 
2218  if (mutt_get_field("Tags: ", buf, buflen, MUTT_COMP_NO_FLAGS) != 0)
2219  return -1;
2220 
2221  /* each keyword must be atom defined by rfc822 as:
2222  *
2223  * atom = 1*<any CHAR except specials, SPACE and CTLs>
2224  * CHAR = ( 0.-127. )
2225  * specials = "(" / ")" / "<" / ">" / "@"
2226  * / "," / ";" / ":" / "\" / <">
2227  * / "." / "[" / "]"
2228  * SPACE = ( 32. )
2229  * CTLS = ( 0.-31., 127.)
2230  *
2231  * And must be separated by one space.
2232  */
2233 
2234  new_tag = buf;
2235  checker = buf;
2236  SKIPWS(checker);
2237  while (*checker != '\0')
2238  {
2239  if ((*checker < 32) || (*checker >= 127) || // We allow space because it's the separator
2240  (*checker == 40) || // (
2241  (*checker == 41) || // )
2242  (*checker == 60) || // <
2243  (*checker == 62) || // >
2244  (*checker == 64) || // @
2245  (*checker == 44) || // ,
2246  (*checker == 59) || // ;
2247  (*checker == 58) || // :
2248  (*checker == 92) || // backslash
2249  (*checker == 34) || // "
2250  (*checker == 46) || // .
2251  (*checker == 91) || // [
2252  (*checker == 93)) // ]
2253  {
2254  mutt_error(_("Invalid IMAP flags"));
2255  return 0;
2256  }
2257 
2258  /* Skip duplicate space */
2259  while ((checker[0] == ' ') && (checker[1] == ' '))
2260  checker++;
2261 
2262  /* copy char to new_tag and go the next one */
2263  *new_tag++ = *checker++;
2264  }
2265  *new_tag = '\0';
2266  new_tag = buf; /* rewind */
2267  mutt_str_remove_trailing_ws(new_tag);
2268 
2269  return !mutt_str_equal(tags, buf);
2270 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:876
#define _(a)
Definition: message.h:28
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: util.c:245
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:91
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
bool imap_has_flag(struct ListHead *flag_list, const char *flag)
Does the flag exist in the list.
Definition: imap.c:832
#define SKIPWS(ch)
Definition: string2.h:46
void * mdata
Driver specific data.
Definition: mailbox.h:136
void mutt_str_remove_trailing_ws(char *s)
Trim trailing whitespace from a string.
Definition: string.c:705
struct ListHead flags
Definition: private.h:227
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:721
IMAP-specific Mailbox data -.
Definition: private.h:216
#define mutt_error(...)
Definition: logging.h:84
+ Here is the call graph for this function:

◆ imap_tags_commit()

static int imap_tags_commit ( struct Mailbox m,
struct Email e,
char *  buf 
)
static

Save the tags to a message - Implements MxOps::tags_commit()

This method update the server flags on the server by removing the last know custom flags of a header and adds the local flags

If everything success we push the local flags to the last know custom flags (flags_remote).

Also this method check that each flags is support by the server first and remove unsupported one.

Definition at line 2285 of file imap.c.

2286 {
2287  if (!m)
2288  return -1;
2289 
2290  char uid[11];
2291 
2292  struct ImapAccountData *adata = imap_adata_get(m);
2293 
2294  if (*buf == '\0')
2295  buf = NULL;
2296 
2297  if (!(adata->mailbox->rights & MUTT_ACL_WRITE))
2298  return 0;
2299 
2300  snprintf(uid, sizeof(uid), "%u", imap_edata_get(e)->uid);
2301 
2302  /* Remove old custom flags */
2303  if (imap_edata_get(e)->flags_remote)
2304  {
2305  struct Buffer cmd = mutt_buffer_make(128); // just a guess
2306  mutt_buffer_addstr(&cmd, "UID STORE ");
2307  mutt_buffer_addstr(&cmd, uid);
2308  mutt_buffer_addstr(&cmd, " -FLAGS.SILENT (");
2309  mutt_buffer_addstr(&cmd, imap_edata_get(e)->flags_remote);
2310  mutt_buffer_addstr(&cmd, ")");
2311 
2312  /* Should we return here, or we are fine and we could
2313  * continue to add new flags */
2314  int rc = imap_exec(adata, cmd.data, IMAP_CMD_NO_FLAGS);
2315  mutt_buffer_dealloc(&cmd);
2316  if (rc != IMAP_EXEC_SUCCESS)
2317  {
2318  return -1;
2319  }
2320  }
2321 
2322  /* Add new custom flags */
2323  if (buf)
2324  {
2325  struct Buffer cmd = mutt_buffer_make(128); // just a guess
2326  mutt_buffer_addstr(&cmd, "UID STORE ");
2327  mutt_buffer_addstr(&cmd, uid);
2328  mutt_buffer_addstr(&cmd, " +FLAGS.SILENT (");
2329  mutt_buffer_addstr(&cmd, buf);
2330  mutt_buffer_addstr(&cmd, ")");
2331 
2332  int rc = imap_exec(adata, cmd.data, IMAP_CMD_NO_FLAGS);
2333  mutt_buffer_dealloc(&cmd);
2334  if (rc != IMAP_EXEC_SUCCESS)
2335  {
2336  mutt_debug(LL_DEBUG1, "fail to add new flags\n");
2337  return -1;
2338  }
2339  }
2340 
2341  /* We are good sync them */
2342  mutt_debug(LL_DEBUG1, "NEW TAGS: %s\n", buf);
2343  driver_tags_replace(&e->tags, buf);
2344  FREE(&imap_edata_get(e)->flags_remote);
2346  return 0;
2347 }
struct ImapEmailData * imap_edata_get(struct Email *e)
Get the private data for this Email.
Definition: message.c:98
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
struct Mailbox * mailbox
Current selected mailbox.
Definition: private.h:206
Imap command executed or queued successfully.
Definition: private.h:83
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:74
struct TagList tags
For drivers that support server tagging.
Definition: email.h:107
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:1247
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
char * flags_remote
Definition: message.h:48
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
char * data
Pointer to data.
Definition: buffer.h:35
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:121
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:72
IMAP-specific Account data -.
Definition: private.h:169
char * driver_tags_get_with_hidden(struct TagList *list)
Get tags with hiddens.
Definition: tags.c:155
Log at debug level 1.
Definition: logging.h:40
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:113
char * buf
Definition: private.h:189
#define FREE(x)
Definition: memory.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
bool driver_tags_replace(struct TagList *head, char *tags)
Replace all tags.
Definition: tags.c:183
+ Here is the call graph for this function:

◆ imap_path_probe()

enum MailboxType imap_path_probe ( const char *  path,
const struct stat *  st 
)

Is this an IMAP Mailbox? - Implements MxOps::path_probe()

Definition at line 2352 of file imap.c.

2353 {
2354  if (!path)
2355  return MUTT_UNKNOWN;
2356 
2357  if (mutt_istr_startswith(path, "imap://"))
2358  return MUTT_IMAP;
2359 
2360  if (mutt_istr_startswith(path, "imaps://"))
2361  return MUTT_IMAP;
2362 
2363  return MUTT_UNKNOWN;
2364 }
Mailbox wasn&#39;t recognised.
Definition: mailbox.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:177
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_path_canon()

int imap_path_canon ( char *  buf,
size_t  buflen 
)

Canonicalise a Mailbox path - Implements MxOps::path_canon()

Definition at line 2369 of file imap.c.

2370 {
2371  if (!buf)
2372  return -1;
2373 
2374  struct Url *url = url_parse(buf);
2375  if (!url)
2376  return 0;
2377 
2378  char tmp[PATH_MAX];
2379  char tmp2[PATH_MAX];
2380 
2381  imap_fix_path('\0', url->path, tmp, sizeof(tmp));
2382  url->path = tmp;
2383  url_tostring(url, tmp2, sizeof(tmp2), 0);
2384  mutt_str_copy(buf, tmp2, buflen);
2385  url_free(&url);
2386 
2387  return 0;
2388 }
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:66
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition: url.c:123
#define PATH_MAX
Definition: mutt.h:44
char * path
Path.
Definition: url.h:73
char * imap_fix_path(char delim, const char *mailbox, char *path, size_t plen)
Fix up the imap path.
Definition: util.c:820
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:721
int url_tostring(struct Url *url, char *dest, size_t len, int flags)
Output the URL string for a given Url object.
Definition: url.c:418
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:234
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_expand_path()

int imap_expand_path ( struct Buffer buf)

Buffer wrapper around imap_path_canon()

Parameters
bufPath to expand
Return values
0Success
-1Failure
Note
The path is expanded in place

Definition at line 2398 of file imap.c.

2399 {
2401  return imap_path_canon(buf->data, PATH_MAX);
2402 }
#define PATH_MAX
Definition: mutt.h:44
char * data
Pointer to data.
Definition: buffer.h:35
int imap_path_canon(char *buf, size_t buflen)
Canonicalise a Mailbox path - Implements MxOps::path_canon()
Definition: imap.c:2369
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:265
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_path_pretty()

static int imap_path_pretty ( char *  buf,
size_t  buflen,
const char *  folder 
)
static

Abbreviate a Mailbox path - Implements MxOps::path_pretty()

Definition at line 2407 of file imap.c.

2408 {
2409  if (!buf || !folder)
2410  return -1;
2411 
2412  imap_pretty_mailbox(buf, buflen, folder);
2413  return 0;
2414 }
void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder)
Prettify an IMAP mailbox name.
Definition: util.c:725
+ Here is the call graph for this function:

◆ imap_path_parent()

static int imap_path_parent ( char *  buf,
size_t  buflen 
)
static

Find the parent of a Mailbox path - Implements MxOps::path_parent()

Definition at line 2419 of file imap.c.

2420 {
2421  char tmp[PATH_MAX] = { 0 };
2422 
2423  imap_get_parent_path(buf, tmp, sizeof(tmp));
2424  mutt_str_copy(buf, tmp, buflen);
2425  return 0;
2426 }
void imap_get_parent_path(const char *path, char *buf, size_t buflen)
Get the path of the parent folder.
Definition: util.c:300
#define PATH_MAX
Definition: mutt.h:44
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:721
+ Here is the call graph for this function:

Variable Documentation

◆ MxImapOps

struct MxOps MxImapOps
Initial value:
= {
.type = MUTT_IMAP,
.name = "imap",
.is_local = false,
.ac_find = imap_ac_find,
.ac_add = imap_ac_add,
.mbox_open = imap_mbox_open,
.mbox_open_append = imap_mbox_open_append,
.mbox_check = imap_mbox_check,
.mbox_check_stats = imap_mbox_check_stats,
.mbox_sync = NULL,
.mbox_close = imap_mbox_close,
.msg_open = imap_msg_open,
.msg_open_new = imap_msg_open_new,
.msg_commit = imap_msg_commit,
.msg_close = imap_msg_close,
.msg_padding_size = NULL,
.msg_save_hcache = imap_msg_save_hcache,
.tags_edit = imap_tags_edit,
.tags_commit = imap_tags_commit,
.path_probe = imap_path_probe,
.path_canon = imap_path_canon,
.path_pretty = imap_path_pretty,
.path_parent = imap_path_parent,
}
int imap_msg_save_hcache(struct Mailbox *m, struct Email *e)
Save message to the header cache - Implements MxOps::msg_save_hcache()
Definition: message.c:2107
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2352
static int imap_tags_edit(struct Mailbox *m, const char *tags, char *buf, size_t buflen)
Prompt and validate new messages tags - Implements MxOps::tags_edit()
Definition: imap.c:2198
static int imap_msg_open_new(struct Mailbox *m, struct Message *msg, struct Email *e)
Open a new message in a Mailbox - Implements MxOps::msg_open_new()
Definition: imap.c:2173
int imap_msg_close(struct Mailbox *m, struct Message *msg)
Close an email - Implements MxOps::msg_close()
Definition: message.c:2099
static int imap_path_parent(char *buf, size_t buflen)
Find the parent of a Mailbox path - Implements MxOps::path_parent()
Definition: imap.c:2419
static int imap_mbox_open(struct Mailbox *m)
Open a mailbox - Implements MxOps::mbox_open()
Definition: imap.c:1876
static struct Account * imap_ac_find(struct Account *a, const char *path)
Find an Account that matches a Mailbox path - Implements MxOps::ac_find()
Definition: imap.c:1686
static int imap_ac_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account - Implements MxOps::ac_add()
Definition: imap.c:1710
int imap_msg_open(struct Mailbox *m, struct Message *msg, int msgno)
Open an email message in a Mailbox - Implements MxOps::msg_open()
Definition: message.c:1881
int imap_msg_commit(struct Mailbox *m, struct Message *msg)
Save changes to an email - Implements MxOps::msg_commit()
Definition: message.c:2085
static int imap_mbox_check(struct Mailbox *m)
Check for new mail - Implements MxOps::mbox_check()
Definition: imap.c:2111
static int imap_mbox_check_stats(struct Mailbox *m, int flags)
Check the Mailbox statistics - Implements MxOps::mbox_check_stats()
Definition: imap.c:1170
static int imap_mbox_close(struct Mailbox *m)
Close a Mailbox - Implements MxOps::mbox_close()
Definition: imap.c:2128
static int imap_tags_commit(struct Mailbox *m, struct Email *e, char *buf)
Save the tags to a message - Implements MxOps::tags_commit()
Definition: imap.c:2285
static int imap_path_pretty(char *buf, size_t buflen, const char *folder)
Abbreviate a Mailbox path - Implements MxOps::path_pretty()
Definition: imap.c:2407
int imap_path_canon(char *buf, size_t buflen)
Canonicalise a Mailbox path - Implements MxOps::path_canon()
Definition: imap.c:2369
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
static int imap_mbox_open_append(struct Mailbox *m, OpenMailboxFlags flags)
Open a Mailbox for appending - Implements MxOps::mbox_open_append()
Definition: imap.c:2078

IMAP Mailbox - Implements MxOps.

Definition at line 2432 of file imap.c.