return(PS_SUCCESS);
}
-static int imap_response(int sock, char *argbuf)
+static int imap_response(int sock, char *argbuf, struct RecvSplit *rs)
/* parse command response */
{
char buf[MSGBUFSIZE+1];
int ok;
char *cp;
- if ((ok = gen_recv(sock, buf, sizeof(buf))))
+ if (rs)
+ ok = gen_recv_split(sock, buf, sizeof(buf), rs);
+ else
+ ok = gen_recv(sock, buf, sizeof(buf));
+ if (ok != PS_SUCCESS)
return(ok);
/* all tokens in responses are caseblind */
{
int ok;
- while ((ok = imap_response(sock, argbuf)) == PS_UNTAGGED)
+ while ((ok = imap_response(sock, argbuf, NULL)) == PS_UNTAGGED)
; /* wait for the tagged response */
return(ok);
}
result[j] = '\0';
}
-static void capa_probe(int sock, struct query *ctl)
+static int capa_probe(int sock, struct query *ctl)
/* set capability variables from a CAPA probe */
{
int ok;
report(stdout, GT_("Protocol identified as IMAP4 rev 0\n"));
}
}
+ else
+ return ok;
/*
* Handle idling. We depend on coming through here on startup
}
peek_capable = TRUE;
+
+ return PS_SUCCESS;
}
static int do_authcert (int sock, const char *command, const char *name)
else
expunge_period = 1;
- capa_probe(sock, ctl);
+ if ((ok = capa_probe(sock, ctl)))
+ return ok;
/*
* If either (a) we saw a PREAUTH token in the greeting, or
* whether TLS is mandatory or opportunistic unless SSLOpen() fails
* (see below). */
if (gen_transact(sock, "STARTTLS") == PS_SUCCESS
- && SSLOpen(sock, ctl->sslcert, ctl->sslkey, "tls1", ctl->sslcertck,
+ && (set_timeout(mytimeout), SSLOpen(sock, ctl->sslcert, ctl->sslkey, "tls1", ctl->sslcertck,
ctl->sslcertfile, ctl->sslcertpath, ctl->sslfingerprint, commonname,
- ctl->server.pollname, &ctl->remotename) != -1)
+ ctl->server.pollname, &ctl->remotename)) != -1)
{
/*
* RFC 2595 says this:
* Now that we're confident in our TLS connection we can
* guarantee a secure capability re-probe.
*/
- capa_probe(sock, ctl);
+ if ((ok = capa_probe(sock, ctl)))
+ return ok;
if (outlevel >= O_VERBOSE)
{
report(stdout, GT_("%s: upgrade to TLS succeeded.\n"), commonname);
} else if (must_tls(ctl)) {
/* Config required TLS but we couldn't guarantee it, so we must
* stop. */
+ set_timeout(0);
report(stderr, GT_("%s: upgrade to TLS failed.\n"), commonname);
return PS_SOCKET;
} else {
+ set_timeout(0);
if (outlevel >= O_VERBOSE) {
report(stdout, GT_("%s: opportunistic upgrade to TLS failed, trying to continue\n"), commonname);
}
return(ok);
}
-/* maximum number of numbers we can process in "SEARCH" response */
-# define IMAP_SEARCH_MAX 1000
-
static int imap_search(int sock, struct query *ctl, int count)
/* search for unseen messages */
{
- int ok, first, last;
+ int ok;
char buf[MSGBUFSIZE+1], *cp;
/* Don't count deleted messages. Enabled only for IMAP4 servers or
flag skipdeleted = ctl->keep;
const char *undeleted;
- /* Skip range search if there are less than or equal to
- * IMAP_SEARCH_MAX mails. */
- flag skiprangesearch = (count <= IMAP_SEARCH_MAX);
+ /* structure to keep the end portion of the incomplete response */
+ struct RecvSplit rs;
/* startcount is higher than count so that if there are no
* unseen messages, imap_getsizes() will not need to do
* anything! */
startcount = count + 1;
- for (first = 1, last = IMAP_SEARCH_MAX; first <= count; first += IMAP_SEARCH_MAX, last += IMAP_SEARCH_MAX)
+ for (;;)
{
- if (last > count)
- last = count;
-
-restartsearch:
undeleted = (skipdeleted ? " UNDELETED" : "");
- if (skiprangesearch)
- gen_send(sock, "SEARCH UNSEEN%s", undeleted);
- else if (last == first)
- gen_send(sock, "SEARCH %d UNSEEN%s", last, undeleted);
- else
- gen_send(sock, "SEARCH %d:%d UNSEEN%s", first, last, undeleted);
- while ((ok = imap_response(sock, buf)) == PS_UNTAGGED)
+ gen_send(sock, "SEARCH UNSEEN%s", undeleted);
+ gen_recv_split_init("* SEARCH", &rs);
+ while ((ok = imap_response(sock, buf, &rs)) == PS_UNTAGGED)
{
if ((cp = strstr(buf, "* SEARCH")))
{
}
}
}
- /* if there is a protocol error on the first loop, try a
- * different search command */
- if (ok == PS_ERROR && first == 1)
+ if (ok != PS_ERROR) /* success or non-protocol error */
+ return(ok);
+
+ /* there is a protocol error. try a different search command. */
+ if (skipdeleted)
{
- if (skipdeleted)
- {
- /* retry with "SEARCH 1:1000 UNSEEN" */
- skipdeleted = FALSE;
- goto restartsearch;
- }
- if (!skiprangesearch)
- {
- /* retry with "SEARCH UNSEEN" */
- skiprangesearch = TRUE;
- goto restartsearch;
- }
- /* try with "FETCH 1:n FLAGS" */
- goto fetchflags;
+ /* retry with "SEARCH UNSEEN" */
+ skipdeleted = FALSE;
+ continue;
}
- if (ok != PS_SUCCESS)
- return(ok);
- /* loop back only when searching in range */
- if (skiprangesearch)
- break;
+ /* try with "FETCH 1:n FLAGS" */
+ break;
}
- return(PS_SUCCESS);
-fetchflags:
if (count == 1)
gen_send(sock, "FETCH %d FLAGS", count);
else
gen_send(sock, "FETCH %d:%d FLAGS", 1, count);
- while ((ok = imap_response(sock, buf)) == PS_UNTAGGED)
+ while ((ok = imap_response(sock, buf, NULL)) == PS_UNTAGGED)
{
unsigned int num;
int consumed;
gen_send(sock, "FETCH %d:%d RFC822.SIZE", first, last);
else /* no unseen messages! */
return(PS_SUCCESS);
- while ((ok = imap_response(sock, buf)) == PS_UNTAGGED)
+ while ((ok = imap_response(sock, buf, NULL)) == PS_UNTAGGED)
{
unsigned int size;
int num;
gen_send(sock, "FETCH %d RFC822.HEADER", number);
/* looking for FETCH response */
- if ((ok = imap_response(sock, buf)) == PS_UNTAGGED)
+ if ((ok = imap_response(sock, buf, NULL)) == PS_UNTAGGED)
{
int consumed;
/* expected response formats:
/* try to recover for some responses */
if (!strncmp(buf, "* NO", 4) ||
- !strncmp(buf, "* BAD", 5))
+ !strncmp(buf, "* BAD", 5) ||
+ strstr(buf, "FETCH ()"))
{
return(PS_TRANSIENT);
}
/* an unexpected tagged response */
if (outlevel > O_SILENT)
report(stderr, GT_("Incorrect FETCH response: %s.\n"), buf);
- return(PS_ERROR);
+ return(PS_TRANSIENT);
}
return(ok);
}
/* set delete flag for given message */
{
int ok;
+ /* Select which flags to set on message deletion: */
+ const char delflags_seen[] = "\\Seen \\Deleted";
+ static const char *delflags;
+ /* Which environment variable to look for: */
+
+ /* DEFAULT since many fetchmail versions <= 6.3.X */
+ delflags = delflags_seen;
(void)ctl;
/* expunges change the fetch numbers */