static address_item *addr_remote = NULL;
static address_item *addr_route = NULL;
static address_item *addr_succeed = NULL;
-#ifdef EXPERIMENTAL_DSN
static address_item *addr_dsntmp = NULL;
static address_item *addr_senddsn = NULL;
-#endif
static FILE *message_log = NULL;
static BOOL update_spool;
{
if (addr == NULL)
{
- uschar ***p = address_expansions;
+ const uschar ***p = address_expansions;
while (*p != NULL) **p++ = NULL;
return;
}
#ifdef EXPERIMENTAL_EVENT
uschar *
-event_raise(uschar * action, uschar * event, uschar * ev_data)
+event_raise(uschar * action, const uschar * event, uschar * ev_data)
{
uschar * s;
if (action)
}
static void
-msg_event_raise(uschar * event, address_item * addr)
+msg_event_raise(const uschar * event, const address_item * addr)
{
-uschar * save_domain = deliver_domain;
+const uschar * save_domain = deliver_domain;
uschar * save_local = deliver_localpart;
-uschar * save_host = deliver_host;
+const uschar * save_host = deliver_host;
if (!addr->transport)
return;
s = string_append(s, &size, &ptr, 2, US"> ", log_address);
}
+if (log_extra_selector & LX_incoming_interface && sending_ip_address)
+ s = string_append(s, &size, &ptr, 3, US" I=[", sending_ip_address, US"]");
+ /* for the port: string_sprintf("%d", sending_port) */
+
if ((log_extra_selector & LX_sender_on_delivery) != 0 || msg)
s = string_append(s, &size, &ptr, 3, US" F=<", sender_address, US">");
addr->message &&
(addr->host_used || Ustrcmp(addr->transport->driver_name, "lmtp") == 0))
{
- int i;
+ unsigned i;
+ unsigned lim = big_buffer_size < 1024 ? big_buffer_size : 1024;
uschar *p = big_buffer;
uschar *ss = addr->message;
*p++ = '\"';
- for (i = 0; i < 256 && ss[i] != 0; i++) /* limit logged amount */
+ for (i = 0; i < lim && ss[i] != 0; i++) /* limit logged amount */
{
if (ss[i] == '\"' || ss[i] == '\\') *p++ = '\\'; /* quote \ and " */
*p++ = ss[i];
if (addr->message != NULL)
{
- addr->message = string_printing(addr->message);
+ const uschar * s = string_printing(addr->message);
+ if (s != addr->message)
+ addr->message = US s;
+ /* deconst cast ok as string_printing known to have alloc'n'copied */
if (((Ustrstr(addr->message, "failed to expand") != NULL) || (Ustrstr(addr->message, "expansion of ") != NULL)) &&
(Ustrstr(addr->message, "mysql") != NULL ||
Ustrstr(addr->message, "pgsql") != NULL ||
if (s != NULL)
{
uschar *p = big_buffer + Ustrlen(big_buffer);
+ const uschar * sp;
while (p > big_buffer && isspace(p[-1])) p--;
*p = 0;
- s = string_printing(big_buffer);
+ sp = string_printing(big_buffer);
log_write(0, LOG_MAIN, "<%s>: %s transport output: %s",
- addr->address, tb->name, s);
+ addr->address, tb->name, sp);
}
(void)fclose(f);
}
{
int sep = 0;
address_item **aptr = &addr_remote;
-uschar *listptr = remote_sort_domains;
+const uschar *listptr = remote_sort_domains;
uschar *pattern;
uschar patbuf[256];
{
address_item **next;
deliver_domain = (*aptr)->domain; /* set $domain */
- if (match_isinlist(deliver_domain, &pattern, UCHAR_MAX+1,
+ if (match_isinlist(deliver_domain, (const uschar **)&pattern, UCHAR_MAX+1,
&domainlist_anchor, NULL, MCL_DOMAIN, TRUE, NULL) == OK)
{
aptr = &((*aptr)->next);
next = &((*aptr)->next);
while (*next != NULL &&
(deliver_domain = (*next)->domain, /* Set $domain */
- match_isinlist(deliver_domain, &pattern, UCHAR_MAX+1,
+ match_isinlist(deliver_domain, (const uschar **)&pattern, UCHAR_MAX+1,
&domainlist_anchor, NULL, MCL_DOMAIN, TRUE, NULL)) != OK)
next = &((*next)->next);
break;
#endif
-#ifdef EXPERIMENTAL_DSN
case 'D':
if (addr == NULL) goto ADDR_MISMATCH;
memcpy(&(addr->dsn_aware), ptr, sizeof(addr->dsn_aware));
ptr += sizeof(addr->dsn_aware);
DEBUG(D_deliver) debug_printf("DSN read: addr->dsn_aware = %d\n", addr->dsn_aware);
break;
-#endif
case 'A':
if (addr == NULL)
addr = addr->next;
break;
+ /* Local interface address/port */
+ case 'I':
+ if (*ptr) sending_ip_address = string_copy(ptr);
+ while (*ptr++) ;
+ if (*ptr) sending_port = atoi(CS ptr);
+ while (*ptr++) ;
+ break;
+
/* Z marks the logical end of the data. It is followed by '0' if
continue_transport was NULL at the end of transporting, otherwise '1'.
We need to know when it becomes NULL during a delivery down a passed SMTP
rmt_dlv_checked_write(fd, 'P', '0', NULL, 0);
#endif
-#ifdef EXPERIMENTAL_DSN
memcpy(big_buffer, &addr->dsn_aware, sizeof(addr->dsn_aware));
rmt_dlv_checked_write(fd, 'D', '0', big_buffer, sizeof(addr->dsn_aware));
DEBUG(D_deliver) debug_printf("DSN write: addr->dsn_aware = %d\n", addr->dsn_aware);
-#endif
/* Retry information: for most success cases this will be null. */
rmt_dlv_checked_write(fd, 'A', '0', big_buffer, ptr - big_buffer);
}
+ /* Local interface address/port */
+ if (log_extra_selector & LX_incoming_interface && sending_ip_address)
+ {
+ uschar * ptr = big_buffer;
+ sprintf(CS ptr, "%.128s", sending_ip_address);
+ while(*ptr++);
+ sprintf(CS ptr, "%d", sending_port);
+ while(*ptr++);
+
+ rmt_dlv_checked_write(fd, 'I', '0', big_buffer, ptr - big_buffer);
+ }
+
/* Add termination flag, close the pipe, and that's it. The character
after 'Z' indicates whether continue_transport is now NULL or not.
A change from non-NULL to NULL indicates a problem with a continuing
deliver_domain = addr->domain; /* set $domain */
- while ((rc = match_isinlist(deliver_domain, &percent_hack_domains, 0,
+ while ((rc = match_isinlist(deliver_domain, (const uschar **)&percent_hack_domains, 0,
&domainlist_anchor, addr->domain_cache, MCL_DOMAIN, TRUE, NULL))
== OK &&
(t = Ustrrchr(local_part, '%')) != NULL)
}
-#ifdef EXPERIMENTAL_DSN
/***********************************************************
* Print Diagnostic-Code for an address *
************************************************************/
fputc('\n', f);
}
-#endif /* EXPERIMENTAL_DSN */
/*************************************************
if (r->pno >= 0)
new->onetime_parent = recipients_list[r->pno].address;
-#ifdef EXPERIMENTAL_DSN
/* If DSN support is enabled, set the dsn flags and the original receipt
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", new->dsn_orcpt, new->dsn_flags);
-#endif
switch (process_recipients)
{
if (process_recipients != RECIP_ACCEPT)
{
uschar * save_local = deliver_localpart;
- uschar * save_domain = deliver_domain;
+ const uschar * save_domain = deliver_domain;
deliver_localpart = expand_string(
string_sprintf("${local_part:%s}", new->address));
deliver_domain = addr->domain; /* set $domain */
if (!forced && hold_domains != NULL &&
- (rc = match_isinlist(addr->domain, &hold_domains, 0,
+ (rc = match_isinlist(addr->domain, (const uschar **)&hold_domains, 0,
&domainlist_anchor, addr->domain_cache, MCL_DOMAIN, TRUE,
NULL)) != FAIL)
{
addr_route = addr->next;
deliver_domain = addr->domain; /* set $domain */
- if ((rc = match_isinlist(addr->domain, &queue_domains, 0,
+ if ((rc = match_isinlist(addr->domain, (const uschar **)&queue_domains, 0,
&domainlist_anchor, addr->domain_cache, MCL_DOMAIN, TRUE, NULL))
!= OK)
{
{
int rc;
address_item *addr = addr_route;
- uschar *old_domain = addr->domain;
+ const uschar *old_domain = addr->domain;
uschar *old_unique = addr->unique;
addr_route = addr->next;
addr->next = NULL;
/* Precompile some regex that are used to recognize parameters in response
to an EHLO command, if they aren't already compiled. */
- if (regex_PIPELINING == NULL) regex_PIPELINING =
- regex_must_compile(US"\\n250[\\s\\-]PIPELINING(\\s|\\n|$)", FALSE, TRUE);
-
- if (regex_SIZE == NULL) regex_SIZE =
- regex_must_compile(US"\\n250[\\s\\-]SIZE(\\s|\\n|$)", FALSE, TRUE);
-
- if (regex_AUTH == NULL) regex_AUTH =
- regex_must_compile(US"\\n250[\\s\\-]AUTH\\s+([\\-\\w\\s]+)(?:\\n|$)",
- FALSE, TRUE);
-
-#ifdef SUPPORT_TLS
- if (regex_STARTTLS == NULL) regex_STARTTLS =
- regex_must_compile(US"\\n250[\\s\\-]STARTTLS(\\s|\\n|$)", FALSE, TRUE);
-#endif
-
-#ifndef DISABLE_PRDR
- if (regex_PRDR == NULL) regex_PRDR =
- regex_must_compile(US"\\n250[\\s\\-]PRDR(\\s|\\n|$)", FALSE, TRUE);
-#endif
-
-#ifdef EXPERIMENTAL_DSN
- /* Set the regex to check for DSN support on remote MTA */
- if (regex_DSN == NULL) regex_DSN =
- regex_must_compile(US"\\n250[\\s\\-]DSN(\\s|\\n|$)", FALSE, TRUE);
-#endif
+ deliver_init();
/* Now sort the addresses if required, and do the deliveries. The yield of
do_remote_deliveries is FALSE when mua_wrapper is set and all addresses
else if (!dont_deliver) retry_update(&addr_defer, &addr_failed, &addr_succeed);
-#ifdef EXPERIMENTAL_DSN
/* Send DSN for successful messages */
addr_dsntmp = addr_succeed;
addr_senddsn = NULL;
"create child process to send failure message: %s", getpid(),
getppid(), strerror(errno));
- DEBUG(D_deliver) debug_printf("DSN: child_open_exim failed\n");
-
+ DEBUG(D_deliver) debug_printf("DSN: child_open_exim failed\n");
}
else /* Creation of child succeeded */
{
int topt = topt_add_return_path | topt_no_body;
uschar * bound;
- DEBUG(D_deliver) debug_printf("sending error message to: %s\n", sender_address);
+ DEBUG(D_deliver)
+ debug_printf("sending error message to: %s\n", sender_address);
/* build unique id for MIME boundary */
bound = string_sprintf(TIME_T_FMT "-eximdsn-%d", time(NULL), rand());
" ----- The following addresses had successful delivery notifications -----\n",
qualify_domain_sender, sender_address, bound, bound);
- addr_dsntmp = addr_senddsn;
- while(addr_dsntmp)
- {
+ for (addr_dsntmp = addr_senddsn; addr_dsntmp;
+ addr_dsntmp = addr_dsntmp->next)
fprintf(f, "<%s> (relayed %s)\n\n",
addr_dsntmp->address,
(addr_dsntmp->dsn_flags & rf_dsnlasthop) == 1
? "to non-DSN-aware mailer"
: "via non \"Remote SMTP\" router"
);
- addr_dsntmp = addr_dsntmp->next;
- }
+
fprintf(f, "--%s\n"
"Content-type: message/delivery-status\n\n"
"Reporting-MTA: dns; %s\n",
bound, smtp_active_hostname);
- if (dsn_envid != NULL) {
- /* must be decoded from xtext: see RFC 3461:6.3a */
+ if (dsn_envid)
+ { /* must be decoded from xtext: see RFC 3461:6.3a */
uschar *xdec_envid;
if (auth_xtextdecode(dsn_envid, &xdec_envid) > 0)
fprintf(f, "Original-Envelope-ID: %s\n", dsn_envid);
addr_dsntmp->address);
if (addr_dsntmp->host_used && addr_dsntmp->host_used->name)
- fprintf(f, "Remote-MTA: dns; %s\nDiagnostic-Code: smtp; 250 Ok\n",
+ fprintf(f, "Remote-MTA: dns; %s\nDiagnostic-Code: smtp; 250 Ok\n\n",
addr_dsntmp->host_used->name);
else
- fprintf(f,"Diagnostic-Code: X-Exim; relayed via non %s router\n",
+ fprintf(f, "Diagnostic-Code: X-Exim; relayed via non %s router\n\n",
(addr_dsntmp->dsn_flags & rf_dsnlasthop) == 1 ? "DSN" : "SMTP");
- fputc('\n', f);
}
fprintf(f, "--%s\nContent-type: text/rfc822-headers\n\n", bound);
rc = child_close(pid, 0); /* Waits for child to close, no timeout */
}
}
-#endif /*EXPERIMENTAL_DSN*/
/* 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
it from the list, throw away any saved message file, log it, and
mark the recipient done. */
- if (testflag(addr_failed, af_ignore_error)
-#ifdef EXPERIMENTAL_DSN
- || (((addr_failed->dsn_flags & rf_dsnflags) != 0)
- && ((addr_failed->dsn_flags & rf_notify_failure) != rf_notify_failure))
-#endif
+ if ( testflag(addr_failed, af_ignore_error)
+ || ( ((addr_failed->dsn_flags & rf_dsnflags) != 0)
+ && ((addr_failed->dsn_flags & rf_notify_failure) != rf_notify_failure))
)
- {
+ {
addr = addr_failed;
addr_failed = addr->next;
if (addr->return_filename != NULL) Uunlink(addr->return_filename);
log_write(0, LOG_MAIN, "%s%s%s%s: error ignored",
addr->address,
- (addr->parent == NULL)? US"" : US" <",
- (addr->parent == NULL)? US"" : addr->parent->address,
- (addr->parent == NULL)? US"" : US">");
+ !addr->parent ? US"" : US" <",
+ !addr->parent ? US"" : addr->parent->address,
+ !addr->parent ? US"" : US">");
address_done(addr, logtod);
child_done(addr, logtod);
else
{
- bounce_recipient = (addr_failed->p.errors_address == NULL)?
- sender_address : addr_failed->p.errors_address;
+ bounce_recipient = addr_failed->p.errors_address
+ ? addr_failed->p.errors_address : sender_address;
/* Make a subprocess to send a message */
- pid = child_open_exim(&fd);
-
- /* Creation of child failed */
-
- if (pid < 0)
+ if ((pid = child_open_exim(&fd)) < 0)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Process %d (parent %d) failed to "
"create child process to send failure message: %s", getpid(),
getppid(), strerror(errno));
BOOL to_sender = strcmpic(sender_address, bounce_recipient) == 0;
int max = (bounce_return_size_limit/DELIVER_IN_BUFFER_SIZE + 1) *
DELIVER_IN_BUFFER_SIZE;
-#ifdef EXPERIMENTAL_DSN
uschar * bound;
uschar *dsnlimitmsg;
uschar *dsnnotifyhdr;
int topt;
-#endif
DEBUG(D_deliver)
debug_printf("sending error message to: %s\n", bounce_recipient);
paddr = &addr_failed;
for (addr = addr_failed; addr != NULL; addr = *paddr)
- {
- if (Ustrcmp(bounce_recipient, (addr->p.errors_address == NULL)?
- sender_address : addr->p.errors_address) != 0)
- {
- paddr = &(addr->next); /* Not the same; skip */
- }
- else /* The same - dechain */
- {
+ if (Ustrcmp(bounce_recipient, addr->p.errors_address
+ ? addr->p.errors_address : sender_address) == 0)
+ { /* The same - dechain */
*paddr = addr->next;
*pmsgchain = addr;
addr->next = NULL;
pmsgchain = &(addr->next);
}
- }
+ else
+ paddr = &addr->next; /* Not the same; skip */
/* Include X-Failed-Recipients: for automatic interpretation, but do
not let any one header line get too long. We do this by starting a
/* Output the standard headers */
- if (errors_reply_to != NULL)
+ if (errors_reply_to)
fprintf(f, "Reply-To: %s\n", errors_reply_to);
fprintf(f, "Auto-Submitted: auto-replied\n");
moan_write_from(f);
fprintf(f, "To: %s\n", bounce_recipient);
-#ifdef EXPERIMENTAL_DSN
/* generate boundary string and output MIME-Headers */
bound = string_sprintf(TIME_T_FMT "-eximdsn-%d", time(NULL), rand());
" report-type=delivery-status; boundary=%s\n"
"MIME-Version: 1.0\n",
bound);
-#endif
/* Open a template file if one is provided. Log failure to open, but
carry on - default texts will be used. */
fprintf(f, "Subject: Mail delivery failed%s\n\n",
to_sender? ": returning message to sender" : "");
-#ifdef EXPERIMENTAL_DSN
/* output human readable part as text/plain section */
fprintf(f, "--%s\n"
"Content-type: text/plain; charset=us-ascii\n\n",
bound);
-#endif
if ((emf_text = next_emf(emf, US"intro")))
fprintf(f, "%s", CS emf_text);
fputc('\n', f);
}
-#ifdef EXPERIMENTAL_DSN
/* output machine readable part */
fprintf(f, "--%s\n"
"Content-type: message/delivery-status\n\n"
addr->host_used->name);
print_dsn_diagnostic_code(addr, f);
}
+ fputc('\n', f);
}
-#endif
/* Now copy the message, trying to give an intelligible comment if
it is too long for it all to be copied. The limit isn't strictly
emf_text = next_emf(emf, US"copy");
-#ifndef EXPERIMENTAL_DSN
- if (bounce_return_message)
- {
- int topt = topt_add_return_path;
- if (!bounce_return_body) topt |= topt_no_body;
-
- if (emf_text)
- fprintf(f, "%s", CS emf_text);
- else
- {
- if (bounce_return_body) fprintf(f,
-"------ This is a copy of the message, including all the headers. ------\n");
- else fprintf(f,
-"------ This is a copy of the message's headers. ------\n");
- }
-
- /* While reading the "truncated" message, set return_size_limit to
- the actual max testing value, rounded. We need to read the message
- whether we are going to use it or not. */
-
- {
- int temp = bounce_return_size_limit;
- bounce_return_size_limit = (max/1000)*1000;
- emf_text = next_emf(emf, US"truncated");
- bounce_return_size_limit = temp;
- }
-
- if (bounce_return_body && bounce_return_size_limit > 0)
- {
- struct stat statbuf;
- if (fstat(deliver_datafile, &statbuf) == 0 && statbuf.st_size > max)
- {
- if (emf_text)
- fprintf(f, "%s", CS emf_text);
- else
- fprintf(f,
-"------ The body of the message is " OFF_T_FMT " characters long; only the first\n"
-"------ %d or so are included here.\n", statbuf.st_size, max);
- }
- }
-
- fputc('\n', f);
- fflush(f);
-
- transport_filter_argv = NULL; /* Just in case */
- return_path = sender_address; /* In case not previously set */
- transport_write_message(NULL, fileno(f), topt,
- bounce_return_size_limit, NULL, NULL, NULL, NULL, NULL, 0);
- }
-
- /* Write final text and close the template file if one is open */
-
- if (emf)
- {
- if ((emf_text = next_emf(emf, US"final")))
- fprintf(f, "%s", CS emf_text);
- (void)fclose(emf);
- }
-#else
/* add message body
we ignore the intro text from template and add
the text for bounce_return_size_limit at the end.
bounce_return_size_limit is always honored.
*/
- fprintf(f, "\n--%s\n", bound);
+ fprintf(f, "--%s\n", bound);
dsnlimitmsg = US"X-Exim-DSN-Information: Due to administrative limits only headers are returned";
dsnnotifyhdr = NULL;
}
}
- if (topt & topt_no_body)
- fprintf(f,"Content-type: text/rfc822-headers\n\n");
- else
- fprintf(f,"Content-type: message/rfc822\n\n");
+ fputs(topt & topt_no_body ? "Content-type: text/rfc822-headers\n\n"
+ : "Content-type: message/rfc822\n\n",
+ f);
fflush(f);
transport_filter_argv = NULL; /* Just in case */
(void)fclose(emf);
fprintf(f, "\n--%s--\n", bound);
-#endif /*EXPERIMENTAL_DSN*/
/* Close the file, which should send an EOF to the child process
that is receiving the message. Wait for it to finish. */
"msglog.OLD directory", spoolname);
}
else
- {
if (Uunlink(spoolname) < 0)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to unlink %s: %s",
spoolname, strerror(errno));
- }
}
/* Remove the two message files. */
if (deliver_domain != NULL)
{
- uschar *d = (testflag(addr, af_pfr))? addr->parent->domain : addr->domain;
+ const uschar *d = testflag(addr, af_pfr)
+ ? addr->parent->domain : addr->domain;
/* The domain may be unset for an address that has never been routed
because the system filter froze the message. */
is not sent. Another attempt will be made at the next delivery attempt (if
it also defers). */
- if (!queue_2stage && delivery_attempted &&
-#ifdef EXPERIMENTAL_DSN
- (((addr_defer->dsn_flags & rf_dsnflags) == 0) ||
- (addr_defer->dsn_flags & rf_notify_delay) == rf_notify_delay) &&
-#endif
- delay_warning[1] > 0 && sender_address[0] != 0 &&
- (delay_warning_condition == NULL ||
- expand_check_condition(delay_warning_condition,
- US"delay_warning", US"option")))
+ if ( !queue_2stage
+ && delivery_attempted
+ && ( ((addr_defer->dsn_flags & rf_dsnflags) == 0)
+ || (addr_defer->dsn_flags & rf_notify_delay) == rf_notify_delay
+ )
+ && delay_warning[1] > 0
+ && sender_address[0] != 0
+ && ( delay_warning_condition == NULL
+ || expand_check_condition(delay_warning_condition,
+ US"delay_warning", US"option")
+ )
+ )
{
int count;
int show_time;
uschar *wmf_text;
FILE *wmf = NULL;
FILE *f = fdopen(fd, "wb");
-#ifdef EXPERIMENTAL_DSN
uschar * bound;
-#endif
if (warn_message_file)
{
moan_write_from(f);
fprintf(f, "To: %s\n", recipients);
-#ifdef EXPERIMENTAL_DSN
/* generated boundary string and output MIME-Headers */
bound = string_sprintf(TIME_T_FMT "-eximdsn-%d", time(NULL), rand());
" report-type=delivery-status; boundary=%s\n"
"MIME-Version: 1.0\n",
bound);
-#endif
if ((wmf_text = next_emf(wmf, US"header")))
fprintf(f, "%s\n", wmf_text);
fprintf(f, "Subject: Warning: message %s delayed %s\n\n",
message_id, warnmsg_delay);
-#ifdef EXPERIMENTAL_DSN
/* output human readable part as text/plain section */
fprintf(f, "--%s\n"
"Content-type: text/plain; charset=us-ascii\n\n",
bound);
-#endif
if ((wmf_text = next_emf(wmf, US"intro")))
fprintf(f, "%s", CS wmf_text);
/* List the addresses, with error information if allowed */
-#ifdef EXPERIMENTAL_DSN
/* store addr_defer for machine readable part */
address_item *addr_dsndefer = addr_defer;
-#endif
fputc('\n', f);
while (addr_defer)
{
"and when that happens, the message will be returned to you.\n");
}
-#ifdef EXPERIMENTAL_DSN
/* output machine readable part */
fprintf(f, "\n--%s\n"
"Content-type: message/delivery-status\n\n"
}
fputc('\n', f);
- while (addr_dsndefer)
+ for ( ; addr_dsndefer; addr_dsndefer = addr_dsndefer->next)
{
if (addr_dsndefer->dsn_orcpt)
- fprintf(f,"Original-Recipient: %s\n", addr_dsndefer->dsn_orcpt);
+ fprintf(f, "Original-Recipient: %s\n", addr_dsndefer->dsn_orcpt);
- fprintf(f,"Action: delayed\n");
- fprintf(f,"Final-Recipient: rfc822;%s\n", addr_dsndefer->address);
- fprintf(f,"Status: 4.0.0\n");
+ 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)
{
- fprintf(f,"Remote-MTA: dns; %s\n",
+ fprintf(f, "Remote-MTA: dns; %s\n",
addr_dsndefer->host_used->name);
print_dsn_diagnostic_code(addr_dsndefer, f);
}
- addr_dsndefer = addr_dsndefer->next;
+ fputc('\n', f);
}
- fprintf(f, "\n--%s\n"
+ fprintf(f, "--%s\n"
"Content-type: text/rfc822-headers\n\n",
bound);
fprintf(f,"\n--%s--\n", bound);
fflush(f);
-#endif /*EXPERIMENTAL_DSN*/
/* Close and wait for child process to complete, without a timeout.
If there's an error, don't update the count. */
return final_yield;
}
+
+
+void
+deliver_init(void)
+{
+if (!regex_PIPELINING) regex_PIPELINING =
+ regex_must_compile(US"\\n250[\\s\\-]PIPELINING(\\s|\\n|$)", FALSE, TRUE);
+
+if (!regex_SIZE) regex_SIZE =
+ regex_must_compile(US"\\n250[\\s\\-]SIZE(\\s|\\n|$)", FALSE, TRUE);
+
+if (!regex_AUTH) regex_AUTH =
+ regex_must_compile(US"\\n250[\\s\\-]AUTH\\s+([\\-\\w\\s]+)(?:\\n|$)",
+ FALSE, TRUE);
+
+#ifdef SUPPORT_TLS
+if (!regex_STARTTLS) regex_STARTTLS =
+ regex_must_compile(US"\\n250[\\s\\-]STARTTLS(\\s|\\n|$)", FALSE, TRUE);
+#endif
+
+#ifndef DISABLE_PRDR
+if (!regex_PRDR) regex_PRDR =
+ regex_must_compile(US"\\n250[\\s\\-]PRDR(\\s|\\n|$)", FALSE, TRUE);
+#endif
+
+if (!regex_DSN) regex_DSN =
+ regex_must_compile(US"\\n250[\\s\\-]DSN(\\s|\\n|$)", FALSE, TRUE);
+
+if (!regex_IGNOREQUOTA) regex_IGNOREQUOTA =
+ regex_must_compile(US"\\n250[\\s\\-]IGNOREQUOTA(\\s|\\n|$)", FALSE, TRUE);
+}
+
+
+uschar *
+deliver_get_sender_address (uschar * id)
+{
+if (!spool_open_datafile(id))
+ return NULL;
+
+sprintf(CS spoolname, "%s-H", id);
+if (spool_read_header(spoolname, TRUE, TRUE) != spool_read_OK)
+ return NULL;
+
+(void)close(deliver_datafile);
+deliver_datafile = -1;
+
+return sender_address;
+}
+
/* vi: aw ai sw=2
*/
/* End of deliver.c */