if (addr->host_list == NULL)
{
deliver_host = deliver_host_address = US"";
+ deliver_host_port = 0;
}
else
{
deliver_host = addr->host_list->name;
deliver_host_address = addr->host_list->address;
+ deliver_host_port = addr->host_list->port;
}
deliver_recipients = addr;
}
#endif
+
+
+
+#ifdef EXPERIMENTAL_TPDA
+int
+tpda_raise_event(uschar * action, uschar * event, uschar * ev_data)
+{
+uschar * s;
+if (action)
+ {
+ DEBUG(D_deliver)
+ debug_printf("TPDA(%s): tpda_event_action=|%s| tpda_delivery_IP=%s\n",
+ event,
+ action, deliver_host_address);
+
+ tpda_event = event;
+ tpda_data = ev_data;
+
+ if (!(s = expand_string(action)) && *expand_string_message)
+ log_write(0, LOG_MAIN|LOG_PANIC,
+ "failed to expand tpda_event_action %s in %s: %s\n",
+ event, transport_name, expand_string_message);
+
+ tpda_event = tpda_data = NULL;
+
+ /* If the expansion returns anything but an empty string, flag for
+ the caller to modify his normal processing
+ */
+ if (s && *s)
+ {
+ DEBUG(D_deliver)
+ debug_printf("TPDA(%s): event_action returned \"%s\"\n", s);
+ return DEFER;
+ }
+ }
+return OK;
+}
+
+static void
+tpda_msg_event(uschar * event, address_item * addr)
+{
+uschar * save_domain = deliver_domain;
+uschar * save_local = deliver_localpart;
+
+if (!addr->transport)
+ return;
+
+router_name = addr->router ? addr->router->name : NULL;
+transport_name = addr->transport->name;
+deliver_domain = addr->domain;
+deliver_localpart = addr->local_part;
+
+(void) tpda_raise_event(addr->transport->tpda_event_action, event,
+ addr->host_used || Ustrcmp(addr->transport->driver_name, "lmtp") == 0
+ ? addr->message : NULL);
+
+deliver_localpart = save_local;
+deliver_domain = save_domain;
+router_name = transport_name = NULL;
+}
+#endif /*EXPERIMENTAL_TPDA*/
+
+
+
/* If msg is NULL this is a delivery log and logchar is used. Otherwise
this is a nonstandard call; no two-character delivery flag is written
but sender-host and sender are prefixed and "msg" is inserted in the log line.
pointer to a single host item in their host list, for use by the transport. */
#ifdef EXPERIMENTAL_TPDA
- tpda_delivery_ip = NULL; /* presume no successful remote delivery */
- tpda_delivery_port = 0;
- tpda_delivery_fqdn = NULL;
- tpda_delivery_local_part = NULL;
- tpda_delivery_domain = NULL;
- tpda_delivery_confirmation = NULL;
+ /* presume no successful remote delivery */
lookup_dnssec_authenticated = NULL;
#endif
if (addr->transport->info->local)
{
- if (addr->host_list != NULL)
- {
+ if (addr->host_list)
s = string_append(s, &size, &ptr, 2, US" H=", addr->host_list->name);
- #ifdef EXPERIMENTAL_TPDA
- tpda_delivery_fqdn = addr->host_list->name;
- #endif
- }
if (addr->shadow_message != NULL)
s = string_cat(s, &size, &ptr, addr->shadow_message,
Ustrlen(addr->shadow_message));
if (continue_sequence > 1)
s = string_cat(s, &size, &ptr, US"*", 1);
- #ifdef EXPERIMENTAL_TPDA
- tpda_delivery_ip = addr->host_used->address;
- tpda_delivery_port = addr->host_used->port;
- tpda_delivery_fqdn = addr->host_used->name;
- tpda_delivery_local_part = addr->local_part;
- tpda_delivery_domain = addr->domain;
- tpda_delivery_confirmation = addr->message;
+#ifdef EXPERIMENTAL_TPDA
+ deliver_host_address = addr->host_used->address;
+ deliver_host_port = addr->host_used->port;
/* DNS lookup status */
lookup_dnssec_authenticated = addr->host_used->dnssec==DS_YES ? US"yes"
: addr->host_used->dnssec==DS_NO ? US"no"
: NULL;
- #endif
+#endif
}
- #ifdef SUPPORT_TLS
+#ifdef SUPPORT_TLS
s = d_tlslog(s, &size, &ptr, addr);
- #endif
+#endif
if (addr->authenticator)
{
}
}
- #ifndef DISABLE_PRDR
+#ifndef DISABLE_PRDR
if (addr->flags & af_prdr_used)
s = string_append(s, &size, &ptr, 1, US" PRDR");
- #endif
+#endif
}
/* confirmation message (SMTP (host_used) and LMTP (driver_name)) */
-if ((log_extra_selector & LX_smtp_confirmation) != 0 &&
- addr->message != NULL &&
- ((addr->host_used != NULL) || (Ustrcmp(addr->transport->driver_name, "lmtp") == 0)))
+if (log_extra_selector & LX_smtp_confirmation &&
+ addr->message &&
+ (addr->host_used || Ustrcmp(addr->transport->driver_name, "lmtp") == 0))
{
int i;
uschar *p = big_buffer;
uschar *ss = addr->message;
*p++ = '\"';
- for (i = 0; i < 100 && ss[i] != 0; i++)
+ for (i = 0; i < 256 && ss[i] != 0; i++) /* limit logged amount */
{
- if (ss[i] == '\"' || ss[i] == '\\') *p++ = '\\';
+ if (ss[i] == '\"' || ss[i] == '\\') *p++ = '\\'; /* quote \ and " */
*p++ = ss[i];
}
*p++ = '\"';
/* Time on queue and actual time taken to deliver */
if ((log_extra_selector & LX_queue_time) != 0)
- {
s = string_append(s, &size, &ptr, 2, US" QT=",
- readconf_printtime(time(NULL) - received_time));
- }
+ readconf_printtime( (int) ((long)time(NULL) - (long)received_time)) );
if ((log_extra_selector & LX_deliver_time) != 0)
- {
s = string_append(s, &size, &ptr, 2, US" DT=",
readconf_printtime(addr->more_errno));
- }
/* 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", s);
#ifdef EXPERIMENTAL_TPDA
-if (addr->transport->tpda_delivery_action)
- {
- DEBUG(D_deliver)
- debug_printf(" TPDA(Delivery): tpda_deliver_action=|%s| tpda_delivery_IP=%s\n",
- addr->transport->tpda_delivery_action, tpda_delivery_ip);
-
- router_name = addr->router->name;
- transport_name = addr->transport->name;
- if (!expand_string(addr->transport->tpda_delivery_action) && *expand_string_message)
- log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand tpda_deliver_action in %s: %s\n",
- transport_name, expand_string_message);
- router_name = NULL;
- transport_name = NULL;
- }
+/*XXX cutthrough calls this also for non-delivery...*/
+tpda_msg_event(US"msg:delivery", addr);
#endif
+
store_reset(reset_point);
return;
}
}
/* Certificates for logging (via TPDA) */
- #ifdef SUPPORT_TLS
+#ifdef SUPPORT_TLS
tls_out.ourcert = addr->ourcert;
addr->ourcert = NULL;
tls_out.peercert = addr->peercert;
tls_out.cipher = addr->cipher;
tls_out.peerdn = addr->peerdn;
tls_out.ocsp = addr->ocsp;
- #endif
+#endif
delivery_log(LOG_MAIN, addr, logchar, NULL);
- #ifdef SUPPORT_TLS
+#ifdef SUPPORT_TLS
if (tls_out.ourcert)
{
tls_free_cert(tls_out.ourcert);
tls_out.cipher = NULL;
tls_out.peerdn = NULL;
tls_out.ocsp = OCSP_NOT_REQ;
- #endif
+#endif
}
if (addr->host_used != NULL)
s = d_hostlog(s, &size, &ptr, addr);
- #ifdef SUPPORT_TLS
+#ifdef SUPPORT_TLS
s = d_tlslog(s, &size, &ptr, addr);
- #endif
+#endif
if (addr->basic_errno > 0)
s = string_append(s, &size, &ptr, 2, US": ",
deliver_msglog("%s %s\n", now, s);
log_write(0, LOG_MAIN, "** %s", s);
+
+#ifdef EXPERIMENTAL_TPDA
+ tpda_msg_event(US"msg:fail:delivery", addr);
+#endif
+
store_reset(reset_point);
}
diagnosis that it's reasonable to make them something that has to be explicitly requested.
*/
- #ifdef RLIMIT_CORE
+#ifdef RLIMIT_CORE
struct rlimit rl;
rl.rlim_cur = 0;
rl.rlim_max = 0;
if (setrlimit(RLIMIT_CORE, &rl) < 0)
{
- #ifdef SETRLIMIT_NOT_SUPPORTED
+# ifdef SETRLIMIT_NOT_SUPPORTED
if (errno != ENOSYS && errno != ENOTSUP)
- #endif
+# endif
log_write(0, LOG_MAIN|LOG_PANIC, "setrlimit(RLIMIT_CORE) failed: %s",
strerror(errno));
}
- #endif
+#endif
/* Reset the random number generator, so different processes don't all
have the same sequence. */
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
+#ifdef SUPPORT_TLS
case 'X':
if (addr == NULL) goto ADDR_MISMATCH; /* Below, in 'A' handler */
switch (*ptr++)
(void) tls_import_cert(ptr, &addr->ourcert);
break;
- #ifndef DISABLE_OCSP
+# ifndef DISABLE_OCSP
case '4':
addr->ocsp = OCSP_NOT_REQ;
if (*ptr)
addr->ocsp = *ptr - '0';
break;
- #endif
+# endif
}
while (*ptr++);
break;
- #endif /*SUPPORT_TLS*/
+#endif /*SUPPORT_TLS*/
case 'C': /* client authenticator information */
switch (*ptr++)
break;
#endif
- #ifdef EXPERIMENTAL_DSN
+#ifdef EXPERIMENTAL_DSN
case 'D':
if (addr == NULL) break;
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
+#endif
case 'A':
if (addr == NULL)
that it can use either of them, though it prefers O_NONBLOCK, which
distinguishes between EOF and no-more-data. */
- #ifdef O_NONBLOCK
+#ifdef O_NONBLOCK
(void)fcntl(pfd[pipe_read], F_SETFL, O_NONBLOCK);
- #else
+#else
(void)fcntl(pfd[pipe_read], F_SETFL, O_NDELAY);
- #endif
+#endif
/* If the maximum number of subprocesses already exist, wait for a process
to finish. If we ran out of file descriptors, parmax will have been reduced
if (tls_out.certificate_verified) setflag(addr, af_cert_verified);
/* Use an X item only if there's something to send */
- #ifdef SUPPORT_TLS
+#ifdef SUPPORT_TLS
if (addr->cipher)
{
ptr = big_buffer;
*ptr++ = 0;
rmt_dlv_checked_write(fd, big_buffer, ptr - big_buffer);
}
- #ifndef DISABLE_OCSP
+# ifndef DISABLE_OCSP
if (addr->ocsp > OCSP_NOT_REQ)
{
ptr = big_buffer;
while(*ptr++);
rmt_dlv_checked_write(fd, big_buffer, ptr - big_buffer);
}
- # endif
- #endif /*SUPPORT_TLS*/
+# endif
+#endif /*SUPPORT_TLS*/
if (client_authenticator)
{
rmt_dlv_checked_write(fd, big_buffer, ptr - big_buffer);
}
- #ifndef DISABLE_PRDR
+#ifndef DISABLE_PRDR
if (addr->flags & af_prdr_used)
rmt_dlv_checked_write(fd, "P", 1);
- #endif
+#endif
- #ifdef EXPERIMENTAL_DSN
+#ifdef EXPERIMENTAL_DSN
big_buffer[0] = 'D';
memcpy(big_buffer+1, &addr->dsn_aware, sizeof(addr->dsn_aware));
rmt_dlv_checked_write(fd, big_buffer, sizeof(addr->dsn_aware) + 1);
DEBUG(D_deliver) debug_printf("DSN write: addr->dsn_aware = %d\n", addr->dsn_aware);
- #endif
+#endif
/* Retry information: for most success cases this will be null. */
if (deliver_freeze)
{
- #ifdef SUPPORT_MOVE_FROZEN_MESSAGES
+#ifdef SUPPORT_MOVE_FROZEN_MESSAGES
/* Moving to another directory removes the message from Exim's view. Other
tools must be used to deal with it. Logging of this action happens in
spool_move_message() and its subfunctions. */
if (move_frozen_messages &&
spool_move_message(id, message_subdir, US"", US"F"))
return continue_closedown(); /* yields DELIVER_NOT_ATTEMPTED */
- #endif
+#endif
/* For all frozen messages (bounces or not), timeout_frozen_after sets the
maximum time to keep messages that are frozen. Thaw if we reach it, with a
if (r->pno >= 0)
new->onetime_parent = recipients_list[r->pno].address;
- #ifdef EXPERIMENTAL_DSN
+#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
+#endif
switch (process_recipients)
{
addr_last = new;
break;
}
+
+#ifdef EXPERIMENTAL_TPDA
+ if (process_recipients != RECIP_ACCEPT)
+ {
+ uschar * save_local = deliver_localpart;
+ uschar * save_domain = deliver_domain;
+
+ deliver_localpart = expand_string(
+ string_sprintf("${local_part:%s}", new->address));
+ deliver_domain = expand_string(
+ string_sprintf("${domain:%s}", new->address));
+
+ (void) tpda_raise_event(delivery_event_action,
+ US"msg:fail:internal", new->message);
+
+ deliver_localpart = save_local;
+ deliver_domain = save_domain;
+ }
+#endif
}
}
}
regex_must_compile(US"\\n250[\\s\\-]AUTH\\s+([\\-\\w\\s]+)(?:\\n|$)",
FALSE, TRUE);
- #ifdef SUPPORT_TLS
+#ifdef SUPPORT_TLS
if (regex_STARTTLS == NULL) regex_STARTTLS =
regex_must_compile(US"\\n250[\\s\\-]STARTTLS(\\s|\\n|$)", FALSE, TRUE);
- #endif
+#endif
- #ifndef DISABLE_PRDR
+#ifndef DISABLE_PRDR
if (regex_PRDR == NULL) regex_PRDR =
regex_must_compile(US"\\n250[\\s\\-]PRDR(\\s|\\n|$)", FALSE, TRUE);
- #endif
+#endif
- #ifdef EXPERIMENTAL_DSN
+#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
+#endif
/* 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
DEBUG(D_deliver) debug_printf("sending error message to: %s\n", sender_address);
/* build unique id for MIME boundary */
- snprintf(boundaryStr, 63, "%d-eximdsn-%d", time(NULL), rand());
+ snprintf(boundaryStr, sizeof(boundaryStr)-1, TIME_T_FMT "-eximdsn-%d",
+ time(NULL), rand());
DEBUG(D_deliver) debug_printf("DSN: MIME boundary: %s\n", boundaryStr);
- if (errors_reply_to != NULL) fprintf(f,"Reply-To: %s\n", errors_reply_to);
+ if (errors_reply_to)
+ fprintf(f, "Reply-To: %s\n", errors_reply_to);
- fprintf(f,"Auto-Submitted: auto-generated\n");
- fprintf(f,"From: Mail Delivery System <Mailer-Daemon@%s>\n", qualify_domain_sender);
- fprintf(f,"To: %s\n", sender_address);
- fprintf(f,"Subject: Delivery Status Notification\n");
- fprintf(f,"Content-Type: multipart/report; report-type=delivery-status; boundary=%s\n", boundaryStr);
- fprintf(f,"MIME-Version: 1.0\n\n");
-
- fprintf(f,"--%s\n", boundaryStr);
- fprintf(f,"Content-type: text/plain; charset=us-ascii\n\n");
+ 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"
+ "MIME-Version: 1.0\n\n"
+
+ "--%s\n"
+ "Content-type: text/plain; charset=us-ascii\n\n"
- fprintf(f,"This message was created automatically by mail delivery software.\n");
- fprintf(f," ----- The following addresses had successful delivery notifications -----\n");
+ "This message was created automatically by mail delivery software.\n"
+ " ----- The following addresses had successful delivery notifications -----\n",
+ qualify_domain_sender, sender_address, boundaryStr, boundaryStr);
addr_dsntmp = addr_senddsn;
- while(addr_dsntmp != NULL)
+ while(addr_dsntmp)
{
- if ((addr_dsntmp->dsn_flags & rf_dsnlasthop) == 1) {
- fprintf(f,"<%s> (relayed via non DSN router)\n\n", addr_dsntmp->address);
- }
- else if (addr_dsntmp->dsn_aware == dsn_support_no) {
- fprintf(f,"<%s> (relayed to non-DSN-aware mailer)\n\n", addr_dsntmp->address);
- }
- else {
- fprintf(f,"<%s> (relayed via non \"Remote SMTP\" router)\n\n", addr_dsntmp->address);
- }
+ fprintf(f, "<%s> (relayed %s)\n\n",
+ addr_dsntmp->address,
+ (addr_dsntmp->dsn_flags & rf_dsnlasthop) == 1
+ ? "via non DSN router"
+ : addr_dsntmp->dsn_aware == dsn_support_no
+ ? "to non-DSN-aware mailer"
+ : "via non \"Remote SMTP\" router"
+ );
addr_dsntmp = addr_dsntmp->next;
}
- fprintf(f,"--%s\n", boundaryStr);
- fprintf(f,"Content-type: message/delivery-status\n\n");
-
- fprintf(f,"Reporting-MTA: dns; %s\n", smtp_active_hostname);
+ fprintf(f, "--%s\n"
+ "Content-type: message/delivery-status\n\n"
+ "Reporting-MTA: dns; %s\n",
+ boundaryStr, smtp_active_hostname);
+
if (dsn_envid != NULL) {
/* 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);
+ fprintf(f, "Original-Envelope-ID: %s\n", dsn_envid);
else
- fprintf(f,"X-Original-Envelope-ID: error decoding xtext formated ENVID\n");
+ fprintf(f, "X-Original-Envelope-ID: error decoding xtext formated ENVID\n");
}
- fprintf(f,"\n");
+ fputc('\n', f);
- addr_dsntmp = addr_senddsn;
- while(addr_dsntmp != NULL)
+ for (addr_dsntmp = addr_senddsn;
+ addr_dsntmp;
+ addr_dsntmp = addr_dsntmp->next)
{
- if (addr_dsntmp->dsn_orcpt != NULL) {
+ if (addr_dsntmp->dsn_orcpt)
fprintf(f,"Original-Recipient: %s\n", addr_dsntmp->dsn_orcpt);
- }
- fprintf(f,"Action: delivered\n");
- fprintf(f,"Final-Recipient: rfc822;%s\n", addr_dsntmp->address);
- fprintf(f,"Status: 2.0.0\n");
- if ((addr_dsntmp->host_used != NULL) && (addr_dsntmp->host_used->name != NULL))
- fprintf(f,"Remote-MTA: dns; %s\nDiagnostic-Code: smtp; 250 Ok\n", addr_dsntmp->host_used->name);
+
+ fprintf(f, "Action: delivered\n"
+ "Final-Recipient: rfc822;%s\n"
+ "Status: 2.0.0\n",
+ 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",
+ addr_dsntmp->host_used->name);
else
- if ((addr_dsntmp->dsn_flags & rf_dsnlasthop) == 1)
- fprintf(f,"Diagnostic-Code: X-Exim; relayed via non DSN router\n");
- else
- fprintf(f,"Diagnostic-Code: X-Exim; relayed via non SMTP router\n");
- fprintf(f,"\n");
- addr_dsntmp = addr_dsntmp->next;
+ fprintf(f,"Diagnostic-Code: X-Exim; relayed via non %s router\n",
+ (addr_dsntmp->dsn_flags & rf_dsnlasthop) == 1 ? "DSN" : "SMTP");
+ fputc('\n', f);
}
- fprintf(f,"--%s\n", boundaryStr);
- fprintf(f,"Content-type: text/rfc822-headers\n\n");
+ fprintf(f, "--%s\nContent-type: text/rfc822-headers\n\n", boundaryStr);
fflush(f);
transport_filter_argv = NULL; /* Just in case */
rc = child_close(pid, 0); /* Waits for child to close, no timeout */
}
}
-#endif
+#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
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 boundaryStr[64];
+ uschar *dsnlimitmsg;
+ uschar *dsnnotifyhdr;
+ int topt;
+#endif
DEBUG(D_deliver)
debug_printf("sending error message to: %s\n", bounce_recipient);
#ifdef EXPERIMENTAL_DSN
/* generate boundary string and output MIME-Headers */
- uschar boundaryStr[64];
- snprintf(boundaryStr, 63, "%d-eximdsn-%d", time(NULL), rand());
- fprintf(f,"Content-Type: multipart/report; report-type=delivery-status; boundary=%s\n", boundaryStr);
- fprintf(f,"MIME-Version: 1.0\n");
+ snprintf(boundaryStr, sizeof(boundaryStr)-1, TIME_T_FMT "-eximdsn-%d",
+ time(NULL), rand());
+
+ fprintf(f, "Content-Type: multipart/report;"
+ " report-type=delivery-status; boundary=%s\n"
+ "MIME-Version: 1.0\n",
+ boundaryStr);
#endif
/* Open a template file if one is provided. Log failure to open, but
carry on - default texts will be used. */
- if (bounce_message_file != NULL)
- {
- emf = Ufopen(bounce_message_file, "rb");
- if (emf == NULL)
+ if (bounce_message_file)
+ if (!(emf = Ufopen(bounce_message_file, "rb")))
log_write(0, LOG_MAIN|LOG_PANIC, "Failed to open %s for error "
"message texts: %s", bounce_message_file, strerror(errno));
- }
/* Quietly copy to configured additional addresses if required. */
- bcc = moan_check_errorcopy(bounce_recipient);
- if (bcc != NULL) fprintf(f, "Bcc: %s\n", bcc);
+ if ((bcc = moan_check_errorcopy(bounce_recipient)))
+ fprintf(f, "Bcc: %s\n", bcc);
/* The texts for the message can be read from a template file; if there
isn't one, or if it is too short, built-in texts are used. The first
emf text is a Subject: and any other headers. */
- emf_text = next_emf(emf, US"header");
- if (emf_text != NULL) fprintf(f, "%s\n", emf_text); else
- {
+ if ((emf_text = next_emf(emf, US"header")))
+ fprintf(f, "%s\n", emf_text);
+ else
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", boundaryStr);
- fprintf(f,"Content-type: text/plain; charset=us-ascii\n\n");
+ fprintf(f, "--%s\n"
+ "Content-type: text/plain; charset=us-ascii\n\n",
+ boundaryStr);
#endif
- emf_text = next_emf(emf, US"intro");
- if (emf_text != NULL) fprintf(f, "%s", CS emf_text); else
+ if ((emf_text = next_emf(emf, US"intro")))
+ fprintf(f, "%s", CS emf_text);
+ else
{
fprintf(f,
/* This message has been reworded several times. It seems to be confusing to
somebody, however it is worded. I have retreated to the original, simple
wording. */
"This message was created automatically by mail delivery software.\n");
- if (bounce_message_text != NULL) fprintf(f, "%s", CS bounce_message_text);
+
+ if (bounce_message_text)
+ fprintf(f, "%s", CS bounce_message_text);
if (to_sender)
- {
fprintf(f,
"\nA message that you sent could not be delivered to one or more of its\n"
"recipients. This is a permanent error. The following address(es) failed:\n");
- }
else
- {
fprintf(f,
"\nA message sent by\n\n <%s>\n\n"
"could not be delivered to one or more of its recipients. The following\n"
"address(es) failed:\n", sender_address);
- }
}
- fprintf(f, "\n");
+ fputc('\n', f);
/* 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
}
}
- fprintf(f, "\n");
+ fputc('\n', f);
/* Get the next text, whether we need it or not, so as to be
positioned for the one after. */
fd, and the return_filename field in the *last* one will be set (to the
name of the file). */
- if (msgchain != NULL)
+ if (msgchain)
{
address_item *nextaddr;
- if (emf_text != NULL) fprintf(f, "%s", CS emf_text); else
+ if (emf_text)
+ fprintf(f, "%s", CS emf_text);
+ else
fprintf(f,
"The following text was generated during the delivery "
"attempt%s:\n", (filecount > 1)? "s" : "");
/* List all the addresses that relate to this file */
- fprintf(f, "\n");
- while(addr != NULL) /* Insurance */
+ fputc('\n', f);
+ while(addr) /* Insurance */
{
print_address_information(addr, f, US"------ ", US"\n ",
US" ------\n");
- if (addr->return_filename != NULL) break;
+ if (addr->return_filename) break;
addr = addr->next;
}
- fprintf(f, "\n");
+ fputc('\n', f);
/* Now copy the file */
addr->next = handled_addr;
handled_addr = topaddr;
}
- fprintf(f, "\n");
+ fputc('\n', f);
}
#ifdef EXPERIMENTAL_DSN
/* output machine readable part */
- fprintf(f,"--%s\n", boundaryStr);
- fprintf(f,"Content-type: message/delivery-status\n\n");
-
- fprintf(f,"Reporting-MTA: dns; %s\n", smtp_active_hostname);
- if (dsn_envid != NULL) {
+ fprintf(f, "--%s\n"
+ "Content-type: message/delivery-status\n\n"
+ "Reporting-MTA: dns; %s\n",
+ boundaryStr, smtp_active_hostname);
+
+ 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);
+ fprintf(f, "Original-Envelope-ID: %s\n", dsn_envid);
else
- fprintf(f,"X-Original-Envelope-ID: error decoding xtext formated ENVID\n");
+ fprintf(f, "X-Original-Envelope-ID: error decoding xtext formated ENVID\n");
}
- fprintf(f,"\n");
+ fputc('\n', f);
- for (addr = handled_addr; addr != NULL; addr = addr->next)
+ for (addr = handled_addr; addr; addr = addr->next)
{
- fprintf(f,"Action: failed\n");
- fprintf(f,"Final-Recipient: rfc822;%s\n", addr->address);
- fprintf(f,"Status: 5.0.0\n");
- if ((addr->host_used != NULL) && (addr->host_used->name != NULL))
- fprintf(f,"Remote-MTA: dns; %s\nDiagnostic-Code: smtp; %d\n", addr->host_used->name, addr->basic_errno);
+ fprintf(f, "Action: failed\n"
+ "Final-Recipient: rfc822;%s\n"
+ "Status: 5.0.0\n",
+ addr->address);
+ if (addr->host_used && addr->host_used->name)
+ fprintf(f, "Remote-MTA: dns; %s\nDiagnostic-Code: smtp; %d\n",
+ addr->host_used->name, addr->basic_errno);
}
#endif
int topt = topt_add_return_path;
if (!bounce_return_body) topt |= topt_no_body;
- if (emf_text != NULL) fprintf(f, "%s", CS emf_text); else
+ 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");
{
struct stat statbuf;
if (fstat(deliver_datafile, &statbuf) == 0 && statbuf.st_size > max)
- {
- if (emf_text != NULL) fprintf(f, "%s", CS emf_text); else
- {
+ 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);
- }
- }
}
- fprintf(f, "\n");
+ 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,
/* Write final text and close the template file if one is open */
- if (emf != NULL)
+ if (emf)
{
- emf_text = next_emf(emf, US"final");
- if (emf_text != NULL) fprintf(f, "%s", CS emf_text);
+ if ((emf_text = next_emf(emf, US"final")))
+ fprintf(f, "%s", CS emf_text);
(void)fclose(emf);
}
#else
bounce_return_size_limit is always honored.
*/
- fprintf(f,"\n--%s\n", boundaryStr);
+ fprintf(f, "\n--%s\n", boundaryStr);
+
+ dsnlimitmsg = US"X-Exim-DSN-Information: Due to administrative limits only headers are returned";
+ dsnnotifyhdr = NULL;
+ topt = topt_add_return_path;
- uschar *dsnlimitmsg = US"X-Exim-DSN-Information: Due to administrative limits only headers are returned";
- uschar *dsnnotifyhdr = NULL;
- int topt = topt_add_return_path;
/* RET=HDRS? top priority */
if (dsn_ret == dsn_ret_hdrs)
topt |= topt_no_body;
fflush(f);
/* we never add the final text. close the file */
- if (emf != NULL)
+ if (emf)
(void)fclose(emf);
- fprintf(f,"\n");
- fprintf(f,"--%s--\n", boundaryStr);
-#endif
+ fprintf(f, "\n--%s--\n", boundaryStr);
+#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. */
if ((log_extra_selector & LX_queue_time_overall) != 0)
log_write(0, LOG_MAIN, "Completed QT=%s",
- readconf_printtime(time(NULL) - received_time));
+ readconf_printtime( (int) ((long)time(NULL) - (long)received_time)) );
else
log_write(0, LOG_MAIN, "Completed");
/* Unset deliver_freeze so that we won't try to move the spool files further down */
deliver_freeze = FALSE;
- }
+
+#ifdef EXPERIMENTAL_TPDA
+ (void) tpda_raise_event(delivery_event_action, US"msg:complete", NULL);
+#endif
+}
/* If there are deferred addresses, we are keeping this message because it is
not yet completed. Lose any temporary files that were catching output from
uschar *wmf_text;
FILE *wmf = NULL;
FILE *f = fdopen(fd, "wb");
+#ifdef EXPERIMENTAL_DSN
+ uschar boundaryStr[64];
+#endif
- if (warn_message_file != NULL)
+ if (warn_message_file)
{
wmf = Ufopen(warn_message_file, "rb");
if (wmf == NULL)
string_sprintf("%d minutes", show_time/60):
string_sprintf("%d hours", show_time/3600);
- 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);
#ifdef EXPERIMENTAL_DSN
/* generated boundary string and output MIME-Headers */
- uschar boundaryStr[64];
- snprintf(boundaryStr, 63, "%d-eximdsn-%d", time(NULL), rand());
- fprintf(f,"Content-Type: multipart/report; report-type=delivery-status; boundary=%s\n", boundaryStr);
- fprintf(f,"MIME-Version: 1.0\n");
+ snprintf(boundaryStr, sizeof(boundaryStr)-1,
+ TIME_T_FMT "-eximdsn-%d", time(NULL), rand());
+
+ fprintf(f, "Content-Type: multipart/report;"
+ " report-type=delivery-status; boundary=%s\n"
+ "MIME-Version: 1.0\n",
+ boundaryStr);
#endif
- wmf_text = next_emf(wmf, US"header");
- if (wmf_text != NULL)
+ if ((wmf_text = next_emf(wmf, US"header")))
fprintf(f, "%s\n", wmf_text);
else
fprintf(f, "Subject: Warning: message %s delayed %s\n\n",
#ifdef EXPERIMENTAL_DSN
/* output human readable part as text/plain section */
- fprintf(f,"--%s\n", boundaryStr);
- fprintf(f,"Content-type: text/plain; charset=us-ascii\n\n");
+ fprintf(f, "--%s\n"
+ "Content-type: text/plain; charset=us-ascii\n\n",
+ boundaryStr);
#endif
- wmf_text = next_emf(wmf, US"intro");
- if (wmf_text != NULL) fprintf(f, "%s", CS wmf_text); else
+ if ((wmf_text = next_emf(wmf, US"intro")))
+ fprintf(f, "%s", CS wmf_text);
+ else
{
fprintf(f,
"This message was created automatically by mail delivery software.\n");
"A message that you sent has not yet been delivered to one or more of its\n"
"recipients after more than ");
- else fprintf(f,
+ else
+ fprintf(f,
"A message sent by\n\n <%s>\n\n"
"has not yet been delivered to one or more of its recipients after more than \n",
- sender_address);
+ sender_address);
- fprintf(f, "%s on the queue on %s.\n\n", warnmsg_delay,
- primary_hostname);
- fprintf(f, "The message identifier is: %s\n", message_id);
+ fprintf(f, "%s on the queue on %s.\n\n"
+ "The message identifier is: %s\n",
+ warnmsg_delay, primary_hostname, message_id);
for (h = header_list; h != NULL; h = h->next)
- {
if (strncmpic(h->text, US"Subject:", 8) == 0)
fprintf(f, "The subject of the message is: %s", h->text + 9);
else if (strncmpic(h->text, US"Date:", 5) == 0)
fprintf(f, "The date of the message is: %s", h->text + 6);
- }
- fprintf(f, "\n");
+ fputc('\n', f);
fprintf(f, "The address%s to which the message has not yet been "
"delivered %s:\n",
- (addr_defer->next == NULL)? "" : "es",
- (addr_defer->next == NULL)? "is": "are");
+ !addr_defer->next ? "" : "es",
+ !addr_defer->next ? "is": "are");
}
/* List the addresses, with error information if allowed */
/* store addr_defer for machine readable part */
address_item *addr_dsndefer = addr_defer;
#endif
- fprintf(f, "\n");
- while (addr_defer != NULL)
+ fputc('\n', f);
+ while (addr_defer)
{
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: ");
- fprintf(f, "\n");
+ fputc('\n', f);
}
- fprintf(f, "\n");
+ fputc('\n', f);
/* Final text */
- if (wmf != NULL)
+ if (wmf)
{
- wmf_text = next_emf(wmf, US"final");
- if (wmf_text != NULL) fprintf(f, "%s", CS wmf_text);
+ if ((wmf_text = next_emf(wmf, US"final")))
+ fprintf(f, "%s", CS wmf_text);
(void)fclose(wmf);
}
else
#ifdef EXPERIMENTAL_DSN
/* output machine readable part */
- fprintf(f,"\n--%s\n", boundaryStr);
- fprintf(f,"Content-type: message/delivery-status\n\n");
+ fprintf(f, "\n--%s\n"
+ "Content-type: message/delivery-status\n\n"
+ "Reporting-MTA: dns; %s\n",
+ boundaryStr,
+ smtp_active_hostname);
- fprintf(f,"Reporting-MTA: dns; %s\n", smtp_active_hostname);
- if (dsn_envid != NULL) {
+
+ if (dsn_envid)
+ {
/* must be decoded from xtext: see RFC 3461:6.3a */
uschar *xdec_envid;
if (auth_xtextdecode(dsn_envid, &xdec_envid) > 0)
else
fprintf(f,"X-Original-Envelope-ID: error decoding xtext formated ENVID\n");
}
- fprintf(f,"\n");
+ fputc('\n', f);
- while (addr_dsndefer != NULL)
+ while (addr_dsndefer)
{
- if (addr_dsndefer->dsn_orcpt != NULL) {
+ if (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");
- if ((addr_dsndefer->host_used != NULL) && (addr_dsndefer->host_used->name != NULL))
+ if (addr_dsndefer->host_used && addr_dsndefer->host_used->name)
fprintf(f,"Remote-MTA: dns; %s\nDiagnostic-Code: smtp; %d\n",
- addr_dsndefer->host_used->name, addr_dsndefer->basic_errno);
+ addr_dsndefer->host_used->name, addr_dsndefer->basic_errno);
addr_dsndefer = addr_dsndefer->next;
}
- fprintf(f,"\n--%s\n", boundaryStr);
- fprintf(f,"Content-type: text/rfc822-headers\n\n");
+ fprintf(f, "\n--%s\n"
+ "Content-type: text/rfc822-headers\n\n",
+ boundaryStr);
fflush(f);
/* header only as required by RFC. only failure DSN needs to honor RET=FULL */
transport_write_message(NULL, fileno(f), topt, 0, NULL, NULL, NULL, NULL, NULL, 0);
fflush(f);
- fprintf(f,"\n");
- fprintf(f,"--%s--\n", boundaryStr);
+ fprintf(f,"\n--%s--\n", boundaryStr);
fflush(f);
-#endif
+#endif /*EXPERIMENTAL_DSN*/
/* Close and wait for child process to complete, without a timeout.
If there's an error, don't update the count. */
/* Move the message off the spool if reqested */
- #ifdef SUPPORT_MOVE_FROZEN_MESSAGES
+#ifdef SUPPORT_MOVE_FROZEN_MESSAGES
if (deliver_freeze && move_frozen_messages)
(void)spool_move_message(id, message_subdir, US"", US"F");
- #endif
+#endif
}
/* Closing the data file frees the lock; if the file has been unlinked it