fetchmail-friends
[Top] [All Lists]

Re: [fetchmail]fetchmail 5.8.14 FETCH response handling

2001-07-31 19:22:15
On Mon, 30 Jul 2001, Eric S. Raymond wrote:

Justin Guyett <jfg(_at_)sonicity(_dot_)com>:
Those handle "BAD" and "NO" responses for [some] other command[s], not
FETCH (when fetching headers).  relevant code is around 672-680 (5.8.14)
in imap_fetch_headers().  The quick patch that worked well enough for me
(since the message wasn't important) was to do a sscanf() looking for NO
instead of FETCH, and if so return 100 (unused error code), then wherever
that gets called from (I forget), i just continued the loop if I saw that
error.

Fixed in 5.8.15.

(looking)

not really.  returning a fatal error so that the message retrieval loop
exits is almost just as bad.  one fucked up message (for Microsoft's
definition of fucked)  shouldn't make all subsequent messages
unretrievable.  IMHO fetchmail should take a best effort approach toward
mail retrieval, not quit at the first sign of trouble, even if the problem
is a Redmond, Inc. mailserver.

Another problem with .15 is that mail server replies aren't read to
completion (this was happening before, but wasn't breaking things as it
seems to be doing now)... so there can be trailing lines from server
responses to old commands that must be read and dealt with before seeing
responses from the command that fetchmail just sent.

also NO and BAD responses don't start with "* ", so the buf+2 guess has
to be improved.

fetchmail: about to deliver with: /usr/bin/procmail -d alt
#
fetchmail: IMAP< )
fetchmail: IMAP< A0995 OK FETCH completed.
fetchmail: IMAP> A0996 FETCH 496 BODY[TEXT]
fetchmail: IMAP< * 496 FETCH (BODY[TEXT] {0}
 (0 body octets)  not flushed
fetchmail: IMAP> A0997 FETCH 497 RFC822.HEADER
beginning to look for response...
fetchmail: IMAP< )
buffer: )
fetchmail: IMAP< A0996 OK FETCH completed.
buffer: A0996 OK FETCH completed.
+++returning PS_ERROR, NO found
fetchmail: IMAP> A0998 LOGOUT
fetchmail: IMAP< * 497 FETCH (RFC822.HEADER {745}
<rest of 497>
fetchmail: IMAP< A0997 OK FETCH completed.
fetchmail: IMAP< * BYE Microsoft Exchange 2000 IMAP4rev1 server version
6.0.4417.0 signing off.
fetchmail: IMAP< A0998 OK LOGOUT completed.

should be obvious, the buffer is printed just after being read, before
the checks for FETCH, NO, and BAD.

and i must have been on crack when i said sscanf(), i don't think it works
right the way you use it (there's no way to tell whether it matched NO or
BAD or not, since it only reports the number of successful conversions,
not how far through the format string it got).

so basically, besides this patch, you probably need to add a transient
error that means continue, not break, the message loop.

also the end-of-message checking may be broken...  it over-reads a
message (with the following patch):

fetchmail: IMAP< * 1210 FETCH (RFC822.HEADER {980}
buffer: * 1210 FETCH (RFC822.HEADER {980}
skip_tok skipped 2 characters
buffer2: 1210 FETCH (RFC822.HEADER {980}
breaking from loop, FETCH response found
+++all clear
reading message 1210 of 6415 (980 header octets)
<rewrite garbage>
fetchmail: about to deliver with: /usr/bin/procmail -d alt
#
fetchmail: IMAP< )
fetchmail: IMAP< A2423 OK FETCH completed.
fetchmail: IMAP> A2424 FETCH 1210 BODY[TEXT]
fetchmail: IMAP< * 1210 FETCH (BODY[TEXT] {1349}
 (1349 body octets) **************************.***********
fetchmail: IMAP< )
fetchmail: IMAP< A2424 OK FETCH completed.
fetchmail: message 1210 was not the expected length (2329 actual != 1952
expected)
 not flushed
fetchmail: IMAP> A2425 FETCH 1211 RFC822.HEADER
beginning to look for response...
fetchmail: timeout after 10 seconds waiting for server ex01.sonicity.com.


the following patch is just what i was using to get to this exchange [npi]
with the exchange server.  obviously most of it is debugging crud.  i'll
try to try to figure out what the deal is with message 1210 soon.

------------------
diff -dur fetchmail-5.8.15/imap.c fetchmail-5.8.15-pf/imap.c
--- fetchmail-5.8.15/imap.c     Mon Jul 30 20:12:39 2001
+++ fetchmail-5.8.15-pf/imap.c  Tue Jul 31 12:07:41 2001
@@ -656,6 +656,16 @@
     return(seen);
 }

+char *
+skip_tok(char *s) {
+  char *ptr;
+  while(isspace(*ptr)) ptr++;
+  while(!isspace(*ptr) && !iscntrl(*ptr)) ptr++;
+  while(isspace(*ptr)) ptr++;
+  printf("skip_tok skipped %lu characters\n", ptr-s);
+  return(ptr);
+}
+
 static int imap_fetch_headers(int sock, struct query *ctl,int number,int *lenp)
 /* request headers of nth message */
 {
@@ -670,26 +680,41 @@
      * According to the RFCs, it should *not* set the \Seen flag.
      */
     gen_send(sock, "FETCH %d RFC822.HEADER", number);
-
+    printf("beginning to look for response...\n");
     /* looking for FETCH response */
     for (;;)
     {
        int     ok;
+       char    *ptr = buf;

        if ((ok = gen_recv(sock, buf, sizeof(buf))))
            return(ok);
-       if (sscanf(buf+2, "%d FETCH (%*s {%d}", &num, lenp) == 2)
+
+       printf("buffer: %s\n", buf);
+       ptr = skip_tok(buf);
+       printf("buffer2: %s\n", ptr);
+       if (sscanf(ptr, "%d FETCH (%*s {%d}", &num, lenp) == 2) {
+           printf("breaking from loop, FETCH response found\n");
            break;
-       else if (sscanf(buf+2, "%d NO", &num) == 1)
+       }
+       else if (!strncmp(ptr, "NO ", 3)) {
+           printf("+++returning PS_ERROR, NO found\n");
            return(PS_ERROR);
-       else if (sscanf(buf+2, "%d BAD", &num) == 1)
+       }
+       else if (!strncmp(ptr, "BAD ", 4)) {
+           printf("+++returning PS_ERROR, BAD found\n");
            return(PS_ERROR);
+       }
     }

-    if (num != number)
+    if (num != number) {
+       printf("+++num != number\n");
        return(PS_ERROR);
-    else
+    }
+    else {
+       printf("+++all clear\n");
        return(PS_SUCCESS);
+    }
 }

 static int imap_fetch_body(int sock, struct query *ctl, int number, int *lenp)



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