diff options
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | driver.c | 5 | ||||
-rw-r--r-- | fetchmail.c | 5 | ||||
-rw-r--r-- | fetchmail.h | 1 | ||||
-rw-r--r-- | imap.c | 42 | ||||
-rw-r--r-- | sink.c | 28 |
6 files changed, 53 insertions, 29 deletions
@@ -6,6 +6,7 @@ * Properly guard some transaction reporting in the SSL code. * Updated German (de) po file. Added Turkish (tr) po file. * Expunge edge case fix by Sunil Shetye. +* Fixes for some odd IMAP and SMTP edge cases by Sunil Shetye. fetchmail-5.9.6 (Fri Dec 14 04:03:50 EST 2001), 21247 lines: @@ -788,10 +788,7 @@ const int maxfetch; /* maximum number of messages to fetch */ /* try to clean up all streams */ release_sink(ctl); - if (ctl->smtp_socket != -1) { - cleanupSockClose(ctl->smtp_socket); - ctl->smtp_socket = -1; - } + smtp_close(ctl, 0); if (mailserver_socket != -1) { cleanupSockClose(mailserver_socket); mailserver_socket = -1; diff --git a/fetchmail.c b/fetchmail.c index 4c07dee6..d7dbf59c 100644 --- a/fetchmail.c +++ b/fetchmail.c @@ -1204,10 +1204,7 @@ static void terminate_poll(int sig) { /* don't send QUIT for ODMR case because we're acting as a proxy between the SMTP server and client. */ - if (ctl->server.protocol != P_ODMR) - SMTP_quit(ctl->smtp_socket); - SockClose(ctl->smtp_socket); - ctl->smtp_socket = -1; + smtp_close(ctl, ctl->server.protocol != P_ODMR); } } diff --git a/fetchmail.h b/fetchmail.h index 0a7fe39b..943765d9 100644 --- a/fetchmail.h +++ b/fetchmail.h @@ -462,6 +462,7 @@ extern int mytimeout; int interruptible_idle(int interval); /* sink.c: forwarding */ +void smtp_close(struct query *, int); int smtp_open(struct query *); int stuffline(struct query *, char *); int open_sink(struct query*, struct msgblk *, int*, int*); @@ -29,7 +29,7 @@ extern char *strstr(); /* needed on sysV68 R3V7.1. */ #define IMAP4 0 /* IMAP4 rev 0, RFC1730 */ #define IMAP4rev1 1 /* IMAP4 rev 1, RFC2060 */ -static int count, unseen, deletions = 0; +static int count = 0, recentcount = 0, unseen = 0, deletions = 0; static int expunged, expunge_period, saved_timeout = 0; static int imap_version, preauth; static flag do_idle; @@ -77,6 +77,10 @@ static int imap_ok(int sock, char *argbuf) stage = STAGE_FETCH; } } + else if (strstr(buf, "RECENT")) + { + recentcount = atoi(buf+2); + } else if (strstr(buf, "PREAUTH")) preauth = TRUE; /* @@ -487,25 +491,38 @@ static int imap_getrange(int sock, * just after deletion. */ ok = 0; - if (deletions && expunge_period != 1) + if (deletions) { ok = internal_expunge(sock); - count = -1; - if (do_idle) - ok = imap_idle(sock); - if (ok || gen_transact(sock, "NOOP")) - { - report(stderr, GT_("re-poll failed\n")); - return(ok); + if (ok) + { + report(stderr, GT_("expunge failed\n")); + return(ok); + } } - else if (count == -1) /* no EXISTS response to NOOP/IDLE */ - { - count = 0; + + /* + * recentcount is already set here by the last imap command which + * returned RECENT on detecting new mail. if recentcount is 0, wait + * for new mail. + */ + + /* this is a while loop because imap_idle() might return on other + * mailbox changes also */ + while (recentcount == 0 && do_idle) { + smtp_close(ctl, 1); + ok = imap_idle(sock); + if (ok) + { + report(stderr, GT_("re-poll failed\n")); + return(ok); + } } if (outlevel >= O_DEBUG) report(stdout, GT_("%d messages waiting after re-poll\n"), count); } else { + count = 0; ok = gen_transact(sock, check_only ? "EXAMINE \"%s\"" : "SELECT \"%s\"", folder ? folder : "INBOX"); @@ -540,6 +557,7 @@ static int imap_getrange(int sock, } *countp = count; + recentcount = 0; /* OK, now get a count of unseen messages and their indices */ if (!ctl->fetchall && count > 0) @@ -46,17 +46,29 @@ /* makes the open_sink()/close_sink() pair non-reentrant */ static int lmtp_responses; +void smtp_close(struct query *ctl, int sayquit) +/* close the socket to SMTP server */ +{ + if (ctl->smtp_socket != -1) + { + if (sayquit) + SMTP_quit(ctl->smtp_socket); + SockClose(ctl->smtp_socket); + ctl->smtp_socket = -1; + } + batchcount = 0; +} + int smtp_open(struct query *ctl) /* try to open a socket to the appropriate SMTP server for this query */ { char *parsed_host = NULL; /* maybe it's time to close the socket in order to force delivery */ - if (NUM_NONZERO(ctl->batchlimit) && (ctl->smtp_socket != -1) && ++batchcount == ctl->batchlimit) - { - SockClose(ctl->smtp_socket); - ctl->smtp_socket = -1; - batchcount = 0; + if (NUM_NONZERO(ctl->batchlimit)) { + if (batchcount == ctl->batchlimit) + smtp_close(ctl, 1); + batchcount++; } /* if no socket to any SMTP host is already set up, try to open one */ @@ -146,8 +158,7 @@ int smtp_open(struct query *ctl) * RFC 1869 warns that some listeners hang up on a failed EHLO, * so it's safest not to assume the socket will still be good. */ - SockClose(ctl->smtp_socket); - ctl->smtp_socket = -1; + smtp_close(ctl, 0); /* if opening for ESMTP failed, try SMTP */ if ((ctl->smtp_socket = SockOpen(parsed_host,portnum,NULL, @@ -158,8 +169,7 @@ int smtp_open(struct query *ctl) SMTP_helo(ctl->smtp_socket, id_me) == SM_OK) break; /* success */ - SockClose(ctl->smtp_socket); - ctl->smtp_socket = -1; + smtp_close(ctl, 0); } set_timeout(0); phase = oldphase; |