X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/ea49d0e16fbc6f56fc5b8519d266f88d09139187..e97957bc478f60d32649b329659d4b72748745c1:/src/src/retry.c diff --git a/src/src/retry.c b/src/src/retry.c index 2a5516003..ca61e5c0c 100644 --- a/src/src/retry.c +++ b/src/src/retry.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/retry.c,v 1.6 2006/02/08 14:28:51 ph10 Exp $ */ +/* $Cambridge: exim/src/src/retry.c,v 1.9 2006/03/09 15:10:16 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -414,20 +414,31 @@ for (yield = retries; yield != NULL; yield = yield->next) continue; } - /* Handle 4xx responses to RCPT. The code that was received is in the 2nd - least significant byte of more_errno (with 400 subtracted). The required - value is coded in the 2nd least significant byte of the yield->more_errno - field as follows: + /* The TLSREQUIRED error also covers TLSFAILURE. These are subtly different + errors, but not worth separating at this level. */ + + else if (yield->basic_errno == ERRNO_TLSREQUIRED) + { + if (basic_errno != ERRNO_TLSREQUIRED && basic_errno != ERRNO_TLSFAILURE) + continue; + } + + /* Handle 4xx responses to MAIL, RCPT, or DATA. The code that was received + is in the 2nd least significant byte of more_errno (with 400 subtracted). + The required value is coded in the 2nd least significant byte of the + yield->more_errno field as follows: 255 => any 4xx code >= 100 => the decade must match the value less 100 < 100 => the exact value must match */ - else if (yield->basic_errno == ERRNO_RCPT4XX) + else if (yield->basic_errno == ERRNO_MAIL4XX || + yield->basic_errno == ERRNO_RCPT4XX || + yield->basic_errno == ERRNO_DATA4XX) { int wanted; - if (basic_errno != ERRNO_RCPT4XX) continue; + if (basic_errno != yield->basic_errno) continue; wanted = (yield->more_errno >> 8) & 255; if (wanted != 255) { @@ -684,6 +695,16 @@ for (i = 0; i < 3; i++) /* Compute how long this destination has been failing */ failing_interval = now - retry_record->first_failed; + DEBUG(D_retry) debug_printf("failing_interval=%d message_age=%d\n", + failing_interval, message_age); + + /* If the message has been on the queue longer than the recorded time + of failure, use the message's age instead. This can happen when some + messages can be delivered and others cannot; a successful delivery will + reset the first_failed time, and this can lead to a failing message + being retried too often. */ + + if (message_age > failing_interval) failing_interval = message_age; /* Search for the current retry rule. The cutoff time of the last rule is handled differently to the others. The rule continues @@ -738,7 +759,14 @@ for (i = 0; i < 3; i++) This implements "timeout this rule if EITHER the host (or routing or directing) has been failing for more than the maximum time, OR if the - message has been on the queue for more than the maximum time." */ + message has been on the queue for more than the maximum time." + + February 2006: It is possible that this code is no longer needed + following the change to the retry calculation to use the message age if + it is larger than the time since first failure. It may be that the + expired flag is always set when the other conditions are met. However, + this is a small bit of code, and it does no harm to leave it in place, + just in case. */ if (received_time <= retry_record->first_failed && addr == endaddr && !retry_record->expired && rule != NULL) @@ -781,7 +809,8 @@ for (i = 0; i < 3; i++) { next_try = now + rule->p1; if (next_gap > rule->p1) - next_try += random_number(next_gap - rule->p1); + next_try += random_number(next_gap - rule->p1)/2 + + (next_gap - rule->p1)/2; } } }