diff options
| -rw-r--r-- | driver.c | 35 | ||||
| -rw-r--r-- | fetchmail.h | 1 | ||||
| -rw-r--r-- | fetchmail.man | 4 | ||||
| -rw-r--r-- | options.c | 1 | 
4 files changed, 36 insertions, 5 deletions
| @@ -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 @@ -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: | 
