diff options
-rw-r--r-- | NEWS | 10 | ||||
-rw-r--r-- | driver.c | 24 | ||||
-rw-r--r-- | fetchmail.h | 1 | ||||
-rw-r--r-- | imap.c | 34 | ||||
-rw-r--r-- | pop2.c | 1 | ||||
-rw-r--r-- | pop3.c | 1 |
6 files changed, 55 insertions, 16 deletions
@@ -1,6 +1,16 @@ Release Notes: ------------------------------------------------------------------------------ +fetchmail-2.3 () + +features -- + +* Full IMAP4 support -- we now probe for IMAP4 capabilities and use + RFC822.PEEK when possible to avoid marking messages seen on the server + before they are deleted. This improves recovery from sendmail and + dropped-connection errors. + +------------------------------------------------------------------------------ fetchmail-2.2 (Mon Dec 9 00:15:01 EST 1996): features -- @@ -47,6 +47,7 @@ int batchlimit; /* how often to tear down the delivery connection */ int batchcount; /* count of messages sent in current batch */ +int peek_capable; /* can we peek for better error recovery? */ static const struct method *protocol; static jmp_buf restart; @@ -935,16 +936,19 @@ const struct method *proto; /* protocol method table */ else if (count > 0) { /* - * What forces this code is that in POP3 you can't fetch a - * message without having it marked `seen'. + * What forces this code is that in POP3 and IMAP2BIS you can't + * fetch a message without having it marked `seen'. In IMAP4, + * on the other hand, you can (peek_capable is set to convey + * this). * - * The result 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. + * 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. @@ -953,7 +957,7 @@ const struct method *proto; /* protocol method table */ * previous pass and forcing all messages to be considered new * if it's nonzero. */ - int force_retrieval = (ctl->errcount > 0); + int force_retrieval = !peek_capable && (ctl->errcount > 0); ctl->errcount = 0; diff --git a/fetchmail.h b/fetchmail.h index 13b9791f..9e10cd0d 100644 --- a/fetchmail.h +++ b/fetchmail.h @@ -149,6 +149,7 @@ extern char *cmd_logfile; /* if --logfile was set */ /* these get computed */ extern int batchlimit; /* if --batchlimit was set */ extern int batchcount; /* count of messages sent in current batch */ +extern int peek_capable; /* can we read msgs without setting seen? */ /* miscellaneous global controls */ extern char *rcfile; /* path name of rc file */ @@ -1,5 +1,5 @@ /* - * imap.c -- IMAP2bis protocol methods + * imap.c -- IMAP2bis/IMAP4 protocol methods * * Copyright 1996 by Eric S. Raymond * All rights reserved. @@ -16,7 +16,7 @@ #include "socket.h" #include "fetchmail.h" -static int count, seen, recent, unseen; +static int count, seen, recent, unseen, imap4; int imap_ok (FILE *sockfp, char *argbuf) /* parse command response */ @@ -74,9 +74,17 @@ int imap_getauth(FILE *sockfp, struct query *ctl, char *buf) /* apply for connection authorization */ { /* try to get authorized */ - return(gen_transact(sockfp, + int ok = gen_transact(sockfp, "LOGIN %s \"%s\"", - ctl->remotename, ctl->password)); + ctl->remotename, ctl->password); + + if (ok) + return(ok); + + /* probe to see if we're running IMAP4 and can use RFC822.PEEK */ + imap4 = ((gen_transact(sockfp, "CAPABILITY")) == 0); + + return(0); } static int imap_getrange(FILE *sockfp, struct query *ctl, int*countp, int*newp) @@ -144,7 +152,16 @@ static int imap_fetch(FILE *sockfp, int number, int *lenp) char buf [POPBUFSIZE+1]; int num; - gen_send(sockfp, "FETCH %d RFC822", number); + /* + * If we're using IMAP4, we can 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 + */ + if (imap4) + gen_send(sockfp, "FETCH %d RFC822.PEEK", number); + else + gen_send(sockfp, "FETCH %d RFC822", number); /* looking for FETCH response */ do { @@ -173,7 +190,12 @@ static int imap_trail(FILE *sockfp, struct query *ctl, int number) static int imap_delete(FILE *sockfp, struct query *ctl, int number) /* set delete flag for given message */ { - return(gen_transact(sockfp, "STORE %d +FLAGS (\\Deleted)", number)); + /* use SILENT if possible as a minor throughput optimization */ + return(gen_transact(sockfp, + imap4 + ? "STORE %d +FLAGS.SILENT (\\Deleted)" + : "STORE %d +FLAGS (\\Deleted)", + number)); } const static struct method imap = @@ -131,6 +131,7 @@ const static struct method pop2 = int doPOP2 (struct query *ctl) /* retrieve messages using POP2 */ { + peek_capable = FALSE; return(do_protocol(ctl, &pop2)); } @@ -276,6 +276,7 @@ int doPOP3 (struct query *ctl) fprintf(stderr,"Option --remote is not supported with POP3\n"); return(PS_SYNTAX); } + peek_capable = FALSE; return(do_protocol(ctl, &pop3)); } |