X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=imap%2Fimap.c;h=43c2426fdcd7099dbead8641916a578ae98173ce;hp=e7fcb773569e516154209abed36d827596347a68;hb=8fac066483c9ae3176984527c037190fca9dc7f0;hpb=ecaab35b973fbceb58b5ed174971c82762cc0199 diff --git a/imap/imap.c b/imap/imap.c index e7fcb77..43c2426 100644 --- a/imap/imap.c +++ b/imap/imap.c @@ -11,40 +11,21 @@ /* Support for IMAP4rev1, with the occasional nod to IMAP 4. */ -#if HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include +#include +#include #include "mutt.h" -#include "buffer.h" -#include "mx.h" #include "globals.h" +#include "pattern.h" #include "sort.h" #include "browser.h" #include "message.h" #include "imap_private.h" -#if defined(USE_SSL) || defined(USE_GNUTLS) -# include "mutt_ssl.h" -#endif #include "buffy.h" -#include -#include "lib/debug.h" - -#include -#include -#include -#include -#include -#include - /* imap forward declarations */ static int imap_get_delim (IMAP_DATA * idata); -static char *imap_get_flags (LIST ** hflags, char *s); +static char *imap_get_flags (string_list_t ** hflags, char *s); static int imap_check_acl (IMAP_DATA * idata); static int imap_check_capabilities (IMAP_DATA * idata); static void imap_set_flag (IMAP_DATA * idata, int aclbit, int flag, @@ -53,7 +34,7 @@ static void imap_set_flag (IMAP_DATA * idata, int aclbit, int flag, /* imap_access: Check permissions on an IMAP mailbox. * TODO: ACL checks. Right now we assume if it exists we can * mess with it. */ -int imap_access (const char *path, int flags) +static int imap_access (const char *path, int flags __attribute__ ((unused))) { IMAP_DATA *idata; IMAP_MBOX mx; @@ -74,7 +55,7 @@ int imap_access (const char *path, int flags) imap_fix_path (idata, mx.mbox, mailbox, sizeof (mailbox)); /* we may already be in the folder we're checking */ - if (!ascii_strcmp(idata->mailbox, mx.mbox)) { + if (!m_strcmp(idata->mailbox, mx.mbox)) { p_delete(&mx.mbox); return 0; } @@ -87,12 +68,10 @@ int imap_access (const char *path, int flags) else if (mutt_bit_isset (idata->capabilities, STATUS)) snprintf (buf, sizeof (buf), "STATUS %s (UID-VALIDITY)", mbox); else { - debug_print (2, ("STATUS not supported?\n")); return -1; } if (imap_exec (idata, buf, IMAP_CMD_FAIL_OK) < 0) { - debug_print (1, ("Can't check STATUS of %s\n", mbox)); return -1; } @@ -190,17 +169,13 @@ int imap_read_literal (FILE * fp, IMAP_DATA * idata, long bytes, progress_t* bar int r = 0; - debug_print (2, ("reading %ld bytes\n", bytes)); - for (pos = 0; pos < bytes; pos++) { if (mutt_socket_readchar (idata->conn, &c) != 1) { - debug_print (1, ("error during read, %ld bytes read\n", pos)); idata->status = IMAP_FATAL; return -1; } -#if 1 if (r == 1 && c != '\n') fputc ('\r', fp); @@ -210,14 +185,10 @@ int imap_read_literal (FILE * fp, IMAP_DATA * idata, long bytes, progress_t* bar } else r = 0; -#endif + fputc (c, fp); if (bar && !(pos % 1024)) mutt_progress_bar (bar, pos); -#ifdef DEBUG - if (DebugFile && DebugLevel >= IMAP_LOG_LTRL) - fputc (c, DebugFile); -#endif } return 0; @@ -235,8 +206,6 @@ void imap_expunge_mailbox (IMAP_DATA * idata) h = idata->ctx->hdrs[i]; if (h->index == -1) { - debug_print (2, ("Expunging message UID %d.\n", HEADER_DATA (h)->uid)); - h->active = 0; /* free cached body from disk, if neccessary */ @@ -266,7 +235,7 @@ static int imap_get_delim (IMAP_DATA * idata) * than getting the delim wrong */ idata->delim = '/'; - imap_cmd_start (idata, "LIST \"\" \"\""); + imap_cmd_start (idata, "LIST\"\" \"\""); do { if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE) @@ -285,13 +254,6 @@ static int imap_get_delim (IMAP_DATA * idata) } while (rc == IMAP_CMD_CONTINUE); - if (rc != IMAP_CMD_OK) { - debug_print (1, ("failed.\n")); - return -1; - } - - debug_print (2, ("Delimiter: %c\n", idata->delim)); - return -1; } @@ -382,11 +344,9 @@ IMAP_DATA *imap_conn_find (const ACCOUNT * account, int flags) if (idata->state == IMAP_CONNECTED) { if (!imap_authenticate (idata)) { idata->state = IMAP_AUTHENTICATED; - if (idata->conn->ssf) - debug_print (2, ("Communication encrypted at %d bits\n", idata->conn->ssf)); - } - else + } else { mutt_account_unsetpass (&idata->conn->account); + } p_delete(&idata->capstr); } @@ -420,7 +380,6 @@ int imap_open_connection (IMAP_DATA * idata) /* TODO: Parse new tagged CAPABILITY data (* OK [CAPABILITY...]) */ if (imap_check_capabilities (idata)) goto bail; -#if defined(USE_SSL) || defined(USE_GNUTLS) /* Attempt STARTTLS if available and desired. */ if (!idata->conn->ssf && (option(OPTSSLFORCETLS) || mutt_bit_isset (idata->capabilities, STARTTLS))) { @@ -435,9 +394,7 @@ int imap_open_connection (IMAP_DATA * idata) if ((rc = imap_exec (idata, "STARTTLS", IMAP_CMD_FAIL_OK)) == -1) goto bail; if (rc != -2) { -#if defined (USE_SSL) || defined (USE_GNUTLS) if (mutt_ssl_starttls (idata->conn)) -#endif { mutt_error (_("Could not negotiate TLS connection")); mutt_sleep (1); @@ -457,7 +414,6 @@ int imap_open_connection (IMAP_DATA * idata) mutt_sleep (1); goto err_close_conn; } -#endif } else if (ascii_strncasecmp ("* PREAUTH", idata->cmd.buf, 9) == 0) { idata->state = IMAP_AUTHENTICATED; @@ -482,31 +438,27 @@ bail: /* imap_get_flags: Make a simple list out of a FLAGS response. * return stream following FLAGS response */ -static char *imap_get_flags (LIST ** hflags, char *s) +static char *imap_get_flags (string_list_t ** hflags, char *s) { - LIST *flags; + string_list_t *flags; char *flag_word; char ctmp; /* sanity-check string */ if (ascii_strncasecmp ("FLAGS", s, 5) != 0) { - debug_print (1, ("not a FLAGS response: %s\n", s)); return NULL; } - s += 5; - SKIPWS (s); + s = vskipspaces(s + 5); if (*s != '(') { - debug_print (1, ("bogus FLAGS response: %s\n", s)); return NULL; } /* create list, update caller's flags handle */ - flags = mutt_new_list (); + flags = string_item_new(); *hflags = flags; while (*s && *s != ')') { - s++; - SKIPWS (s); + s = vskipspaces(s + 1); flag_word = s; while (*s && (*s != ')') && !ISSPACE (*s)) s++; @@ -519,8 +471,7 @@ static char *imap_get_flags (LIST ** hflags, char *s) /* note bad flags response */ if (*s != ')') { - debug_print (1, ("Unterminated FLAGS response: %s\n", s)); - mutt_free_list (hflags); + string_list_wipe(hflags); return NULL; } @@ -530,7 +481,7 @@ static char *imap_get_flags (LIST ** hflags, char *s) return s; } -int imap_open_mailbox (CONTEXT * ctx) +static int imap_open_mailbox (CONTEXT * ctx) { CONNECTION *conn; IMAP_DATA *idata; @@ -594,16 +545,14 @@ int imap_open_mailbox (CONTEXT * ctx) if (ascii_strncasecmp ("FLAGS", pc, 5) == 0) { /* don't override PERMANENTFLAGS */ if (!idata->flags) { - debug_print (2, ("Getting mailbox FLAGS\n")); if ((pc = imap_get_flags (&(idata->flags), pc)) == NULL) goto fail; } } /* PERMANENTFLAGS are massaged to look like FLAGS, then override FLAGS */ else if (ascii_strncasecmp ("OK [PERMANENTFLAGS", pc, 18) == 0) { - debug_print (2, ("Getting mailbox PERMANENTFLAGS\n")); /* safe to call on NULL */ - mutt_free_list (&(idata->flags)); + string_list_wipe(&(idata->flags)); /* skip "OK [PERMANENT" so syntax is the same as FLAGS */ pc += 13; if ((pc = imap_get_flags (&(idata->flags), pc)) == NULL) @@ -612,7 +561,6 @@ int imap_open_mailbox (CONTEXT * ctx) #ifdef USE_HCACHE /* save UIDVALIDITY for the header cache */ else if (ascii_strncasecmp ("OK [UIDVALIDITY", pc, 14) == 0) { - debug_print (2, ("Getting mailbox UIDVALIDITY\n")); pc += 3; pc = imap_next_word (pc); @@ -646,29 +594,9 @@ int imap_open_mailbox (CONTEXT * ctx) if (!ascii_strncasecmp (imap_get_qualifier (idata->cmd.buf), "[READ-ONLY]", 11) && !mutt_bit_isset (idata->capabilities, ACL)) { - debug_print (2, ("Mailbox is read-only.\n")); ctx->readonly = 1; } -#ifdef DEBUG - /* dump the mailbox flags we've found */ - if (DebugLevel > 2) { - if (!idata->flags) - debug_print (3, ("No folder flags found\n")); - else { - LIST *t = idata->flags; - - debug_print (3, ("Mailbox flags:\n")); - - t = t->next; - while (t) { - debug_print (3, ("[%s]\n", t->data)); - t = t->next; - } - } - } -#endif - if (mutt_bit_isset (idata->capabilities, ACL)) { if (imap_check_acl (idata)) goto fail; @@ -701,7 +629,6 @@ int imap_open_mailbox (CONTEXT * ctx) goto fail; } - debug_print (2, ("msgcount is %d\n", ctx->msgcount)); p_delete(&mx.mbox); return 0; @@ -769,7 +696,6 @@ void imap_logout (IMAP_DATA * idata) /* int imap_close_connection (CONTEXT *ctx) { - debug_print (1, (debugfile, "imap_close_connection(): closing connection\n")); if (CTX_DATA->status != IMAP_BYE) { mutt_message _("Closing connection to IMAP server..."); @@ -785,12 +711,13 @@ int imap_close_connection (CONTEXT *ctx) /* imap_set_flag: append str to flags if we currently have permission * according to aclbit */ -static void imap_set_flag (IMAP_DATA * idata, int aclbit, int flag, - const char *str, char *flags, size_t flsize) +static void imap_set_flag(IMAP_DATA *idata, int aclbit, int flag, + const char *str, char *flags, size_t flsize) { - if (mutt_bit_isset (idata->rights, aclbit)) - if (flag) - str_cat (flags, flsize, str); + if (mutt_bit_isset(idata->rights, aclbit)) { + if (flag) + m_strcat(flags, flsize, str); + } } /* imap_make_msg_set: make an IMAP4rev1 UID message set out of a set of @@ -806,7 +733,7 @@ int imap_make_msg_set (IMAP_DATA * idata, BUFFER * buf, int flag, int changed) HEADER **hdrs; /* sorted local copy */ int count = 0; /* number of messages in message set */ int match = 0; /* whether current message matches flag condition */ - unsigned int setstart = 0; /* start of current message range */ + int setstart = 0; /* start of current message range */ int n; short oldsort; /* we clobber reverse, must restore it */ @@ -905,7 +832,7 @@ int imap_sync_message (IMAP_DATA *idata, HEADER *hdr, BUFFER *cmd, if (mutt_bit_isset (idata->rights, ACL_WRITE)) imap_add_keywords (flags, hdr, idata->flags, sizeof (flags)); - str_skip_trailws (flags); + m_strrtrim(flags); /* UW-IMAP is OK with null flags, Cyrus isn't. The only solution is to * explicitly revoke all system flags (if we have permission) */ @@ -916,7 +843,7 @@ int imap_sync_message (IMAP_DATA *idata, HEADER *hdr, BUFFER *cmd, imap_set_flag (idata, ACL_WRITE, 1, "\\Answered ", flags, sizeof (flags)); imap_set_flag (idata, ACL_DELETE, 1, "\\Deleted ", flags, sizeof (flags)); - str_skip_trailws (flags); + m_strrtrim(flags); mutt_buffer_addstr (cmd, " -FLAGS.SILENT ("); } else @@ -964,7 +891,6 @@ int imap_sync_mailbox (CONTEXT * ctx, int expunge, int *index_hint) idata = (IMAP_DATA *) ctx->data; if (idata->state != IMAP_SELECTED) { - debug_print (2, ("no mailbox selected\n")); return -1; } @@ -975,7 +901,7 @@ int imap_sync_mailbox (CONTEXT * ctx, int expunge, int *index_hint) if ((rc = imap_check_mailbox (ctx, index_hint, 0)) != 0) return rc; - memset (&cmd, 0, sizeof (cmd)); + p_clear(&cmd, 1); /* if we are expunging anyway, we can do deleted messages very quickly... */ if (expunge && mutt_bit_isset (idata->rights, ACL_DELETE)) { @@ -1012,14 +938,11 @@ int imap_sync_mailbox (CONTEXT * ctx, int expunge, int *index_hint) * This works better if we're expunging, of course. */ if ((ctx->hdrs[n]->env && (ctx->hdrs[n]->env->refs_changed || ctx->hdrs[n]->env->irt_changed)) || ctx->hdrs[n]->attach_del) { - debug_print (3, ("Attachments to be deleted, falling back to _mutt_save_message\n")); if (!appendctx) appendctx = mx_open_mailbox (ctx->path, M_APPEND | M_QUIET, NULL); - if (!appendctx) { - debug_print (1, ("Error opening mailbox in append mode\n")); - } - else + if (appendctx) { _mutt_save_message (ctx->hdrs[n], appendctx, 1, 0, 0); + } } if (imap_sync_message (idata, ctx->hdrs[n], &cmd, &err_continue) < 0) { @@ -1062,7 +985,7 @@ out: } /* imap_close_mailbox: clean up IMAP data in CONTEXT */ -void imap_close_mailbox (CONTEXT * ctx) +static void imap_close_mailbox (CONTEXT * ctx) { IMAP_DATA *idata; int i; @@ -1083,7 +1006,7 @@ void imap_close_mailbox (CONTEXT * ctx) idata->reopen &= IMAP_REOPEN_ALLOW; p_delete(&(idata->mailbox)); - mutt_free_list (&idata->flags); + string_list_wipe(&idata->flags); idata->ctx = NULL; } @@ -1107,7 +1030,7 @@ void imap_close_mailbox (CONTEXT * ctx) * 0 no change * -1 error */ -int imap_check_mailbox (CONTEXT * ctx, int *index_hint, int force) +int imap_check_mailbox (CONTEXT * ctx, int *index_hint __attribute__ ((unused)), int force) { /* overload keyboard timeout to avoid many mailbox checks in a row. * Most users don't like having to wait exactly when they press a key. */ @@ -1175,16 +1098,16 @@ int imap_mailbox_check (char *path, int new) p_delete(&mx.mbox); imap_munge_mbox_name (mbox, sizeof (mbox), buf); - strfcpy (mbox_unquoted, buf, sizeof (mbox_unquoted)); + m_strcpy(mbox_unquoted, sizeof(mbox_unquoted), buf); /* The draft IMAP implementor's guide warns againts using the STATUS * command on a mailbox that you have selected */ - if (str_cmp (mbox_unquoted, idata->mailbox) == 0 + if (m_strcmp(mbox_unquoted, idata->mailbox) == 0 || (ascii_strcasecmp (mbox_unquoted, "INBOX") == 0 - && str_casecmp (mbox_unquoted, idata->mailbox) == 0)) { - strfcpy (buf, "NOOP", sizeof (buf)); + && m_strcasecmp(mbox_unquoted, idata->mailbox) == 0)) { + m_strcpy(buf, sizeof(buf), "NOOP"); } else if (mutt_bit_isset (idata->capabilities, IMAP4REV1) || mutt_bit_isset (idata->capabilities, STATUS)) { @@ -1208,19 +1131,16 @@ int imap_mailbox_check (char *path, int new) /* The mailbox name may or may not be quoted here. We could try to * munge the server response and compare with quoted (or vise versa) * but it is probably more efficient to just strncmp against both. */ - if (str_ncmp (mbox_unquoted, s, m_strlen(mbox_unquoted)) == 0 - || str_ncmp (mbox, s, m_strlen(mbox)) == 0) { + if (m_strncmp(mbox_unquoted, s, m_strlen(mbox_unquoted)) == 0 + || m_strncmp(mbox, s, m_strlen(mbox)) == 0) { s = imap_next_word (s); s = imap_next_word (s); if (isdigit ((unsigned char) *s)) { if (*s != '0') { msgcount = atoi (s); - debug_print (2, ("%d new messages in %s\n", msgcount, path)); } } } - else - debug_print (1, ("STATUS response doesn't match requested mailbox.\n")); } } while (rc == IMAP_CMD_CONTINUE); @@ -1310,9 +1230,8 @@ static int imap_compile_search (const pattern_t* pat, BUFFER* buf) mutt_buffer_addch (buf, ' '); /* and field */ - *delim = ':'; - delim++; - SKIPWS(delim); + *delim++ = ':'; + delim = vskipspaces(delim); imap_quote_string (term, sizeof (term), delim); mutt_buffer_addstr (buf, term); break; @@ -1345,7 +1264,7 @@ int imap_search (CONTEXT* ctx, const pattern_t* pat) { if (!do_search (pat, 1)) return 0; - memset (&buf, 0, sizeof (buf)); + p_clear(&buf, 1); mutt_buffer_addstr (&buf, "UID SEARCH "); if (imap_compile_search (pat, &buf) < 0) { p_delete(&buf.data); @@ -1363,7 +1282,7 @@ int imap_search (CONTEXT* ctx, const pattern_t* pat) { /* all this listing/browsing is a mess. I don't like that name is a pointer * into idata->buf (used to be a pointer into the passed in buffer, just * as bad), nor do I like the fact that the fetch is done here. This - * code can't possibly handle non-LIST untagged responses properly. + * code can't possibly handle non-string_list_t untagged responses properly. * FIXME. ?! */ int imap_parse_list_response (IMAP_DATA * idata, char **name, int *noselect, int *noinferiors, char *delim) @@ -1457,13 +1376,12 @@ int imap_subscribe (char *path, int subscribe) imap_fix_path (idata, mx.mbox, buf, sizeof (buf)); if (option (OPTIMAPCHECKSUBSCRIBED)) { - memset (&token, 0, sizeof (token)); + p_clear(&token, 1); err.data = errstr; err.dsize = sizeof (errstr); snprintf (mbox, sizeof (mbox), "%smailboxes \"%s\"", subscribe ? "" : "un", path); - if (mutt_parse_rc_line (mbox, &token, &err)) - debug_print (1, ("Error adding subscribed mailbox: %s\n", errstr)); + mutt_parse_rc_line (mbox, &token, &err); p_delete(&token.data); } @@ -1489,7 +1407,7 @@ fail: /* trim dest to the length of the longest prefix it shares with src, * returning the length of the trimmed string */ static int longest_common_prefix (char *dest, const char* src, - int start, size_t dlen) { + int start, ssize_t dlen) { int pos = start; while (pos < dlen && dest[pos] && dest[pos] == src[pos]) @@ -1501,7 +1419,7 @@ static int longest_common_prefix (char *dest, const char* src, /* look for IMAP URLs to complete from defined mailboxes. Could be extended * to complete over open connections and account/folder hooks too. */ -static int imap_complete_hosts (char *dest, size_t len) { +static int imap_complete_hosts (char *dest, ssize_t len) { BUFFY* mailbox; CONNECTION* conn; int rc = -1; @@ -1509,13 +1427,13 @@ static int imap_complete_hosts (char *dest, size_t len) { int i = 0; matchlen = m_strlen(dest); - if (list_empty (Incoming)) + if (!Incoming.len) return (-1); - for (i = 0; i < Incoming->length; i++) { - mailbox = (BUFFY*) Incoming->data[i]; - if (!str_ncmp (dest, mailbox->path, matchlen)) { + for (i = 0; i < Incoming.len; i++) { + mailbox = Incoming.arr[i]; + if (!m_strncmp(dest, mailbox->path, matchlen)) { if (rc) { - strfcpy (dest, mailbox->path, len); + m_strcpy(dest, len, mailbox->path); rc = 0; } else longest_common_prefix (dest, mailbox->path, matchlen, len); @@ -1534,9 +1452,9 @@ static int imap_complete_hosts (char *dest, size_t len) { url.user = NULL; url.path = NULL; url_ciss_tostring (&url, urlstr, sizeof (urlstr), 0); - if (!str_ncmp (dest, urlstr, matchlen)) { + if (!m_strncmp(dest, urlstr, matchlen)) { if (rc) { - strfcpy (dest, urlstr, len); + m_strcpy(dest, len, urlstr); rc = 0; } else longest_common_prefix (dest, urlstr, matchlen, len); @@ -1562,7 +1480,7 @@ int imap_complete (char *dest, size_t dlen, char *path) { IMAP_MBOX mx; if (imap_parse_path (path, &mx) || !mx.mbox) { - strfcpy (dest, path, dlen); + m_strcpy(dest, dlen, path); return imap_complete_hosts (dest, dlen); } @@ -1570,7 +1488,7 @@ int imap_complete (char *dest, size_t dlen, char *path) { * known mailboxes/hooks/etc */ if (!(idata = imap_conn_find (&(mx.account), M_IMAP_CONN_NONEW))) { p_delete(&mx.mbox); - strfcpy (dest, path, dlen); + m_strcpy(dest, dlen, path); return imap_complete_hosts (dest, dlen); } conn = idata->conn; @@ -1589,7 +1507,7 @@ int imap_complete (char *dest, size_t dlen, char *path) { imap_cmd_start (idata, buf); /* and see what the results are */ - strfcpy (completion, NONULL (mx.mbox), sizeof (completion)); + m_strcpy(completion, sizeof(completion), NONULL(mx.mbox)); do { if (imap_parse_list_response (idata, &list_word, &noselect, &noinferiors, &delim)) @@ -1608,7 +1526,7 @@ int imap_complete (char *dest, size_t dlen, char *path) { } /* copy in first word */ if (!completions) { - strfcpy (completion, list_word, sizeof (completion)); + m_strcpy(completion, sizeof(completion), list_word); matchlen = m_strlen(completion); completions++; continue; @@ -1618,7 +1536,7 @@ int imap_complete (char *dest, size_t dlen, char *path) { completions++; } } - while (ascii_strncmp (idata->cmd.seq, idata->cmd.buf, SEQLEN)); + while (m_strncmp(idata->cmd.seq, idata->cmd.buf, SEQLEN)); if (completions) { /* reformat output */ @@ -1655,3 +1573,63 @@ int imap_reconnect (CONTEXT * ctx) mx_open_mailbox (ctx->path, 0, ctx); return 0; } + +int imap_is_magic (const char* path, struct stat* st __attribute__ ((unused))) { + url_scheme_t s; + if (!path || !*path) + return (-1); + s = url_check_scheme (NONULL (path)); + return ((s == U_IMAP || s == U_IMAPS) ? M_IMAP : -1); +} + +static int acl_check_imap (CONTEXT* ctx, int bit) { + return (!mutt_bit_isset (((IMAP_DATA*) ctx->data)->capabilities, ACL) || + mutt_bit_isset (((IMAP_DATA*) ctx->data)->rights, bit)); +} + +static int imap_open_new_message (MESSAGE * msg, + CONTEXT * dest __attribute__ ((unused)), + HEADER * hdr __attribute__ ((unused))) +{ + char tmp[_POSIX_PATH_MAX]; + + msg->fp = m_tempfile(tmp, sizeof(tmp), NONULL(MCore.tmpdir), NULL); + if (!msg->fp) { + mutt_perror(tmp); + return -1; + } + + msg->path = m_strdup(tmp); + return 0; +} + +/* this ugly kludge is required since the last int to + * imap_check_mailbox() doesn't mean 'lock' but 'force'... */ +static int _imap_check_mailbox (CONTEXT* ctx, + int* index_hint, + int lock __attribute__ ((unused))) { + return (imap_check_mailbox (ctx, index_hint, 0)); +} + +static int imap_commit_message (MESSAGE* msg, CONTEXT* ctx) { + int r = 0; + + if ((r = m_fclose(&msg->fp)) == 0) + r = imap_append_message (ctx, msg); + return (r); +} + +mx_t const imap_mx = { + M_IMAP, + 0, + imap_is_magic, + NULL, + imap_access, + imap_open_mailbox, + imap_open_new_message, + acl_check_imap, + _imap_check_mailbox, + imap_close_mailbox, + imap_sync_mailbox, + imap_commit_message, +};