diff -Naur fetchmail-6.2.4.orig/conf.c fetchmail-6.2.4/conf.c --- fetchmail-6.2.4.orig/conf.c 2003-07-17 06:33:20.000000000 +0530 +++ fetchmail-6.2.4/conf.c 2003-09-19 11:27:54.000000000 +0530 @@ -376,6 +376,7 @@ numdump("limit", ctl->limit); numdump("warnings", ctl->warnings); numdump("fetchlimit", ctl->fetchlimit); + numdump("fetchsizelimit", ctl->fetchsizelimit); numdump("batchlimit", ctl->batchlimit); #ifdef SSL_ENABLE booldump("ssl", ctl->use_ssl); diff -Naur fetchmail-6.2.4.orig/driver.c fetchmail-6.2.4/driver.c --- fetchmail-6.2.4.orig/driver.c 2003-08-06 09:17:46.000000000 +0530 +++ fetchmail-6.2.4/driver.c 2003-09-19 12:30:31.000000000 +0530 @@ -415,11 +415,55 @@ } static int fetch_messages(int mailserver_socket, struct query *ctl, - int count, int *msgsizes, int *msgcodes, int maxfetch, + int count, int *msgsizes, int maxfetch, int *fetches, int *dispatches, int *deletions) /* fetch messages in lockstep mode */ { - int num, err, len; + flag force_retrieval; + int num, firstnum = 1, lastnum = 0, err, len; + int fetchsizelimit = ctl->fetchsizelimit; + int msgsize; + + if (ctl->server.base_protocol->getpartialsizes && NUM_NONZERO(fetchsizelimit)) + { + /* for POP3, we can get the size of one mail only! Unfortunately, this + * protocol specific test cannot be done elsewhere as the protocol + * could be "auto". */ + if (ctl->server.protocol == P_POP3) + fetchsizelimit = 1; + + /* Time to allocate memory to store the sizes */ + xalloca(msgsizes, int *, sizeof(int) * fetchsizelimit); + } + + /* + * What forces this code is that in POP2 and + * IMAP2bis you can't fetch a message without + * having it marked `seen'. In POP3 and IMAP4, on the + * other hand, you can (peek_capable is set by + * each driver module to convey this; it's not a + * method constant because of the difference between + * IMAP2bis and IMAP4, and because POP3 doesn't peek + * if fetchall is on). + * + * The result of being unable to peek is that if there's + * any kind of transient error (DNS lookup failure, or + * sendmail refusing delivery due to process-table limits) + * the message will be marked "seen" on the server without + * having been delivered. This is not a big problem if + * fetchmail is running in foreground, because the user + * will see a "skipped" message when it next runs and get + * clued in. + * + * But in daemon mode this leads to the message + * being silently ignored forever. This is not + * acceptable. + * + * We compensate for this by checking the error + * count from the previous pass and forcing all + * messages to be considered new if it's nonzero. + */ + force_retrieval = !peek_capable && (ctl->errcount > 0); for (num = 1; num <= count; num++) { @@ -427,30 +471,82 @@ flag suppress_forward = FALSE; flag suppress_readbody = FALSE; flag retained = FALSE; + int msgcode = MSGLEN_UNKNOWN; - if (msgcodes[num-1] < 0) + /* check if the message is old + * Note: the size of the message may not be known here */ + if (ctl->fetchall || force_retrieval) + ; + else if (ctl->server.base_protocol->is_old && (ctl->server.base_protocol->is_old)(mailserver_socket,ctl,num)) + msgcode = MSGLEN_OLD; + if (msgcode == MSGLEN_OLD) { - if ((msgcodes[num-1] == MSGLEN_TOOLARGE) && !check_only) - { - mark_oversized(ctl, num, msgsizes[num-1]); - suppress_delete = TRUE; - } /* To avoid flooding the syslog when using --keep, * report "Skipped message" only when: * 1) --verbose is on, or * 2) fetchmail does not use syslog, or - * 3) the message was skipped for some other - * reason than being old. */ if ( (outlevel >= O_VERBOSE) || - (outlevel > O_SILENT && (!run.use_syslog || msgcodes[num-1] != MSGLEN_OLD)) + (outlevel > O_SILENT && !run.use_syslog) ) { + report(stdout, + GT_("skipping message %s(_at_)%s:%d"), + ctl->remotename, ctl->server.truename, num); + } + + goto flagthemail; + } + + if (ctl->server.base_protocol->getpartialsizes && NUM_NONZERO(fetchsizelimit) && + lastnum < num) + { + /* Instead of getting the sizes of all mails at the start, we get + * the sizes in blocks of fetchsizelimit. This leads to better + * performance when there are too many mails (say, 10000) in + * the mailbox and either we are not getting all the mails at + * one go (--fetchlimit 100) or there is a frequent socket + * error while just getting the sizes of all mails! */ + + int i; + int oldstage = stage; + firstnum = num; + lastnum = num + fetchsizelimit - 1; + if (lastnum > count) + lastnum = count; + for (i = 0; i < fetchsizelimit; i++) + msgsizes[i] = 0; + + stage = STAGE_GETSIZES; + err = (ctl->server.base_protocol->getpartialsizes)(mailserver_socket, num, lastnum, msgsizes); + if (err != 0) + return err; + stage = oldstage; + } + + msgsize = msgsizes[num-firstnum]; + + /* check if the message is oversized */ + if (NUM_NONZERO(ctl->limit) && (msgsize > ctl->limit)) + msgcode = MSGLEN_TOOLARGE; +/* else if (msgsize == 512) + msgcode = MSGLEN_OLD; (hmh) sample code to skip message */ + + if (msgcode < 0) + { + if ((msgcode == MSGLEN_TOOLARGE) && !check_only) + { + mark_oversized(ctl, num, msgsize); + suppress_delete = TRUE; + } + if (outlevel > O_SILENT) + { + /* old messages are already handled above */ report_build(stdout, GT_("skipping message %s(_at_)%s:%d (%d octets)"), ctl->remotename, ctl->server.truename, num, - msgsizes[num-1]); - switch (msgcodes[num-1]) + msgsize); + switch (msgcode) { case MSGLEN_INVALID: /* @@ -483,7 +579,7 @@ report(stdout, GT_("couldn't fetch headers, message %s(_at_)%s:%d (%d octets)\n"), ctl->remotename, ctl->server.truename, num, - msgsizes[num-1]); + msgsize); continue; } else if (err != 0) @@ -492,7 +588,7 @@ /* -1 means we didn't see a size in the response */ if (len == -1) { - len = msgsizes[num - 1]; + len = msgsize; wholesize = TRUE; } @@ -515,7 +611,7 @@ * Read the message headers and ship them to the * output sink. */ - err = readheaders(mailserver_socket, len, msgsizes[num-1], + err = readheaders(mailserver_socket, len, msgsize, ctl, num, /* pass the suppress_readbody flag only if the underlying * protocol does not fetch the body separately */ @@ -573,7 +669,7 @@ * string. This violates RFC2060. */ if (len == -1) - len = msgsizes[num-1] - msgblk.msglen; + len = msgsize - msgblk.msglen; if (outlevel > O_SILENT && !wholesize) report_complete(stdout, GT_(" (%d body octets) "), len); @@ -630,13 +726,13 @@ * QUALCOMM server (at least) seems to be * reporting the on-disk size correctly. */ - if (msgblk.msglen != msgsizes[num-1]) + if (msgblk.msglen != msgsize) { if (outlevel >= O_DEBUG) report(stdout, GT_("message %s(_at_)%s:%d was not the expected length (%d actual != %d expected)\n"), ctl->remotename, ctl->server.truename, num, - msgblk.msglen, msgsizes[num-1]); + msgblk.msglen, msgsize); } /* end-of-message processing starts here */ @@ -649,6 +745,7 @@ (*fetches)++; } +flagthemail: /* * At this point in flow of control, either * we've bombed on a protocol error or had @@ -668,8 +765,8 @@ } else if (ctl->server.base_protocol->delete && !suppress_delete - && ((msgcodes[num-1] >= 0 && !ctl->keep) - || (msgcodes[num-1] == MSGLEN_OLD && ctl->flush))) + && ((msgcode >= 0 && !ctl->keep) + || (msgcode == MSGLEN_OLD && ctl->flush))) { (*deletions)++; if (outlevel > O_SILENT) @@ -688,14 +785,14 @@ * 3) the message was skipped for some other * reason than just being old. */ - (outlevel > O_SILENT && (!run.use_syslog || msgcodes[num-1] != MSGLEN_OLD)) + (outlevel > O_SILENT && (!run.use_syslog || msgcode != MSGLEN_OLD)) ) report_complete(stdout, GT_(" not flushed\n")); /* maybe we mark this message as seen now? */ if (ctl->server.base_protocol->mark_seen && !suppress_delete - && (msgcodes[num-1] >= 0 && ctl->keep)) + && (msgcode >= 0 && ctl->keep)) { err = (ctl->server.base_protocol->mark_seen)(mailserver_socket, ctl, num); if (err != 0) @@ -826,7 +923,6 @@ char buf[MSGBUFSIZE+1], *realhost; int count, new, bytes, deletions = 0; int *msgsizes = (int *)NULL; - int *msgcodes = (int *)NULL; #if INET6_ENABLE int fetches, dispatches, oldphase; #else /* INET6_ENABLE */ @@ -1301,37 +1397,7 @@ } else if (count > 0) { - flag force_retrieval; - int i, num; - - /* - * What forces this code is that in POP2 and - * IMAP2bis you can't fetch a message without - * having it marked `seen'. In POP3 and IMAP4, on the - * other hand, you can (peek_capable is set by - * each driver module to convey this; it's not a - * method constant because of the difference between - * IMAP2bis and IMAP4, and because POP3 doesn't peek - * if fetchall is on). - * - * The result of being unable to peek is that if there's - * any kind of transient error (DNS lookup failure, or - * sendmail refusing delivery due to process-table limits) - * the message will be marked "seen" on the server without - * having been delivered. This is not a big problem if - * fetchmail is running in foreground, because the user - * will see a "skipped" message when it next runs and get - * clued in. - * - * But in daemon mode this leads to the message - * being silently ignored forever. This is not - * acceptable. - * - * We compensate for this by checking the error - * count from the previous pass and forcing all - * messages to be considered new if it's nonzero. - */ - force_retrieval = !peek_capable && (ctl->errcount > 0); + int i; /* * Don't trust the message count passed by the server. @@ -1346,23 +1412,23 @@ return(PS_PROTOCOL); } - /* OK, we're going to gather size info next */ - xalloca(msgsizes, int *, sizeof(int) * count); - xalloca(msgcodes, int *, sizeof(int) * count); - for (i = 0; i < count; i++) { - msgsizes[i] = 0; - msgcodes[i] = MSGLEN_UNKNOWN; - } - /* * We need the size of each message before it's * loaded in order to pass it to the ESMTP SIZE * option. If the protocol has a getsizes method, * we presume this means it doesn't get reliable * sizes from message fetch responses. + * + * If the protocol supports getting sizes of subset of + * messages, we skip this step now. */ - if (proto->getsizes) + if (proto->getsizes && + !(proto->getpartialsizes && NUM_NONZERO(ctl->fetchsizelimit))) { + xalloca(msgsizes, int *, sizeof(int) * count); + for (i = 0; i < count; i++) + msgsizes[i] = 0; + stage = STAGE_GETSIZES; err = (proto->getsizes)(mailserver_socket, count, msgsizes); if (err != 0) @@ -1376,25 +1442,12 @@ } } - /* mark some messages not to be retrieved */ - for (num = 1; num <= count; num++) - { - if (NUM_NONZERO(ctl->limit) && (msgsizes[num-1] > ctl->limit)) - msgcodes[num-1] = MSGLEN_TOOLARGE; - else if (ctl->fetchall || force_retrieval) - continue; - else if (ctl->server.base_protocol->is_old && (ctl->server.base_protocol->is_old)(mailserver_socket,ctl,num)) - msgcodes[num-1] = MSGLEN_OLD; -/* else if (msgsizes[num-1] == 512) - msgcodes[num-1] = MSGLEN_OLD; (hmh) sample code to skip message */ - } - /* read, forward, and delete messages */ stage = STAGE_FETCH; /* fetch in lockstep mode */ err = fetch_messages(mailserver_socket, ctl, - count, msgsizes, msgcodes, + count, msgsizes, maxfetch, &fetches, &dispatches, &deletions); if (err) diff -Naur fetchmail-6.2.4.orig/etrn.c fetchmail-6.2.4/etrn.c --- fetchmail-6.2.4.orig/etrn.c 2003-07-17 06:33:20.000000000 +0530 +++ fetchmail-6.2.4/etrn.c 2003-09-19 11:27:54.000000000 +0530 @@ -135,6 +135,7 @@ NULL, /* no need to get authentication */ etrn_getrange, /* initialize message sending */ NULL, /* we cannot get a list of sizes */ + NULL, /* we cannot get a list of sizes of subsets */ NULL, /* how do we tell a message is old? */ NULL, /* no way to fetch headers */ NULL, /* no way to fetch body */ diff -Naur fetchmail-6.2.4.orig/fetchmail.c fetchmail-6.2.4/fetchmail.c --- fetchmail-6.2.4.orig/fetchmail.c 2003-08-13 13:38:14.000000000 +0530 +++ fetchmail-6.2.4/fetchmail.c 2003-09-19 11:27:54.000000000 +0530 @@ -872,6 +872,7 @@ FLAG_MERGE(limit); FLAG_MERGE(warnings); FLAG_MERGE(fetchlimit); + FLAG_MERGE(fetchsizelimit); FLAG_MERGE(batchlimit); #ifdef SSL_ENABLE FLAG_MERGE(use_ssl); @@ -910,6 +911,7 @@ def_opts.warnings = WARNING_INTERVAL; def_opts.remotename = user; def_opts.listener = SMTP_MODE; + def_opts.fetchsizelimit = 100; /* get the location of rcfile */ rcfiledir[0] = 0; @@ -1630,6 +1632,11 @@ ctl->fetchlimit, ctl->fetchlimit); else if (outlevel >= O_VERBOSE) printf(GT_(" No received-message limit (--fetchlimit 0).\n")); + if (NUM_NONZERO(ctl->fetchsizelimit)) + printf(GT_(" Fetch message size limit is %d (--fetchsizelimit %d).\n"), + ctl->fetchsizelimit, ctl->fetchsizelimit); + else if (outlevel >= O_VERBOSE) + printf(GT_(" No fetch message size limit (--fetchsizelimit 0).\n")); if (NUM_NONZERO(ctl->batchlimit)) printf(GT_(" SMTP message batch limit is %d.\n"), ctl->batchlimit); else if (outlevel >= O_VERBOSE) diff -Naur fetchmail-6.2.4.orig/fetchmail.h fetchmail-6.2.4/fetchmail.h --- fetchmail-6.2.4.orig/fetchmail.h 2003-08-06 09:00:16.000000000 +0530 +++ fetchmail-6.2.4/fetchmail.h 2003-09-19 11:27:54.000000000 +0530 @@ -182,6 +182,8 @@ /* get message range to fetch */ int (*getsizes)(int, int, int *); /* get sizes of messages */ + int (*getpartialsizes)(int, int, int, int *); + /* get sizes of subset of messages */ int (*is_old)(int, struct query *, int); /* check for old message */ int (*fetch_headers)(int, struct query *, int, int *); @@ -289,6 +291,7 @@ int limit; /* limit size of retrieved messages */ int warnings; /* size warning interval */ int fetchlimit; /* max # msgs to get in single poll */ + int fetchsizelimit; /* max # msg sizes to get in a request */ int batchlimit; /* max # msgs to pass in single SMTP session */ int expunge; /* max # msgs to pass between expunges */ flag use_ssl; /* use SSL encrypted session */ diff -Naur fetchmail-6.2.4.orig/fetchmail.man fetchmail-6.2.4/fetchmail.man --- fetchmail-6.2.4.orig/fetchmail.man 2003-07-22 08:01:02.000000000 +0530 +++ fetchmail-6.2.4/fetchmail.man 2003-09-19 11:27:54.000000000 +0530 @@ -486,6 +486,16 @@ overrides any limits set in your run control file. This option does not work with ETRN or ODMR. .TP +.B \-\-fetchsizelimit +(Keyword: fetchsizelimit) +Limit the number of sizes of messages accepted from a given server in +a single transaction. This option is useful in reducing the delay in +downloading the first mail when there are too many mails in the +mailbox. By default, the limit is 100. If set to 0, sizes of all +messages are downloaded at the start. +This option does not work with ETRN or ODMR. For POP3, the only valid +non-zero value is 1. +.TP .B \-e | \-\-expunge (keyword: expunge) Arrange for deletions to be made final after a given number of @@ -1478,6 +1488,9 @@ fetchlimit -B T{ Max # messages to fetch in single connect T} +fetchsizelimit \& T{ +Max # message sizes to fetch in single transaction +T} expunge -e T{ Perform an expunge on every #th message (IMAP and POP3 only) T} diff -Naur fetchmail-6.2.4.orig/fetchmailconf fetchmail-6.2.4/fetchmailconf --- fetchmail-6.2.4.orig/fetchmailconf 2003-08-06 09:13:17.000000000 +0530 +++ fetchmail-6.2.4/fetchmailconf 2003-09-19 11:27:54.000000000 +0530 @@ -250,6 +250,7 @@ self.limit = 0 # Message size limit self.warnings = 3600 # Size warning interval (see tunable.h) self.fetchlimit = 0 # Max messages fetched per batch + self.fetchsizelimit = 0 # Max message sizes fetched per transaction self.batchlimit = 0 # Max message forwarded per batch self.expunge = 0 # Interval between expunges (IMAP) self.ssl = 0 # Enable Seccure Socket Layer @@ -287,6 +288,7 @@ ('limit', 'Int'), ('warnings', 'Int'), ('fetchlimit', 'Int'), + ('fetchsizelimit', 'Int'), ('batchlimit', 'Int'), ('expunge', 'Int'), ('ssl', 'Boolean'), @@ -347,6 +349,8 @@ res = res + " warnings " + `self.warnings` if self.fetchlimit != UserDefaults.fetchlimit: res = res + " fetchlimit " + `self.fetchlimit` + if self.fetchsizelimit != UserDefaults.fetchsizelimit: + res = res + " fetchsizelimit " + `self.fetchsizelimit` if self.batchlimit != UserDefaults.batchlimit: res = res + " batchlimit " + `self.batchlimit` if self.ssl and self.ssl != UserDefaults.ssl: @@ -1701,6 +1705,8 @@ self.warnings, '30').pack(side=TOP, fill=X) LabeledEntry(limwin, 'Max messages to fetch per poll:', self.fetchlimit, '30').pack(side=TOP, fill=X) + LabeledEntry(limwin, 'Max message sizes to fetch per transaction:', + self.fetchsizelimit, '30').pack(side=TOP, fill=X) LabeledEntry(limwin, 'Max messages to forward per poll:', self.batchlimit, '30').pack(side=TOP, fill=X) if self.parent.server.protocol not in ('ETRN', 'ODMR'): diff -Naur fetchmail-6.2.4.orig/imap.c fetchmail-6.2.4/imap.c --- fetchmail-6.2.4.orig/imap.c 2003-09-17 11:57:22.000000000 +0530 +++ fetchmail-6.2.4/imap.c 2003-09-19 12:24:38.000000000 +0530 @@ -780,8 +780,8 @@ return(PS_SUCCESS); } -static int imap_getsizes(int sock, int count, int *sizes) -/* capture the sizes of all messages */ +static int imap_getpartialsizes(int sock, int first, int last, int *sizes) +/* capture the sizes of messages #first-#last */ { char buf [MSGBUFSIZE+1]; @@ -819,14 +819,15 @@ * on the fact that the sizes array has been preinitialized with a * known-bad size value. */ - /* if fetchall is specified, startcount is 1; - * else if there is new mail, startcount is first unseen message; - * else startcount is greater than count. - */ - if (count == startcount) - gen_send(sock, "FETCH %d RFC822.SIZE", count); - else if (count > startcount) - gen_send(sock, "FETCH %d:%d RFC822.SIZE", startcount, count); + + /* expunges change the fetch numbers */ + first -= expunged; + last -= expunged; + + if (last == first) + gen_send(sock, "FETCH %d RFC822.SIZE", last); + else if (last > first) + gen_send(sock, "FETCH %d:%d RFC822.SIZE", first, last); else /* no unseen messages! */ return(PS_SUCCESS); for (;;) @@ -847,8 +848,8 @@ break; else if (sscanf(buf, "* %u FETCH (RFC822.SIZE %u)", &num, &size) == 2) { - if (num > 0 && num <= count) - sizes[num - 1] = size; + if (num >= first && num <= last) + sizes[num - first] = size; else report(stderr, "Warning: ignoring bogus data for message sizes returned by the server.\n"); } @@ -857,6 +858,12 @@ return(PS_SUCCESS); } +static int imap_getsizes(int sock, int count, int *sizes) +/* capture the sizes of all messages */ +{ + return imap_getpartialsizes(sock, 1, count, sizes); +} + static int imap_is_old(int sock, struct query *ctl, int number) /* is the given message old? */ { @@ -1109,6 +1116,7 @@ imap_getauth, /* get authorization */ imap_getrange, /* query range of messages */ imap_getsizes, /* get sizes of messages (used for ESMTP SIZE option) */ + imap_getpartialsizes, /* get sizes of subset of messages (used for ESMTP SIZE option) */ imap_is_old, /* no UID check */ imap_fetch_headers, /* request given message headers */ imap_fetch_body, /* request given message body */ diff -Naur fetchmail-6.2.4.orig/odmr.c fetchmail-6.2.4/odmr.c --- fetchmail-6.2.4.orig/odmr.c 2003-07-17 06:33:22.000000000 +0530 +++ fetchmail-6.2.4/odmr.c 2003-09-19 11:27:54.000000000 +0530 @@ -224,6 +224,7 @@ NULL, /* no need to get authentication */ odmr_getrange, /* initialize message sending */ NULL, /* we cannot get a list of sizes */ + NULL, /* we cannot get a list of sizes of subsets */ NULL, /* how do we tell a message is old? */ NULL, /* no way to fetch headers */ NULL, /* no way to fetch body */ diff -Naur fetchmail-6.2.4.orig/options.c fetchmail-6.2.4/options.c --- fetchmail-6.2.4.orig/options.c 2003-07-17 06:33:20.000000000 +0530 +++ fetchmail-6.2.4/options.c 2003-09-19 11:27:54.000000000 +0530 @@ -86,6 +86,7 @@ #define LA_SSLFINGERPRINT 60 #endif +#define LA_FETCHSIZELIMIT 61 /* options still left: CDgGhHjJoORwWxXYz */ static const char *shortoptions = @@ -140,6 +141,7 @@ {"batchlimit",required_argument, (int *) 0, LA_BATCHLIMIT }, {"fetchlimit",required_argument, (int *) 0, LA_FETCHLIMIT }, + {"fetchsizelimit",required_argument, (int *) 0, LA_FETCHSIZELIMIT }, {"expunge", required_argument, (int *) 0, LA_EXPUNGE }, {"mda", required_argument, (int *) 0, LA_MDA }, {"bsmtp", required_argument, (int *) 0, LA_BSMTP }, @@ -529,6 +531,10 @@ c = xatoi(optarg, &errflag); ctl->fetchlimit = NUM_VALUE_IN(c); break; + case LA_FETCHSIZELIMIT: + c = xatoi(optarg, &errflag); + ctl->fetchsizelimit = NUM_VALUE_IN(c); + break; case 'e': case LA_EXPUNGE: c = xatoi(optarg, &errflag); @@ -705,6 +711,7 @@ P(GT_(" -Z, --antispam, set antispam response values\n")); P(GT_(" -b, --batchlimit set batch limit for SMTP connections\n")); P(GT_(" -B, --fetchlimit set fetch limit for server connections\n")); + P(GT_(" --fetchsizelimit set fetch message size limit\n")); P(GT_(" -e, --expunge set max deletions between expunges\n")); P(GT_(" -m, --mda set MDA to use for forwarding\n")); P(GT_(" --bsmtp set output BSMTP file\n")); diff -Naur fetchmail-6.2.4.orig/pop2.c fetchmail-6.2.4/pop2.c --- fetchmail-6.2.4.orig/pop2.c 2003-07-17 06:33:20.000000000 +0530 +++ fetchmail-6.2.4/pop2.c 2003-09-19 11:27:54.000000000 +0530 @@ -141,6 +141,7 @@ pop2_getauth, /* get authorization */ pop2_getrange, /* query range of messages */ NULL, /* no way to get sizes */ + NULL, /* no way to get sizes of subsets */ NULL, /* messages are always new */ pop2_fetch, /* request given message */ NULL, /* no way to fetch body alone */ diff -Naur fetchmail-6.2.4.orig/pop3.c fetchmail-6.2.4/pop3.c --- fetchmail-6.2.4.orig/pop3.c 2003-08-06 09:00:17.000000000 +0530 +++ fetchmail-6.2.4/pop3.c 2003-09-19 11:45:36.000000000 +0530 @@ -796,6 +796,32 @@ return(PS_SUCCESS); } +static int pop3_getpartialsizes(int sock, int first, int last, int *sizes) +/* capture the size of message #first */ +{ + int ok; + char buf [POPBUFSIZE+1]; + unsigned int num, size; + + /* for POP3, we can get the size of one mail only! */ + if (first != last) + { + report(stderr, "cannot get a range of message sizes (%d-%d).\n", first, last); + return(PS_PROTOCOL); + } + gen_send(sock, "LIST %d", first); + if ((ok = pop3_ok(sock, buf)) != 0) + return(ok); + if (sscanf(buf, "%u %u", &num, &size) == 2) { + if (num == first) + sizes[0] = size; + else + /* warn about possible attempt to induce buffer overrun */ + report(stderr, "Warning: ignoring bogus data for message sizes returned by server.\n"); + } + return(ok); +} + static int pop3_getsizes(int sock, int count, int *sizes) /* capture the sizes of all messages */ { @@ -1029,6 +1055,7 @@ pop3_getauth, /* get authorization */ pop3_getrange, /* query range of messages */ pop3_getsizes, /* we can get a list of sizes */ + pop3_getpartialsizes, /* we can get the size of 1 mail */ pop3_is_old, /* how do we tell a message is old? */ pop3_fetch, /* request given message */ NULL, /* no way to fetch body alone */ diff -Naur fetchmail-6.2.4.orig/rcfile_l.l fetchmail-6.2.4/rcfile_l.l --- fetchmail-6.2.4.orig/rcfile_l.l 2003-08-06 09:17:47.000000000 +0530 +++ fetchmail-6.2.4/rcfile_l.l 2003-09-19 11:27:54.000000000 +0530 @@ -124,6 +124,7 @@ plugout { return PLUGOUT; } batchlimit { return BATCHLIMIT; } fetchlimit { return FETCHLIMIT; } +fetchsizelimit { return FETCHSIZELIMIT; } expunge { return EXPUNGE; } properties { return PROPERTIES; } diff -Naur fetchmail-6.2.4.orig/rcfile_y.y fetchmail-6.2.4/rcfile_y.y --- fetchmail-6.2.4.orig/rcfile_y.y 2003-07-17 06:33:20.000000000 +0530 +++ fetchmail-6.2.4/rcfile_y.y 2003-09-19 11:27:54.000000000 +0530 @@ -67,7 +67,7 @@ %token SMTPADDRESS SMTPNAME SPAMRESPONSE PRECONNECT POSTCONNECT LIMIT WARNINGS %token NETSEC INTERFACE MONITOR PLUGIN PLUGOUT %token IS HERE THERE TO MAP WILDCARD -%token BATCHLIMIT FETCHLIMIT EXPUNGE PROPERTIES +%token BATCHLIMIT FETCHLIMIT FETCHSIZELIMIT EXPUNGE PROPERTIES %token SET LOGFILE DAEMON SYSLOG IDFILE INVISIBLE POSTMASTER BOUNCEMAIL %token SPAMBOUNCE SHOWDOTS %token PROTO AUTHTYPE @@ -374,6 +374,7 @@ | LIMIT NUMBER {current.limit = NUM_VALUE_IN($2);} | WARNINGS NUMBER {current.warnings = NUM_VALUE_IN($2);} | FETCHLIMIT NUMBER {current.fetchlimit = NUM_VALUE_IN($2);} + | FETCHSIZELIMIT NUMBER {current.fetchsizelimit = NUM_VALUE_IN($2);} | BATCHLIMIT NUMBER {current.batchlimit = NUM_VALUE_IN($2);} | EXPUNGE NUMBER {current.expunge = NUM_VALUE_IN($2);}