NeoMutt  2018-07-16 +2481-68dcde
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 <time.h>
#include "imap_private.h"
#include "mutt/mutt.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "conn/conn.h"
#include "mutt.h"
#include "imap.h"
#include "auth.h"
#include "commands.h"
#include "curs_lib.h"
#include "globals.h"
#include "hook.h"
#include "message.h"
#include "mutt_account.h"
#include "mutt_logging.h"
#include "mutt_socket.h"
#include "muttlib.h"
#include "mx.h"
#include "pattern.h"
#include "progress.h"
#include "sort.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 int do_search (const struct PatternList *search, bool allpats)
 Perform a search of messages. More...
 
static int compile_search (struct Mailbox *m, const struct PatternList *pat, struct Buffer *buf)
 Convert NeoMutt pattern to IMAP search. 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...
 
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_search (struct Mailbox *m, const struct PatternList *pat)
 Find a matching mailbox. More...
 
int imap_subscribe (char *path, bool subscribe)
 Subscribe to a mailbox. More...
 
int imap_complete (char *buf, size_t buflen, 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...
 
struct Accountimap_ac_find (struct Account *a, const char *path)
 Find an Account that matches a Mailbox path - Implements MxOps::ac_find() More...
 
int imap_ac_add (struct Account *a, struct Mailbox *m)
 Add a Mailbox to an Account - Implements MxOps::ac_add() 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, int *index_hint)
 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...
 
int imap_path_pretty (char *buf, size_t buflen, const char *folder)
 Abbreviate a Mailbox path - Implements MxOps::path_pretty() More...
 
int imap_path_parent (char *buf, size_t buflen)
 Find the parent of a Mailbox path - Implements MxOps::path_parent() More...
 

Variables

bool C_ImapIdle
 Config: (imap) Use the IMAP IDLE extension to check for new mail. More...
 
bool C_ImapRfc5161
 Config: (imap) Use the IMAP ENABLE extension to select capabilities. More...
 
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 77 of file imap.c.

