fetchmail-friends
[Top] [All Lists]

Re: [fetchmail] keep and top

2003-05-23 16:23:06
"Jakob Hirsch" <jh(_at_)plonk(_dot_)de> writes:

I wanted to use the "keep" option on a server where TOP should be used
and saw, that "keep" forces TOP to be disabled. On first thought this is
sensible, but only if "uidl" is not enabled, because then fetchmail can
determine which messages are new.
My patch below fixes this. It also uses this check made for
peek_cabable to reduce code redundancy.  In the end I think think
usage of TOP or RETR should be configurable (what has fetchall to do
with it?).

This is all ugly cruft that appears as though it was once meant to yield
to the LAST command (which was busted by design).

The whole TOP-vs-RETR issue is bogus. TOP isn't ever needed except for
the UIDL emulation code to retrieve Message-IDs. Anything short of
"retrieve everything" or "retrieve by UID" won't work and can miss any
amount of mail at any time. There is no such thing as a "read flag" in
POP3, so there's nothing to avoid and nothing to be gained by using TOP
other than a waste of bandwidth.

The whole code can drop 82 lines on the floor without losing
functionality. Servers that don't support either TOP or UIDL can then
only be used in fetchall nokeep mode, but who cares. That's what POP3
has always been meant for. If you want to keep mail on the server, you
need a current server, for current as in "implements 100-months-old
standard" (RFC-1725 or 1939), which is about high time now...

Here goes the diff.

diff -u fetchmail-6.2.2/driver.c fetchmail-6.2.2.ma1/driver.c
--- fetchmail-6.2.2/driver.c    2003-02-28 11:53:57.000000000 +0100
+++ fetchmail-6.2.2.ma1/driver.c        2003-05-24 01:12:15.000000000 +0200
@@ -66,7 +66,6 @@
 int stage;             /* where are we? */
 int phase;             /* where are we, for error-logging purposes? */
 int batchcount;                /* count of messages sent in current batch */
-flag peek_capable;     /* can we peek for better error recovery? */
 int mailserver_socket_temp = -1;       /* socket to free if connect timeout */ 
 
 static int timeoutcount;               /* count consecutive timeouts */
diff -u fetchmail-6.2.2/pop3.c fetchmail-6.2.2.ma1/pop3.c
--- fetchmail-6.2.2/pop3.c      2003-02-28 12:44:57.000000000 +0100
+++ fetchmail-6.2.2.ma1/pop3.c  2003-05-24 01:08:04.000000000 +0200
@@ -466,9 +466,6 @@
      */
     sleep(3); /* to be _really_ safe, probably need sleep(5)! */
 
-    /* we're peek-capable if use of TOP is enabled */
-    peek_capable = !(ctl->fetchall || ctl->keep);
-
     /* we're approved */
     return(PS_SUCCESS);
 }
@@ -611,69 +608,47 @@
     else
        return(ok);
 
-    /*
-     * Newer, RFC-1725-conformant POP servers may not have the LAST command.
-     * We work as hard as possible to hide this ugliness, but it makes 
-     * counting new messages intrinsically quadratic in the worst case.
-     */
     last = 0;
     *newp = -1;
     if (*countp > 0 && !ctl->fetchall)
     {
        char id [IDLEN+1];
 
-       if (!ctl->server.uidl) {
-           gen_send(sock, "LAST");
-           ok = pop3_ok(sock, buf);
-       } else
-           ok = 1;
-       if (ok == 0)
+       /* grab the mailbox's UID list */
+       if ((ok = gen_transact(sock, "UIDL")) != 0)
        {
-           if (sscanf(buf, "%d", &last) == 0)
+           /* don't worry, yet! do it the slow way */
+           if((ok = pop3_slowuidl( sock, ctl, countp, newp))!=0)
            {
-               report(stderr, GT_("protocol error\n"));
+               report(stderr, GT_("protocol error while fetching UIDLs\n"));
                return(PS_ERROR);
            }
-           *newp = (*countp - last);
        }
-       else
-       {
-           /* grab the mailbox's UID list */
-           if ((ok = gen_transact(sock, "UIDL")) != 0)
+       else
+       {
+           int num;
+
+           *newp = 0;
+           while ((ok = gen_recv(sock, buf, sizeof(buf))) == 0)
            {
-               /* don't worry, yet! do it the slow way */
-               if((ok = pop3_slowuidl( sock, ctl, countp, newp))!=0)
+               if (DOTLINE(buf))
+                   break;
+               else if (sscanf(buf, "%d %s", &num, id) == 2)
                {
-                   report(stderr, GT_("protocol error while fetching 
UIDLs\n"));
-                   return(PS_ERROR);
-               }
-           }
-           else
-           {
-               int     num;
+                   struct idlist       *new;
 
-               *newp = 0;
-               while ((ok = gen_recv(sock, buf, sizeof(buf))) == 0)
-               {
-                   if (DOTLINE(buf))
-                       break;
-                   else if (sscanf(buf, "%d %s", &num, id) == 2)
-                   {
-                       struct idlist   *new;
-
-                       new = save_str(&ctl->newsaved, id, UID_UNSEEN);
-                       new->val.status.num = num;
-
-                       if (str_in_list(&ctl->oldsaved, id, FALSE)) {
-                           new->val.status.mark = UID_SEEN;
-                           str_set_mark(&ctl->oldsaved, id, UID_SEEN);
-                       }
-                       else
-                           (*newp)++;
+                   new = save_str(&ctl->newsaved, id, UID_UNSEEN);
+                   new->val.status.num = num;
+
+                   if (str_in_list(&ctl->oldsaved, id, FALSE)) {
+                       new->val.status.mark = UID_SEEN;
+                       str_set_mark(&ctl->oldsaved, id, UID_SEEN);
                    }
-               }
-           }
-       }
+                   else
+                       (*newp)++;
+               }
+           }
+       }
     }
 
     return(PS_SUCCESS);
@@ -719,29 +694,6 @@
                            str_find(&ctl->newsaved, num), FALSE));
 }
 
