imap: change from "FETCH" to "UID FETCH"

... and add "MAILINDEX".

As described in #2789, this is a suggested solution.  Changing UID=xx to
actually get mail with UID xx and add "MAILINDEX" to get a mail with a
special index in the mail box (old behavior).  So MAILINDEX=1 gives the
first non deleted mail in the mail box.

Fixes #2789
Closes #2815
This commit is contained in:
Nicklas Avén 2018-07-31 13:12:18 +02:00 committed by Daniel Stenberg
parent 2825f46d95
commit 6987fcef65
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
40 changed files with 139 additions and 59 deletions

View file

@ -421,7 +421,6 @@ static CURLcode imap_perform_capability(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct imap_conn *imapc = &conn->proto.imapc;
imapc->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanisms yet */
imapc->sasl.authused = SASL_AUTH_NONE; /* Clear the auth. mechanism used */
imapc->tls_supported = FALSE; /* Clear the TLS capability */
@ -683,24 +682,37 @@ static CURLcode imap_perform_fetch(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct IMAP *imap = conn->data->req.protop;
/* Check we have a UID */
if(!imap->uid) {
failf(conn->data, "Cannot FETCH without a UID.");
return CURLE_URL_MALFORMAT;
if(imap->uid) {
/* Send the FETCH command */
if(imap->partial)
result = imap_sendf(conn, "UID FETCH %s BODY[%s]<%s>",
imap->uid,
imap->section ? imap->section : "",
imap->partial);
else
result = imap_sendf(conn, "UID FETCH %s BODY[%s]",
imap->uid,
imap->section ? imap->section : "");
}
else if(imap->mindex) {
/* Send the FETCH command */
if(imap->partial)
result = imap_sendf(conn, "FETCH %s BODY[%s]<%s>",
imap->uid,
imap->section ? imap->section : "",
imap->partial);
else
result = imap_sendf(conn, "FETCH %s BODY[%s]",
imap->uid,
imap->section ? imap->section : "");
/* Send the FETCH command */
if(imap->partial)
result = imap_sendf(conn, "FETCH %s BODY[%s]<%s>",
imap->mindex,
imap->section ? imap->section : "",
imap->partial);
else
result = imap_sendf(conn, "FETCH %s BODY[%s]",
imap->mindex,
imap->section ? imap->section : "");
}
else {
failf(conn->data, "Cannot FETCH without a UID.");
return CURLE_URL_MALFORMAT;
}
if(!result)
state(conn, IMAP_FETCH);
@ -1464,9 +1476,10 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
result = status; /* use the already set error code */
}
else if(!data->set.connect_only && !imap->custom &&
(imap->uid || data->set.upload ||
(imap->uid || imap->mindex || data->set.upload ||
data->set.mimepost.kind != MIMEKIND_NONE)) {
/* Handle responses after FETCH or APPEND transfer has finished */
if(!data->set.upload && data->set.mimepost.kind == MIMEKIND_NONE)
state(conn, IMAP_FETCH_FINAL);
else {
@ -1490,6 +1503,7 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
Curl_safefree(imap->mailbox);
Curl_safefree(imap->uidvalidity);
Curl_safefree(imap->uid);
Curl_safefree(imap->mindex);
Curl_safefree(imap->section);
Curl_safefree(imap->partial);
Curl_safefree(imap->query);
@ -1543,14 +1557,14 @@ static CURLcode imap_perform(struct connectdata *conn, bool *connected,
else if(imap->custom && (selected || !imap->mailbox))
/* Custom command using the same mailbox or no mailbox */
result = imap_perform_list(conn);
else if(!imap->custom && selected && imap->uid)
else if(!imap->custom && selected && (imap->uid || imap->mindex))
/* FETCH from the same mailbox */
result = imap_perform_fetch(conn);
else if(!imap->custom && selected && imap->query)
/* SEARCH the current mailbox */
result = imap_perform_search(conn);
else if(imap->mailbox && !selected &&
(imap->custom || imap->uid || imap->query))
(imap->custom || imap->uid || imap->mindex || imap->query))
/* SELECT the mailbox */
result = imap_perform_select(conn);
else
@ -2016,6 +2030,13 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
imap->uid = value;
value = NULL;
}
else if(strcasecompare(name, "MAILINDEX") && !imap->mindex) {
if(valuelen > 0 && value[valuelen - 1] == '/')
value[valuelen - 1] = '\0';
imap->mindex = value;
value = NULL;
}
else if(strcasecompare(name, "SECTION") && !imap->section) {
if(valuelen > 0 && value[valuelen - 1] == '/')
value[valuelen - 1] = '\0';
@ -2043,7 +2064,7 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
/* Does the URL contain a query parameter? Only valid when we have a mailbox
and no UID as per RFC-5092 */
if(imap->mailbox && !imap->uid && *ptr == '?') {
if(imap->mailbox && !imap->uid && !imap->mindex && *ptr == '?') {
/* Find the length of the query parameter */
begin = ++ptr;
while(imap_is_bchar(*ptr))

View file

@ -58,6 +58,7 @@ struct IMAP {
char *mailbox; /* Mailbox to select */
char *uidvalidity; /* UIDVALIDITY to check in select */
char *uid; /* Message UID to fetch */
char *mindex; /* Index in mail box of mail to fetch */
char *section; /* Message SECTION to fetch */
char *partial; /* Message PARTIAL to fetch */
char *query; /* Query to search for */