aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--driver.c35
-rw-r--r--fetchmail.h1
-rw-r--r--fetchmail.man4
-rw-r--r--options.c1
4 files changed, 36 insertions, 5 deletions
diff --git a/driver.c b/driver.c
index 51e0fedc..fde38a46 100644
--- a/driver.c
+++ b/driver.c
@@ -141,8 +141,9 @@ static int is_host_alias(const char *name, struct query *ctl)
if (outlevel != O_SILENT)
putchar('\n'); /* terminate the progress message */
fprintf(stderr,
- "fetchmail: nameserver evaporated while looking for `%s' during poll of %s.\n",
+ "fetchmail: nameserver failure while looking for `%s' during poll of %s.\n",
name, ctl->servername);
+ ctl->errcount++;
longjmp(restart, 2); /* try again next poll cycle */
break;
}
@@ -168,6 +169,10 @@ static int is_host_alias(const char *name, struct query *ctl)
case NO_RECOVERY: /* non-recoverable name server error */
case TRY_AGAIN: /* temporary error on authoritative server */
default:
+ fprintf(stderr,
+ "fetchmail: nameserver failure while looking for `%s' during poll of %s.\n",
+ name, ctl->servername);
+ ctl->errcount++;
longjmp(restart, 2); /* try again next poll cycle */
break;
}
@@ -778,6 +783,7 @@ const struct method *proto; /* protocol method table */
return(PS_ERROR);
}
+
if (check_only)
{
if (new == -1 || ctl->fetchall)
@@ -787,12 +793,35 @@ 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'.
+ *
+ * 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.
+ *
+ * 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.
+ */
+ int force_retrieval = (ctl->errcount > 0);
+
+ ctl->errcount = 0;
+
/* read, forward, and delete messages */
for (num = 1; num <= count; num++)
{
- int toolarge = msgsizes && msgsizes[num-1]>ctl->limit;
+ int toolarge = msgsizes && (msgsizes[num-1] > ctl->limit);
int fetch_it = ctl->fetchall ||
- (!(protocol->is_old && (protocol->is_old)(sockfp,ctl,num)) && !toolarge);
+ (!toolarge && (force_retrieval || !(protocol->is_old && (protocol->is_old)(sockfp,ctl,num)));
/* we may want to reject this message if it's old */
if (!fetch_it)
diff --git a/fetchmail.h b/fetchmail.h
index 93ec9131..b1ebf927 100644
--- a/fetchmail.h
+++ b/fetchmail.h
@@ -92,6 +92,7 @@ struct query
/* internal use */
int active;
+ int errcount; /* count transient errors in last pass */
struct query *next; /* next query control block in chain */
struct query *leader; /* pointer to this query's SMTP leader */
FILE *smtp_sockfp; /* socket descriptor for SMTP connection */
diff --git a/fetchmail.man b/fetchmail.man
index 054225ef..be3c558c 100644
--- a/fetchmail.man
+++ b/fetchmail.man
@@ -332,7 +332,9 @@ The
or --nodetach option suppresses detachment of the daemon process
from its control terminal. This is primarily useful for debugging.
.PP
-Note that running fetchmail in daemon mode forces the --fetchall option on.
+Note that while running in daemon mode, transient errors (such as DNS
+failures or sendmail delivery refusals) effectively force the fetchall
+option on for the duration of the next polling cycle.
This is a robustness feature. It means that if a message is fetched
(and thus marked seen by the mailserver) but not delivered locally
due to some transient error, it will be re-fetched during the next
diff --git a/options.c b/options.c
index d557fc88..4f1cd937 100644
--- a/options.c
+++ b/options.c
@@ -130,7 +130,6 @@ struct query *ctl; /* option record to be initialized */
case 'd':
case LA_DAEMON:
poll_interval = atoi(optarg);
- ctl->fetchall = TRUE;
break;
case 'N':
case LA_NODETACH: