summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPhilip Hazel <ph10@hermes.cam.ac.uk>2006-11-06 15:50:12 +0000
committerPhilip Hazel <ph10@hermes.cam.ac.uk>2006-11-06 15:50:12 +0000
commit48c7f9e2e3b50cd5548447de62c77c7ddfe21519 (patch)
tree588f2c5e5885f5e9f67d5faba9045a0c76f84cb5 /src
parent520de300979cb6cf448cd23f729dd39368202a16 (diff)
Include sender address in retry key for 4xx errors.
Diffstat (limited to 'src')
-rw-r--r--src/src/deliver.c22
-rw-r--r--src/src/transports/smtp.c58
-rw-r--r--src/src/transports/smtp.h3
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;