-#ifdef UNUSED
-/*
- * We could use this to fetch headers only as we do for IMAP.  The trouble 
- * is that there's no way to fetch the body only.  So the following RETR 
- * would have to re-fetch the header.  Enough messages have longer headers
- * than bodies to make this a net loss.
- */
-static int pop_fetch_headers(int sock, struct query *ctl,int number,int *lenp)
-/* request headers of nth message */
-{
-    int ok;
-    char buf[POPBUFSIZE+1];
-
-    gen_send(sock, "TOP %d 0", number);
-    if ((ok = pop3_ok(sock, buf)) != 0)
-       return(ok);
-
-    *lenp = -1;                /* we got sizes from the LIST response */
-
-    return(PS_SUCCESS);
-}
-#endif /* UNUSED */
-
 static int pop3_fetch(int sock, struct query *ctl, int number, int *lenp)
 /* request nth message */
 {
@@ -783,39 +735,7 @@
     }
 #endif /* SDPS_ENABLE */
 
-    /*
-     * Though the POP RFCs don't document this fact, on almost every
-     * POP3 server I know of messages are marked "seen" only at the
-     * time the OK response to a RETR is issued.
-     *
-     * This means we can use TOP to fetch the message without setting its
-     * seen flag.  This is good!  It means that if the protocol exchange
-     * craps out during the message, it will still be marked `unseen' on
-     * the server.  (Exception: in early 1999 SpryNet's POP3 servers were
-     * reported to mark messages seen on a TOP fetch.)
-     *
-     * However...*don't* do this if we're using keep to suppress deletion!
-     * In that case, marking the seen flag is the only way to prevent the
-     * message from being re-fetched on subsequent runs.
-     *
-     * Also use RETR if fetchall is on.  This gives us a workaround
-     * for servers like usa.net's that bungle TOP.  It's pretty
-     * harmless because fetchall guarantees that any message dropped
-     * by an interrupted RETR will be picked up on the next poll of the
-     * site.
-     *
-     * We take advantage here of the fact that, according to all the
-     * POP RFCs, "if the number of lines requested by the POP3 client
-     * is greater than than the number of lines in the body, then the
-     * POP3 server sends the entire message.").
-     *
-     * The line count passed (99999999) is the maximum value CompuServe will
-     * accept; it's much lower than the natural value 2147483646 (the maximum
-     * twos-complement signed 32-bit integer minus 1) */
-    if (ctl->keep || ctl->fetchall)
-       gen_send(sock, "RETR %d", number);
-    else
-       gen_send(sock, "TOP %d 99999999", number);
+    gen_send(sock, "RETR %d", number);
     if ((ok = pop3_ok(sock, buf)) != 0)
        return(ok);
 
@@ -931,7 +851,6 @@
        return(PS_SYNTAX);
     }
 #endif /* MBOX */
-    peek_capable = !ctl->fetchall;
     return(do_protocol(ctl, &pop3));
 }
 #endif /* POP3_ENABLE */
diff -u fetchmail-6.2.2/fetchmail.man fetchmail-6.2.2.ma1/fetchmail.man
--- fetchmail-6.2.2/fetchmail.man       2003-02-28 22:45:09.000000000 +0100
+++ fetchmail-6.2.2.ma1/fetchmail.man   2003-05-24 01:16:12.000000000 +0200
@@ -140,7 +140,6 @@
 (Keyword: fetchall)
 Retrieve both old (seen) and new messages from the mailserver.  The
 default is to fetch only messages the server has not marked seen.
-Under POP3, this option also forces the use of RETR rather than TOP.
 Note that POP2 retrieval behaves as though --all is always on (see
 RETRIEVAL FAILURE MODES below) and this option does not work with ETRN
 or ODMR.


-- 
Matthias Andree

<Prev in Thread] Current Thread [Next in Thread>