add fallbacks for determining UIDNEXT
if the server sends no UIDNEXT, do an initial FETCH to query the UID of the last message. same if the server sends no APPENDUID. this allows us to remove the arbitrary limitation of the UID range to INT_MAX, at the cost of additional round-trips.
This commit is contained in:
parent
416ced25dd
commit
72be55b0e3
|
@ -151,6 +151,7 @@ struct imap_cmd {
|
||||||
char to_trash; /* we are storing to trash, not current. */
|
char to_trash; /* we are storing to trash, not current. */
|
||||||
char create; /* create the mailbox if we get an error which suggests so. */
|
char create; /* create the mailbox if we get an error which suggests so. */
|
||||||
char failok; /* Don't complain about NO response. */
|
char failok; /* Don't complain about NO response. */
|
||||||
|
char lastuid; /* querying the last UID in the mailbox. */
|
||||||
} param;
|
} param;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1051,7 +1052,15 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (body) {
|
if (!uid) {
|
||||||
|
assert( !body && !tuid && !msgid );
|
||||||
|
// Ignore async flag updates for now.
|
||||||
|
} else if ((cmdp = ctx->in_progress) && cmdp->param.lastuid) {
|
||||||
|
assert( !body && !tuid && !msgid );
|
||||||
|
// Workaround for server not sending UIDNEXT and/or APPENDUID.
|
||||||
|
ctx->gen.uidnext = uid + 1;
|
||||||
|
} else if (body) {
|
||||||
|
assert( !tuid && !msgid );
|
||||||
for (cmdp = ctx->in_progress; cmdp; cmdp = cmdp->next)
|
for (cmdp = ctx->in_progress; cmdp; cmdp = cmdp->next)
|
||||||
if (cmdp->param.uid == uid)
|
if (cmdp->param.uid == uid)
|
||||||
goto gotuid;
|
goto gotuid;
|
||||||
|
@ -1065,7 +1074,7 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
|
||||||
msgdata->date = date;
|
msgdata->date = date;
|
||||||
if (status & M_FLAGS)
|
if (status & M_FLAGS)
|
||||||
msgdata->flags = mask;
|
msgdata->flags = mask;
|
||||||
} else if (uid) { /* ignore async flag updates for now */
|
} else {
|
||||||
/* XXX this will need sorting for out-of-order (multiple queries) */
|
/* XXX this will need sorting for out-of-order (multiple queries) */
|
||||||
cur = nfcalloc( sizeof(*cur) );
|
cur = nfcalloc( sizeof(*cur) );
|
||||||
*ctx->msgapp = &cur->gen;
|
*ctx->msgapp = &cur->gen;
|
||||||
|
@ -1081,8 +1090,6 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
|
||||||
memcpy( cur->gen.tuid, tuid, TUIDL );
|
memcpy( cur->gen.tuid, tuid, TUIDL );
|
||||||
else
|
else
|
||||||
cur->gen.tuid[0] = 0;
|
cur->gen.tuid[0] = 0;
|
||||||
if (ctx->gen.uidnext <= uid) /* in case the server sends no UIDNEXT */
|
|
||||||
ctx->gen.uidnext = uid + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free_list( list );
|
free_list( list );
|
||||||
|
@ -2287,6 +2294,9 @@ imap_select_box( store_t *gctx, const char *name )
|
||||||
return DRV_OK;
|
return DRV_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void imap_open_box_p2( imap_store_t *, imap_cmd_t *, int );
|
||||||
|
static void imap_open_box_p3( imap_store_t *, imap_cmd_t *, int );
|
||||||
|
|
||||||
static void
|
static void
|
||||||
imap_open_box( store_t *gctx,
|
imap_open_box( store_t *gctx,
|
||||||
void (*cb)( int sts, void *aux ), void *aux )
|
void (*cb)( int sts, void *aux ), void *aux )
|
||||||
|
@ -2304,11 +2314,38 @@ imap_open_box( store_t *gctx,
|
||||||
|
|
||||||
INIT_IMAP_CMD(imap_cmd_simple_t, cmd, cb, aux)
|
INIT_IMAP_CMD(imap_cmd_simple_t, cmd, cb, aux)
|
||||||
cmd->gen.param.failok = 1;
|
cmd->gen.param.failok = 1;
|
||||||
imap_exec( ctx, &cmd->gen, imap_done_simple_box,
|
imap_exec( ctx, &cmd->gen, imap_open_box_p2,
|
||||||
"SELECT \"%\\s\"", buf );
|
"SELECT \"%\\s\"", buf );
|
||||||
free( buf );
|
free( buf );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
imap_open_box_p2( imap_store_t *ctx, imap_cmd_t *gcmd, int response )
|
||||||
|
{
|
||||||
|
imap_cmd_simple_t *cmdp = (imap_cmd_simple_t *)gcmd;
|
||||||
|
imap_cmd_simple_t *cmd;
|
||||||
|
|
||||||
|
if (response != RESP_OK || ctx->gen.uidnext) {
|
||||||
|
imap_done_simple_box( ctx, &cmdp->gen, response );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
INIT_IMAP_CMD(imap_cmd_simple_t, cmd, cmdp->callback, cmdp->callback_aux)
|
||||||
|
cmd->gen.param.lastuid = 1;
|
||||||
|
imap_exec( ctx, &cmd->gen, imap_open_box_p3,
|
||||||
|
"UID FETCH *:* (UID)" );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
imap_open_box_p3( imap_store_t *ctx, imap_cmd_t *gcmd, int response )
|
||||||
|
{
|
||||||
|
// This will happen if the box is empty.
|
||||||
|
if (!ctx->gen.uidnext)
|
||||||
|
ctx->gen.uidnext = 1;
|
||||||
|
|
||||||
|
imap_done_simple_box( ctx, gcmd, response );
|
||||||
|
}
|
||||||
|
|
||||||
/******************* imap_create_box *******************/
|
/******************* imap_create_box *******************/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2443,7 +2480,7 @@ imap_load_box( store_t *gctx, int minuid, int maxuid, int newuid, int seenuid, i
|
||||||
imap_submit_load( ctx, buf, shifted_bit( ctx->gen.opts, OPEN_OLD_IDS, WantMsgids ), sts );
|
imap_submit_load( ctx, buf, shifted_bit( ctx->gen.opts, OPEN_OLD_IDS, WantMsgids ), sts );
|
||||||
}
|
}
|
||||||
if (maxuid == INT_MAX)
|
if (maxuid == INT_MAX)
|
||||||
maxuid = ctx->gen.uidnext ? ctx->gen.uidnext - 1 : 0x7fffffff;
|
maxuid = ctx->gen.uidnext - 1;
|
||||||
if (maxuid >= minuid) {
|
if (maxuid >= minuid) {
|
||||||
imap_range_t ranges[3];
|
imap_range_t ranges[3];
|
||||||
ranges[0].first = minuid;
|
ranges[0].first = minuid;
|
||||||
|
@ -2720,6 +2757,7 @@ imap_store_msg_p2( imap_store_t *ctx ATTR_UNUSED, imap_cmd_t *cmd, int response
|
||||||
/******************* imap_find_new_msgs *******************/
|
/******************* imap_find_new_msgs *******************/
|
||||||
|
|
||||||
static void imap_find_new_msgs_p2( imap_store_t *, imap_cmd_t *, int );
|
static void imap_find_new_msgs_p2( imap_store_t *, imap_cmd_t *, int );
|
||||||
|
static void imap_find_new_msgs_p3( imap_store_t *, imap_cmd_t *, int );
|
||||||
|
|
||||||
static void
|
static void
|
||||||
imap_find_new_msgs( store_t *gctx, int newuid,
|
imap_find_new_msgs( store_t *gctx, int newuid,
|
||||||
|
@ -2738,15 +2776,35 @@ static void
|
||||||
imap_find_new_msgs_p2( imap_store_t *ctx, imap_cmd_t *gcmd, int response )
|
imap_find_new_msgs_p2( imap_store_t *ctx, imap_cmd_t *gcmd, int response )
|
||||||
{
|
{
|
||||||
imap_cmd_find_new_t *cmdp = (imap_cmd_find_new_t *)gcmd;
|
imap_cmd_find_new_t *cmdp = (imap_cmd_find_new_t *)gcmd;
|
||||||
imap_cmd_simple_t *cmd;
|
imap_cmd_find_new_t *cmd;
|
||||||
|
|
||||||
if (response != RESP_OK) {
|
if (response != RESP_OK) {
|
||||||
imap_done_simple_box( ctx, gcmd, response );
|
imap_done_simple_box( ctx, gcmd, response );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx->gen.uidnext = 0;
|
||||||
|
|
||||||
|
INIT_IMAP_CMD_X(imap_cmd_find_new_t, cmd, cmdp->gen.callback, cmdp->gen.callback_aux)
|
||||||
|
cmd->uid = cmdp->uid;
|
||||||
|
cmd->gen.gen.param.lastuid = 1;
|
||||||
|
imap_exec( ctx, &cmd->gen.gen, imap_find_new_msgs_p3,
|
||||||
|
"UID FETCH *:* (UID)" );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
imap_find_new_msgs_p3( imap_store_t *ctx, imap_cmd_t *gcmd, int response )
|
||||||
|
{
|
||||||
|
imap_cmd_find_new_t *cmdp = (imap_cmd_find_new_t *)gcmd;
|
||||||
|
imap_cmd_simple_t *cmd;
|
||||||
|
|
||||||
|
if (response != RESP_OK || ctx->gen.uidnext <= cmdp->uid) {
|
||||||
|
imap_done_simple_box( ctx, gcmd, response );
|
||||||
|
return;
|
||||||
|
}
|
||||||
INIT_IMAP_CMD(imap_cmd_simple_t, cmd, cmdp->gen.callback, cmdp->gen.callback_aux)
|
INIT_IMAP_CMD(imap_cmd_simple_t, cmd, cmdp->gen.callback, cmdp->gen.callback_aux)
|
||||||
imap_exec( (imap_store_t *)ctx, &cmd->gen, imap_done_simple_box,
|
imap_exec( (imap_store_t *)ctx, &cmd->gen, imap_done_simple_box,
|
||||||
"UID FETCH %d:" stringify(INT_MAX) " (UID BODY.PEEK[HEADER.FIELDS (X-TUID)])", cmdp->uid );
|
"UID FETCH %d:%d (UID BODY.PEEK[HEADER.FIELDS (X-TUID)])", cmdp->uid, ctx->gen.uidnext - 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************* imap_list_store *******************/
|
/******************* imap_list_store *******************/
|
||||||
|
|
Loading…
Reference in New Issue
Block a user