static address_item *addr_remote = NULL;
static address_item *addr_route = NULL;
static address_item *addr_succeed = NULL;
-static address_item *addr_dsntmp = NULL;
static address_item *addr_senddsn = NULL;
static FILE *message_log = NULL;
static ssize_t
readn(int fd, void * buffer, size_t len)
{
- void * next = buffer;
- void * end = buffer + len;
+uschar * next = buffer;
+uschar * end = next + len;
- while (next < end)
- {
- ssize_t got = read(fd, next, end - next);
+while (next < end)
+ {
+ ssize_t got = read(fd, next, end - next);
- /* I'm not sure if there are signals that can interrupt us,
- for now I assume the worst */
- if (got == -1 && errno == EINTR) continue;
- if (got <= 0) return next - buffer;
- next += got;
- }
+ /* I'm not sure if there are signals that can interrupt us,
+ for now I assume the worst */
+ if (got == -1 && errno == EINTR) continue;
+ if (got <= 0) return next - US buffer;
+ next += got;
+ }
- return len;
+return len;
}
address_item *
deliver_make_addr(uschar *address, BOOL copy)
{
-address_item *addr = store_get(sizeof(address_item));
+address_item *addr = store_get(sizeof(address_item), FALSE);
*addr = address_defaults;
if (copy) address = string_copy(address);
addr->address = address;
deliver_address_data = addr->prop.address_data;
deliver_domain_data = addr->prop.domain_data;
deliver_localpart_data = addr->prop.localpart_data;
+router_var = addr->prop.variables;
/* These may be unset for multiple addresses */
static int
open_msglog_file(uschar *filename, int mode, uschar **error)
{
+if (Ustrstr(filename, US"/../"))
+ log_write(0, LOG_MAIN|LOG_PANIC,
+ "Attempt to open msglog file path with upward-traversal: '%s'\n", filename);
+
for (int i = 2; i > 0; i--)
{
int fd = Uopen(filename,
#ifndef O_CLOEXEC
(void)fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
#endif
- if (fchown(fd, exim_uid, exim_gid) < 0)
+ if (exim_fchown(fd, exim_uid, exim_gid, filename) < 0)
{
*error = US"chown";
return -1;
MSGLOG_DIRECTORY_MODE, TRUE);
}
-*error = US"create";
+*error = US"create or open";
return -1;
}
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
static gstring *
-d_tlslog(gstring * s, address_item * addr)
+d_tlslog(gstring * g, address_item * addr)
{
if (LOGGING(tls_cipher) && addr->cipher)
- s = string_append(s, 2, US" X=", addr->cipher);
+ {
+ g = string_append(g, 2, US" X=", addr->cipher);
+#ifdef EXPERIMENTAL_TLS_RESUME
+ if (LOGGING(tls_resumption) && testflag(addr, af_tls_resume))
+ g = string_catn(g, US"*", 1);
+#endif
+ }
if (LOGGING(tls_certificate_verified) && addr->cipher)
- s = string_append(s, 2, US" CV=",
+ g = string_append(g, 2, US" CV=",
testflag(addr, af_cert_verified)
?
#ifdef SUPPORT_DANE
"yes"
: "no");
if (LOGGING(tls_peerdn) && addr->peerdn)
- s = string_append(s, 3, US" DN=\"", string_printing(addr->peerdn), US"\"");
-return s;
+ g = string_append(g, 3, US" DN=\"", string_printing(addr->peerdn), US"\"");
+return g;
}
#endif
else
{
- uschar * cmp = g->s + g->ptr;
+ uschar * cmp;
+ int off = g->ptr; /* start of the "full address" */
if (addr->local_part)
{
of all, do a caseless comparison; if this succeeds, do a caseful comparison
on the local parts. */
+ cmp = g->s + off; /* only now, as rebuffer likely done */
string_from_gstring(g); /* ensure nul-terminated */
if ( strcmpic(cmp, topaddr->address) == 0
&& Ustrncmp(cmp, topaddr->address, Ustrchr(cmp, '@') - cmp) == 0
delivery_log(int flags, address_item * addr, int logchar, uschar * msg)
{
gstring * g; /* Used for a temporary, expanding buffer, for building log lines */
-void * reset_point; /* released afterwards. */
+rmark reset_point;
/* Log the delivery on the main log. We use an extensible string to build up
the log line, and reset the store afterwards. Remote deliveries should always
lookup_dnssec_authenticated = NULL;
#endif
-g = reset_point = string_get(256);
+reset_point = store_mark();
+g = string_get_tainted(256, TRUE); /* addrs will be tainted, so avoid copy */
if (msg)
g = string_append(g, 2, host_and_ident(TRUE), US" ");
#endif
}
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
g = d_tlslog(g, addr);
#endif
{
if (testflag(addr, af_pipelining))
g = string_catn(g, US" L", 2);
-#ifdef EXPERIMENTAL_PIPE_CONNECT
+#ifdef SUPPORT_PIPE_CONNECT
if (testflag(addr, af_early_pipe))
g = string_catn(g, US"*", 1);
#endif
deferral_log(address_item * addr, uschar * now,
int logflags, uschar * driver_name, uschar * driver_kind)
{
-gstring * g;
-void * reset_point;
+rmark reset_point = store_mark();
+gstring * g = string_get(256);
/* Build up the line that is used for both the message log and the main
log. */
-g = reset_point = string_get(256);
-
/* Create the address string for logging. Must not do this earlier, because
an OK result may be changed to FAIL when a pipe returns text. */
static void
failure_log(address_item * addr, uschar * driver_kind, uschar * now)
{
-void * reset_point;
-gstring * g = reset_point = string_get(256);
+rmark reset_point = store_mark();
+gstring * g = string_get(256);
#ifndef DISABLE_EVENT
/* Message failures for which we will send a DSN get their event raised
if (addr->host_used)
g = d_hostlog(g, addr);
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
g = d_tlslog(g, addr);
#endif
}
/* Certificates for logging (via events) */
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
tls_out.ourcert = addr->ourcert;
addr->ourcert = NULL;
tls_out.peercert = addr->peercert;
delivery_log(LOG_MAIN, addr, logchar, NULL);
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
tls_free_cert(&tls_out.ourcert);
tls_free_cert(&tls_out.peercert);
tls_out.cipher = NULL;
gstring * g;
va_start(ap, format);
- g = string_vformat(NULL, TRUE, CS format, ap);
+ g = string_vformat(NULL, SVFMT_EXTEND|SVFMT_REBUFFER, CS format, ap);
va_end(ap);
addr->message = string_from_gstring(g);
}
static BOOL
previously_transported(address_item *addr, BOOL testing)
{
-(void)string_format(big_buffer, big_buffer_size, "%s/%s",
+uschar * s = string_sprintf("%s/%s",
addr->unique + (testflag(addr, af_homonym)? 3:0), addr->transport->name);
-if (tree_search(tree_nonrecipients, big_buffer) != 0)
+if (tree_search(tree_nonrecipients, s) != 0)
{
DEBUG(D_deliver|D_route|D_transport)
debug_printf("%s was previously delivered (%s transport): discarded\n",
f.disable_logging = FALSE; /* Jic */
addr->message = addr->router
? string_sprintf("No transport set by %s router", addr->router->name)
- : string_sprintf("No transport set by system filter");
+ : US"No transport set by system filter";
post_process_one(addr, DEFER, logflags, EXIM_DTYPE_TRANSPORT, 0);
continue;
}
of these checks, rather than for all local deliveries, because some local
deliveries (e.g. to pipes) can take a substantial time. */
- if (!(dbm_file = dbfn_open(US"retry", O_RDONLY, &dbblock, FALSE)))
+ if (!(dbm_file = dbfn_open(US"retry", O_RDONLY, &dbblock, FALSE, TRUE)))
{
DEBUG(D_deliver|D_retry|D_hints_lookup)
debug_printf("no retry data available\n");
else for (addr2 = addr; addr2; addr2 = addr2->next)
if (addr2->transport_return == OK)
{
- addr3 = store_get(sizeof(address_item));
+ addr3 = store_get(sizeof(address_item), FALSE);
*addr3 = *addr2;
addr3->next = NULL;
addr3->shadow_message = US &addr2->shadow_message;
if (!r || !(*ptr & rf_delete))
{
- r = store_get(sizeof(retry_item));
+ r = store_get(sizeof(retry_item), FALSE);
r->next = addr->retries;
addr->retries = r;
r->flags = *ptr++;
it in with the other info, in order to keep each message short enough to
guarantee it won't be split in the pipe. */
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
case 'X':
if (!addr) goto ADDR_MISMATCH; /* Below, in 'A' handler */
switch (*subid)
}
while (*ptr++);
break;
-#endif /*SUPPORT_TLS*/
+#endif /*DISABLE_TLS*/
case 'C': /* client authenticator information */
switch (*subid)
case 'L':
switch (*subid)
{
-#ifdef EXPERIMENTAL_PIPE_CONNECT
+#ifdef SUPPORT_PIPE_CONNECT
case 2: setflag(addr, af_early_pipe); /*FALLTHROUGH*/
#endif
case 1: setflag(addr, af_pipelining); break;
if (*ptr)
{
- h = store_get(sizeof(host_item));
+ h = store_get(sizeof(host_item), FALSE);
h->name = string_copy(ptr);
while (*ptr++);
h->address = string_copy(ptr);
if (!parlist)
{
- parlist = store_get(remote_max_parallel * sizeof(pardata));
+ parlist = store_get(remote_max_parallel * sizeof(pardata), FALSE);
for (poffset = 0; poffset < remote_max_parallel; poffset++)
parlist[poffset].pid = 0;
}
for(; addr; addr = addr->next)
{
uschar *ptr;
- retry_item *r;
/* The certificate verification status goes into the flags */
if (tls_out.certificate_verified) setflag(addr, af_cert_verified);
#ifdef SUPPORT_DANE
if (tls_out.dane_verified) setflag(addr, af_dane_verified);
#endif
+# ifdef EXPERIMENTAL_TLS_RESUME
+ if (tls_out.resumption & RESUME_USED) setflag(addr, af_tls_resume);
+# endif
/* Use an X item only if there's something to send */
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
if (addr->cipher)
{
ptr = big_buffer + sprintf(CS big_buffer, "%.128s", addr->cipher) + 1;
if (addr->peercert)
{
ptr = big_buffer;
- if (!tls_export_cert(ptr, big_buffer_size-2, addr->peercert))
+ if (tls_export_cert(ptr, big_buffer_size-2, addr->peercert))
while(*ptr++);
else
*ptr++ = 0;
if (addr->ourcert)
{
ptr = big_buffer;
- if (!tls_export_cert(ptr, big_buffer_size-2, addr->ourcert))
+ if (tls_export_cert(ptr, big_buffer_size-2, addr->ourcert))
while(*ptr++);
else
*ptr++ = 0;
rmt_dlv_checked_write(fd, 'X', '4', big_buffer, ptr - big_buffer);
}
# endif
-#endif /*SUPPORT_TLS*/
+#endif /*DISABLE_TLS*/
if (client_authenticator)
{
#endif
if (testflag(addr, af_pipelining))
-#ifdef EXPERIMENTAL_PIPE_CONNECT
+#ifdef SUPPORT_PIPE_CONNECT
if (testflag(addr, af_early_pipe))
rmt_dlv_checked_write(fd, 'L', '2', NULL, 0);
else
/* Retry information: for most success cases this will be null. */
- for (r = addr->retries; r; r = r->next)
+ for (retry_item * r = addr->retries; r; r = r->next)
{
sprintf(CS big_buffer, "%c%.500s", r->flags, r->key);
ptr = big_buffer + Ustrlen(big_buffer+2) + 3;
if (cutthrough.cctx.sock >= 0 && cutthrough.callout_hold_only)
{
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
if (cutthrough.is_tls)
tls_close(cutthrough.cctx.tls_ctx, TLS_NO_SHUTDOWN);
#endif
this, Jan 1999.] We know the syntax is valid, so this can be done by simply
removing quoting backslashes and any unquoted doublequotes. */
-t = addr->cc_local_part = store_get(len+1);
+t = addr->cc_local_part = store_get(len+1, is_tainted(address));
while(len-- > 0)
{
int c = *address++;
if (new_address)
{
- address_item *new_parent = store_get(sizeof(address_item));
+ address_item *new_parent = store_get(sizeof(address_item), FALSE);
*new_parent = *addr;
addr->parent = new_parent;
new_parent->child_count = 1;
+/************************************************/
+
+static void
+print_dsn_addr_action(FILE * f, address_item * addr,
+ uschar * action, uschar * status)
+{
+address_item * pa;
+
+if (addr->dsn_orcpt)
+ fprintf(f,"Original-Recipient: %s\n", addr->dsn_orcpt);
+
+for (pa = addr; pa->parent; ) pa = pa->parent;
+fprintf(f, "Action: %s\n"
+ "Final-Recipient: rfc822;%s\n"
+ "Status: %s\n",
+ action, pa->address, status);
+}
+
+
/*************************************************
* Deliver one message *
*************************************************/
if (addr_new)
{
- int uid = (system_filter_uid_set)? system_filter_uid : geteuid();
- int gid = (system_filter_gid_set)? system_filter_gid : getegid();
+ int uid = system_filter_uid_set ? system_filter_uid : geteuid();
+ int gid = system_filter_gid_set ? system_filter_gid : getegid();
/* The text "system-filter" is tested in transport_set_up_command() and in
set_up_shell_command() in the pipe transport, to enable them to permit
if (!tmp)
p->message = string_sprintf("failed to expand \"%s\" as a "
"system filter transport name", tpname);
+ if (is_tainted(tmp))
+ p->message = string_sprintf("attempt to used tainted value '%s' for"
+ "transport '%s' as a system filter", tmp, tpname);
tpname = tmp;
}
else
to be passed on to other DSN enabled MTAs */
new->dsn_flags = r->dsn_flags & rf_dsnflags;
new->dsn_orcpt = r->orcpt;
- DEBUG(D_deliver) debug_printf("DSN: set orcpt: %s flags: %d\n",
+ DEBUG(D_deliver) debug_printf("DSN: set orcpt: %s flags: 0x%x\n",
new->dsn_orcpt ? new->dsn_orcpt : US"", new->dsn_flags);
switch (process_recipients)
}
#ifndef DISABLE_EVENT
- if (process_recipients != RECIP_ACCEPT)
+ if (process_recipients != RECIP_ACCEPT && event_action)
{
uschar * save_local = deliver_localpart;
const uschar * save_domain = deliver_domain;
/* Failure to open the retry database is treated the same as if it does
not exist. In both cases, dbm_file is NULL. */
- if (!(dbm_file = dbfn_open(US"retry", O_RDONLY, &dbblock, FALSE)))
+ if (!(dbm_file = dbfn_open(US"retry", O_RDONLY, &dbblock, FALSE, TRUE)))
DEBUG(D_deliver|D_retry|D_route|D_hints_lookup)
debug_printf("no retry data available\n");
keep piling '>' characters on the front. */
if (addr->address[0] == '>')
- {
while (tree_search(tree_duplicates, addr->unique))
addr->unique = string_sprintf(">%s", addr->unique);
- }
else if ((tnode = tree_search(tree_duplicates, addr->unique)))
{
(void)post_process_one(addr, DEFER, LOG_MAIN, EXIM_DTYPE_ROUTER, 0);
/* For remote-retry errors (here and just above) that we've not yet
- hit the rery time, use the error recorded in the retry database
+ hit the retry time, use the error recorded in the retry database
as info in the warning message. This lets us send a message even
when we're not failing on a fresh attempt. We assume that this
info is not sensitive. */
&addr_succeed, v_none)) == DEFER)
retry_add_item(addr,
addr->router->retry_use_local_part
- ? string_sprintf("R:%s@%s", addr->local_part, addr->domain)
- : string_sprintf("R:%s", addr->domain),
+ ? string_sprintf("R:%s@%s", addr->local_part, addr->domain)
+ : string_sprintf("R:%s", addr->domain),
0);
/* Otherwise, if there is an existing retry record in the database, add
that the mode is correct - the group setting doesn't always seem to get
set automatically. */
- if( fchown(journal_fd, exim_uid, exim_gid)
+ if( exim_fchown(journal_fd, exim_uid, exim_gid, fname)
|| fchmod(journal_fd, SPOOL_MODE)
#ifndef O_CLOEXEC
|| fcntl(journal_fd, F_SETFD, fcntl(journal_fd, F_GETFD) | FD_CLOEXEC)
/* Send DSN for successful messages if requested */
addr_senddsn = NULL;
-for (addr_dsntmp = addr_succeed; addr_dsntmp; addr_dsntmp = addr_dsntmp->next)
+for (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"
"DSN: processing successful delivery address: %s\n"
"DSN: Sender_address: %s\n"
- "DSN: orcpt: %s flags: %d\n"
+ "DSN: orcpt: %s flags: 0x%x\n"
"DSN: envid: %s ret: %d\n"
"DSN: Final recipient: %s\n"
"DSN: Remote SMTP server supports DSN: %d\n",
- addr_dsntmp->router ? addr_dsntmp->router->name : US"(unknown)",
- addr_dsntmp->address,
+ a->router ? a->router->name : US"(unknown)",
+ a->address,
sender_address,
- addr_dsntmp->dsn_orcpt ? addr_dsntmp->dsn_orcpt : US"NULL",
- addr_dsntmp->dsn_flags,
+ a->dsn_orcpt ? a->dsn_orcpt : US"NULL",
+ a->dsn_flags,
dsn_envid ? dsn_envid : US"NULL", dsn_ret,
- addr_dsntmp->address,
- addr_dsntmp->dsn_aware
+ a->address,
+ a->dsn_aware
);
/* send report if next hop not DSN aware or a router flagged "last DSN hop"
and a report was requested */
- if ( ( addr_dsntmp->dsn_aware != dsn_support_yes
- || addr_dsntmp->dsn_flags & rf_dsnlasthop
+ if ( ( a->dsn_aware != dsn_support_yes
+ || a->dsn_flags & rf_dsnlasthop
)
- && addr_dsntmp->dsn_flags & rf_notify_success
+ && a->dsn_flags & rf_notify_success
)
{
/* copy and relink address_item and send report with all of them at once later */
address_item * addr_next = addr_senddsn;
- addr_senddsn = store_get(sizeof(address_item));
- *addr_senddsn = *addr_dsntmp;
+ addr_senddsn = store_get(sizeof(address_item), FALSE);
+ *addr_senddsn = *a;
addr_senddsn->next = addr_next;
}
else
if (pid < 0) /* Creation of child failed */
{
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Process %d (parent %d) failed to "
- "create child process to send failure message: %s", getpid(),
+ "create child process to send success-dsn message: %s", getpid(),
getppid(), strerror(errno));
DEBUG(D_deliver) debug_printf("DSN: child_open_exim failed\n");
transport_ctx tctx = {{0}};
DEBUG(D_deliver)
- debug_printf("sending error message to: %s\n", sender_address);
+ debug_printf("sending success-dsn to: %s\n", sender_address);
/* build unique id for MIME boundary */
bound = string_sprintf(TIME_T_FMT "-eximdsn-%d", time(NULL), rand());
if (errors_reply_to)
fprintf(f, "Reply-To: %s\n", errors_reply_to);
+ moan_write_from(f);
fprintf(f, "Auto-Submitted: auto-generated\n"
- "From: Mail Delivery System <Mailer-Daemon@%s>\n"
"To: %s\n"
- "Subject: Delivery Status Notification\n"
- "Content-Type: multipart/report; report-type=delivery-status; boundary=%s\n"
+ "Subject: Delivery Status Notification\n",
+ sender_address);
+ moan_write_references(f, NULL);
+ fprintf(f, "Content-Type: multipart/report;"
+ " report-type=delivery-status; boundary=%s\n"
"MIME-Version: 1.0\n\n"
"--%s\n"
"This message was created automatically by mail delivery software.\n"
" ----- The following addresses had successful delivery notifications -----\n",
- qualify_domain_sender, sender_address, bound, bound);
+ bound, bound);
- for (addr_dsntmp = addr_senddsn; addr_dsntmp;
- addr_dsntmp = addr_dsntmp->next)
+ for (address_item * a = addr_senddsn; a; a = a->next)
fprintf(f, "<%s> (relayed %s)\n\n",
- addr_dsntmp->address,
- addr_dsntmp->dsn_flags & rf_dsnlasthop ? "via non DSN router"
- : addr_dsntmp->dsn_aware == dsn_support_no ? "to non-DSN-aware mailer"
+ a->address,
+ a->dsn_flags & rf_dsnlasthop ? "via non DSN router"
+ : a->dsn_aware == dsn_support_no ? "to non-DSN-aware mailer"
: "via non \"Remote SMTP\" router"
);
}
fputc('\n', f);
- for (addr_dsntmp = addr_senddsn;
- addr_dsntmp;
- addr_dsntmp = addr_dsntmp->next)
+ for (address_item * a = addr_senddsn; a; a = a->next)
{
- if (addr_dsntmp->dsn_orcpt)
- fprintf(f,"Original-Recipient: %s\n", addr_dsntmp->dsn_orcpt);
+ host_item * hu;
- fprintf(f, "Action: delivered\n"
- "Final-Recipient: rfc822;%s\n"
- "Status: 2.0.0\n",
- addr_dsntmp->address);
+ print_dsn_addr_action(f, a, US"delivered", US"2.0.0");
- if (addr_dsntmp->host_used && addr_dsntmp->host_used->name)
+ if ((hu = a->host_used) && hu->name)
fprintf(f, "Remote-MTA: dns; %s\nDiagnostic-Code: smtp; 250 Ok\n\n",
- addr_dsntmp->host_used->name);
+ hu->name);
else
fprintf(f, "Diagnostic-Code: X-Exim; relayed via non %s router\n\n",
- addr_dsntmp->dsn_flags & rf_dsnlasthop ? "DSN" : "SMTP");
+ a->dsn_flags & rf_dsnlasthop ? "DSN" : "SMTP");
}
fprintf(f, "--%s\nContent-type: text/rfc822-headers\n\n", bound);
mark the recipient done. */
if ( addr_failed->prop.ignore_error
- || addr_failed->dsn_flags & (rf_dsnflags & ~rf_notify_failure)
+ || addr_failed->dsn_flags & rf_dsnflags
+ && !(addr_failed->dsn_flags & rf_notify_failure)
)
{
addr = addr_failed;
#ifndef DISABLE_EVENT
msg_event_raise(US"msg:fail:delivery", addr);
#endif
- log_write(0, LOG_MAIN, "%s%s%s%s: error ignored",
+ log_write(0, LOG_MAIN, "%s%s%s%s: error ignored%s",
addr->address,
!addr->parent ? US"" : US" <",
!addr->parent ? US"" : addr->parent->address,
- !addr->parent ? US"" : US">");
+ !addr->parent ? US"" : US">",
+ addr->prop.ignore_error
+ ? US"" : US": RFC 3461 DSN, failure notify not requested");
address_done(addr, logtod);
child_done(addr, logtod);
fprintf(fp, "Auto-Submitted: auto-replied\n");
moan_write_from(fp);
fprintf(fp, "To: %s\n", bounce_recipient);
+ moan_write_references(fp, NULL);
/* generate boundary string and output MIME-Headers */
bound = string_sprintf(TIME_T_FMT "-eximdsn-%d", time(NULL), rand());
for (addr = handled_addr; addr; addr = addr->next)
{
host_item * hu;
- fprintf(fp, "Action: failed\n"
- "Final-Recipient: rfc822;%s\n"
- "Status: 5.0.0\n",
- addr->address);
+
+ print_dsn_addr_action(fp, addr, US"failed", US"5.0.0");
+
if ((hu = addr->host_used) && hu->name)
{
fprintf(fp, "Remote-MTA: dns; %s\n", hu->name);
DEBUG(D_deliver)
{
- debug_printf("time on queue = %s id %s addr %s\n", readconf_printtime(queue_time), message_id, addr_defer->address);
+ debug_printf("time on queue = %s id %s addr %s\n",
+ readconf_printtime(queue_time), message_id, addr_defer->address);
debug_printf("warning counts: required %d done %d\n", count,
warning_count);
}
fprintf(f, "Auto-Submitted: auto-replied\n");
moan_write_from(f);
fprintf(f, "To: %s\n", recipients);
+ moan_write_references(f, NULL);
/* generated boundary string and output MIME-Headers */
bound = string_sprintf(TIME_T_FMT "-eximdsn-%d", time(NULL), rand());
/* List the addresses, with error information if allowed */
- /* store addr_defer for machine readable part */
- address_item *addr_dsndefer = addr_defer;
fputc('\n', f);
- while (addr_defer)
+ for (address_item * addr = addr_defer; addr; addr = addr->next)
{
- address_item *addr = addr_defer;
- addr_defer = addr->next;
if (print_address_information(addr, f, US" ", US"\n ", US""))
print_address_error(addr, f, US"Delay reason: ");
fputc('\n', f);
}
fputc('\n', f);
- for ( ; addr_dsndefer; addr_dsndefer = addr_dsndefer->next)
+ for (address_item * addr = addr_defer; addr; addr = addr->next)
{
- if (addr_dsndefer->dsn_orcpt)
- fprintf(f, "Original-Recipient: %s\n", addr_dsndefer->dsn_orcpt);
-
- fprintf(f, "Action: delayed\n"
- "Final-Recipient: rfc822;%s\n"
- "Status: 4.0.0\n",
- addr_dsndefer->address);
- if (addr_dsndefer->host_used && addr_dsndefer->host_used->name)
+ host_item * hu;
+
+ print_dsn_addr_action(f, addr, US"delayed", US"4.0.0");
+
+ if ((hu = addr->host_used) && hu->name)
{
- fprintf(f, "Remote-MTA: dns; %s\n",
- addr_dsndefer->host_used->name);
- print_dsn_diagnostic_code(addr_dsndefer, f);
+ fprintf(f, "Remote-MTA: dns; %s\n", hu->name);
+ print_dsn_diagnostic_code(addr, f);
}
fputc('\n', f);
}
if (!regex_AUTH) regex_AUTH =
regex_must_compile(AUTHS_REGEX, FALSE, TRUE);
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
if (!regex_STARTTLS) regex_STARTTLS =
regex_must_compile(US"\\n250[\\s\\-]STARTTLS(\\s|\\n|$)", FALSE, TRUE);
-
-# ifdef EXPERIMENTAL_REQUIRETLS
-if (!regex_REQUIRETLS) regex_REQUIRETLS =
- regex_must_compile(US"\\n250[\\s\\-]REQUIRETLS(\\s|\\n|$)", FALSE, TRUE);
-# endif
#endif
if (!regex_CHUNKING) regex_CHUNKING =
if (!regex_IGNOREQUOTA) regex_IGNOREQUOTA =
regex_must_compile(US"\\n250[\\s\\-]IGNOREQUOTA(\\s|\\n|$)", FALSE, TRUE);
-#ifdef EXPERIMENTAL_PIPE_CONNECT
+#ifdef SUPPORT_PIPE_CONNECT
if (!regex_EARLY_PIPE) regex_EARLY_PIPE =
regex_must_compile(US"\\n250[\\s\\-]" EARLY_PIPE_FEATURE_NAME "(\\s|\\n|$)", FALSE, TRUE);
#endif
smtp_peer_options = cutthrough.peer_options;
continue_sequence = 0;
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
if (cutthrough.is_tls)
{
int pfd[2], pid;
}
return; /* compiler quietening; control does not reach here. */
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
fail:
log_write(0,
LOG_MAIN | (exec_type == CEE_EXEC_EXIT ? LOG_PANIC : LOG_PANIC_DIE),