{
while (addr->parent)
{
- address_item *aa;
+ address_item * aa;
addr = addr->parent;
if (--addr->child_count > 0) return; /* Incomplete parent */
/* string_cat() always leaves room for the terminator. Release the
store we used to build the line after writing it. */
-log_write(0, flags, "%s", string_from_gstring(g));
+log_write(0, flags, "%Y", g);
#ifndef DISABLE_EVENT
if (!msg) msg_event_raise(US"msg:delivery", addr);
if (addr->message)
g = string_append(g, 2, US": ", addr->message);
- {
- const uschar * s = string_from_gstring(g);
+/* Log the deferment in the message log, but don't clutter it
+up with retry-time defers after the first delivery attempt. */
- /* Log the deferment in the message log, but don't clutter it
- up with retry-time defers after the first delivery attempt. */
+if (f.deliver_firsttime || addr->basic_errno > ERRNO_RETRY_BASE)
+ deliver_msglog("%s %.*s\n", now, g->ptr, g->s);
- if (f.deliver_firsttime || addr->basic_errno > ERRNO_RETRY_BASE)
- deliver_msglog("%s %s\n", now, s);
+/* Write the main log and reset the store.
+For errors of the type "retry time not reached" (also remotes skipped
+on queue run), logging is controlled by L_retry_defer. Note that this kind
+of error number is negative, and all the retry ones are less than any
+others. */
- /* Write the main log and reset the store.
- For errors of the type "retry time not reached" (also remotes skipped
- on queue run), logging is controlled by L_retry_defer. Note that this kind
- of error number is negative, and all the retry ones are less than any
- others. */
-
- log_write(addr->basic_errno <= ERRNO_RETRY_BASE ? L_retry_defer : 0, logflags,
- "== %s", s);
- }
+log_write(addr->basic_errno <= ERRNO_RETRY_BASE ? L_retry_defer : 0, logflags,
+ "== %Y", g);
store_reset(reset_point);
return;
/* Do the logging. For the message log, "routing failed" for those cases,
just to make it clearer. */
- {
- const uschar * s = string_from_gstring(g);
-
- if (driver_kind)
- deliver_msglog("%s %s failed for %s\n", now, driver_kind, s);
- else
- deliver_msglog("%s %s\n", now, s);
+if (driver_kind)
+ deliver_msglog("%s %s failed for %.*s\n", now, driver_kind, g->ptr, g->s);
+else
+ deliver_msglog("%s %.*s\n", now, g->ptr, g->s);
- log_write(0, LOG_MAIN, "** %s", s);
- }
+log_write(0, LOG_MAIN, "** %Y", g);
store_reset(reset_point);
return;
addr->local_part, tp->name);
/* Setting these globals in the subprocess means we need never clear them */
- transport_name = addr->transport->name;
+
+ transport_name = tp->name;
+ if (addr->router) router_name = addr->router->name;
driver_srcfile = tp->srcfile;
driver_srcline = tp->srcline;
{
ok = transport_set_up_command(&transport_filter_argv,
tp->filter_command,
- TRUE, PANIC, addr, FALSE, US"transport filter", NULL);
+ TSUC_EXPAND_ARGS, PANIC, addr, US"transport filter", NULL);
transport_filter_timeout = tp->filter_timeout;
}
else transport_filter_argv = NULL;
pipeheader[PIPE_HEADER_SIZE] = '\0';
DEBUG(D_deliver)
- debug_printf("got %ld bytes (pipeheader) from transport process %d\n",
- (long) got, pid);
+ debug_printf("got %ld bytes (pipeheader) '%c' from transport process %d\n",
+ (long) got, *id, pid);
{
/* If we can't decode the pipeheader, the subprocess seems to have a
/* Put the amount of data written into the parlist block */
- case 'S':
+ case 'S': /* Size */
memcpy(&(p->transport_count), ptr, sizeof(transport_count));
ptr += sizeof(transport_count);
break;
if (*subid > '1') setflag(addr, af_tcp_fastopen_data);
break;
- case 'D':
+ case 'D': /* DSN */
if (!addr) goto ADDR_MISMATCH;
memcpy(&(addr->dsn_aware), ptr, sizeof(addr->dsn_aware));
ptr += sizeof(addr->dsn_aware);
host_item *h;
/* Setting these globals in the subprocess means we need never clear them */
- transport_name = addr->transport->name;
+
+ transport_name = tp->name;
+ if (addr->router) router_name = addr->router->name;
driver_srcfile = tp->srcfile;
driver_srcline = tp->srcline;
if (addr->return_file >= 0)
{
- paddr = &(addr->next);
+ paddr = &addr->next;
filecount++;
}
for (address_item * addr = handled_addr; addr; addr = addr->next)
{
host_item * hu;
+#ifdef EXPERIMENTAL_DSN_INFO
+ const uschar * s;
+#endif
print_dsn_addr_action(fp, addr, US"failed", US"5.0.0");
{
fprintf(fp, "Remote-MTA: dns; %s\n", hu->name);
#ifdef EXPERIMENTAL_DSN_INFO
- {
- const uschar * s;
if (hu->address)
{
uschar * p = hu->port == 25
dsn_put_wrapped(fp, US"X-Remote-MTA-smtp-greeting: X-str; ", s);
if ((s = addr->helo_response) && *s)
dsn_put_wrapped(fp, US"X-Remote-MTA-helo-response: X-str; ", s);
- if ((s = addr->message) && *s)
+ if (testflag(addr, af_pass_message) && (s = addr->message) && *s)
dsn_put_wrapped(fp, US"X-Exim-Diagnostic: X-str; ", s);
- }
#endif
print_dsn_diagnostic_code(addr, fp);
}
+#ifdef EXPERIMENTAL_DSN_INFO
+ else if (testflag(addr, af_pass_message) && (s = addr->message) && *s)
+ dsn_put_wrapped(fp, US"X-Exim-Diagnostic: X-str; ", s);
+#endif
fputc('\n', fp);
}
tctx.u.fd = fileno(fp);
tctx.tblock = &tb;
- tctx.options = topt;
+ tctx.options = topt | topt_truncate_headers;
tb.add_headers = dsnnotifyhdr;
/*XXX no checking for failure! buggy! */
if (rc != 0)
{
- uschar *s = US"";
+ uschar * s = US"";
if (now - received_time.tv_sec < retry_maximum_timeout && !addr_defer)
{
addr_defer = (address_item *)(+1);
fflush(f);
/* header only as required by RFC. only failure DSN needs to honor RET=FULL */
tctx.u.fd = fileno(f);
-tctx.options = topt_add_return_path | topt_no_body;
+tctx.options = topt_add_return_path | topt_truncate_headers | topt_no_body;
transport_filter_argv = NULL; /* Just in case */
return_path = sender_address; /* In case not previously set */
/* Write the original email out */
/*XXX no checking for failure! buggy! */
-/*XXX overlong headers in the original become overlong body lines here*/
transport_write_message(&tctx, 0);
fflush(f);
*************************************************/
static void
-maybe_send_dsn(void)
+maybe_send_dsn(const address_item * const addr_succeed)
{
address_item * addr_senddsn = NULL;
-for (address_item * a = addr_succeed; a; a = a->next)
+for (const address_item * a = addr_succeed; a; a = a->next)
{
/* af_ignore_error not honored here. it's not an error */
DEBUG(D_deliver) debug_printf("DSN: processing router : %s\n"
/* Write the original email out */
tctx.u.fd = fd;
- tctx.options = topt_add_return_path | topt_no_body;
+ tctx.options = topt_add_return_path | topt_truncate_headers | topt_no_body;
/*XXX hmm, FALSE(fail) retval ignored.
Could error for any number of reasons, and they are not handled. */
transport_write_message(&tctx, 0);
*/
int
-deliver_message(uschar *id, BOOL forced, BOOL give_up)
+deliver_message(uschar * id, BOOL forced, BOOL give_up)
{
int i, rc;
int final_yield = DELIVER_ATTEMPTED_NORMAL;
if ((deliver_datafile = spool_open_datafile(id)) < 0)
return continue_closedown(); /* yields DELIVER_NOT_ATTEMPTED */
-/* The value of message_size at this point has been set to the data length,
+/* tHe value of message_size at this point has been set to the data length,
plus one for the blank line that notionally precedes the data. */
/* Now read the contents of the header file, which will set up the headers in
if (rc != spool_read_hdrerror)
{
received_time.tv_sec = received_time.tv_usec = 0;
- /*XXX subsec precision?*/
- for (i = 0; i < 6; i++)
+ /*III subsec precision?*/
+ for (i = 0; i < MESSAGE_ID_TIME_LEN; i++)
received_time.tv_sec = received_time.tv_sec * BASE_62 + tab62[id[i] - '0'];
}
for (i = 0; i < recipients_count; i++)
if (!tree_search(tree_nonrecipients, recipients_list[i].address))
{
- recipient_item *r = recipients_list + i;
- address_item *new = deliver_make_addr(r->address, FALSE);
+ recipient_item * r = recipients_list + i;
+ address_item * new = deliver_make_addr(r->address, FALSE);
+
new->prop.errors_address = r->errors_to;
#ifdef SUPPORT_I18N
if ((new->prop.utf8_msg = message_smtputf8))
case RECIP_FAIL:
new->message = US"delivery cancelled by administrator";
+ /* not setting af_pass_message here means that will not
+ appear in the bounce message */
/* Fall through */
/* Common code for the failure cases above. If this is not a bounce
The incident has already been logged. */
RECIP_QUEUE_FAILED:
- if (sender_address[0])
+ if (*sender_address)
{
new->next = addr_failed;
addr_failed = new;
/* Send DSN for successful messages if requested */
-maybe_send_dsn();
+maybe_send_dsn(addr_succeed);
/* If any addresses failed, we must send a message to somebody, unless
af_ignore_error is set, in which case no action is taken. It is possible for