aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS1
-rw-r--r--driver.c5
-rw-r--r--fetchmail.c5
-rw-r--r--fetchmail.h1
-rw-r--r--imap.c42
-rw-r--r--sink.c28
6 files changed, 53 insertions, 29 deletions
diff --git a/NEWS b/NEWS
index a4335e35..025017fb 100644
--- a/NEWS
+++ b/NEWS
@@ -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:
diff --git a/driver.c b/driver.c
index ec461410..aa35cfa4 100644
--- a/driver.c
+++ b/driver.c
@@ -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*);
diff --git a/imap.c b/imap.c
index 9043a9ad..c07ceec7 100644
--- a/imap.c
+++ b/imap.c
@@ -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)
diff --git a/sink.c b/sink.c
index e7e4d5c0..8b7484c4 100644
--- a/sink.c
+++ b/sink.c
@@ -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;