summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/doc-txt/ChangeLog16
-rw-r--r--src/README.UPDATING6
-rw-r--r--src/src/deliver.c95
-rw-r--r--src/src/routers/queryprogram.c8
-rw-r--r--src/src/routers/redirect.c11
-rw-r--r--src/src/structs.h3
-rw-r--r--src/src/transports/smtp.c87
7 files changed, 131 insertions, 95 deletions
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index d8272ab92..cbb8e9cbb 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.127 2005/04/27 13:29:32 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.128 2005/04/28 13:06:32 ph10 Exp $
Change log file for Exim from version 4.21
-------------------------------------------
@@ -249,6 +249,20 @@ PH/41 $message_linecount is a new variable that contains the total number of
lines in the message. Compare $body_linecount, which is the count for the
body only.
+PH/42 Exim no longer gives details of delivery errors for specific addresses in
+ bounce and delay warning messages, except in certain special cases, which
+ are as follows:
+
+ (a) An SMTP error message from a remote host;
+ (b) A message specified in a :fail: redirection;
+ (c) A message specified in a "fail" command in a system filter;
+ (d) A message specified in a FAIL return from the queryprogram router;
+ (e) A message specified by the cannot_route_message router option.
+
+ In these cases only, Exim does include the error details in bounce and
+ warning messages. There are also a few cases where bland messages such
+ as "unrouteable address" or "local delivery error" are given.
+
A note about Exim versions 4.44 and 4.50
----------------------------------------
diff --git a/src/README.UPDATING b/src/README.UPDATING
index c91c57680..efc123c15 100644
--- a/src/README.UPDATING
+++ b/src/README.UPDATING
@@ -1,4 +1,4 @@
-$Cambridge: exim/src/README.UPDATING,v 1.6 2005/04/06 16:26:42 ph10 Exp $
+$Cambridge: exim/src/README.UPDATING,v 1.7 2005/04/28 13:06:32 ph10 Exp $
This document contains detailed information about incompatibilities that might
be encountered when upgrading from one release of Exim to another. The
@@ -50,6 +50,10 @@ uses prefixes or suffixes on addresses that could be used for callouts, and you
want the affixes to be retained, you must make sure that rcpt_include_affixes
is set on the transport.
+3. Bounce and delay warning messages no longer contain details of delivery
+errors, except for explicit messages (e.g. generated by :fail:) and SMTP
+responses from remote hosts.
+
Version 4.50
------------
diff --git a/src/src/deliver.c b/src/src/deliver.c
index 78eb65bc6..a7b367d80 100644
--- a/src/src/deliver.c
+++ b/src/src/deliver.c
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/deliver.c,v 1.13 2005/04/07 15:40:50 ph10 Exp $ */
+/* $Cambridge: exim/src/src/deliver.c,v 1.14 2005/04/28 13:06:32 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -4180,7 +4180,6 @@ if (addr->parent != NULL && testflag(addr, af_hide_child))
printed = US"an undisclosed address";
yield = FALSE;
}
-
else if (!testflag(addr, af_pfr) || addr->parent == NULL)
printed = addr->address;
@@ -4217,7 +4216,6 @@ return yield;
-
/*************************************************
* Print error for an address *
*************************************************/
@@ -4227,53 +4225,62 @@ a bounce or a warning message. It tries to format the message reasonably by
introducing newlines. All lines are indented by 4; the initial printing
position must be set before calling.
+This function used always to print the error. Nowadays we want to restrict it
+to cases such as SMTP errors from a remote host, and errors from :fail: and
+filter "fail". We no longer pass other information willy-nilly in bounce and
+warning messages. Text in user_message is always output; text in message only
+if the af_pass_message flag is set.
+
Arguments:
- addr points to the address
+ addr the address
f the FILE to print on
+ s some leading text
Returns: nothing
*/
static void
-print_address_error(address_item *addr, FILE *f)
+print_address_error(address_item *addr, FILE *f, uschar *t)
{
+int count = Ustrlen(t);
uschar *s = (addr->user_message != NULL)? addr->user_message : addr->message;
-if (addr->basic_errno > 0)
- {
- fprintf(f, "%s%s", strerror(addr->basic_errno),
- (s == NULL)? "" : ":\n ");
- }
-if (s == NULL)
+
+if (addr->user_message != NULL)
+ s = addr->user_message;
+else
{
- if (addr->basic_errno <= 0) fprintf(f, "unknown error");
+ if (!testflag(addr, af_pass_message) || addr->message == NULL) return;
+ s = addr->message;
}
-else
+
+fprintf(f, "\n %s", t);
+
+while (*s != 0)
{
- int count = 0;
- while (*s != 0)
+ if (*s == '\\' && s[1] == 'n')
+ {
+ fprintf(f, "\n ");
+ s += 2;
+ count = 0;
+ }
+ else
{
- if (*s == '\\' && s[1] == 'n')
+ fputc(*s, f);
+ count++;
+ if (*s++ == ':' && isspace(*s) && count > 45)
{
- fprintf(f, "\n ");
- s += 2;
+ fprintf(f, "\n "); /* sic (because space follows) */
count = 0;
}
- else
- {
- fputc(*s, f);
- count++;
- if (*s++ == ':' && isspace(*s) && count > 45)
- {
- fprintf(f, "\n "); /* sic (because space follows) */
- count = 0;
- }
- }
}
}
}
+
+
+
/*************************************************
* Check list of addresses for duplication *
*************************************************/
@@ -4994,6 +5001,7 @@ if (process_recipients != RECIP_IGNORE)
case RECIP_FAIL_FILTER:
new->message =
(filter_message == NULL)? US"delivery cancelled" : filter_message;
+ setflag(new, af_pass_message);
goto RECIP_QUEUE_FAILED; /* below */
@@ -6182,26 +6190,15 @@ wording. */
/* Process the addresses, leaving them on the msgchain if they have a
file name for a return message. (There has already been a check in
- post_process_one() for the existence of data in the message file.) */
+ post_process_one() for the existence of data in the message file.) A TRUE
+ return from print_address_information() means that the address is not
+ hidden. */
paddr = &msgchain;
for (addr = msgchain; addr != NULL; addr = *paddr)
{
if (print_address_information(addr, f, US" ", US"\n ", US""))
- {
- /* A TRUE return from print_address_information() means that the
- address is not hidden. If there is a return file, it has already
- been checked to ensure it is not empty. Omit the bland "return
- message generated" error, but otherwise include error information. */
-
- if (addr->return_file < 0 ||
- addr->message == NULL ||
- Ustrcmp(addr->message, "return message generated") != 0)
- {
- fprintf(f, "\n ");
- print_address_error(addr, f);
- }
- }
+ print_address_error(addr, f, US"");
/* End the final line for the address */
@@ -6703,21 +6700,15 @@ else if (addr_defer != (address_item *)(+1))
(addr_defer->next == NULL)? "is": "are");
}
- /* List the addresses. For any that are hidden, don't give the delay
- reason, because it might expose that which is hidden. Also, do not give
- "retry time not reached" because that isn't helpful. */
+ /* List the addresses, with error information if allowed */
fprintf(f, "\n");
while (addr_defer != NULL)
{
address_item *addr = addr_defer;
addr_defer = addr->next;
- if (print_address_information(addr, f, US" ", US"\n ", US"") &&
- addr->basic_errno > ERRNO_RETRY_BASE)
- {
- fprintf(f, "\n Delay reason: ");
- print_address_error(addr, f);
- }
+ if (print_address_information(addr, f, US" ", US"\n ", US""))
+ print_address_error(addr, f, US"Delay reason: ");
fprintf(f, "\n");
}
fprintf(f, "\n");
diff --git a/src/src/routers/queryprogram.c b/src/src/routers/queryprogram.c
index 5d7a51fdf..5282a1fa6 100644
--- a/src/src/routers/queryprogram.c
+++ b/src/src/routers/queryprogram.c
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/routers/queryprogram.c,v 1.3 2005/04/06 14:40:24 ph10 Exp $ */
+/* $Cambridge: exim/src/src/routers/queryprogram.c,v 1.4 2005/04/28 13:06:32 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -416,7 +416,11 @@ if (strcmpic(rword, US"accept") != 0)
if (strcmpic(rword, US"decline") == 0) return DECLINE;
if (strcmpic(rword, US"pass") == 0) return PASS;
addr->message = string_copy(rdata); /* data is a message */
- if (strcmpic(rword, US"fail") == 0) return FAIL;
+ if (strcmpic(rword, US"fail") == 0)
+ {
+ setflag(addr, af_pass_message);
+ return FAIL;
+ }
if (strcmpic(rword, US"freeze") == 0) addr->special_action = SPECIAL_FREEZE;
else if (strcmpic(rword, US"defer") != 0)
{
diff --git a/src/src/routers/redirect.c b/src/src/routers/redirect.c
index 0153a4d49..8e8fc876c 100644
--- a/src/src/routers/redirect.c
+++ b/src/src/routers/redirect.c
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/routers/redirect.c,v 1.9 2005/04/06 14:40:24 ph10 Exp $ */
+/* $Cambridge: exim/src/src/routers/redirect.c,v 1.10 2005/04/28 13:06:32 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -655,8 +655,13 @@ switch (frc)
if ((xrc = sort_errors_and_headers(rblock, addr, verify, &addr_prop)) != OK)
return xrc;
add_generated(rblock, addr_new, addr, generated, &addr_prop, &ugid, pw);
- if (addr->message == NULL) addr->message = US"forced rejection";
- else addr->user_message = addr->message;
+ if (addr->message == NULL)
+ addr->message = US"forced rejection";
+ else
+ {
+ addr->user_message = addr->message;
+ setflag(addr, af_pass_message);
+ }
return FAIL;
/* As in the case of a system filter, a freeze does not happen after a manual
diff --git a/src/src/structs.h b/src/src/structs.h
index 791e11c69..645dfc25c 100644
--- a/src/src/structs.h
+++ b/src/src/structs.h
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/structs.h,v 1.4 2005/02/17 11:58:26 ph10 Exp $ */
+/* $Cambridge: exim/src/src/structs.h,v 1.5 2005/04/28 13:06:32 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -498,6 +498,7 @@ typedef struct address_item_propagated {
#define af_verify_callout 0x00400000 /* for cached sender verify: callout was specified */
#define af_include_affixes 0x00800000 /* delivered with affixes in RCPT */
#define af_cert_verified 0x01000000 /* delivered with verified TLS cert */
+#define af_pass_message 0x02000000 /* pass message in bounces */
/* These flags must be propagated when a child is created */
diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
index f53d742e4..69b1c1965 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.10 2005/04/07 10:54:54 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/smtp.c,v 1.11 2005/04/28 13:06:32 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -313,10 +313,11 @@ host_build_hostlist(&(ob->fallback_hostlist), ob->fallback_hosts, FALSE);
status means that an address is not currently being processed.
Arguments:
- addrlist points to a chain of addresses
- errno_value to put in each address's errno field
- msg to put in each address's message field
- rc to put in each address's transport_return field
+ addrlist points to a chain of addresses
+ errno_value to put in each address's errno field
+ msg to put in each address's message field
+ rc to put in each address's transport_return field
+ pass_message if TRUE, set the "pass message" flag in the address
If errno_value has the special value ERRNO_CONNECTTIMEOUT, ETIMEDOUT is put in
the errno field, and RTEF_CTOUT is ORed into the more_errno field, to indicate
@@ -326,7 +327,8 @@ Returns: nothing
*/
static
-void set_errno(address_item *addrlist, int errno_value, uschar *msg, int rc)
+void set_errno(address_item *addrlist, int errno_value, uschar *msg, int rc,
+ BOOL pass_message)
{
address_item *addr;
int orvalue = 0;
@@ -340,7 +342,11 @@ for (addr = addrlist; addr != NULL; addr = addr->next)
if (addr->transport_return < PENDING) continue;
addr->basic_errno = errno_value;
addr->more_errno |= orvalue;
- if (msg != NULL) addr->message = msg;
+ if (msg != NULL)
+ {
+ addr->message = msg;
+ if (pass_message) setflag(addr, af_pass_message);
+ }
addr->transport_return = rc;
}
}
@@ -358,18 +364,19 @@ the yield variable. If no response was actually read, a suitable digit is
chosen.
Arguments:
- host the current host, to get its name for messages
- errno_value pointer to the errno value
- more_errno from the top address for use with ERRNO_FILTER_FAIL
- buffer the SMTP response buffer
- yield where to put a one-digit SMTP response code
- message where to put an errror message
-
-Returns: TRUE if an SMTP "QUIT" command should be sent, else FALSE
+ host the current host, to get its name for messages
+ errno_value pointer to the errno value
+ more_errno from the top address for use with ERRNO_FILTER_FAIL
+ buffer the SMTP response buffer
+ yield where to put a one-digit SMTP response code
+ message where to put an errror message
+ pass_message set TRUE if message is an SMTP response
+
+Returns: TRUE if an SMTP "QUIT" command should be sent, else FALSE
*/
static BOOL check_response(host_item *host, int *errno_value, int more_errno,
- uschar *buffer, int *yield, uschar **message)
+ uschar *buffer, int *yield, uschar **message, BOOL *pass_message)
{
uschar *pl = US"";
@@ -444,8 +451,9 @@ if (*errno_value == ERRNO_WRITEINCOMPLETE)
if (buffer[0] != 0)
{
uschar *s = string_printing(buffer);
- *message = US string_sprintf("SMTP error from remote mailer after %s%s: "
+ *message = US string_sprintf("SMTP error from remote mail server after %s%s: "
"host %s [%s]: %s", pl, smtp_command, host->name, host->address, s);
+ *pass_message = TRUE;
*yield = buffer[0];
return TRUE;
}
@@ -623,7 +631,7 @@ while (count-- > 0)
uschar *message = string_sprintf("SMTP timeout while connected to %s [%s] "
"after RCPT TO:<%s>", host->name, host->address,
transport_rcpt_address(addr, include_affixes));
- set_errno(addrlist, save_errno, message, DEFER);
+ set_errno(addrlist, save_errno, message, DEFER, FALSE);
retry_add_item(addr, addr->address_retry_key, 0);
host->update_waiting = FALSE;
return -1;
@@ -646,9 +654,10 @@ while (count-- > 0)
else
{
addr->message =
- string_sprintf("SMTP error from remote mailer after RCPT TO:<%s>: "
+ string_sprintf("SMTP error from remote mail server after RCPT TO:<%s>: "
"host %s [%s]: %s", transport_rcpt_address(addr, include_affixes),
host->name, host->address, string_printing(buffer));
+ setflag(addr, af_pass_message);
deliver_msglog("%s %s\n", tod_stamp(tod_log), addr->message);
/* The response was 5xx */
@@ -699,8 +708,9 @@ if (pending_DATA != 0 &&
{
int code;
uschar *msg;
+ BOOL pass_message;
if (pending_DATA > 0 || (yield & 1) != 0) return -3;
- (void)check_response(host, &errno, 0, buffer, &code, &msg);
+ (void)check_response(host, &errno, 0, buffer, &code, &msg, &pass_message);
DEBUG(D_transport) debug_printf("%s\nerror for DATA ignored: pipelining "
"is in use and there were no good recipients\n", msg);
}
@@ -782,6 +792,7 @@ BOOL setting_up = TRUE;
BOOL completed_address = FALSE;
BOOL esmtp = TRUE;
BOOL pending_MAIL;
+BOOL pass_message = FALSE;
smtp_inblock inblock;
smtp_outblock outblock;
int max_rcpt = tblock->max_addresses;
@@ -822,7 +833,7 @@ if (helo_data == NULL)
{
uschar *message = string_sprintf("failed to expand helo_data: %s",
expand_string_message);
- set_errno(addrlist, 0, message, DEFER);
+ set_errno(addrlist, 0, message, DEFER, FALSE);
return ERROR;
}
@@ -842,7 +853,7 @@ if (ob->authenticated_sender != NULL)
{
uschar *message = string_sprintf("failed to expand "
"authenticated_sender: %s", expand_string_message);
- set_errno(addrlist, 0, message, DEFER);
+ set_errno(addrlist, 0, message, DEFER, FALSE);
return ERROR;
}
}
@@ -861,7 +872,7 @@ if (continue_hostname == NULL)
if (inblock.sock < 0)
{
set_errno(addrlist, (errno == ETIMEDOUT)? ERRNO_CONNECTTIMEOUT : errno,
- NULL, DEFER);
+ NULL, DEFER, FALSE);
return DEFER;
}
@@ -1186,7 +1197,7 @@ if (continue_hostname == NULL
case ERROR:
yield = ERROR;
- set_errno(addrlist, 0, string_copy(buffer), DEFER);
+ set_errno(addrlist, 0, string_copy(buffer), DEFER, FALSE);
goto SEND_QUIT;
}
@@ -1202,7 +1213,8 @@ if (continue_hostname == NULL
{
yield = DEFER;
set_errno(addrlist, ERRNO_AUTHFAIL,
- string_sprintf("authentication required but %s", fail_reason), DEFER);
+ string_sprintf("authentication required but %s", fail_reason), DEFER,
+ FALSE);
goto SEND_QUIT;
}
}
@@ -1228,7 +1240,8 @@ if (tblock->filter_command != NULL)
if (!rc)
{
- set_errno(addrlist->next, addrlist->basic_errno, addrlist->message, DEFER);
+ set_errno(addrlist->next, addrlist->basic_errno, addrlist->message, DEFER,
+ FALSE);
yield = ERROR;
goto SEND_QUIT;
}
@@ -1368,7 +1381,8 @@ if (mua_wrapper)
}
if (badaddr != NULL)
{
- set_errno(addrlist, 0, badaddr->message, FAIL);
+ set_errno(addrlist, 0, badaddr->message, FAIL,
+ testflag(badaddr, af_pass_message));
ok = FALSE;
}
}
@@ -1597,7 +1611,7 @@ if (!ok)
save_errno = errno;
message = NULL;
send_quit = check_response(host, &save_errno, addrlist->more_errno,
- buffer, &code, &message);
+ buffer, &code, &message, &pass_message);
goto FAILED;
SEND_FAILED:
@@ -1632,11 +1646,11 @@ if (!ok)
{
if (code == '5')
{
- set_errno(addrlist, save_errno, message, FAIL);
+ set_errno(addrlist, save_errno, message, FAIL, pass_message);
}
else
{
- set_errno(addrlist, save_errno, message, DEFER);
+ set_errno(addrlist, save_errno, message, DEFER, pass_message);
yield = DEFER;
}
}
@@ -1662,7 +1676,7 @@ if (!ok)
{
yield = (save_errno == ERRNO_CHHEADER_FAIL ||
save_errno == ERRNO_FILTER_FAIL)? ERROR : DEFER;
- set_errno(addrlist, save_errno, message, DEFER);
+ set_errno(addrlist, save_errno, message, DEFER, pass_message);
}
/* Otherwise we have a message-specific error response from the remote
@@ -1683,7 +1697,8 @@ if (!ok)
{
if (mua_wrapper) code = '5'; /* Force hard failure in wrapper mode */
- set_errno(addrlist, save_errno, message, (code == '5')? FAIL : DEFER);
+ set_errno(addrlist, save_errno, message, (code == '5')? FAIL : DEFER,
+ pass_message);
/* If there's an errno, the message contains just the identity of
the host. */
@@ -1747,6 +1762,7 @@ if (completed_address && ok && send_quit)
))
{
uschar *msg;
+ BOOL pass_message;
if (send_rset)
{
@@ -1760,7 +1776,8 @@ if (completed_address && ok && send_quit)
ob->command_timeout)))
{
int code;
- send_quit = check_response(host, &errno, 0, buffer, &code, &msg);
+ send_quit = check_response(host, &errno, 0, buffer, &code, &msg,
+ &pass_message);
if (!send_quit)
{
DEBUG(D_transport) debug_printf("%s\n", msg);
@@ -1806,7 +1823,7 @@ if (completed_address && ok && send_quit)
/* If RSET failed and there are addresses left, they get deferred. */
- else set_errno(first_addr, errno, msg, DEFER);
+ else set_errno(first_addr, errno, msg, DEFER, FALSE);
}
}
@@ -2449,7 +2466,7 @@ for (cutoff_retry = 0; expired &&
if (dont_deliver)
{
host_item *host2;
- set_errno(addrlist, 0, NULL, OK);
+ set_errno(addrlist, 0, NULL, OK, FALSE);
for (addr = addrlist; addr != NULL; addr = addr->next)
{
addr->host_used = host;