]> Pileus Git - ~andy/fetchmail/blobdiff - pop3.c
Can specify multiple spam-blocks now.
[~andy/fetchmail] / pop3.c
diff --git a/pop3.c b/pop3.c
index 1634755b624df7bde8ff94601b1cf7b05ca4f96f..21432bcde8e6bf5cd34c3231007d9495f30472b2 100644 (file)
--- a/pop3.c
+++ b/pop3.c
@@ -67,7 +67,7 @@ int pop3_ok (int sock, char *argbuf)
 #endif /* OPIE */
            ok = 0;
        }
-       else if (strcmp(buf,"-ERR") == 0)
+       else if (strncmp(buf,"-ERR", 4) == 0)
        {
            if (phase > PHASE_GETAUTH) 
                ok = PS_PROTOCOL;
@@ -119,7 +119,9 @@ int pop3_getauth(int sock, struct query *ctl, char *greeting)
          * CompuServe has changed its RPA behavior.  Used to be they didn't
          * accept PASS, but I'm told this changed in mid-November 1997.
          */
-        if (strstr(greeting, "csi.com"))
+        if (strstr(greeting, "csi.com")
+            && (start = strchr(ctl->remotename, '@'))
+            && !strcmp("@compuserve.com", start))
         {
              /* temporary fix to get back out of cleartext authentication */
              gen_transact(sock, "PASS %s", "dummypass");
@@ -153,7 +155,7 @@ int pop3_getauth(int sock, struct query *ctl, char *greeting)
          int i;
 
          i = opiegenerator(challenge, !strcmp(ctl->password, "opie") ? "" : ctl->password, response);
-         if ((i == -2) && (cmd_daemon == -1)) {
+         if ((i == -2) && !run.poll_interval) {
            char secret[OPIE_SECRET_MAX+1];
            fprintf(stderr, "Secret pass phrase: ");
            if (opiereadpass(secret, sizeof(secret), 0))
@@ -234,6 +236,9 @@ int pop3_getauth(int sock, struct query *ctl, char *greeting)
      */
     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);
 }
@@ -353,7 +358,7 @@ pop3_slowuidl( int sock,  struct query *ctl, int *countp, int *newp)
 static int pop3_getrange(int sock, 
                         struct query *ctl,
                         const char *folder,
-                        int *countp, int *newp)
+                        int *countp, int *newp, int *bytes)
 /* get range of messages to be fetched */
 {
     int ok;
@@ -375,7 +380,7 @@ static int pop3_getrange(int sock,
     gen_send(sock, "STAT");
     ok = pop3_ok(sock, buf);
     if (ok == 0)
-       sscanf(buf,"%d %*d", countp);
+       sscanf(buf,"%d %d", countp, bytes);
     else
        return(ok);
 
@@ -432,9 +437,10 @@ static int pop3_getrange(int sock,
                        new = save_str(&ctl->newsaved, id, UID_UNSEEN);
                        new->val.status.num = num;
 
-                       /* note: ID comparison is caseblind */
-                       if (str_in_list(&ctl->oldsaved, id))
+                       if (str_in_list(&ctl->oldsaved, id, FALSE)) {
                            new->val.status.mark = UID_SEEN;
+                           str_set_mark(&ctl->oldsaved, id, UID_SEEN);
+                       }
                        else
                            (*newp)++;
                    }
@@ -443,7 +449,7 @@ static int pop3_getrange(int sock,
        }
     }
 
-    return(0);
+    return(PS_SUCCESS);
 }
 
 static int pop3_getsizes(int sock, int count, int *sizes)
@@ -479,26 +485,82 @@ static int pop3_is_old(int sock, struct query *ctl, int num)
     if (!ctl->oldsaved)
        return (num <= last);
     else
-       /* note: ID comparison is caseblind */
         return (str_in_list(&ctl->oldsaved,
-                           str_find (&ctl->newsaved, num)));
+                           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];
+
+    /* phase = PHASE_FETCH */
+
+    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 */
 {
     int ok;
-    char buf [POPBUFSIZE+1];
+    char buf[POPBUFSIZE+1];
 
     /* phase = PHASE_FETCH */
 
-    gen_send(sock, "RETR %d", number);
+    /*
+     * Though the POP RFCs don't document this fact, on 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.
+     *
+     * 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);
     if ((ok = pop3_ok(sock, buf)) != 0)
        return(ok);
 
     *lenp = -1;                /* we got sizes from the LIST response */
 
-    return(0);
+    return(PS_SUCCESS);
 }
 
 static int pop3_delete(int sock, struct query *ctl, int number)
@@ -533,6 +595,7 @@ const static struct method pop3 =
     FALSE,             /* this is not a tagged protocol */
     TRUE,              /* this uses a message delimiter */
     pop3_ok,           /* parse command response */
+    NULL,              /* no password canonicalization */
     pop3_getauth,      /* get authorization */
     pop3_getrange,     /* query range of messages */
     pop3_getsizes,     /* we can get a list of sizes */