fetchmail-friends
[Top] [All Lists]

[fetchmail]More on MS Exchange 2000 issues

2001-04-24 12:39:39
After examining a whole bunch of messages that were giving me grief,
I've come to the conclusion that Exchange 2000 is sometimes sending
'.\r' or '.\r\n' to end messages, and relying on the message to
end with '\r\n' itself (or that the client fetching is accurately
counting the number of bytes to expect and then double checking for
the '.\r\n').

Here is a transcript (created with 'script' of a telnet session to
delete a message. The '^M' are how vi shows the '\r's, and I cut
and pasted from vi:

Escape character is '^]'.^M^M
+OK Microsoft Exchange 2000 POP3 server version 6.0.4417.0 (exchange2000.site.c
om) ready.^M
USER me^M
+OK^M
PASS XXXXXXX^M
+OK User successfully logged on.^M
TOP 22 99999999^M
+OK^M
Received: from mail.site.com ([10.10.10.31]) by exchange2000.site.com with Micr
osoft SMTPSVC(5.0.2195.1600);^M
         Mon, 23 Apr 2001 17:28:03 -0700^M
[more headers and body snipped]
-- ^M
$jhi++; # http://www.iki.fi/jhi/^M
        # There is this special biologist word we use for 'stable'.^M
        # It is 'dead'. -- Jack Cohen^M.^M
DELE 22^M
+OK^M
QUIT^M
+OK Microsoft Exchange 2000 POP3 server version 6.0.4417.0 signing off.^M
Connection closed by foreign host.^M^M


I modified readbody() in driver.c (handmade patch, patch(1) probably won't
like it) which helps a bit:

1209 a 1
  {
      int linelen;
      unsigned char buf[MSGBUFSIZE+4];
      unsigned char *inbufp = buf;
+     unsigned char *dotp;
      flag issoftline = FALSE;

      /*
       * Pass through the text lines in the body.
1258 a 12
          /* check for end of message */
          if (protocol->delimited && *inbufp == '.')
          {
              if (inbufp[1] == '\r' && inbufp[2] == '\n' && inbufp[3] == '\0')
                  break;
              else if (inbufp[1] == '\n' && inbufp[2] == '\0')
                  break;
              else
                  msglen--;       /* subtract the size of the dot escape */
+         } else if (protocol->delimited && (dotp = strstr(inbufp, "\r.\r"))) {
+           /* If Exchange 2000 sends \r.\r, why not make it look like \n.\n?
+           ** Will that help us?
+           */
+           if (dotp[3] == '\0') {
+             dotp[0] == '\n';
+             dotp[2] == '\n';
+             break;
+           } else if ((dotp[3] == '\n') && (dotp[4] == '\0')) {
+             dotp[0] == '\n';
+             break;
+           }
          }

          msglen += linelen;

          if (ctl->mimedecode && (ctl->mimemsg & MSG_NEEDS_DECODE)) {


But that still leaves me problems because some messages don't even
have a '\r' before the final '.'.

I thought of changing this line

    while (protocol->delimited || len > 0)

to use an && despite the comment in front of it, but it seems that
len as returned by the server includes the size of the headers, but
that size has not been subtracted prior to readbody() being called.
Thus I reach the end and len is still a thousand or two octets from
zero.

I'm tempted to modify fetchmail to shorten the timeout before the
"fetchmail: client/server synchronization error" would come up and
change it to try look for a trailing '.' on the last line read,
to see if it can resume. This sounds like mucking around with a
lot more than one function, so I'm a bit resistant.

Or would it be better to fix len to be body size somehow? (Where?)


Elijah


<Prev in Thread] Current Thread [Next in Thread>
  • [fetchmail]More on MS Exchange 2000 issues, eli <=