78 {
79  if (imap_exec(adata, "CAPABILITY", IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS)
80  {
81  imap_error("check_capabilities", adata->buf);
82  return -1;
83  }
84 
85  if (!((adata->capabilities & IMAP_CAP_IMAP4) || (adata->capabilities & IMAP_CAP_IMAP4REV1)))
86  {
87  mutt_error(
88  _("This IMAP server is ancient. NeoMutt does not work with it."));
89  return -1;
90  }
91 
92  return 0;
93 }
#define _(a)
Definition: message.h:28
Imap command executed or queued successfully.
Definition: imap_private.h:81
#define IMAP_CAP_IMAP4REV1
Server supports IMAP4rev1.
Definition: imap_private.h:121
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:1242
void imap_error(const char *where, const char *msg)
show an error and abort
Definition: util.c:760
ImapCapFlags capabilities
Definition: imap_private.h:183
#define mutt_error(...)
Definition: logging.h:84
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: imap_private.h:71
#define IMAP_CAP_IMAP4
Server supports IMAP4.
Definition: imap_private.h:120
+ 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
ptrNULL Failure

return stream following FLAGS response

Definition at line 104 of file imap.c.

105 {
106  /* sanity-check string */
107  const size_t plen = mutt_str_startswith(s, "FLAGS", CASE_IGNORE);
108  if (plen == 0)
109  {
110  mutt_debug(LL_DEBUG1, "not a FLAGS response: %s\n", s);
111  return NULL;
112  }
113  s += plen;
114  SKIPWS(s);
115  if (*s != '(')
116  {
117  mutt_debug(LL_DEBUG1, "bogus FLAGS response: %s\n", s);
118  return NULL;
119  }
120 
121  /* update caller's flags handle */
122  while (*s && (*s != ')'))
123  {
124  s++;
125  SKIPWS(s);
126  const char *flag_word = s;
127  while (*s && (*s != ')') && !IS_SPACE(*s))
128  s++;
129  const char ctmp = *s;
130  *s = '\0';
131  if (*flag_word)
132  mutt_list_insert_tail(hflags, mutt_str_strdup(flag_word));
133  *s = ctmp;
134  }
135 
136  /* note bad flags response */
137  if (*s != ')')
138  {
139  mutt_debug(LL_DEBUG1, "Unterminated FLAGS response: %s\n", s);
140  mutt_list_free(hflags);
141 
142  return NULL;
143  }
144 
145  s++;
146 
147  return s;
148 }
static size_t plen
Length of cached packet.
Definition: pgppacket.c:38
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:123
#define SKIPWS(ch)
Definition: string2.h:47
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:65
Ignore case when comparing strings.
Definition: string2.h:68
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
#define IS_SPACE(ch)
Definition: string2.h:38
Log at debug level 1.
Definition: logging.h:56
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#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 159 of file imap.c.

161 {
162  if (m->rights & aclflag)
163  if (flag && imap_has_flag(&imap_mdata_get(m)->flags, str))
164  mutt_str_strcat(flags, flsize, str);
165 }
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: util.c:242
bool imap_has_flag(struct ListHead *flag_list, const char *flag)
Does the flag exist in the list.
Definition: imap.c:963
struct ListHead flags
Definition: imap_private.h:224
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:132
char * mutt_str_strcat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
Definition: string.c:395
+ 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 180 of file imap.c.

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

278 {
279  struct ImapEmailData *edata = e->edata;
280 
281  if (e->read != edata->read)
282  return true;
283  if (e->old != edata->old)
284  return true;
285  if (e->flagged != edata->flagged)
286  return true;
287  if (e->replied != edata->replied)
288  return true;
289 
290  return false;
291 }
bool flagged
Definition: message.h:39
bool read
Email is read.
Definition: email.h:53
bool old
Email is seen, but unread.
Definition: email.h:52
bool replied
Definition: message.h:40
bool old
Definition: message.h:37
bool flagged
Marked important?
Definition: email.h:45
void * edata
Driver-specific data.
Definition: email.h:112
bool replied
Email has been replied to.
Definition: email.h:56
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 302 of file imap.c.

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

◆ do_search()

static int do_search ( const struct PatternList *  search,
bool  allpats 
)
static

Perform a search of messages.

Parameters
searchList of pattern to match
allpatsMust all patterns match?
Return values
numNumber of patterns search that should be done server-side

Count the number of patterns that can be done by the server (are full-text).

Definition at line 340 of file imap.c.

341 {
342  int rc = 0;
343  const struct Pattern *pat = NULL;
344 
345  SLIST_FOREACH(pat, search, entries)
346  {
347  switch (pat->op)
348  {
349  case MUTT_PAT_BODY:
350  case MUTT_PAT_HEADER:
351  case MUTT_PAT_WHOLE_MSG:
352  if (pat->string_match)
353  rc++;
354  break;
356  rc++;
357  break;
358  default:
359  if (pat->child && do_search(pat->child, true))
360  rc++;
361  }
362 
363  if (!allpats)
364  break;
365  }
366 
367  return rc;
368 }
struct PatternList * child
Arguments to logical operation.
Definition: pattern.h:62
Pattern matches email&#39;s header.
Definition: pattern.h:124
A simple (non-regex) pattern.
Definition: pattern.h:49
bool string_match
Check a string for a match.
Definition: pattern.h:54
Server-side pattern matches.
Definition: pattern.h:143
short op
Operation, e.g. MUTT_PAT_SCORE.
Definition: pattern.h:51
Pattern matches email&#39;s body.
Definition: pattern.h:123
static int do_search(const struct PatternList *search, bool allpats)
Perform a search of messages.
Definition: imap.c:340
#define SLIST_FOREACH(var, head, field)
Definition: queue.h:231
Pattern matches raw email text.
Definition: pattern.h:126
+ Here is the caller graph for this function:

◆ compile_search()

static int compile_search ( struct Mailbox m,
const struct PatternList *  pat,
struct Buffer buf 
)
static

Convert NeoMutt pattern to IMAP search.

Parameters
mMailbox
patPattern to convert
bufBuffer for result
Return values
0Success
-1Failure

Convert neomutt Pattern to IMAP SEARCH command containing only elements that require full-text search (neomutt already has what it needs for most match types, and does a better job (eg server doesn't support regexes).

Definition at line 382 of file imap.c.

383 {
384  struct Pattern *firstpat = SLIST_FIRST(pat);
385 
386  if (do_search(pat, false) == 0)
387  return 0;
388 
389  if (firstpat->pat_not)
390  mutt_buffer_addstr(buf, "NOT ");
391 
392  if (firstpat->child)
393  {
394  int clauses;
395 
396  clauses = do_search(firstpat->child, true);
397  if (clauses > 0)
398  {
399  mutt_buffer_addch(buf, '(');
400 
401  while (clauses)
402  {
403  if (do_search(firstpat->child, false))
404  {
405  if ((firstpat->op == MUTT_PAT_OR) && (clauses > 1))
406  mutt_buffer_addstr(buf, "OR ");
407  clauses--;
408 
409  if (compile_search(m, firstpat->child, buf) < 0)
410  return -1;
411 
412  if (clauses)
413  mutt_buffer_addch(buf, ' ');
414  }
415 
416  SLIST_REMOVE_HEAD(firstpat->child, entries);
417  }
418 
419  mutt_buffer_addch(buf, ')');
420  }
421  }
422  else
423  {
424  char term[256];
425  char *delim = NULL;
426 
427  switch (firstpat->op)
428  {
429  case MUTT_PAT_HEADER:
430  mutt_buffer_addstr(buf, "HEADER ");
431 
432  /* extract header name */
433  delim = strchr(firstpat->p.str, ':');
434  if (!delim)
435  {
436  mutt_error(_("Header search without header name: %s"), firstpat->p.str);
437  return -1;
438  }
439  *delim = '\0';
440  imap_quote_string(term, sizeof(term), firstpat->p.str, false);
441  mutt_buffer_addstr(buf, term);
442  mutt_buffer_addch(buf, ' ');
443 
444  /* and field */
445  *delim = ':';
446  delim++;
447  SKIPWS(delim);
448  imap_quote_string(term, sizeof(term), delim, false);
449  mutt_buffer_addstr(buf, term);
450  break;
451  case MUTT_PAT_BODY:
452  mutt_buffer_addstr(buf, "BODY ");
453  imap_quote_string(term, sizeof(term), firstpat->p.str, false);
454  mutt_buffer_addstr(buf, term);
455  break;
456  case MUTT_PAT_WHOLE_MSG:
457  mutt_buffer_addstr(buf, "TEXT ");
458  imap_quote_string(term, sizeof(term), firstpat->p.str, false);
459  mutt_buffer_addstr(buf, term);
460  break;
462  {
463  struct ImapAccountData *adata = imap_adata_get(m);
464  if (!(adata->capabilities & IMAP_CAP_X_GM_EXT_1))
465  {
466  mutt_error(_("Server-side custom search not supported: %s"),
467  firstpat->p.str);
468  return -1;
469  }
470  }
471  mutt_buffer_addstr(buf, "X-GM-RAW ");
472  imap_quote_string(term, sizeof(term), firstpat->p.str, false);
473  mutt_buffer_addstr(buf, term);
474  break;
475  }
476  }
477 
478  return 0;
479 }
struct PatternList * child
Arguments to logical operation.
Definition: pattern.h:62
Pattern matches email&#39;s header.
Definition: pattern.h:124
void imap_quote_string(char *dest, size_t dlen, const char *src, bool quote_backtick)
quote string according to IMAP rules
Definition: util.c:945
#define _(a)
Definition: message.h:28
#define SLIST_REMOVE_HEAD(head, field)
Definition: queue.h:291
A simple (non-regex) pattern.
Definition: pattern.h:49
#define SKIPWS(ch)
Definition: string2.h:47
bool pat_not
Pattern should be inverted (not)
Definition: pattern.h:52
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
Server-side pattern matches.
Definition: pattern.h:143
#define SLIST_FIRST(head)
Definition: queue.h:229
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
Either pattern can match.
Definition: pattern.h:107
static int compile_search(struct Mailbox *m, const struct PatternList *pat, struct Buffer *buf)
Convert NeoMutt pattern to IMAP search.
Definition: imap.c:382
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:114
short op
Operation, e.g. MUTT_PAT_SCORE.
Definition: pattern.h:51
ImapCapFlags capabilities
Definition: imap_private.h:183
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
IMAP-specific Account data -.
Definition: imap_private.h:166
Pattern matches email&#39;s body.
Definition: pattern.h:123
union Pattern::@2 p
static int do_search(const struct PatternList *search, bool allpats)
Perform a search of messages.
Definition: imap.c:340
char * str
String, if string_match is set.
Definition: pattern.h:66
#define mutt_error(...)
Definition: logging.h:84
#define IMAP_CAP_X_GM_EXT_1
https://developers.google.com/gmail/imap/imap-extensions
Definition: imap_private.h:137
Pattern matches raw email text.
Definition: pattern.h:126
+ 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 491 of file imap.c.

492 {
493  size_t pos = start;
494 
495  while ((pos < dlen) && dest[pos] && (dest[pos] == src[pos]))
496  pos++;
497  dest[pos] = '\0';
498 
499  return pos;
500 }
+ 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 512 of file imap.c.

513 {
514  // struct Connection *conn = NULL;
515  int rc = -1;
516  size_t matchlen;
517 
518  matchlen = mutt_str_strlen(buf);
519  struct MailboxList ml = neomutt_mailboxlist_get_all(NeoMutt, MUTT_MAILBOX_ANY);
520  struct MailboxNode *np = NULL;
521  STAILQ_FOREACH(np, &ml, entries)
522  {
524  continue;
525 
526  if (rc)
527  {
528  mutt_str_strfcpy(buf, mailbox_path(np->mailbox), buflen);
529  rc = 0;
530  }
531  else
532  longest_common_prefix(buf, mailbox_path(np->mailbox), matchlen, buflen);
533  }
535 
536 #if 0
537  TAILQ_FOREACH(conn, mutt_socket_head(), entries)
538  {
539  struct Url url;
540  char urlstr[1024];
541 
542  if (conn->account.type != MUTT_ACCT_TYPE_IMAP)
543  continue;
544 
545  mutt_account_tourl(&conn->account, &url);
546  /* FIXME: how to handle multiple users on the same host? */
547  url.user = NULL;
548  url.path = NULL;
549  url_tostring(&url, urlstr, sizeof(urlstr), 0);
550  if (mutt_str_strncmp(buf, urlstr, matchlen) == 0)
551  {
552  if (rc)
553  {
554  mutt_str_strfcpy(buf, urlstr, buflen);
555  rc = 0;
556  }
557  else
558  longest_common_prefix(buf, urlstr, matchlen, buflen);
559  }
560  }
561 #endif
562 
563  return rc;
564 }
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:194
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
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:134
Match any Mailbox type.
Definition: mailbox.h:44
Match case when comparing strings.
Definition: string2.h:67
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
int url_tostring(struct Url *u, char *dest, size_t len, int flags)
Output the URL string for a given Url object.
Definition: url.c:399
Container for Accounts, Notifications.
Definition: neomutt.h:35
struct MailboxList neomutt_mailboxlist_get_all(struct NeoMutt *n, enum MailboxType magic)
Get a List of all Mailboxes.
Definition: neomutt.c:156
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
Imap Account.
Definition: mutt_account.h:52
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
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:491
int mutt_str_strncmp(const char *a, const char *b, size_t l)
Compare two strings (to a maximum), safely.
Definition: string.c:642
void mutt_account_tourl(struct ConnAccount *account, struct Url *url)
Fill URL with info from account.
Definition: mutt_account.c:145
List of Mailboxes.
Definition: mailbox.h:156
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:158
+ 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 573 of file imap.c.

574 {
575  char buf[2048], mbox[1024];
576 
577  imap_munge_mbox_name(adata->unicode, mbox, sizeof(mbox), mailbox);
578  snprintf(buf, sizeof(buf), "CREATE %s", mbox);
579 
580  if (imap_exec(adata, buf, IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS)
581  {
582  mutt_error(_("CREATE failed: %s"), imap_cmd_trailer(adata));
583  return -1;
584  }
585 
586  return 0;
587 }
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:1019
#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:1204
Imap command executed or queued successfully.
Definition: imap_private.h:81
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:1242
#define mutt_error(...)
Definition: logging.h:84
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: imap_private.h:71
+ 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 599 of file imap.c.

600 {
601  if (imap_path_status(path, false) >= 0)
602  return 0;
603  else
604  return -1;
605 }
int imap_path_status(const char *path, bool queue)
Refresh the number of total and new messages.
Definition: imap.c:1309
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 615 of file imap.c.

616 {
617  char oldmbox[1024];
618  char newmbox[1024];
619  int rc = 0;
620 
621  imap_munge_mbox_name(adata->unicode, oldmbox, sizeof(oldmbox), oldname);
622  imap_munge_mbox_name(adata->unicode, newmbox, sizeof(newmbox), newname);
623 
624  struct Buffer *buf = mutt_buffer_pool_get();
625  mutt_buffer_printf(buf, "RENAME %s %s", oldmbox, newmbox);
626 
628  rc = -1;
629 
631 
632  return rc;
633 }
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:100
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:1019
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:111
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: imap_private.h:81
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:1242
#define mutt_b2s(buf)
Definition: buffer.h:41
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: imap_private.h:71
+ 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 642 of file imap.c.

643 {
644  char buf[PATH_MAX + 7];
645  char mbox[PATH_MAX];
646  struct Url *url = url_parse(path);
647 
648  struct ImapAccountData *adata = imap_adata_get(m);
649  imap_munge_mbox_name(adata->unicode, mbox, sizeof(mbox), url->path);
650  url_free(&url);
651  snprintf(buf, sizeof(buf), "DELETE %s", mbox);
653  return -1;
654 
655  return 0;
656 }
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:1019
Imap command executed or queued successfully.
Definition: imap_private.h:81
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:1242
#define PATH_MAX
Definition: mutt.h:52
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:114
char * path
Path.
Definition: url.h:73
IMAP-specific Account data -.
Definition: imap_private.h:166
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:142
void url_free(struct Url **u)
Free the contents of a URL.
Definition: url.c:288
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: imap_private.h:71
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:161
+ 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 662 of file imap.c.

663 {
664  /* we set status here to let imap_handle_untagged know we _expect_ to
665  * receive a bye response (so it doesn't freak out and close the conn) */
666  if (adata->state == IMAP_DISCONNECTED)
667  {
668  return;
669  }
670 
671  adata->status = IMAP_BYE;
672  imap_cmd_start(adata, "LOGOUT");
673  if ((C_ImapPollTimeout <= 0) || (mutt_socket_poll(adata->conn, C_ImapPollTimeout) != 0))
674  {
675  while (imap_cmd_step(adata) == IMAP_RES_CONTINUE)
676  ;
677  }
678  mutt_socket_close(adata->conn);
679  adata->state = IMAP_DISCONNECTED;
680 }
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1072
WHERE short C_ImapPollTimeout
Config: (imap) Maximum time to wait for a server response.
Definition: globals.h:164
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: imap_private.h:172
int imap_cmd_start(struct ImapAccountData *adata, const char *cmdstr)
Given an IMAP command, send it to the server.
Definition: command.c:1058
int mutt_socket_poll(struct Connection *conn, time_t wait_secs)
Checks whether reads would block.
Definition: socket.c:188
unsigned char status
ImapFlags, e.g. IMAP_FATAL.
Definition: imap_private.h:173
int mutt_socket_close(struct Connection *conn)
Close a socket.
Definition: socket.c:95
#define IMAP_RES_CONTINUE
* ...
Definition: imap_private.h:55
Logged out from server.
Definition: imap_private.h:95
Disconnected from server.
Definition: imap_private.h:104
struct Connection * conn
Definition: imap_private.h:168
+ 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 687 of file imap.c.

688 {
689  struct Account *np = NULL;
690  TAILQ_FOREACH(np, &NeoMutt->accounts, entries)
691  {
692  if (np->magic != MUTT_IMAP)
693  continue;
694 
695  struct ImapAccountData *adata = np->adata;
696  if (!adata)
697  continue;
698 
699  struct Connection *conn = adata->conn;
700  if (!conn || (conn->fd < 0))
701  continue;
702 
703  mutt_message(_("Closing connection to %s..."), conn->account.host);
704  imap_logout(np->adata);
706  }
707 }
struct ConnAccount account
Definition: connection.h:36
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
#define mutt_message(...)
Definition: logging.h:83
struct AccountList accounts
List of all Accounts.
Definition: neomutt.h:39
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:662
#define _(a)
Definition: message.h:28
Container for Accounts, Notifications.
Definition: neomutt.h:35
char host[128]
Definition: connaccount.h:36
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:109
enum MailboxType magic
Type of Mailboxes this Account contains.
Definition: account.h:38
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
IMAP-specific Account data -.
Definition: imap_private.h:166
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:52
struct Connection * conn
Definition: imap_private.h:168
+ 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 723 of file imap.c.

725 {
726  char c;
727  bool r = false;
728  struct Buffer buf = { 0 }; // Do not allocate, maybe it won't be used
729 
731  mutt_buffer_alloc(&buf, bytes + 10);
732 
733  mutt_debug(LL_DEBUG2, "reading %ld bytes\n", bytes);
734 
735  for (unsigned long pos = 0; pos < bytes; pos++)
736  {
737  if (mutt_socket_readchar(adata->conn, &c) != 1)
738  {
739  mutt_debug(LL_DEBUG1, "error during read, %ld bytes read\n", pos);
740  adata->status = IMAP_FATAL;
741 
742  mutt_buffer_dealloc(&buf);
743  return -1;
744  }
745 
746  if (r && (c != '\n'))
747  fputc('\r', fp);
748 
749  if (c == '\r')
750  {
751  r = true;
752  continue;
753  }
754  else
755  r = false;
756 
757  fputc(c, fp);
758 
759  if (pbar && !(pos % 1024))
760  mutt_progress_update(pbar, pos, -1);
762  mutt_buffer_addch(&buf, c);
763  }
764 
766  {
767  mutt_debug(IMAP_LOG_LTRL, "\n%s", buf.data);
768  mutt_buffer_dealloc(&buf);
769  }
770  return 0;
771 }
#define IMAP_LOG_LTRL
Definition: imap_private.h:48
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:206
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:57
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:293
short C_DebugLevel
Config: Logging level for debug logs.
Definition: mutt_logging.c:48
unsigned char status
ImapFlags, e.g. IMAP_FATAL.
Definition: imap_private.h:173
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:56
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Unrecoverable error occurred.
Definition: imap_private.h:94
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: imap_private.h:168
+ 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 781 of file imap.c.

782 {
783  struct ImapAccountData *adata = imap_adata_get(m);
784  struct ImapMboxData *mdata = imap_mdata_get(m);
785  if (!adata || !mdata)
786  return;
787 
788  struct Email *e = NULL;
789 
790 #ifdef USE_HCACHE
791  mdata->hcache = imap_hcache_open(adata, mdata);
792 #endif
793 
794  for (int i = 0; i < m->msg_count; i++)
795  {
796  e = m->emails[i];
797 
798  if (e->index == INT_MAX)
799  {
800  mutt_debug(LL_DEBUG2, "Expunging message UID %u\n", imap_edata_get(e)->uid);
801 
802  e->deleted = true;
803 
804  imap_cache_del(m, e);
805 #ifdef USE_HCACHE
806  imap_hcache_del(mdata, imap_edata_get(e)->uid);
807 #endif
808 
809  mutt_hash_int_delete(mdata->uid_hash, imap_edata_get(e)->uid, e);
810 
811  imap_edata_free((void **) &e->edata);
812  }
813  else
814  {
815  e->index = i;
816  /* NeoMutt has several places where it turns off e->active as a
817  * hack. For example to avoid FLAG updates, or to exclude from
818  * imap_exec_msgset.
819  *
820  * Unfortunately, when a reopen is allowed and the IMAP_EXPUNGE_PENDING
821  * flag becomes set (e.g. a flag update to a modified header),
822  * this function will be called by imap_cmd_finish().
823  *
824  * The ctx_update_tables() will free and remove these "inactive" headers,
825  * despite that an EXPUNGE was not received for them.
826  * This would result in memory leaks and segfaults due to dangling
827  * pointers in the msn_index and uid_hash.
828  *
829  * So this is another hack to work around the hacks. We don't want to
830  * remove the messages, so make sure active is on.
831  */
832  e->active = true;
833  }
834  }
835 
836 #ifdef USE_HCACHE
837  imap_hcache_close(mdata);
838 #endif
839 
842 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
header_cache_t * imap_hcache_open(struct ImapAccountData *adata, struct ImapMboxData *mdata)
Open a header cache.
Definition: util.c:415
int msg_count
Total number of messages.
Definition: mailbox.h:102
The envelope/body of an email.
Definition: email.h:39
void mailbox_changed(struct Mailbox *m, enum MailboxNotification action)
Notify observers of a change to a Mailbox.
Definition: mailbox.c:160
struct ImapEmailData * imap_edata_get(struct Email *e)
Get the private data for this Email.
Definition: message.c:98
void imap_edata_free(void **ptr)
free ImapHeader structure
Definition: message.c:73
int imap_hcache_del(struct ImapMboxData *mdata, unsigned int uid)
Delete an item from the header cache.
Definition: util.c:507
Update internal tables.
Definition: mailbox.h:66
header_cache_t * hcache
Definition: imap_private.h:239
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: util.c:242
Log at debug level 2.
Definition: logging.h:57
void imap_hcache_close(struct ImapMboxData *mdata)
Close the header cache.
Definition: util.c:443
void * mdata
Driver specific data.
Definition: mailbox.h:147
bool active
Message is not to be removed.
Definition: email.h:61
struct Hash * uid_hash
Definition: imap_private.h:233
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
Email list needs resorting.
Definition: mailbox.h:65
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:114
IMAP-specific Account data -.
Definition: imap_private.h:166
IMAP-specific Mailbox data -.
Definition: imap_private.h:213
bool deleted
Email is deleted.
Definition: email.h:47
void * edata
Driver-specific data.
Definition: email.h:112
int index
The absolute (unsorted) message number.
Definition: email.h:87
void mutt_hash_int_delete(struct Hash *table, unsigned int intkey, const void *data)
Remove an element from a Hash table.
Definition: hash.c:459
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
int imap_cache_del(struct Mailbox *m, struct Email *e)
Delete an email from the body cache.
Definition: message.c:1748
+ 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 850 of file imap.c.

851 {
852  if (mutt_socket_open(adata->conn) < 0)
853  return -1;
854 
855  adata->state = IMAP_CONNECTED;
856 
857  if (imap_cmd_step(adata) != IMAP_RES_OK)
858  {
859  imap_close_connection(adata);
860  return -1;
861  }
862 
863  if (mutt_str_startswith(adata->buf, "* OK", CASE_IGNORE))
864  {
865  if (!mutt_str_startswith(adata->buf, "* OK [CAPABILITY", CASE_IGNORE) &&
866  check_capabilities(adata))
867  {
868  goto bail;
869  }
870 #ifdef USE_SSL
871  /* Attempt STARTTLS if available and desired. */
872  if (!adata->conn->ssf && (C_SslForceTls || (adata->capabilities & IMAP_CAP_STARTTLS)))
873  {
874  enum QuadOption ans;
875 
876  if (C_SslForceTls)
877  ans = MUTT_YES;
878  else if ((ans = query_quadoption(C_SslStarttls,
879  _("Secure connection with TLS?"))) == MUTT_ABORT)
880  {
881  goto err_close_conn;
882  }
883  if (ans == MUTT_YES)
884  {
885  enum ImapExecResult rc = imap_exec(adata, "STARTTLS", IMAP_CMD_NO_FLAGS);
886  if (rc == IMAP_EXEC_FATAL)
887  goto bail;
888  if (rc != IMAP_EXEC_ERROR)
889  {
890  if (mutt_ssl_starttls(adata->conn))
891  {
892  mutt_error(_("Could not negotiate TLS connection"));
893  goto err_close_conn;
894  }
895  else
896  {
897  /* RFC2595 demands we recheck CAPABILITY after TLS completes. */
898  if (imap_exec(adata, "CAPABILITY", IMAP_CMD_NO_FLAGS))
899  goto bail;
900  }
901  }
902  }
903  }
904 
905  if (C_SslForceTls && !adata->conn->ssf)
906  {
907  mutt_error(_("Encrypted connection unavailable"));
908  goto err_close_conn;
909  }
910 #endif
911  }
912  else if (mutt_str_startswith(adata->buf, "* PREAUTH", CASE_IGNORE))
913  {
914  adata->state = IMAP_AUTHENTICATED;
915  if (check_capabilities(adata) != 0)
916  goto bail;
917  FREE(&adata->capstr);
918  }
919  else
920  {
921  imap_error("imap_open_connection()", adata->buf);
922  goto bail;
923  }
924 
925  return 0;
926 
927 #ifdef USE_SSL
928 err_close_conn:
929  imap_close_connection(adata);
930 #endif
931 bail:
932  FREE(&adata->capstr);
933  return -1;
934 }
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1072
unsigned int ssf
security strength factor, in bits
Definition: connection.h:37
ImapExecResult
imap_exec return code
Definition: imap_private.h:79
User aborted the question (with Ctrl-G)
Definition: quad.h:37
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: init.c:3331
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: imap_private.h:172
#define _(a)
Definition: message.h:28
void imap_close_connection(struct ImapAccountData *adata)
Close an IMAP connection.
Definition: imap.c:940
WHERE bool C_SslForceTls
Config: (ssl) Require TLS encryption for all connections.
Definition: globals.h:241
int mutt_socket_open(struct Connection *conn)
Simple wrapper.
Definition: socket.c:74
#define IMAP_CAP_STARTTLS
RFC2595: STARTTLS.
Definition: imap_private.h:129
int mutt_ssl_starttls(struct Connection *conn)
Negotiate TLS over an already opened connection.
Definition: ssl.c:1444
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:1242
void imap_error(const char *where, const char *msg)
show an error and abort
Definition: util.c:760
Connection is authenticated.
Definition: imap_private.h:106
Imap connection failure.
Definition: imap_private.h:83
Ignore case when comparing strings.
Definition: string2.h:68
ImapCapFlags capabilities
Definition: imap_private.h:183
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
#define mutt_error(...)
Definition: logging.h:84
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: imap_private.h:71
#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:77
Connected to server.
Definition: imap_private.h:105
QuadOption
Possible values for a quad-option.
Definition: quad.h:35
WHERE unsigned char C_SslStarttls
Config: (ssl) Use STARTTLS on servers advertising the capability.
Definition: globals.h:193
struct Connection * conn
Definition: imap_private.h:168
#define IMAP_RES_OK
<tag> OK ...
Definition: imap_private.h:54
Imap command failure.
Definition: imap_private.h:82
+ 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 940 of file imap.c.

941 {
942  if (adata->state != IMAP_DISCONNECTED)
943  {
944  mutt_socket_close(adata->conn);
945  adata->state = IMAP_DISCONNECTED;
946  }
947  adata->seqno = false;
948  adata->nextcmd = false;
949  adata->lastcmd = false;
950  adata->status = 0;
951  memset(adata->cmds, 0, sizeof(struct ImapCommand) * adata->cmdslots);
952 }
struct ImapCommand * cmds
Definition: imap_private.h:198
unsigned int seqno
tag sequence number, e.g. &#39;{seqid}0001&#39;
Definition: imap_private.h:185
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: imap_private.h:172
IMAP command structure.
Definition: imap_private.h:155
unsigned char status
ImapFlags, e.g. IMAP_FATAL.
Definition: imap_private.h:173
int mutt_socket_close(struct Connection *conn)
Close a socket.
Definition: socket.c:95
Disconnected from server.
Definition: imap_private.h:104
struct Connection * conn
Definition: imap_private.h:168
+ 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 '*'.

Definition at line 963 of file imap.c.

964 {
965  if (STAILQ_EMPTY(flag_list))
966  return false;
967 
968  struct ListNode *np = NULL;
969  STAILQ_FOREACH(np, flag_list, entries)
970  {
971  if (mutt_str_strcasecmp(np->data, flag) == 0)
972  return true;
973 
974  if (mutt_str_strcmp(np->data, "\\*") == 0)
975  return true;
976  }
977 
978  return false;
979 }
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
char * data
String.
Definition: list.h:35
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
#define STAILQ_EMPTY(head)
Definition: queue.h:346
A List node for strings.
Definition: list.h:33
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
+ 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 984 of file imap.c.

985 {
986  const struct Email *ea = *(struct Email const *const *) a;
987  const struct Email *eb = *(struct Email const *const *) b;
988  return imap_edata_get((struct Email *) ea)->uid -
989  imap_edata_get((struct Email *) eb)->uid;
990 }
The envelope/body of an email.
Definition: email.h:39
struct ImapEmailData * imap_edata_get(struct Email *e)
Get the private data for this Email.
Definition: message.c:98
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 1007 of file imap.c.

1009 {
1010  struct ImapAccountData *adata = imap_adata_get(m);
1011  if (!adata || (adata->mailbox != m))
1012  return -1;
1013 
1014  struct Email **emails = NULL;
1015  short oldsort;
1016  int pos;
1017  int rc;
1018  int count = 0;
1019 
1020  struct Buffer cmd = mutt_buffer_make(0);
1021 
1022  /* We make a copy of the headers just in case resorting doesn't give
1023  exactly the original order (duplicate messages?), because other parts of
1024  the ctx are tied to the header order. This may be overkill. */
1025  oldsort = C_Sort;
1026  if (C_Sort != SORT_ORDER)
1027  {
1028  emails = m->emails;
1029  m->emails = mutt_mem_malloc(m->msg_count * sizeof(struct Email *));
1030  memcpy(m->emails, emails, m->msg_count * sizeof(struct Email *));
1031 
1032  C_Sort = SORT_ORDER;
1033  qsort(m->emails, m->msg_count, sizeof(struct Email *), compare_uid);
1034  }
1035 
1036  pos = 0;
1037 
1038  do
1039  {
1040  mutt_buffer_reset(&cmd);
1041  mutt_buffer_add_printf(&cmd, "%s ", pre);
1042  rc = make_msg_set(m, &cmd, flag, changed, invert, &pos);
1043  if (rc > 0)
1044  {
1045  mutt_buffer_add_printf(&cmd, " %s", post);
1046  if (imap_exec(adata, cmd.data, IMAP_CMD_QUEUE) != IMAP_EXEC_SUCCESS)
1047  {
1048  rc = -1;
1049  goto out;
1050  }
1051  count += rc;
1052  }
1053  } while (rc > 0);
1054 
1055  rc = count;
1056 
1057 out:
1058  mutt_buffer_dealloc(&cmd);
1059  if (oldsort != C_Sort)
1060  {
1061  C_Sort = oldsort;
1062  FREE(&m->emails);
1063  m->emails = emails;
1064  }
1065 
1066  return rc;
1067 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
int msg_count
Total number of messages.
Definition: mailbox.h:102
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
The envelope/body of an email.
Definition: email.h:39
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:180
struct Mailbox * mailbox
Definition: imap_private.h:205
Imap command executed or queued successfully.
Definition: imap_private.h:81
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:293
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:1242
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
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:114
IMAP-specific Account data -.
Definition: imap_private.h:166
#define IMAP_CMD_QUEUE
Queue a command, do not execute.
Definition: imap_private.h:73
#define FREE(x)
Definition: memory.h:40
static int compare_uid(const void *a, const void *b)
Compare two Emails by UID - Implements sort_t.
Definition: imap.c:984
Sort by the order the messages appear in the mailbox.
Definition: sort.h:55
+ 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 1084 of file imap.c.

1086 {
1087  struct ImapAccountData *adata = imap_adata_get(m);
1088  if (!adata || (adata->mailbox != m))
1089  return -1;
1090 
1091  char flags[1024];
1092  char *tags = NULL;
1093  char uid[11];
1094 
1095  if (!compare_flags_for_copy(e))
1096  {
1097  if (e->deleted == imap_edata_get(e)->deleted)
1098  e->changed = false;
1099  return 0;
1100  }
1101 
1102  snprintf(uid, sizeof(uid), "%u", imap_edata_get(e)->uid);
1103  mutt_buffer_reset(cmd);
1104  mutt_buffer_addstr(cmd, "UID STORE ");
1105  mutt_buffer_addstr(cmd, uid);
1106 
1107  flags[0] = '\0';
1108 
1109  set_flag(m, MUTT_ACL_SEEN, e->read, "\\Seen ", flags, sizeof(flags));
1110  set_flag(m, MUTT_ACL_WRITE, e->old, "Old ", flags, sizeof(flags));
1111  set_flag(m, MUTT_ACL_WRITE, e->flagged, "\\Flagged ", flags, sizeof(flags));
1112  set_flag(m, MUTT_ACL_WRITE, e->replied, "\\Answered ", flags, sizeof(flags));
1113  set_flag(m, MUTT_ACL_DELETE, imap_edata_get(e)->deleted, "\\Deleted ", flags,
1114  sizeof(flags));
1115 
1116  if (m->rights & MUTT_ACL_WRITE)
1117  {
1118  /* restore system flags */
1119  if (imap_edata_get(e)->flags_system)
1120  mutt_str_strcat(flags, sizeof(flags), imap_edata_get(e)->flags_system);
1121  /* set custom flags */
1122  tags = driver_tags_get_with_hidden(&e->tags);
1123  if (tags)
1124  {
1125  mutt_str_strcat(flags, sizeof(flags), tags);
1126  FREE(&tags);
1127  }
1128  }
1129 
1131 
1132  /* UW-IMAP is OK with null flags, Cyrus isn't. The only solution is to
1133  * explicitly revoke all system flags (if we have permission) */
1134  if (!*flags)
1135  {
1136  set_flag(m, MUTT_ACL_SEEN, 1, "\\Seen ", flags, sizeof(flags));
1137  set_flag(m, MUTT_ACL_WRITE, 1, "Old ", flags, sizeof(flags));
1138  set_flag(m, MUTT_ACL_WRITE, 1, "\\Flagged ", flags, sizeof(flags));
1139  set_flag(m, MUTT_ACL_WRITE, 1, "\\Answered ", flags, sizeof(flags));
1140  set_flag(m, MUTT_ACL_DELETE, !imap_edata_get(e)->deleted, "\\Deleted ",
1141  flags, sizeof(flags));
1142 
1143  /* erase custom flags */
1144  if ((m->rights & MUTT_ACL_WRITE) && imap_edata_get(e)->flags_remote)
1145  mutt_str_strcat(flags, sizeof(flags), imap_edata_get(e)->flags_remote);
1146 
1148 
1149  mutt_buffer_addstr(cmd, " -FLAGS.SILENT (");
1150  }
1151  else
1152  mutt_buffer_addstr(cmd, " FLAGS.SILENT (");
1153 
1154  mutt_buffer_addstr(cmd, flags);
1155  mutt_buffer_addstr(cmd, ")");
1156 
1157  /* after all this it's still possible to have no flags, if you
1158  * have no ACL rights */
1159  if (*flags && (imap_exec(adata, cmd->data, IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS) &&
1160  err_continue && (*err_continue != MUTT_YES))
1161  {
1162  *err_continue = imap_continue("imap_sync_message: STORE failed", adata->buf);
1163  if (*err_continue != MUTT_YES)
1164  return -1;
1165  }
1166 
1167  /* server have now the updated flags */
1168  FREE(&imap_edata_get(e)->flags_remote);
1170 
1171  if (e->deleted == imap_edata_get(e)->deleted)
1172  e->changed = false;
1173 
1174  return 0;
1175 }
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
struct ImapEmailData * imap_edata_get(struct Email *e)
Get the private data for this Email.
Definition: message.c:98
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
struct Mailbox * mailbox
Definition: imap_private.h:205
bool changed
Email has been edited.
Definition: email.h:50
#define MUTT_ACL_DELETE
Delete a message.
Definition: mailbox.h:77
Imap command executed or queued successfully.
Definition: imap_private.h:81
bool read
Email is read.
Definition: email.h:53
bool old
Email is seen, but unread.
Definition: email.h:52
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:85
struct TagList tags
For drivers that support server tagging.
Definition: email.h:108
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:1242
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:734
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
char * data
Pointer to data.
Definition: buffer.h:35
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:114
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:132
char * mutt_str_strcat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
Definition: string.c:395
IMAP-specific Account data -.
Definition: imap_private.h:166
char * driver_tags_get_with_hidden(struct TagList *list)
Get tags with hiddens.
Definition: tags.c:154
static bool compare_flags_for_copy(struct Email *e)
Compare local flags against the server.
Definition: imap.c:277
bool flagged
Marked important?
Definition: email.h:45
bool deleted
Email is deleted.
Definition: email.h:47
bool replied
Email has been replied to.
Definition: email.h:56
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: imap_private.h:71
#define FREE(x)
Definition: memory.h:40
#define MUTT_ACL_SEEN
Change the &#39;seen&#39; status of a message.
Definition: mailbox.h:84
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:749
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:159
+ 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 1186 of file imap.c.

1187 {
1188  if (!m || !m->account)
1189  return -1;
1190 
1191  struct ImapAccountData *adata = imap_adata_get(m);
1192  struct ImapMboxData *mdata = imap_mdata_get(m);
1193 
1194  /* overload keyboard timeout to avoid many mailbox checks in a row.
1195  * Most users don't like having to wait exactly when they press a key. */
1196  int rc = 0;
1197 
1198  /* try IDLE first, unless force is set */
1199  if (!force && C_ImapIdle && (adata->capabilities & IMAP_CAP_IDLE) &&
1200  ((adata->state != IMAP_IDLE) || (mutt_date_epoch() >= adata->lastread + C_ImapKeepalive)))
1201  {
1202  if (imap_cmd_idle(adata) < 0)
1203  return -1;
1204  }
1205  if (adata->state == IMAP_IDLE)
1206  {
1207  while ((rc = mutt_socket_poll(adata->conn, 0)) > 0)
1208  {
1209  if (imap_cmd_step(adata) != IMAP_RES_CONTINUE)
1210  {
1211  mutt_debug(LL_DEBUG1, "Error reading IDLE response\n");
1212  return -1;
1213  }
1214  }
1215  if (rc < 0)
1216  {
1217  mutt_debug(LL_DEBUG1, "Poll failed, disabling IDLE\n");
1218  adata->capabilities &= ~IMAP_CAP_IDLE; // Clear the flag
1219  }
1220  }
1221 
1222  if ((force || ((adata->state != IMAP_IDLE) &&
1223  (mutt_date_epoch() >= adata->lastread + C_Timeout))) &&
1224  (imap_exec(adata, "NOOP", IMAP_CMD_POLL) != IMAP_EXEC_SUCCESS))
1225  {
1226  return -1;
1227  }
1228 
1229  /* We call this even when we haven't run NOOP in case we have pending
1230  * changes to process, since we can reopen here. */
1231  imap_cmd_finish(adata);
1232 
1233  if (mdata->check_status & IMAP_EXPUNGE_PENDING)
1234  rc = MUTT_REOPENED;
1235  else if (mdata->check_status & IMAP_NEWMAIL_PENDING)
1236  rc = MUTT_NEW_MAIL;
1237  else if (mdata->check_status & IMAP_FLAGS_PENDING)
1238  rc = MUTT_FLAGS;
1239 
1241 
1242  return rc;
1243 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:410
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1072
#define IMAP_EXPUNGE_PENDING
Messages on the server have been expunged.
Definition: imap_private.h:66
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: imap_private.h:172
#define IMAP_FLAGS_PENDING
Flags have changed on the server.
Definition: imap_private.h:68
#define IMAP_CMD_POLL
Poll the tcp connection before running the imap command.
Definition: imap_private.h:74
Imap command executed or queued successfully.
Definition: imap_private.h:81
Connection is idle.
Definition: imap_private.h:110
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: util.c:242
int mutt_socket_poll(struct Connection *conn, time_t wait_secs)
Checks whether reads would block.
Definition: socket.c:188
int imap_cmd_idle(struct ImapAccountData *adata)
Enter the IDLE state.
Definition: command.c:1358
ImapOpenFlags check_status
Flags, e.g.
Definition: imap_private.h:220
void * mdata
Driver specific data.
Definition: mailbox.h:147
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:1242
WHERE short C_ImapKeepalive
Config: (imap) Time to wait before polling an open IMAP connection.
Definition: globals.h:163
Nondestructive flags change (IMAP)
Definition: mx.h:75
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
WHERE short C_Timeout
Config: Time to wait for user input in menus.
Definition: globals.h:156
#define IMAP_OPEN_NO_FLAGS
No flags are set.
Definition: imap_private.h:63
void imap_cmd_finish(struct ImapAccountData *adata)
Attempt to perform cleanup.
Definition: command.c:1295
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:114
ImapCapFlags capabilities
Definition: imap_private.h:183
time_t lastread
last time we read a command for the server
Definition: imap_private.h:186
bool C_ImapIdle
Config: (imap) Use the IMAP IDLE extension to check for new mail.
Definition: imap.c:65
#define IMAP_RES_CONTINUE
* ...
Definition: imap_private.h:55
IMAP-specific Account data -.
Definition: imap_private.h:166
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:142
Log at debug level 1.
Definition: logging.h:56
IMAP-specific Mailbox data -.
Definition: imap_private.h:213
#define IMAP_CAP_IDLE
RFC2177: IDLE.
Definition: imap_private.h:131
#define IMAP_NEWMAIL_PENDING
New mail is waiting on the server.
Definition: imap_private.h:67
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
New mail received in Mailbox.
Definition: mx.h:72
Mailbox was reopened.
Definition: mx.h:74
struct Connection * conn
Definition: imap_private.h:168
+ 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 1252 of file imap.c.

1253 {
1254  char *uid_validity_flag = NULL;
1255  char cmd[2048];
1256 
1257  if (!adata || !mdata)
1258  return -1;
1259 
1260  /* Don't issue STATUS on the selected mailbox, it will be NOOPed or
1261  * IDLEd elsewhere.
1262  * adata->mailbox may be NULL for connections other than the current
1263  * mailbox's.. #3216. */
1264  if (adata->mailbox && (adata->mailbox->mdata == mdata))
1265  {
1266  adata->mailbox->has_new = false;
1267  return mdata->messages;
1268  }
1269 
1270  if (adata->capabilities & IMAP_CAP_IMAP4REV1)
1271  uid_validity_flag = "UIDVALIDITY";
1272  else if (adata->capabilities & IMAP_CAP_STATUS)
1273  uid_validity_flag = "UID-VALIDITY";
1274  else
1275  {
1276  mutt_debug(LL_DEBUG2, "Server doesn't support STATUS\n");
1277  return -1;
1278  }
1279 
1280  snprintf(cmd, sizeof(cmd), "STATUS %s (UIDNEXT %s UNSEEN RECENT MESSAGES)",
1281  mdata->munge_name, uid_validity_flag);
1282 
1283  int rc = imap_exec(adata, cmd, queue ? IMAP_CMD_QUEUE : IMAP_CMD_NO_FLAGS | IMAP_CMD_POLL);
1284  if (rc < 0)
1285  {
1286  mutt_debug(LL_DEBUG1, "Error queueing command\n");
1287  return rc;
1288  }
1289  return mdata->messages;
1290 }
struct Mailbox * mailbox
Definition: imap_private.h:205
#define IMAP_CMD_POLL
Poll the tcp connection before running the imap command.
Definition: imap_private.h:74
bool has_new
Mailbox has new mail.
Definition: mailbox.h:99
Log at debug level 2.
Definition: logging.h:57
#define IMAP_CAP_IMAP4REV1
Server supports IMAP4rev1.
Definition: imap_private.h:121
void * mdata
Driver specific data.
Definition: mailbox.h:147
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:1242
#define IMAP_CAP_STATUS
Server supports STATUS command.
Definition: imap_private.h:122
ImapCapFlags capabilities
Definition: imap_private.h:183
Log at debug level 1.
Definition: logging.h:56
#define IMAP_CMD_QUEUE
Queue a command, do not execute.
Definition: imap_private.h:73
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: imap_private.h:71
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
char * munge_name
Munged version of the mailbox name.
Definition: imap_private.h:216
unsigned int messages
Definition: imap_private.h:228
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_mbox_check_stats()

int imap_mbox_check_stats ( struct Mailbox m,
int  flags 
)

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

Definition at line 1295 of file imap.c.

1296 {
1297  int rc = imap_mailbox_status(m, true);
1298  if (rc > 0)
1299  rc = 0;
1300  return rc;
1301 }
int imap_mailbox_status(struct Mailbox *m, bool queue)
Refresh the number of total and new messages.
Definition: imap.c:1334
+ 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 1309 of file imap.c.

1310 {
1311  struct Mailbox *m = mx_mbox_find2(path);
1312  if (m)
1313  return imap_mailbox_status(m, queue);
1314 
1315  // FIXME(sileht): Is that case possible ?
1316  struct ImapAccountData *adata = NULL;
1317  struct ImapMboxData *mdata = NULL;
1318 
1319  if (imap_adata_find(path, &adata, &mdata) < 0)
1320  return -1;
1321  int rc = imap_status(adata, mdata, queue);
1322  imap_mdata_free((void *) &mdata);
1323  return rc;
1324 }
void imap_mdata_free(void **ptr)
Release and clear storage in an ImapMboxData structure.
Definition: util.c:224
static int imap_status(struct ImapAccountData *adata, struct ImapMboxData *mdata, bool queue)
Refresh the number of total and new messages.
Definition: imap.c:1252
struct Mailbox * mx_mbox_find2(const char *path)
XXX.
Definition: mx.c:1516
int imap_adata_find(const char *path, struct ImapAccountData **adata, struct ImapMboxData **mdata)
Find the Account data for this path.
Definition: util.c:129
void * mdata
Driver specific data.
Definition: mailbox.h:147
A mailbox.
Definition: mailbox.h:92
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
int imap_mailbox_status(struct Mailbox *m, bool queue)
Refresh the number of total and new messages.
Definition: imap.c:1334
IMAP-specific Account data -.
Definition: imap_private.h:166
IMAP-specific Mailbox data -.
Definition: imap_private.h:213
+ 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
Note
Prepare the mailbox if we are not connected

Definition at line 1334 of file imap.c.

1335 {
1336  struct ImapAccountData *adata = imap_adata_get(m);
1337  struct ImapMboxData *mdata = imap_mdata_get(m);
1338  if (!adata || !mdata)
1339  return -1;
1340  return imap_status(adata, mdata, queue);
1341 }
static int imap_status(struct ImapAccountData *adata, struct ImapMboxData *mdata, bool queue)
Refresh the number of total and new messages.
Definition: imap.c:1252
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: util.c:242
void * mdata
Driver specific data.
Definition: mailbox.h:147
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:114
IMAP-specific Account data -.
Definition: imap_private.h:166
IMAP-specific Mailbox data -.
Definition: imap_private.h:213
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_search()

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

Find a matching mailbox.

Parameters
mMailbox
patPattern to match
Return values
0Success
-1Failure

Definition at line 1350 of file imap.c.

1351 {
1352  struct Buffer buf;
1353  struct ImapAccountData *adata = imap_adata_get(m);
1354  for (int i = 0; i < m->msg_count; i++)
1355  m->emails[i]->matched = false;
1356 
1357  if (do_search(pat, true) == 0)
1358  return 0;
1359 
1361  mutt_buffer_addstr(&buf, "UID SEARCH ");
1362  if (compile_search(m, pat, &buf) < 0)
1363  {
1364  FREE(&buf.data);
1365  return -1;
1366  }
1367  if (imap_exec(adata, buf.data, IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS)
1368  {
1369  FREE(&buf.data);
1370  return -1;
1371  }
1372 
1373  FREE(&buf.data);
1374  return 0;
1375 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
int msg_count
Total number of messages.
Definition: mailbox.h:102
String manipulation buffer.
Definition: buffer.h:33
Imap command executed or queued successfully.
Definition: imap_private.h:81
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:1242
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
static int compile_search(struct Mailbox *m, const struct PatternList *pat, struct Buffer *buf)
Convert NeoMutt pattern to IMAP search.
Definition: imap.c:382
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:114
IMAP-specific Account data -.
Definition: imap_private.h:166
static int do_search(const struct PatternList *search, bool allpats)
Perform a search of messages.
Definition: imap.c:340
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: imap_private.h:71
#define FREE(x)
Definition: memory.h:40
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:46
bool matched
Search matches this Email.
Definition: email.h:70
+ 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 1384 of file imap.c.

1385 {
1386  struct ImapAccountData *adata = NULL;
1387  struct ImapMboxData *mdata = NULL;
1388  char buf[2048];
1389  char errstr[256];
1390  struct Buffer err, token;
1391 
1392  if (imap_adata_find(path, &adata, &mdata) < 0)
1393  return -1;
1394 
1396  {
1397  char mbox[1024];
1398  mutt_buffer_init(&token);
1399  mutt_buffer_init(&err);
1400  err.data = errstr;
1401  err.dsize = sizeof(errstr);
1402  size_t len = snprintf(mbox, sizeof(mbox), "%smailboxes ", subscribe ? "" : "un");
1403  imap_quote_string(mbox + len, sizeof(mbox) - len, path, true);
1404  if (mutt_parse_rc_line(mbox, &token, &err))
1405  mutt_debug(LL_DEBUG1, "Error adding subscribed mailbox: %s\n", errstr);
1406  FREE(&token.data);
1407  }
1408 
1409  if (subscribe)
1410  mutt_message(_("Subscribing to %s..."), mdata->name);
1411  else
1412  mutt_message(_("Unsubscribing from %s..."), mdata->name);
1413 
1414  snprintf(buf, sizeof(buf), "%sSUBSCRIBE %s", subscribe ? "" : "UN", mdata->munge_name);
1415 
1416  if (imap_exec(adata, buf, IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS)
1417  {
1418  imap_mdata_free((void *) &mdata);
1419  return -1;
1420  }
1421 
1422  if (subscribe)
1423  mutt_message(_("Subscribed to %s"), mdata->name);
1424  else
1425  mutt_message(_("Unsubscribed from %s"), mdata->name);
1426  imap_mdata_free((void *) &mdata);
1427  return 0;
1428 }
void imap_quote_string(char *dest, size_t dlen, const char *src, bool quote_backtick)
quote string according to IMAP rules
Definition: util.c:945
#define mutt_message(...)
Definition: logging.h:83
void imap_mdata_free(void **ptr)
Release and clear storage in an ImapMboxData structure.
Definition: util.c:224
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
Imap command executed or queued successfully.
Definition: imap_private.h:81
int imap_adata_find(const char *path, struct ImapAccountData **adata, struct ImapMboxData **mdata)
Find the Account data for this path.
Definition: util.c:129
void * mdata
Driver specific data.
Definition: mailbox.h:147
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:1242
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
char * name
Mailbox name.
Definition: imap_private.h:215
WHERE bool C_ImapCheckSubscribed
Config: (imap) When opening a mailbox, ask the server for a list of subscribed folders.
Definition: globals.h:229
IMAP-specific Account data -.
Definition: imap_private.h:166
Log at debug level 1.
Definition: logging.h:56
IMAP-specific Mailbox data -.
Definition: imap_private.h:213
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: imap_private.h:71
#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: imap_private.h:216
enum CommandResult mutt_parse_rc_line(char *line, struct Buffer *token, struct Buffer *err)
Parse a line of user config.
Definition: init.c:3224
+ 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,
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 1441 of file imap.c.

1442 {
1443  struct ImapAccountData *adata = NULL;
1444  struct ImapMboxData *mdata = NULL;
1445  char tmp[2048];
1446  struct ImapList listresp;
1447  char completion[1024];
1448  int clen;
1449  size_t matchlen = 0;
1450  int completions = 0;
1451  int rc;
1452 
1453  if (imap_adata_find(path, &adata, &mdata) < 0)
1454  {
1455  mutt_str_strfcpy(buf, path, buflen);
1456  return complete_hosts(buf, buflen);
1457  }
1458 
1459  /* fire off command */
1460  snprintf(tmp, sizeof(tmp), "%s \"\" \"%s%%\"",
1461  C_ImapListSubscribed ? "LSUB" : "LIST", mdata->real_name);
1462 
1463  imap_cmd_start(adata, tmp);
1464 
1465  /* and see what the results are */
1466  mutt_str_strfcpy(completion, mdata->name, sizeof(completion));
1467  imap_mdata_free((void *) &mdata);
1468 
1469  adata->cmdresult = &listresp;
1470  do
1471  {
1472  listresp.name = NULL;
1473  rc = imap_cmd_step(adata);
1474 
1475  if ((rc == IMAP_RES_CONTINUE) && listresp.name)
1476  {
1477  /* if the folder isn't selectable, append delimiter to force browse
1478  * to enter it on second tab. */
1479  if (listresp.noselect)
1480  {
1481  clen = strlen(listresp.name);
1482  listresp.name[clen++] = listresp.delim;
1483  listresp.name[clen] = '\0';
1484  }
1485  /* copy in first word */
1486  if (!completions)
1487  {
1488  mutt_str_strfcpy(completion, listresp.name, sizeof(completion));
1489  matchlen = strlen(completion);
1490  completions++;
1491  continue;
1492  }
1493 
1494  matchlen = longest_common_prefix(completion, listresp.name, 0, matchlen);
1495  completions++;
1496  }
1497  } while (rc == IMAP_RES_CONTINUE);
1498  adata->cmdresult = NULL;
1499 
1500  if (completions)
1501  {
1502  /* reformat output */
1503  imap_qualify_path(buf, buflen, &adata->conn_account, completion);
1504  mutt_pretty_mailbox(buf, buflen);
1505  return 0;
1506  }
1507 
1508  return -1;
1509 }
WHERE bool C_ImapListSubscribed
Config: (imap) When browsing a mailbox, only display subscribed folders.
Definition: globals.h:231
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1072
void imap_mdata_free(void **ptr)
Release and clear storage in an ImapMboxData structure.
Definition: util.c:224
struct ConnAccount conn_account
Definition: imap_private.h:169
void imap_qualify_path(char *buf, size_t buflen, struct ConnAccount *conn_account, char *path)
Make an absolute IMAP folder target.
Definition: util.c:928
Items in an IMAP browser.
Definition: imap_private.h:144
int imap_cmd_start(struct ImapAccountData *adata, const char *cmdstr)
Given an IMAP command, send it to the server.
Definition: command.c:1058
static int complete_hosts(char *buf, size_t buflen)
Look for completion matches for mailboxes.
Definition: imap.c:512
int imap_adata_find(const char *path, struct ImapAccountData **adata, struct ImapMboxData **mdata)
Find the Account data for this path.
Definition: util.c:129
void * mdata
Driver specific data.
Definition: mailbox.h:147
char * name
Definition: imap_private.h:146
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
char * name
Mailbox name.
Definition: imap_private.h:215
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:612
char * real_name
Original Mailbox name, e.g.
Definition: imap_private.h:217
#define IMAP_RES_CONTINUE
* ...
Definition: imap_private.h:55
IMAP-specific Account data -.
Definition: imap_private.h:166
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:491
IMAP-specific Mailbox data -.
Definition: imap_private.h:213
struct ImapList * cmdresult
Definition: imap_private.h:195
+ 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 1519 of file imap.c.

1520 {
1521  char prompt[1024];
1522  int rc = -1;
1523  bool triedcreate = false;
1524  enum QuadOption err_continue = MUTT_NO;
1525 
1526  struct ImapAccountData *adata = imap_adata_get(m);
1527  struct ImapAccountData *dest_adata = NULL;
1528  struct ImapMboxData *dest_mdata = NULL;
1529 
1530  if (imap_adata_find(dest, &dest_adata, &dest_mdata) < 0)
1531  return -1;
1532 
1533  struct Buffer sync_cmd = mutt_buffer_make(0);
1534 
1535  /* check that the save-to folder is in the same account */
1536  if (!mutt_account_match(&(adata->conn->account), &(dest_adata->conn->account)))
1537  {
1538  mutt_debug(LL_DEBUG3, "%s not same server as %s\n", dest, mailbox_path(m));
1539  goto out;
1540  }
1541 
1542  for (int i = 0; i < m->msg_count; i++)
1543  {
1544  if (m->emails[i]->active && m->emails[i]->changed &&
1545  m->emails[i]->deleted && !m->emails[i]->purge)
1546  {
1547  rc = imap_sync_message_for_copy(m, m->emails[i], &sync_cmd, &err_continue);
1548  if (rc < 0)
1549  {
1550  mutt_debug(LL_DEBUG1, "could not sync\n");
1551  goto out;
1552  }
1553  }
1554  }
1555 
1556  /* loop in case of TRYCREATE */
1557  do
1558  {
1559  rc = imap_exec_msgset(m, "UID COPY", dest_mdata->munge_name, MUTT_TRASH, false, false);
1560  if (rc == 0)
1561  {
1562  mutt_debug(LL_DEBUG1, "No messages to trash\n");
1563  rc = -1;
1564  goto out;
1565  }
1566  else if (rc < 0)
1567  {
1568  mutt_debug(LL_DEBUG1, "could not queue copy\n");
1569  goto out;
1570  }
1571  else
1572  {
1573  mutt_message(ngettext("Copying %d message to %s...", "Copying %d messages to %s...", rc),
1574  rc, dest_mdata->name);
1575  }
1576 
1577  /* let's get it on */
1578  rc = imap_exec(adata, NULL, IMAP_CMD_NO_FLAGS);
1579  if (rc == IMAP_EXEC_ERROR)
1580  {
1581  if (triedcreate)
1582  {
1583  mutt_debug(LL_DEBUG1, "Already tried to create mailbox %s\n", dest_mdata->name);
1584  break;
1585  }
1586  /* bail out if command failed for reasons other than nonexistent target */
1587  if (!mutt_str_startswith(imap_get_qualifier(adata->buf), "[TRYCREATE]", CASE_IGNORE))
1588  break;
1589  mutt_debug(LL_DEBUG3, "server suggests TRYCREATE\n");
1590  snprintf(prompt, sizeof(prompt), _("Create %s?"), dest_mdata->name);
1591  if (C_Confirmcreate && (mutt_yesorno(prompt, MUTT_YES) != MUTT_YES))
1592  {
1593  mutt_clear_error();
1594  goto out;
1595  }
1596  if (imap_create_mailbox(adata, dest_mdata->name) < 0)
1597  break;
1598  triedcreate = true;
1599  }
1600  } while (rc == IMAP_EXEC_ERROR);
1601 
1602  if (rc != IMAP_EXEC_SUCCESS)
1603  {
1604  imap_error("imap_fast_trash", adata->buf);
1605  goto out;
1606  }
1607 
1608  rc = IMAP_EXEC_SUCCESS;
1609 
1610 out:
1611  mutt_buffer_dealloc(&sync_cmd);
1612  imap_mdata_free((void *) &dest_mdata);
1613 
1614  return ((rc == IMAP_EXEC_SUCCESS) ? 0 : -1);
1615 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:194
int msg_count
Total number of messages.
Definition: mailbox.h:102
struct ConnAccount account
Definition: connection.h:36
#define mutt_message(...)
Definition: logging.h:83
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
void imap_mdata_free(void **ptr)
Release and clear storage in an ImapMboxData structure.
Definition: util.c:224
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:50
WHERE bool C_Confirmcreate
Config: Confirm before creating a new mailbox.
Definition: globals.h:215
Imap command executed or queued successfully.
Definition: imap_private.h:81
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:332
int imap_adata_find(const char *path, struct ImapAccountData **adata, struct ImapMboxData **mdata)
Find the Account data for this path.
Definition: util.c:129
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:1007
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:293
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:109
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:1242
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:1084
bool active
Message is not to be removed.
Definition: email.h:61
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
void imap_error(const char *where, const char *msg)
show an error and abort
Definition: util.c:760
char * name
Mailbox name.
Definition: imap_private.h:215
bool mutt_account_match(const struct ConnAccount *a1, const struct ConnAccount *a2)
Compare account info (host/port/user)
Definition: mutt_account.c:61
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:114
Ignore case when comparing strings.
Definition: string2.h:68
bool purge
Skip trash folder when deleting.
Definition: email.h:48
char * imap_get_qualifier(char *buf)
Get the qualifier from a tagged response.
Definition: util.c:880
int imap_create_mailbox(struct ImapAccountData *adata, char *mailbox)
Create a new mailbox.
Definition: imap.c:573
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
IMAP-specific Account data -.
Definition: imap_private.h:166
Log at debug level 1.
Definition: logging.h:56
IMAP-specific Mailbox data -.
Definition: imap_private.h:213
bool deleted
Email is deleted.
Definition: email.h:47
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: imap_private.h:71
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
char * munge_name
Munged version of the mailbox name.
Definition: imap_private.h:216
Trashed messages.
Definition: mutt.h:114
Log at debug level 3.
Definition: logging.h:58
QuadOption
Possible values for a quad-option.
Definition: quad.h:35
struct Connection * conn
Definition: imap_private.h:168
Imap command failure.
Definition: imap_private.h:82
+ 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
0Success
-1Error

Definition at line 1625 of file imap.c.

1626 {
1627  if (!m)
1628  return -1;
1629 
1630  struct Email *e = NULL;
1631  struct Email **emails = NULL;
1632  int oldsort;
1633  int rc;
1634 
1635  struct ImapAccountData *adata = imap_adata_get(m);
1636  struct ImapMboxData *mdata = imap_mdata_get(m);
1637 
1638  if (adata->state < IMAP_SELECTED)
1639  {
1640  mutt_debug(LL_DEBUG2, "no mailbox selected\n");
1641  return -1;
1642  }
1643 
1644  /* This function is only called when the calling code expects the context
1645  * to be changed. */
1646  imap_allow_reopen(m);
1647 
1648  rc = imap_check_mailbox(m, false);
1649  if (rc < 0)
1650  return rc;
1651 
1652  /* if we are expunging anyway, we can do deleted messages very quickly... */
1653  if (expunge && (m->rights & MUTT_ACL_DELETE))
1654  {
1655  rc = imap_exec_msgset(m, "UID STORE", "+FLAGS.SILENT (\\Deleted)",
1656  MUTT_DELETED, true, false);
1657  if (rc < 0)
1658  {
1659  mutt_error(_("Expunge failed"));
1660  return rc;
1661  }
1662 
1663  if (rc > 0)
1664  {
1665  /* mark these messages as unchanged so second pass ignores them. Done
1666  * here so BOGUS UW-IMAP 4.7 SILENT FLAGS updates are ignored. */
1667  for (int i = 0; i < m->msg_count; i++)
1668  if (m->emails[i]->deleted && m->emails[i]->changed)
1669  m->emails[i]->active = false;
1670  mutt_message(ngettext("Marking %d message deleted...",
1671  "Marking %d messages deleted...", rc),
1672  rc);
1673  }
1674  }
1675 
1676 #ifdef USE_HCACHE
1677  mdata->hcache = imap_hcache_open(adata, mdata);
1678 #endif
1679 
1680  /* save messages with real (non-flag) changes */
1681  for (int i = 0; i < m->msg_count; i++)
1682  {
1683  e = m->emails[i];
1684 
1685  if (e->deleted)
1686  {
1687  imap_cache_del(m, e);
1688 #ifdef USE_HCACHE
1689  imap_hcache_del(mdata, imap_edata_get(e)->uid);
1690 #endif
1691  }
1692 
1693  if (e->active && e->changed)
1694  {
1695 #ifdef USE_HCACHE
1696  imap_hcache_put(mdata, e);
1697 #endif
1698  /* if the message has been rethreaded or attachments have been deleted
1699  * we delete the message and reupload it.
1700  * This works better if we're expunging, of course. */
1701  /* TODO: why the e->env check? */
1702  if ((e->env && e->env->changed) || e->attach_del)
1703  {
1704  /* L10N: The plural is chosen by the last %d, i.e. the total number */
1705  mutt_message(ngettext("Saving changed message... [%d/%d]",
1706  "Saving changed messages... [%d/%d]", m->msg_count),
1707  i + 1, m->msg_count);
1708  mutt_save_message_ctx(e, true, false, false, m);
1709  /* TODO: why the check for h->env? Is this possible? */
1710  if (e->env)
1711  e->env->changed = 0;
1712  }
1713  }
1714  }
1715 
1716 #ifdef USE_HCACHE
1717  imap_hcache_close(mdata);
1718 #endif
1719 
1720  /* presort here to avoid doing 10 resorts in imap_exec_msgset */
1721  oldsort = C_Sort;
1722  if (C_Sort != SORT_ORDER)
1723  {
1724  emails = m->emails;
1725  m->emails = mutt_mem_malloc(m->msg_count * sizeof(struct Email *));
1726  memcpy(m->emails, emails, m->msg_count * sizeof(struct Email *));
1727 
1728  C_Sort = SORT_ORDER;
1729  qsort(m->emails, m->msg_count, sizeof(struct Email *), mutt_get_sort_func(SORT_ORDER));
1730  }
1731 
1732  rc = sync_helper(m, MUTT_ACL_DELETE, MUTT_DELETED, "\\Deleted");
1733  if (rc >= 0)
1734  rc |= sync_helper(m, MUTT_ACL_WRITE, MUTT_FLAG, "\\Flagged");
1735  if (rc >= 0)
1736  rc |= sync_helper(m, MUTT_ACL_WRITE, MUTT_OLD, "Old");
1737  if (rc >= 0)
1738  rc |= sync_helper(m, MUTT_ACL_SEEN, MUTT_READ, "\\Seen");
1739  if (rc >= 0)
1740  rc |= sync_helper(m, MUTT_ACL_WRITE, MUTT_REPLIED, "\\Answered");
1741 
1742  if (oldsort != C_Sort)
1743  {
1744  C_Sort = oldsort;
1745  FREE(&m->emails);
1746  m->emails = emails;
1747  }
1748 
1749  /* Flush the queued flags if any were changed in sync_helper. */
1750  if (rc > 0)
1751  if (imap_exec(adata, NULL, IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS)
1752  rc = -1;
1753 
1754  if (rc < 0)
1755  {
1756  if (close)
1757  {
1758  if (mutt_yesorno(_("Error saving flags. Close anyway?"), MUTT_NO) == MUTT_YES)
1759  {
1760  adata->state = IMAP_AUTHENTICATED;
1761  return 0;
1762  }
1763  }
1764  else
1765  mutt_error(_("Error saving flags"));
1766  return -1;
1767  }
1768 
1769  /* Update local record of server state to reflect the synchronization just
1770  * completed. imap_read_headers always overwrites hcache-origin flags, so
1771  * there is no need to mutate the hcache after flag-only changes. */
1772  for (int i = 0; i < m->msg_count; i++)
1773  {
1774  struct ImapEmailData *edata = imap_edata_get(m->emails[i]);
1775  edata->deleted = m->emails[i]->deleted;
1776  edata->flagged = m->emails[i]->flagged;
1777  edata->old = m->emails[i]->old;
1778  edata->read = m->emails[i]->read;
1779  edata->replied = m->emails[i]->replied;
1780  m->emails[i]->changed = false;
1781  }
1782  m->changed = false;
1783 
1784  /* We must send an EXPUNGE command if we're not closing. */
1785  if (expunge && !close && (m->rights & MUTT_ACL_DELETE))
1786  {
1787  mutt_message(_("Expunging messages from server..."));
1788  /* Set expunge bit so we don't get spurious reopened messages */
1789  mdata->reopen |= IMAP_EXPUNGE_EXPECTED;
1790  if (imap_exec(adata, "EXPUNGE", IMAP_CMD_NO_FLAGS) != IMAP_EXEC_SUCCESS)
1791  {
1792  mdata->reopen &= ~IMAP_EXPUNGE_EXPECTED;
1793  imap_error(_("imap_sync_mailbox: EXPUNGE failed"), adata->buf);
1794  return -1;
1795  }
1796  mdata->reopen &= ~IMAP_EXPUNGE_EXPECTED;
1797  }
1798 
1799  if (expunge && close)
1800  {
1801  adata->closing = true;
1802  imap_exec(adata, "CLOSE", IMAP_CMD_QUEUE);
1803  adata->state = IMAP_AUTHENTICATED;
1804  }
1805 
1806  if (C_MessageCacheClean)
1807  imap_cache_clean(m);
1808 
1809  return 0;
1810 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
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:965
Deleted messages.
Definition: mutt.h:107
WHERE bool C_MessageCacheClean
Config: (imap/pop) Clean out obsolete entries from the message cache.
Definition: globals.h:250
header_cache_t * imap_hcache_open(struct ImapAccountData *adata, struct ImapMboxData *mdata)
Open a header cache.
Definition: util.c:415
int msg_count
Total number of messages.
Definition: mailbox.h:102
The envelope/body of an email.
Definition: email.h:39
int imap_hcache_put(struct ImapMboxData *mdata, struct Email *e)
Add an entry to the header cache.
Definition: util.c:489
struct ImapEmailData * imap_edata_get(struct Email *e)
Get the private data for this Email.
Definition: message.c:98
Mailbox is selected.
Definition: imap_private.h:107
#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:302
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
bool attach_del
Has an attachment marked for deletion.
Definition: email.h:51
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: imap_private.h:172
ImapOpenFlags reopen
Flags, e.g.
Definition: imap_private.h:219
Flagged messages.
Definition: mutt.h:108
#define _(a)
Definition: message.h:28
bool changed
Email has been edited.
Definition: email.h:50
int imap_hcache_del(struct ImapMboxData *mdata, unsigned int uid)
Delete an item from the header cache.
Definition: util.c:507
#define MUTT_ACL_DELETE
Delete a message.
Definition: mailbox.h:77
Messages that have been replied to.
Definition: mutt.h:101
bool flagged
Definition: message.h:39
unsigned char changed
Changed fields, e.g. MUTT_ENV_CHANGED_SUBJECT.
Definition: envelope.h:88
Imap command executed or queued successfully.
Definition: imap_private.h:81
bool deleted
Definition: message.h:38
header_cache_t * hcache
Definition: imap_private.h:239
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: util.c:242
bool read
Email is read.
Definition: email.h:53
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:332
Log at debug level 2.
Definition: logging.h:57
bool old
Email is seen, but unread.
Definition: email.h:52
struct Envelope * env
Envelope information.
Definition: email.h:91
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:1007
void imap_hcache_close(struct ImapMboxData *mdata)
Close the header cache.
Definition: util.c:443
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:58
void * mdata
Driver specific data.
Definition: mailbox.h:147
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:85
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:1242
Old messages.
Definition: mutt.h:100
sort_t * mutt_get_sort_func(enum SortType method)
Get the sort function for a given sort id.
Definition: sort.c:322
bool active
Message is not to be removed.
Definition: email.h:61
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
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
void imap_error(const char *where, const char *msg)
show an error and abort
Definition: util.c:760
Messages that have been read.
Definition: mutt.h:102
Connection is authenticated.
Definition: imap_private.h:106
bool replied
Definition: message.h:40
bool old
Definition: message.h:37
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:114
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:132
int imap_check_mailbox(struct Mailbox *m, bool force)
use the NOOP or IDLE command to poll for new mail
Definition: imap.c:1186
IMAP-specific Account data -.
Definition: imap_private.h:166
#define IMAP_EXPUNGE_EXPECTED
Messages will be expunged from the server.
Definition: imap_private.h:65
bool flagged
Marked important?
Definition: email.h:45
IMAP-specific Mailbox data -.
Definition: imap_private.h:213
bool deleted
Email is deleted.
Definition: email.h:47
void * edata
Driver-specific data.
Definition: email.h:112
#define IMAP_CMD_QUEUE
Queue a command, do not execute.
Definition: imap_private.h:73
#define mutt_error(...)
Definition: logging.h:84
bool replied
Email has been replied to.
Definition: email.h:56
void imap_allow_reopen(struct Mailbox *m)
Allow re-opening a folder upon expunge.
Definition: util.c:1124
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: imap_private.h:71
#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:84
bool changed
Mailbox has been modified.
Definition: mailbox.h:125
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
IMAP-specific Email data -.
Definition: message.h:33
Sort by the order the messages appear in the mailbox.
Definition: sort.h:55
int imap_cache_del(struct Mailbox *m, struct Email *e)
Delete an email from the body cache.
Definition: message.c:1748
int imap_cache_clean(struct Mailbox *m)
Delete all the entries in the message cache.
Definition: message.c:1767
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_ac_find()

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

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

Definition at line 1815 of file imap.c.

1816 {
1817  if (!a || (a->magic != MUTT_IMAP) || !path)
1818  return NULL;
1819 
1820  struct Url *url = url_parse(path);
1821 
1822  struct ImapAccountData *adata = a->adata;
1823  struct ConnAccount *ac = &adata->conn_account;
1824 
1825  if ((mutt_str_strcasecmp(url->host, ac->host) != 0) ||
1826  (mutt_str_strcasecmp(url->user, ac->user) != 0))
1827  {
1828  a = NULL;
1829  }
1830 
1831  url_free(&url);
1832  return a;
1833 }
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:66
struct ConnAccount conn_account
Definition: imap_private.h:169
char user[128]
Definition: connaccount.h:33
char host[128]
Definition: connaccount.h:36
char * user
Username.
Definition: url.h:69
enum MailboxType magic
Type of Mailboxes this Account contains.
Definition: account.h:38
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:31
char * path
Path.
Definition: url.h:73
IMAP-specific Account data -.
Definition: imap_private.h:166
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
char * path
Path of Email (for local Mailboxes)
Definition: email.h:93
void url_free(struct Url **u)
Free the contents of a URL.
Definition: url.c:288
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:52
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:161
+ Here is the call graph for this function:

◆ imap_ac_add()

int imap_ac_add ( struct Account a,
struct Mailbox m 
)

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

Definition at line 1838 of file imap.c.

1839 {
1840  if (!a || !m || (m->magic != MUTT_IMAP))
1841  return -1;
1842 
1843  struct ImapAccountData *adata = a->adata;
1844 
1845  if (!adata)
1846  {
1847  struct ConnAccount conn_account;
1848  char mailbox[PATH_MAX];
1849 
1850  if (imap_parse_path(mailbox_path(m), &conn_account, mailbox, sizeof(mailbox)) < 0)
1851  return -1;
1852 
1853  adata = imap_adata_new();
1854  adata->conn_account = conn_account;
1855  adata->conn = mutt_conn_new(&conn_account);
1856  if (!adata->conn)
1857  return -1;
1858 
1860 
1861  if (imap_login(adata) < 0)
1862  return -1;
1863 
1864  a->adata = adata;
1866  }
1867 
1868  if (!m->mdata)
1869  {
1870  struct Url *url = url_parse(mailbox_path(m));
1871  struct ImapMboxData *mdata = imap_mdata_new(adata, url->path);
1872 
1873  /* fixup path and realpath, mainly to replace / by /INBOX */
1874  char buf[1024];
1875  imap_qualify_path(buf, sizeof(buf), &adata->conn_account, mdata->name);
1876  mutt_buffer_strcpy(&m->pathbuf, buf);
1878 
1879  m->mdata = mdata;
1881  url_free(&url);
1882  }
1883  return 0;
1884 }
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:194
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:66
struct ImapAccountData * imap_adata_new(void)
Allocate and initialise a new ImapAccountData structure.
Definition: util.c:94
void imap_mdata_free(void **ptr)
Release and clear storage in an ImapMboxData structure.
Definition: util.c:224
int imap_login(struct ImapAccountData *adata)
Open an IMAP connection.
Definition: imap.c:1894
struct ConnAccount conn_account
Definition: imap_private.h:169
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:95
void imap_qualify_path(char *buf, size_t buflen, struct ConnAccount *conn_account, char *path)
Make an absolute IMAP folder target.
Definition: util.c:928
void imap_adata_free(void **ptr)
Release and clear storage in an ImapAccountData structure.
Definition: util.c:68
struct Connection * mutt_conn_new(const struct ConnAccount *account)
Create a new Connection.
Definition: mutt_socket.c:43
struct ImapMboxData * imap_mdata_new(struct ImapAccountData *adata, const char *name)
Allocate and initialise a new ImapMboxData structure.
Definition: util.c:163
void(* free_mdata)(void **)
Driver-specific data free function.
Definition: mailbox.h:148
enum MailboxType magic
Mailbox type.
Definition: mailbox.h:116
void * mdata
Driver specific data.
Definition: mailbox.h:147
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:310
int imap_parse_path(const char *path, struct ConnAccount *account, char *mailbox, size_t mailboxlen)
Parse an IMAP mailbox name into ConnAccount, name.
Definition: util.c:586
void mutt_account_hook(const char *url)
Perform an account hook.
Definition: hook.c:758
#define PATH_MAX
Definition: mutt.h:52
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
char * name
Mailbox name.
Definition: imap_private.h:215
Login details for a remote server.
Definition: connaccount.h:31
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:453
char * path
Path.
Definition: url.h:73
IMAP-specific Account data -.
Definition: imap_private.h:166
IMAP-specific Mailbox data -.
Definition: imap_private.h:213
void url_free(struct Url **u)
Free the contents of a URL.
Definition: url.c:288
struct Buffer pathbuf
Definition: mailbox.h:94
void(* free_adata)(void **)
Callback function to free private data.
Definition: account.h:44
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:52
struct Connection * conn
Definition: imap_private.h:168
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:161
+ Here is the call 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 1894 of file imap.c.

1895 {
1896  if (!adata)
1897  return -1;
1898 
1899  if (adata->state == IMAP_DISCONNECTED)
1900  imap_open_connection(adata);
1901  if (adata->state == IMAP_CONNECTED)
1902  {
1903  if (imap_authenticate(adata) == IMAP_AUTH_SUCCESS)
1904  {
1905  adata->state = IMAP_AUTHENTICATED;
1906  FREE(&adata->capstr);
1907  if (adata->conn->ssf)
1908  mutt_debug(LL_DEBUG2, "Communication encrypted at %d bits\n",
1909  adata->conn->ssf);
1910  }
1911  else
1913  }
1914  if (adata->state == IMAP_AUTHENTICATED)
1915  {
1916  /* capabilities may have changed */
1917  imap_exec(adata, "CAPABILITY", IMAP_CMD_QUEUE);
1918 
1919  /* enable RFC6855, if the server supports that */
1920  if (C_ImapRfc5161 && (adata->capabilities & IMAP_CAP_ENABLE))
1921  imap_exec(adata, "ENABLE UTF8=ACCEPT", IMAP_CMD_QUEUE);
1922 
1923  /* enable QRESYNC. Advertising QRESYNC also means CONDSTORE
1924  * is supported (even if not advertised), so flip that bit. */
1925  if (adata->capabilities & IMAP_CAP_QRESYNC)
1926  {
1927  adata->capabilities |= IMAP_CAP_CONDSTORE;
1929  imap_exec(adata, "ENABLE QRESYNC", IMAP_CMD_QUEUE);
1930  }
1931 
1932  /* get root delimiter, '/' as default */
1933  adata->delim = '/';
1934  imap_exec(adata, "LIST \"\" \"\"", IMAP_CMD_QUEUE);
1935 
1936  /* we may need the root delimiter before we open a mailbox */
1937  imap_exec(adata, NULL, IMAP_CMD_NO_FLAGS);
1938  }
1939 
1940  if (adata->state < IMAP_AUTHENTICATED)
1941  return -1;
1942 
1943  return 0;
1944 }
bool C_ImapRfc5161
Config: (imap) Use the IMAP ENABLE extension to select capabilities.
Definition: imap.c:69
struct ConnAccount account
Definition: connection.h:36
unsigned int ssf
security strength factor, in bits
Definition: connection.h:37
int imap_open_connection(struct ImapAccountData *adata)
Open an IMAP connection.
Definition: imap.c:850
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: imap_private.h:172
#define IMAP_CAP_ENABLE
RFC5161.
Definition: imap_private.h:133
Log at debug level 2.
Definition: logging.h:57
int imap_authenticate(struct ImapAccountData *adata)
Authenticate to an IMAP server.
Definition: auth.c:67
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:1242
WHERE bool C_ImapQresync
Config: (imap) Enable the QRESYNC extension.
Definition: globals.h:234
Connection is authenticated.
Definition: imap_private.h:106
ImapCapFlags capabilities
Definition: imap_private.h:183
#define IMAP_CAP_CONDSTORE
RFC7162.
Definition: imap_private.h:134
#define IMAP_CMD_QUEUE
Queue a command, do not execute.
Definition: imap_private.h:73
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: imap_private.h:71
#define FREE(x)
Definition: memory.h:40
Connected to server.
Definition: imap_private.h:105
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Disconnected from server.
Definition: imap_private.h:104
Authentication successful.
Definition: auth.h:37
#define IMAP_CAP_QRESYNC
RFC7162.
Definition: imap_private.h:135
struct Connection * conn
Definition: imap_private.h:168
void mutt_account_unsetpass(struct ConnAccount *account)
Unset ConnAccount&#39;s password.
Definition: mutt_account.c:332
+ 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 1949 of file imap.c.

1950 {
1951  if (!m || !m->account || !m->mdata)
1952  return -1;
1953 
1954  char buf[PATH_MAX];
1955  int count = 0;
1956  int rc;
1957  const char *condstore = NULL;
1958 
1959  struct ImapAccountData *adata = imap_adata_get(m);
1960  struct ImapMboxData *mdata = imap_mdata_get(m);
1961 
1962  adata->mailbox = m;
1963 
1964  /* clear mailbox status */
1965  adata->status = 0;
1966  m->rights = 0;
1967  mdata->new_mail_count = 0;
1968 
1969  mutt_message(_("Selecting %s..."), mdata->name);
1970 
1971  /* pipeline ACL test */
1972  if (adata->capabilities & IMAP_CAP_ACL)
1973  {
1974  snprintf(buf, sizeof(buf), "MYRIGHTS %s", mdata->munge_name);
1975  imap_exec(adata, buf, IMAP_CMD_QUEUE);
1976  }
1977  /* assume we have all rights if ACL is unavailable */
1978  else
1979  {
1982  }
1983 
1984  /* pipeline the postponed count if possible */
1985  struct Mailbox *m_postponed = mx_mbox_find2(C_Postponed);
1986  struct ImapAccountData *postponed_adata = imap_adata_get(m_postponed);
1987  if (postponed_adata &&
1988  mutt_account_match(&postponed_adata->conn_account, &adata->conn_account))
1989  imap_mailbox_status(m_postponed, true);
1990 
1992  imap_exec(adata, "LSUB \"\" \"*\"", IMAP_CMD_QUEUE);
1993 
1994 #ifdef USE_HCACHE
1996  condstore = " (CONDSTORE)";
1997  else
1998 #endif
1999  condstore = "";
2000 
2001  snprintf(buf, sizeof(buf), "%s %s%s", m->readonly ? "EXAMINE" : "SELECT",
2002  mdata->munge_name, condstore);
2003 
2004  adata->state = IMAP_SELECTED;
2005 
2006  imap_cmd_start(adata, buf);
2007 
2008  do
2009  {
2010  char *pc = NULL;
2011 
2012  rc = imap_cmd_step(adata);
2013  if (rc != IMAP_RES_CONTINUE)
2014  break;
2015 
2016  pc = adata->buf + 2;
2017 
2018  /* Obtain list of available flags here, may be overridden by a
2019  * PERMANENTFLAGS tag in the OK response */
2020  if (mutt_str_startswith(pc, "FLAGS", CASE_IGNORE))
2021  {
2022  /* don't override PERMANENTFLAGS */
2023  if (STAILQ_EMPTY(&mdata->flags))
2024  {
2025  mutt_debug(LL_DEBUG3, "Getting mailbox FLAGS\n");
2026  pc = get_flags(&mdata->flags, pc);
2027  if (!pc)
2028  goto fail;
2029  }
2030  }
2031  /* PERMANENTFLAGS are massaged to look like FLAGS, then override FLAGS */
2032  else if (mutt_str_startswith(pc, "OK [PERMANENTFLAGS", CASE_IGNORE))
2033  {
2034  mutt_debug(LL_DEBUG3, "Getting mailbox PERMANENTFLAGS\n");
2035  /* safe to call on NULL */
2036  mutt_list_free(&mdata->flags);
2037  /* skip "OK [PERMANENT" so syntax is the same as FLAGS */
2038  pc += 13;
2039  pc = get_flags(&(mdata->flags), pc);
2040  if (!pc)
2041  goto fail;
2042  }
2043  /* save UIDVALIDITY for the header cache */
2044  else if (mutt_str_startswith(pc, "OK [UIDVALIDITY", CASE_IGNORE))
2045  {
2046  mutt_debug(LL_DEBUG3, "Getting mailbox UIDVALIDITY\n");
2047  pc += 3;
2048  pc = imap_next_word(pc);
2049  if (mutt_str_atoui(pc, &mdata->uid_validity) < 0)
2050  goto fail;
2051  }
2052  else if (mutt_str_startswith(pc, "OK [UIDNEXT", CASE_IGNORE))
2053  {
2054  mutt_debug(LL_DEBUG3, "Getting mailbox UIDNEXT\n");
2055  pc += 3;
2056  pc = imap_next_word(pc);
2057  if (mutt_str_atoui(pc, &mdata->uid_next) < 0)
2058  goto fail;
2059  }
2060  else if (mutt_str_startswith(pc, "OK [HIGHESTMODSEQ", CASE_IGNORE))
2061  {
2062  mutt_debug(LL_DEBUG3, "Getting mailbox HIGHESTMODSEQ\n");
2063  pc += 3;
2064  pc = imap_next_word(pc);
2065  if (mutt_str_atoull(pc, &mdata->modseq) < 0)
2066  goto fail;
2067  }
2068  else if (mutt_str_startswith(pc, "OK [NOMODSEQ", CASE_IGNORE))
2069  {
2070  mutt_debug(LL_DEBUG3, "Mailbox has NOMODSEQ set\n");
2071  mdata->modseq = 0;
2072  }
2073  else
2074  {
2075  pc = imap_next_word(pc);
2076  if (mutt_str_startswith(pc, "EXISTS", CASE_IGNORE))
2077  {
2078  count = mdata->new_mail_count;
2079  mdata->new_mail_count = 0;
2080  }
2081  }
2082  } while (rc == IMAP_RES_CONTINUE);
2083 
2084  if (rc == IMAP_RES_NO)
2085  {
2086  char *s = imap_next_word(adata->buf); /* skip seq */
2087  s = imap_next_word(s); /* Skip response */
2088  mutt_error("%s", s);
2089  goto fail;
2090  }
2091 
2092  if (rc != IMAP_RES_OK)
2093  goto fail;
2094 
2095  /* check for READ-ONLY notification */
2096  if (mutt_str_startswith(imap_get_qualifier(adata->buf), "[READ-ONLY]", CASE_IGNORE) &&
2097  !(adata->capabilities & IMAP_CAP_ACL))
2098  {
2099  mutt_debug(LL_DEBUG2, "Mailbox is read-only\n");
2100  m->readonly = true;
2101  }
2102 
2103  /* dump the mailbox flags we've found */
2104  if (C_DebugLevel > LL_DEBUG2)
2105  {
2106  if (STAILQ_EMPTY(&mdata->flags))
2107  mutt_debug(LL_DEBUG3, "No folder flags found\n");
2108  else
2109  {
2110  struct ListNode *np = NULL;
2111  struct Buffer flag_buffer;
2112  mutt_buffer_init(&flag_buffer);
2113  mutt_buffer_printf(&flag_buffer, "Mailbox flags: ");
2114  STAILQ_FOREACH(np, &mdata->flags, entries)
2115  {
2116  mutt_buffer_add_printf(&flag_buffer, "[%s] ", np->data);
2117  }
2118  mutt_debug(LL_DEBUG3, "%s\n", flag_buffer.data);
2119  FREE(&flag_buffer.data);
2120  }
2121  }
2122 
2123  if (!((m->rights & MUTT_ACL_DELETE) || (m->rights & MUTT_ACL_SEEN) ||
2124  (m->rights & MUTT_ACL_WRITE) || (m->rights & MUTT_ACL_INSERT)))
2125  {
2126  m->readonly = true;
2127  }
2128 
2129  m->email_max = count;
2130  m->emails = mutt_mem_calloc(count, sizeof(struct Email *));
2131  m->v2r = mutt_mem_calloc(count, sizeof(int));
2132  m->msg_count = 0;
2133  m->msg_unread = 0;
2134  m->msg_flagged = 0;
2135  m->msg_new = 0;
2136  m->msg_deleted = 0;
2137  m->size = 0;
2138  m->vcount = 0;
2139 
2140  if (count && (imap_read_headers(m, 1, count, true) < 0))
2141  {
2142  mutt_error(_("Error opening mailbox"));
2143  goto fail;
2144  }
2145 
2146  mutt_debug(LL_DEBUG2, "msg_count is %d\n", m->msg_count);
2147  return 0;
2148 
2149 fail:
2150  if (adata->state == IMAP_SELECTED)
2151  adata->state = IMAP_AUTHENTICATED;
2152  return -1;
2153 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
int msg_count
Total number of messages.
Definition: mailbox.h:102
off_t size
Size of the Mailbox.
Definition: mailbox.h:98
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1072
#define IMAP_CAP_ACL
RFC2086: IMAP4 ACL extension.
Definition: imap_private.h:123
The envelope/body of an email.
Definition: email.h:39
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:107
int msg_unread
Number of unread messages.
Definition: mailbox.h:103
#define MUTT_ACL_READ
Read the mailbox.
Definition: mailbox.h:83
Mailbox is selected.
Definition: imap_private.h:107
#define mutt_message(...)
Definition: logging.h:83
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:104
#define MUTT_ACL_CREATE
Create a mailbox.
Definition: mailbox.h:76
struct ConnAccount conn_account
Definition: imap_private.h:169
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: imap_private.h:172
String manipulation buffer.
Definition: buffer.h:33
#define MUTT_ACL_INSERT
Add/copy into the mailbox (used when editing a message)
Definition: mailbox.h:80
#define _(a)
Definition: message.h:28
struct Mailbox * mailbox
Definition: imap_private.h:205
int imap_cmd_start(struct ImapAccountData *adata, const char *cmdstr)
Given an IMAP command, send it to the server.
Definition: command.c:1058
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)
XXX.
Definition: mx.c:1516
#define MUTT_ACL_DELETE
Delete a message.
Definition: mailbox.h:77
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:123
static char * get_flags(struct ListHead *hflags, char *s)
Make a simple list out of a FLAGS response.
Definition: imap.c:104
int vcount
The number of virtual messages.
Definition: mailbox.h:113
unsigned int new_mail_count
Set when EXISTS notifies of new mail.
Definition: imap_private.h:221
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: util.c:242
Log at debug level 2.
Definition: logging.h:57
bool readonly
Don&#39;t allow changes to the mailbox.
Definition: mailbox.h:130
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:82
void * mdata
Driver specific data.
Definition: mailbox.h:147
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:85
unsigned long long modseq
Definition: imap_private.h:227
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:1242
char * imap_next_word(char *s)
Find where the next IMAP word begins.
Definition: util.c:897
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:111
A mailbox.
Definition: mailbox.h:92
#define PATH_MAX
Definition: mutt.h:52
#define IMAP_RES_NO
<tag> NO ...
Definition: imap_private.h:52
struct ListHead flags
Definition: imap_private.h:224
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
unsigned char status
ImapFlags, e.g. IMAP_FATAL.
Definition: imap_private.h:173
Connection is authenticated.
Definition: imap_private.h:106
char * name
Mailbox name.
Definition: imap_private.h:215
bool mutt_account_match(const struct ConnAccount *a1, const struct ConnAccount *a2)
Compare account info (host/port/user)
Definition: mutt_account.c:61
int mutt_str_atoui(const char *str, unsigned int *dst)
Convert ASCII string to an unsigned integer.
Definition: string.c:292
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:114
Ignore case when comparing strings.
Definition: string2.h:68
WHERE bool C_ImapCheckSubscribed
Config: (imap) When opening a mailbox, ask the server for a list of subscribed folders.
Definition: globals.h:229
int mutt_str_atoull(const char *str, unsigned long long *dst)
Convert ASCII string to an unsigned long long.
Definition: string.c:353
int imap_mailbox_status(struct Mailbox *m, bool queue)
Refresh the number of total and new messages.
Definition: imap.c:1334
ImapCapFlags capabilities
Definition: imap_private.h:183
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:132
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
char * imap_get_qualifier(char *buf)
Get the qualifier from a tagged response.
Definition: util.c:880
WHERE bool C_ImapCondstore
Config: (imap) Enable the CONDSTORE extension.
Definition: globals.h:230
unsigned int uid_validity
Definition: imap_private.h:225
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
#define IMAP_RES_CONTINUE
* ...
Definition: imap_private.h:55
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:112
#define IMAP_CAP_CONDSTORE
RFC7162.
Definition: imap_private.h:134
IMAP-specific Account data -.
Definition: imap_private.h:166
unsigned int uid_next
Definition: imap_private.h:226
char * data
String.
Definition: list.h:35
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:142
IMAP-specific Mailbox data -.
Definition: imap_private.h:213
int msg_new
Number of new messages.
Definition: mailbox.h:106
#define IMAP_CMD_QUEUE
Queue a command, do not execute.
Definition: imap_private.h:73
#define mutt_error(...)
Definition: logging.h:84
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:1265
#define FREE(x)
Definition: memory.h:40
#define MUTT_ACL_SEEN
Change the &#39;seen&#39; status of a message.
Definition: mailbox.h:84
#define STAILQ_EMPTY(head)
Definition: queue.h:346
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:46
WHERE char * C_Postponed
Config: Folder to store postponed messages.
Definition: globals.h:139
A List node for strings.
Definition: list.h:33
char * munge_name
Munged version of the mailbox name.
Definition: imap_private.h:216
Log at debug level 3.
Definition: logging.h:58
#define MUTT_ACL_LOOKUP
Lookup mailbox (visible to &#39;list&#39;)
Definition: mailbox.h:81
#define IMAP_RES_OK
<tag> OK ...
Definition: imap_private.h:54
+ 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 2158 of file imap.c.

2159 {
2160  if (!m || !m->account)
2161  return -1;
2162 
2163  /* in APPEND mode, we appear to hijack an existing IMAP connection -
2164  * ctx is brand new and mostly empty */
2165  struct ImapAccountData *adata = imap_adata_get(m);
2166  struct ImapMboxData *mdata = imap_mdata_get(m);
2167 
2168  int rc = imap_mailbox_status(m, false);
2169  if (rc >= 0)
2170  return 0;
2171  if (rc == -1)
2172  return -1;
2173 
2174  char buf[PATH_MAX + 64];
2175  snprintf(buf, sizeof(buf), _("Create %s?"), mdata->name);
2176  if (C_Confirmcreate && (mutt_yesorno(buf, MUTT_YES) != MUTT_YES))
2177  return -1;
2178 
2179  if (imap_create_mailbox(adata, mdata->name) < 0)
2180  return -1;
2181 
2182  return 0;
2183 }
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
#define _(a)
Definition: message.h:28
WHERE bool C_Confirmcreate
Config: Confirm before creating a new mailbox.
Definition: globals.h:215
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: util.c:242
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:332
void * mdata
Driver specific data.
Definition: mailbox.h:147
#define PATH_MAX
Definition: mutt.h:52
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
char * name
Mailbox name.
Definition: imap_private.h:215
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:114
int imap_mailbox_status(struct Mailbox *m, bool queue)
Refresh the number of total and new messages.
Definition: imap.c:1334
int imap_create_mailbox(struct ImapAccountData *adata, char *mailbox)
Create a new mailbox.
Definition: imap.c:573
IMAP-specific Account data -.
Definition: imap_private.h:166
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:142
IMAP-specific Mailbox data -.
Definition: imap_private.h:213
+ Here is the call graph for this function:

◆ imap_mbox_check()

static int imap_mbox_check ( struct Mailbox m,
int *  index_hint 
)
static

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

Parameters
mMailbox
index_hintRemember our place in the index
Return values
>0Success, e.g. MUTT_REOPENED
-1Failure

Definition at line 2192 of file imap.c.

2193 {
2194  if (!m)
2195  return -1;
2196 
2197  imap_allow_reopen(m);
2198  int rc = imap_check_mailbox(m, false);
2199  /* NOTE - ctx might have been changed at this point. In particular,
2200  * m could be NULL. Beware. */
2202 
2203  return rc;
2204 }
void imap_disallow_reopen(struct Mailbox *m)
Disallow re-opening a folder upon expunge.
Definition: util.c:1137
int imap_check_mailbox(struct Mailbox *m, bool force)
use the NOOP or IDLE command to poll for new mail
Definition: imap.c:1186
void imap_allow_reopen(struct Mailbox *m)
Allow re-opening a folder upon expunge.
Definition: util.c:1124
+ 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 2209 of file imap.c.

2210 {
2211  if (!m)
2212  return -1;
2213 
2214  struct ImapAccountData *adata = imap_adata_get(m);
2215  struct ImapMboxData *mdata = imap_mdata_get(m);
2216 
2217  /* Check to see if the mailbox is actually open */
2218  if (!adata || !mdata)
2219  return 0;
2220 
2221  /* imap_mbox_open_append() borrows the struct ImapAccountData temporarily,
2222  * just for the connection.
2223  *
2224  * So when these are equal, it means we are actually closing the
2225  * mailbox and should clean up adata. Otherwise, we don't want to
2226  * touch adata - it's still being used. */
2227  if (m == adata->mailbox)
2228  {
2229  if ((adata->status != IMAP_FATAL) && (adata->state >= IMAP_SELECTED))
2230  {
2231  /* mx_mbox_close won't sync if there are no deleted messages
2232  * and the mailbox is unchanged, so we may have to close here */
2233  if (m->msg_deleted == 0)
2234  {
2235  adata->closing = true;
2236  imap_exec(adata, "CLOSE", IMAP_CMD_QUEUE);
2237  }
2238  adata->state = IMAP_AUTHENTICATED;
2239  }
2240 
2241  adata->mailbox = NULL;
2243  }
2244 
2245  return 0;
2246 }
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:107
Mailbox is selected.
Definition: imap_private.h:107
unsigned char state
ImapState, e.g. IMAP_AUTHENTICATED.
Definition: imap_private.h:172
struct Mailbox * mailbox
Definition: imap_private.h:205
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: util.c:242
void * mdata
Driver specific data.
Definition: mailbox.h:147
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:1242
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
unsigned char status
ImapFlags, e.g. IMAP_FATAL.
Definition: imap_private.h:173
Connection is authenticated.
Definition: imap_private.h:106
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:114
IMAP-specific Account data -.
Definition: imap_private.h:166
IMAP-specific Mailbox data -.
Definition: imap_private.h:213
#define IMAP_CMD_QUEUE
Queue a command, do not execute.
Definition: imap_private.h:73
Unrecoverable error occurred.
Definition: imap_private.h:94
void imap_mdata_cache_reset(struct ImapMboxData *mdata)
Release and clear cache data of ImapMboxData structure.
Definition: util.c:211
+ 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 2251 of file imap.c.

2252 {
2253  char tmp[PATH_MAX];
2254 
2255  mutt_mktemp(tmp, sizeof(tmp));
2256  msg->fp = mutt_file_fopen(tmp, "w");
2257  if (!msg->fp)
2258  {
2259  mutt_perror(tmp);
2260  return -1;
2261  }
2262  msg->path = mutt_str_strdup(tmp);
2263  return 0;
2264 }
#define mutt_perror(...)
Definition: logging.h:85
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:76
#define PATH_MAX
Definition: mutt.h:52
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
FILE * fp
pointer to the message data
Definition: mx.h:83
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:583
char * path
path to temp file
Definition: mx.h:84
+ 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 2269 of file imap.c.

2270 {
2271  struct ImapMboxData *mdata = imap_mdata_get(m);
2272  if (!mdata)
2273  return -1;
2274 
2275  char *new_tag = NULL;
2276  char *checker = NULL;
2277 
2278  /* Check for \* flags capability */
2279  if (!imap_has_flag(&mdata->flags, NULL))
2280  {
2281  mutt_error(_("IMAP server doesn't support custom flags"));
2282  return -1;
2283  }
2284 
2285  *buf = '\0';
2286  if (tags)
2287  mutt_str_strfcpy(buf, tags, buflen);
2288 
2289  if (mutt_get_field("Tags: ", buf, buflen, 0) != 0)
2290  return -1;
2291 
2292  /* each keyword must be atom defined by rfc822 as:
2293  *
2294  * atom = 1*<any CHAR except specials, SPACE and CTLs>
2295  * CHAR = ( 0.-127. )
2296  * specials = "(" / ")" / "<" / ">" / "@"
2297  * / "," / ";" / ":" / "\" / <">
2298  * / "." / "[" / "]"
2299  * SPACE = ( 32. )
2300  * CTLS = ( 0.-31., 127.)
2301  *
2302  * And must be separated by one space.
2303  */
2304 
2305  new_tag = buf;
2306  checker = buf;
2307  SKIPWS(checker);
2308  while (*checker != '\0')
2309  {
2310  if ((*checker < 32) || (*checker >= 127) || // We allow space because it's the separator
2311  (*checker == 40) || // (
2312  (*checker == 41) || // )
2313  (*checker == 60) || // <
2314  (*checker == 62) || // >
2315  (*checker == 64) || // @
2316  (*checker == 44) || // ,
2317  (*checker == 59) || // ;
2318  (*checker == 58) || // :
2319  (*checker == 92) || // backslash
2320  (*checker == 34) || // "
2321  (*checker == 46) || // .
2322  (*checker == 91) || // [
2323  (*checker == 93)) // ]
2324  {
2325  mutt_error(_("Invalid IMAP flags"));
2326  return 0;
2327  }
2328 
2329  /* Skip duplicate space */
2330  while ((checker[0] == ' ') && (checker[1] == ' '))
2331  checker++;
2332 
2333  /* copy char to new_tag and go the next one */
2334  *new_tag++ = *checker++;
2335  }
2336  *new_tag = '\0';
2337  new_tag = buf; /* rewind */
2338  mutt_str_remove_trailing_ws(new_tag);
2339 
2340  if (mutt_str_strcmp(tags, buf) == 0)
2341  return 0;
2342  return 1;
2343 }
#define _(a)
Definition: message.h:28
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:86
struct ImapMboxData * imap_mdata_get(struct Mailbox *m)
Get the Mailbox data for this mailbox.
Definition: util.c:242
bool imap_has_flag(struct ListHead *flag_list, const char *flag)
Does the flag exist in the list.
Definition: imap.c:963
#define SKIPWS(ch)
Definition: string2.h:47
void * mdata
Driver specific data.
Definition: mailbox.h:147
void mutt_str_remove_trailing_ws(char *s)
Trim trailing whitespace from a string.
Definition: string.c:734
struct ListHead flags
Definition: imap_private.h:224
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
IMAP-specific Mailbox data -.
Definition: imap_private.h:213
#define mutt_error(...)
Definition: logging.h:84
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
+ 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 2358 of file imap.c.

2359 {
2360  if (!m)
2361  return -1;
2362 
2363  char uid[11];
2364 
2365  struct ImapAccountData *adata = imap_adata_get(m);
2366 
2367  if (*buf == '\0')
2368  buf = NULL;
2369 
2370  if (!(adata->mailbox->rights & MUTT_ACL_WRITE))
2371  return 0;
2372 
2373  snprintf(uid, sizeof(uid), "%u", imap_edata_get(e)->uid);
2374 
2375  /* Remove old custom flags */
2376  if (imap_edata_get(e)->flags_remote)
2377  {
2378  struct Buffer cmd = mutt_buffer_make(128); // just a guess
2379  mutt_buffer_addstr(&cmd, "UID STORE ");
2380  mutt_buffer_addstr(&cmd, uid);
2381  mutt_buffer_addstr(&cmd, " -FLAGS.SILENT (");
2382  mutt_buffer_addstr(&cmd, imap_edata_get(e)->flags_remote);
2383  mutt_buffer_addstr(&cmd, ")");
2384 
2385  /* Should we return here, or we are fine and we could
2386  * continue to add new flags */
2387  int rc = imap_exec(adata, cmd.data, IMAP_CMD_NO_FLAGS);
2388  mutt_buffer_dealloc(&cmd);
2389  if (rc != IMAP_EXEC_SUCCESS)
2390  {
2391  return -1;
2392  }
2393  }
2394 
2395  /* Add new custom flags */
2396  if (buf)
2397  {
2398  struct Buffer cmd = mutt_buffer_make(128); // just a guess
2399  mutt_buffer_addstr(&cmd, "UID STORE ");
2400  mutt_buffer_addstr(&cmd, uid);
2401  mutt_buffer_addstr(&cmd, " +FLAGS.SILENT (");
2402  mutt_buffer_addstr(&cmd, buf);
2403  mutt_buffer_addstr(&cmd, ")");
2404 
2405  int rc = imap_exec(adata, cmd.data, IMAP_CMD_NO_FLAGS);
2406  mutt_buffer_dealloc(&cmd);
2407  if (rc != IMAP_EXEC_SUCCESS)
2408  {
2409  mutt_debug(LL_DEBUG1, "fail to add new flags\n");
2410  return -1;
2411  }
2412  }
2413 
2414  /* We are good sync them */
2415  mutt_debug(LL_DEBUG1, "NEW TAGS: %s\n", buf);
2416  driver_tags_replace(&e->tags, buf);
2417  FREE(&imap_edata_get(e)->flags_remote);
2419  return 0;
2420 }
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
Definition: imap_private.h:205
Imap command executed or queued successfully.
Definition: imap_private.h:81
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:293
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:85
struct TagList tags
For drivers that support server tagging.
Definition: email.h:108
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:1242
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
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:114
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:132
IMAP-specific Account data -.
Definition: imap_private.h:166
char * driver_tags_get_with_hidden(struct TagList *list)
Get tags with hiddens.
Definition: tags.c:154
Log at debug level 1.
Definition: logging.h:56
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: imap_private.h:71
#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:182
+ 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 2425 of file imap.c.

2426 {
2427  if (!path)
2428  return MUTT_UNKNOWN;
2429 
2430  if (mutt_str_startswith(path, "imap://", CASE_IGNORE))
2431  return MUTT_IMAP;
2432 
2433  if (mutt_str_startswith(path, "imaps://", CASE_IGNORE))
2434  return MUTT_IMAP;
2435 
2436  return MUTT_UNKNOWN;
2437 }
Mailbox wasn&#39;t recognised.
Definition: mailbox.h:46
Ignore case when comparing strings.
Definition: string2.h:68
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:52
+ 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 2442 of file imap.c.

2443 {
2444  if (!buf)
2445  return -1;
2446 
2447  struct Url *url = url_parse(buf);
2448  if (!url)
2449  return 0;
2450 
2451  char tmp[PATH_MAX];
2452  char tmp2[PATH_MAX];
2453 
2454  imap_fix_path('\0', url->path, tmp, sizeof(tmp));
2455  url->path = tmp;
2456  url_tostring(url, tmp2, sizeof(tmp2), 0);
2457  mutt_str_strfcpy(buf, tmp2, buflen);
2458  url_free(&url);
2459 
2460  return 0;
2461 }
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:66
int url_tostring(struct Url *u, char *dest, size_t len, int flags)
Output the URL string for a given Url object.
Definition: url.c:399
#define PATH_MAX
Definition: mutt.h:52
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
char * imap_fix_path(char delim, const char *mailbox, char *path, size_t plen)
Fix up the imap path.
Definition: util.c:779
char * path
Path.
Definition: url.h:73
void url_free(struct Url **u)
Free the contents of a URL.
Definition: url.c:288
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:161
+ 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 2471 of file imap.c.

2472 {
2474  return imap_path_canon(buf->data, PATH_MAX);
2475 }
#define PATH_MAX
Definition: mutt.h:52
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:2442
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()

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

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

Definition at line 2480 of file imap.c.

2481 {
2482  if (!buf || !folder)
2483  return -1;
2484 
2485  imap_pretty_mailbox(buf, buflen, folder);
2486  return 0;
2487 }
void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder)
Prettify an IMAP mailbox name.
Definition: util.c:688
+ Here is the call graph for this function:

◆ imap_path_parent()

int imap_path_parent ( char *  buf,
size_t  buflen 
)

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

Definition at line 2492 of file imap.c.

2493 {
2494  char tmp[PATH_MAX] = { 0 };
2495 
2496  imap_get_parent_path(buf, tmp, sizeof(tmp));
2497  mutt_str_strfcpy(buf, tmp, buflen);
2498  return 0;
2499 }
void imap_get_parent_path(const char *path, char *buf, size_t buflen)
Get the path of the parent folder.
Definition: util.c:299
#define PATH_MAX
Definition: mutt.h:52
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
+ Here is the call graph for this function:

Variable Documentation

◆ C_ImapIdle

bool C_ImapIdle

Config: (imap) Use the IMAP IDLE extension to check for new mail.

Definition at line 65 of file imap.c.

◆ C_ImapRfc5161

bool C_ImapRfc5161

Config: (imap) Use the IMAP ENABLE extension to select capabilities.

Definition at line 69 of file imap.c.

◆ MxImapOps

struct MxOps MxImapOps
Initial value:
= {
.magic = MUTT_IMAP,
.name = "imap",
.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_path_pretty(char *buf, size_t buflen, const char *folder)
Abbreviate a Mailbox path - Implements MxOps::path_pretty()
Definition: imap.c:2480
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2425
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:2269
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:2251
static int imap_mbox_open(struct Mailbox *m)
Open a mailbox - Implements MxOps::mbox_open()
Definition: imap.c:1949
int imap_msg_commit(struct Mailbox *m, struct Message *msg)
Save changes to an email - Implements MxOps::msg_commit()
Definition: message.c:2061
int imap_msg_close(struct Mailbox *m, struct Message *msg)
Close an email - Implements MxOps::msg_close()
Definition: message.c:2075
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:2083
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:1856
static int imap_mbox_check(struct Mailbox *m, int *index_hint)
Check for new mail - Implements MxOps::mbox_check()
Definition: imap.c:2192
static int imap_mbox_close(struct Mailbox *m)
Close a Mailbox - Implements MxOps::mbox_close()
Definition: imap.c:2209
int imap_path_parent(char *buf, size_t buflen)
Find the parent of a Mailbox path - Implements MxOps::path_parent()
Definition: imap.c:2492
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:2358
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:1815
int imap_path_canon(char *buf, size_t buflen)
Canonicalise a Mailbox path - Implements MxOps::path_canon()
Definition: imap.c:2442
int imap_mbox_check_stats(struct Mailbox *m, int flags)
Check the Mailbox statistics - Implements MxOps::mbox_check_stats()
Definition: imap.c:1295
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:52
static int imap_mbox_open_append(struct Mailbox *m, OpenMailboxFlags flags)
Open a Mailbox for appending - Implements MxOps::mbox_open_append()
Definition: imap.c:2158
int imap_ac_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account - Implements MxOps::ac_add()
Definition: imap.c:1838

IMAP Mailbox - Implements MxOps.

Definition at line 2505 of file imap.c.