diff options
author | Philip Hazel <ph10@hermes.cam.ac.uk> | 2006-11-06 15:50:12 +0000 |
---|---|---|
committer | Philip Hazel <ph10@hermes.cam.ac.uk> | 2006-11-06 15:50:12 +0000 |
commit | 48c7f9e2e3b50cd5548447de62c77c7ddfe21519 (patch) | |
tree | 588f2c5e5885f5e9f67d5faba9045a0c76f84cb5 /src | |
parent | 520de300979cb6cf448cd23f729dd39368202a16 (diff) |
Include sender address in retry key for 4xx errors.
Diffstat (limited to 'src')
-rw-r--r-- | src/src/deliver.c | 22 | ||||
-rw-r--r-- | src/src/transports/smtp.c | 58 | ||||
-rw-r--r-- | src/src/transports/smtp.h | 3 |
3 files changed, 55 insertions, 28 deletions
diff --git a/src/src/deliver.c b/src/src/deliver.c index 81df0e083..02552317a 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/deliver.c,v 1.37 2006/10/30 16:41:04 ph10 Exp $ */ +/* $Cambridge: exim/src/src/deliver.c,v 1.38 2006/11/06 15:50:12 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -5452,8 +5452,10 @@ while (addr_new != NULL) /* Loop until all addresses dealt with */ } /* Get the routing retry status, saving the two retry keys (with and - without the local part) for subsequent use. Ignore retry records that - are too old. */ + without the local part) for subsequent use. If there is no retry record for + the standard address routing retry key, we look for the same key with the + sender attached, because this form is used by the smtp transport after a + 4xx response to RCPT when address_retry_include_sender is true. */ addr->domain_retry_key = string_sprintf("R:%s", addr->domain); addr->address_retry_key = string_sprintf("R:%s@%s", addr->local_part, @@ -5466,12 +5468,22 @@ while (addr_new != NULL) /* Loop until all addresses dealt with */ domain_retry_record = dbfn_read(dbm_file, addr->domain_retry_key); if (domain_retry_record != NULL && now - domain_retry_record->time_stamp > retry_data_expire) - domain_retry_record = NULL; + domain_retry_record = NULL; /* Ignore if too old */ address_retry_record = dbfn_read(dbm_file, addr->address_retry_key); if (address_retry_record != NULL && now - address_retry_record->time_stamp > retry_data_expire) - address_retry_record = NULL; + address_retry_record = NULL; /* Ignore if too old */ + + if (address_retry_record == NULL) + { + uschar * altkey = string_sprintf("%s:<%s>", addr->address_retry_key, + sender_address); + address_retry_record = dbfn_read(dbm_file, altkey); + if (address_retry_record != NULL && + now - address_retry_record->time_stamp > retry_data_expire) + address_retry_record = NULL; /* Ignore if too old */ + } } DEBUG(D_deliver|D_retry) diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index ac013470b..f9e56c2e1 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/transports/smtp.c,v 1.28 2006/10/30 16:41:04 ph10 Exp $ */ +/* $Cambridge: exim/src/src/transports/smtp.c,v 1.29 2006/11/06 15:50:12 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -21,6 +21,8 @@ before the lower case letters). Some live in the transport_instance block so as to be publicly visible; these are flagged with opt_public. */ optionlist smtp_transport_options[] = { + { "address_retry_include_sender", opt_bool, + (void *)offsetof(smtp_transport_options_block, address_retry_include_sender) }, { "allow_localhost", opt_bool, (void *)offsetof(smtp_transport_options_block, allow_localhost) }, { "authenticated_sender", opt_stringptr, @@ -159,6 +161,7 @@ smtp_transport_options_block smtp_transport_option_defaults = { 1024, /* size_addition */ 5, /* hosts_max_try */ 50, /* hosts_max_try_hardlimit */ + TRUE, /* address_retry_include_sender */ FALSE, /* allow_localhost */ FALSE, /* authenticated_sender_force */ FALSE, /* gethostbyname */ @@ -555,19 +558,21 @@ subsequent general error, it will get reset accordingly. If not, it will get converted to OK at the end. Arguments: - addrlist the complete address list - include_affixes TRUE if affixes include in RCPT - sync_addr ptr to the ptr of the one to start scanning at (updated) - host the host we are connected to - count the number of responses to read - pending_MAIL true if the first response is for MAIL - pending_DATA 0 if last command sent was not DATA - +1 if previously had a good recipient - -1 if not previously had a good recipient - inblock incoming SMTP block - timeout timeout value - buffer buffer for reading response - buffsize size of buffer + addrlist the complete address list + include_affixes TRUE if affixes include in RCPT + sync_addr ptr to the ptr of the one to start scanning at (updated) + host the host we are connected to + count the number of responses to read + address_retry_ + include_sender true if 4xx retry is to include the sender it its key + pending_MAIL true if the first response is for MAIL + pending_DATA 0 if last command sent was not DATA + +1 if previously had a good recipient + -1 if not previously had a good recipient + inblock incoming SMTP block + timeout timeout value + buffer buffer for reading response + buffsize size of buffer Returns: 3 if at least one address had 2xx and one had 5xx 2 if at least one address had 5xx but none had 2xx @@ -580,7 +585,8 @@ Returns: 3 if at least one address had 2xx and one had 5xx static int sync_responses(address_item *addrlist, BOOL include_affixes, - address_item **sync_addr, host_item *host, int count, BOOL pending_MAIL, + address_item **sync_addr, host_item *host, int count, + BOOL address_retry_include_sender, BOOL pending_MAIL, int pending_DATA, smtp_inblock *inblock, int timeout, uschar *buffer, int buffsize) { @@ -705,10 +711,17 @@ while (count-- > 0) update_waiting = FALSE; - /* Add a retry item for the address so that it doesn't get tried - again too soon. */ + /* Add a retry item for the address so that it doesn't get tried again + too soon. If address_retry_include_sender is true, add the sender address + to the retry key. */ - retry_add_item(addr, addr->address_retry_key, 0); + if (address_retry_include_sender) + { + uschar *altkey = string_sprintf("%s:<%s>", addr->address_retry_key, + sender_address); + retry_add_item(addr, altkey, 0); + } + else retry_add_item(addr, addr->address_retry_key, 0); } } } /* Loop for next RCPT response */ @@ -1404,8 +1417,9 @@ for (addr = first_addr; if (count > 0) { switch(sync_responses(first_addr, tblock->rcpt_include_affixes, - &sync_addr, host, count, pending_MAIL, 0, &inblock, - ob->command_timeout, buffer, sizeof(buffer))) + &sync_addr, host, count, ob->address_retry_include_sender, + pending_MAIL, 0, &inblock, ob->command_timeout, buffer, + sizeof(buffer))) { case 3: ok = TRUE; /* 2xx & 5xx => OK & progress made */ case 2: completed_address = TRUE; /* 5xx (only) => progress made */ @@ -1453,8 +1467,8 @@ if (ok || (smtp_use_pipelining && !mua_wrapper)) int count = smtp_write_command(&outblock, FALSE, "DATA\r\n"); if (count < 0) goto SEND_FAILED; switch(sync_responses(first_addr, tblock->rcpt_include_affixes, &sync_addr, - host, count, pending_MAIL, ok? +1 : -1, &inblock, - ob->command_timeout, buffer, sizeof(buffer))) + host, count, ob->address_retry_include_sender, pending_MAIL, + ok? +1 : -1, &inblock, ob->command_timeout, buffer, sizeof(buffer))) { case 3: ok = TRUE; /* 2xx & 5xx => OK & progress made */ case 2: completed_address = TRUE; /* 5xx (only) => progress made */ diff --git a/src/src/transports/smtp.h b/src/src/transports/smtp.h index 05f02bc00..107b91853 100644 --- a/src/src/transports/smtp.h +++ b/src/src/transports/smtp.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/transports/smtp.h,v 1.8 2006/02/28 12:42:47 ph10 Exp $ */ +/* $Cambridge: exim/src/src/transports/smtp.h,v 1.9 2006/11/06 15:50:12 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -33,6 +33,7 @@ typedef struct { int size_addition; int hosts_max_try; int hosts_max_try_hardlimit; + BOOL address_retry_include_sender; BOOL allow_localhost; BOOL authenticated_sender_force; BOOL gethostbyname; |