aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS10
-rw-r--r--driver.c24
-rw-r--r--fetchmail.h1
-rw-r--r--imap.c34
-rw-r--r--pop2.c1
-rw-r--r--pop3.c1
6 files changed, 55 insertions, 16 deletions
diff --git a/NEWS b/NEWS
index dfb1bc88..81d05218 100644
--- a/NEWS
+++ b/NEWS
@@ -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 --
diff --git a/driver.c b/driver.c
index 8d673078..b85b4e14 100644
--- a/driver.c
+++ b/driver.c
@@ -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 */
diff --git a/imap.c b/imap.c
index ec529cf1..12f53719 100644
--- a/imap.c
+++ b/imap.c
@@ -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 =
diff --git a/pop2.c b/pop2.c
index 35f69fbd..bb668ad9 100644
--- a/pop2.c
+++ b/pop2.c
@@ -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));
}
diff --git a/pop3.c b/pop3.c
index 8f5a1a16..1e429d30 100644
--- a/pop3.c
+++ b/pop3.c
@@ -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));
}