diff options
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | imap.c | 52 |
2 files changed, 32 insertions, 23 deletions
@@ -45,6 +45,9 @@ fetchmail 6.3.3 (not yet released): the same messages again when the fetchall keyword is removed. Patch by Sunil Shetye. For details, please see <http://lists.berlios.de/pipermail/fetchmail-users/2006-March/000308.html> +* IMAP: fix hangs in NOOP-based IDLE emulation. Reported by Casper Gripenberg + and Brendan Lynch, fix by Sunil Shetye (his patch was merged) and Brendan + Lynch. # CHANGES: * --idle can now be specified on the command line, too. @@ -621,7 +621,6 @@ static int imap_idle(int sock) { int ok; - stage = STAGE_IDLE; saved_timeout = mytimeout; if (has_idle) { @@ -629,6 +628,7 @@ static int imap_idle(int sock) * at least every 28 minutes: * (the server may have an inactivity timeout) */ mytimeout = 1680; /* 28 min */ + stage = STAGE_IDLE; /* enter IDLE mode */ ok = gen_transact(sock, "IDLE"); @@ -637,37 +637,43 @@ static int imap_idle(int sock) SockWrite(sock, "DONE\r\n", 6); if (outlevel >= O_MONITOR) report(stdout, "IMAP> DONE\n"); - } else - /* not idle timeout */ - return ok; + /* reset stage and timeout here: we are not idling any more */ + mytimeout = saved_timeout; + stage = STAGE_FETCH; + /* get OK IDLE message */ + ok = imap_ok(sock, NULL); + } } else { /* no idle support, fake it */ - /* when faking an idle, we can't assume the server will - * send us the new messages out of the blue (RFC2060); - * this timeout is potentially the delay before we notice - * new mail (can be small since NOOP checking is cheap) */ - mytimeout = 28; + /* Note: stage and timeout have not been changed here as NOOP + * does not idle */ ok = gen_transact(sock, "NOOP"); - /* if there's an error (not likely) or we just found mail (stage - * has changed, timeout has also been restored), we're done */ - if (ok != 0 || stage != STAGE_IDLE) - return(ok); - /* wait (briefly) for an unsolicited status update */ - ok = imap_ok(sock, NULL); - /* again, this is new mail or an error */ - if (ok != PS_IDLETIMEOUT) - return(ok); + /* no error, but no new mail either */ + if (ok == PS_SUCCESS && recentcount == 0) + { + /* There are some servers who do send new mail + * notification out of the blue. This is in compliance + * with RFC 2060 section 5.3. Wait for that with a low + * timeout */ + mytimeout = 28; + stage = STAGE_IDLE; + /* We are waiting for notification; no tag needed */ + tag[0] = '\0'; + /* wait (briefly) for an unsolicited status update */ + ok = imap_ok(sock, NULL); + if (ok == PS_IDLETIMEOUT) { + /* no notification came; ok */ + ok = PS_SUCCESS; + } + } } /* restore normal timeout value */ + set_timeout(0); mytimeout = saved_timeout; stage = STAGE_FETCH; - /* get OK IDLE message */ - if (has_idle) - return imap_ok(sock, NULL); - - return PS_SUCCESS; + return(ok); } static int imap_getrange(int sock, |