]> Pileus Git - ~andy/fetchmail/commitdiff
Sunil Shetye's fixews for IMAP and SMTP edge cases.
authorEric S. Raymond <esr@thyrsus.com>
Fri, 1 Feb 2002 02:22:24 +0000 (02:22 -0000)
committerEric S. Raymond <esr@thyrsus.com>
Fri, 1 Feb 2002 02:22:24 +0000 (02:22 -0000)
svn path=/trunk/; revision=3570

NEWS
driver.c
fetchmail.c
fetchmail.h
imap.c
sink.c

diff --git a/NEWS b/NEWS
index a4335e3597d38a35a64c313341d1930fc5388cb2..025017fb191cb9109646aaa4a5c29881760a15e0 100644 (file)
--- 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:
 
index ec46141025b601e7d15e4e6437bfe6178a9c8c56..aa35cfa40efb6349f230f8bc248fdf1c8b94ca95 100644 (file)
--- 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;
index 4c07dee6b9c75f87a99b5244ab6623198a8ccc87..d7dbf59cbe825937f2add5d70825a07b06b3a6d1 100644 (file)
@@ -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);
            }
     }
 
index 0a7fe39b546571fe79af6271bc336f4c31c3067e..943765d93d5b410ac06ee27ff2b33098e377872d 100644 (file)
@@ -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 9043a9ad3e6b222e7dfea551499ca4de9eaeace2..c07ceec7549b680eed30f5b17132b0f0df2f08ea 100644 (file)
--- 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 e7e4d5c03c43e3d3b0254ea42e14a88baf95843d..8b7484c44718d434b017a447fa63b7f6654db24f 100644 (file)
--- a/sink.c
+++ b/sink.c
 /* 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;