if (!(s = expand_string(action)) && *expand_string_message)
log_write(0, LOG_MAIN|LOG_PANIC,
"failed to expand event_action %s in %s: %s\n",
- event, transport_name, expand_string_message);
+ event, transport_name ? transport_name : US"main", expand_string_message);
event_name = event_data = NULL;
const uschar * save_address = deliver_host_address;
const int save_port = deliver_host_port;
-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;
deliver_host = addr->host_used ? addr->host_used->name : NULL;
-(void) event_raise(addr->transport->event_action, event,
- addr->host_used
- || Ustrcmp(addr->transport->driver_name, "smtp") == 0
- || Ustrcmp(addr->transport->driver_name, "lmtp") == 0
- ? addr->message : NULL);
+if (!addr->transport)
+ {
+ if (Ustrcmp(event, "msg:fail:delivery") == 0)
+ {
+ /* An address failed with no transport involved. This happens when
+ a filter was used which triggered a fail command (in such a case
+ a transport isn't needed). Convert it to an internal fail event. */
+
+ (void) event_raise(event_action, US"msg:fail:internal", addr->message);
+ }
+ }
+else
+ {
+ transport_name = addr->transport->name;
+
+ (void) event_raise(addr->transport->event_action, event,
+ addr->host_used
+ || Ustrcmp(addr->transport->driver_name, "smtp") == 0
+ || Ustrcmp(addr->transport->driver_name, "lmtp") == 0
+ || Ustrcmp(addr->transport->driver_name, "autoreply") == 0
+ ? addr->message : NULL);
+ }
deliver_host_port = save_port;
deliver_host_address = save_address;
if (diff->tv_sec >= 5 || !LOGGING(millisec))
return readconf_printtime((int)diff->tv_sec);
-sprintf(CS buf, "%d.%03ds", (int)diff->tv_sec, (int)diff->tv_usec/1000);
+sprintf(CS buf, "%u.%03us", (uint)diff->tv_sec, (uint)diff->tv_usec/1000);
return buf;
}
void * reset_point;
gstring * g = reset_point = string_get(256);
+#ifndef DISABLE_EVENT
+/* Message failures for which we will send a DSN get their event raised
+later so avoid doing it here. */
+
+if ( !addr->prop.ignore_error
+ && !(addr->dsn_flags & (rf_dsnflags & ~rf_notify_failure))
+ )
+ msg_event_raise(US"msg:fail:delivery", addr);
+#endif
+
/* Build up the log line for the message and main logs */
/* Create the address string for logging. Must not do this earlier, because
log_write(0, LOG_MAIN, "** %s", g->s);
-#ifndef DISABLE_EVENT
-msg_event_raise(US"msg:fail:delivery", addr);
-#endif
-
store_reset(reset_point);
return;
}
/* RECIP_DEFER is set when a system filter freezes a message. */
case RECIP_DEFER:
- new->next = addr_defer;
- addr_defer = new;
- break;
+ new->next = addr_defer;
+ addr_defer = new;
+ break;
/* RECIP_FAIL_FILTER is set when a system filter has obeyed a "fail"
command. */
case RECIP_FAIL_FILTER:
- new->message =
- filter_message ? filter_message : US"delivery cancelled";
- setflag(new, af_pass_message);
- goto RECIP_QUEUE_FAILED; /* below */
+ new->message =
+ filter_message ? filter_message : US"delivery cancelled";
+ setflag(new, af_pass_message);
+ goto RECIP_QUEUE_FAILED; /* below */
/* RECIP_FAIL_TIMEOUT is set when a message is frozen, but is older
been logged. */
case RECIP_FAIL_TIMEOUT:
- new->message = US"delivery cancelled; message timed out";
- goto RECIP_QUEUE_FAILED; /* below */
+ new->message = US"delivery cancelled; message timed out";
+ goto RECIP_QUEUE_FAILED; /* below */
/* RECIP_FAIL is set when -Mg has been used. */
case RECIP_FAIL:
- new->message = US"delivery cancelled by administrator";
- /* Fall through */
+ new->message = US"delivery cancelled by administrator";
+ /* Fall through */
/* Common code for the failure cases above. If this is not a bounce
message, put the address on the failed list so that it is used to
The incident has already been logged. */
RECIP_QUEUE_FAILED:
- if (sender_address[0] != 0)
- {
- new->next = addr_failed;
- addr_failed = new;
- }
+ if (sender_address[0])
+ {
+ new->next = addr_failed;
+ addr_failed = new;
+ }
break;
is a bounce message, it will get frozen. */
case RECIP_FAIL_LOOP:
- new->message = US"Too many \"Received\" headers - suspected mail loop";
- post_process_one(new, FAIL, LOG_MAIN, EXIM_DTYPE_ROUTER, 0);
- break;
+ new->message = US"Too many \"Received\" headers - suspected mail loop";
+ post_process_one(new, FAIL, LOG_MAIN, EXIM_DTYPE_ROUTER, 0);
+ break;
/* Value should be RECIP_ACCEPT; take this as the safe default. */
default:
- if (!addr_new) addr_new = new; else addr_last->next = new;
- addr_last = new;
- break;
+ if (!addr_new) addr_new = new; else addr_last->next = new;
+ addr_last = new;
+ break;
}
#ifndef DISABLE_EVENT
{
uschar * save_local = deliver_localpart;
const uschar * save_domain = deliver_domain;
+ uschar * addr = new->address, * errmsg = NULL;
+ int start, end, dom;
- deliver_localpart = expand_string(
- string_sprintf("${local_part:%s}", new->address));
- deliver_domain = expand_string(
- string_sprintf("${domain:%s}", new->address));
+ if (!parse_extract_address(addr, &errmsg, &start, &end, &dom, TRUE))
+ log_write(0, LOG_MAIN|LOG_PANIC,
+ "failed to parse address '%.100s': %s\n", addr, errmsg);
+ else
+ {
+ deliver_localpart =
+ string_copyn(addr+start, dom ? (dom-1) - start : end - start);
+ deliver_domain = dom ? CUS string_copyn(addr+dom, end - dom) : CUS"";
- (void) event_raise(event_action,
- US"msg:fail:internal", new->message);
+ event_raise(event_action, US"msg:fail:internal", new->message);
- deliver_localpart = save_local;
- deliver_domain = save_domain;
+ deliver_localpart = save_local;
+ deliver_domain = save_domain;
+ }
}
#endif
}
if ( ( addr_dsntmp->dsn_aware != dsn_support_yes
|| addr_dsntmp->dsn_flags & rf_dsnlasthop
)
- && addr_dsntmp->dsn_flags & rf_dsnflags
&& addr_dsntmp->dsn_flags & rf_notify_success
)
{
addr_dsntmp = addr_dsntmp->next)
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->dsn_flags & rf_dsnlasthop ? "via non DSN router"
+ : addr_dsntmp->dsn_aware == dsn_support_no ? "to non-DSN-aware mailer"
+ : "via non \"Remote SMTP\" router"
);
fprintf(f, "--%s\n"
addr_dsntmp->host_used->name);
else
fprintf(f, "Diagnostic-Code: X-Exim; relayed via non %s router\n\n",
- (addr_dsntmp->dsn_flags & rf_dsnlasthop) == 1 ? "DSN" : "SMTP");
+ addr_dsntmp->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
- && (addr_failed->dsn_flags & rf_notify_failure) != rf_notify_failure
- ) )
+ || addr_failed->dsn_flags & (rf_dsnflags & ~rf_notify_failure)
+ )
{
addr = addr_failed;
addr_failed = addr->next;
if (addr->return_filename) Uunlink(addr->return_filename);
+#ifndef DISABLE_EVENT
+ msg_event_raise(US"msg:fail:delivery", addr);
+#endif
log_write(0, LOG_MAIN, "%s%s%s%s: error ignored",
addr->address,
!addr->parent ? US"" : US" <",
if ( !f.queue_2stage
&& delivery_attempted
- && ( ((addr_defer->dsn_flags & rf_dsnflags) == 0)
- || (addr_defer->dsn_flags & rf_notify_delay) == rf_notify_delay
+ && ( !(addr_defer->dsn_flags & rf_dsnflags)
+ || addr_defer->dsn_flags & rf_notify_delay
)
&& delay_warning[1] > 0
&& sender_address[0] != 0
}
return; /* compiler quietening; control does not reach here. */
+#ifdef SUPPORT_TLS
fail:
log_write(0,
LOG_MAIN | (exec_type == CEE_EXEC_EXIT ? LOG_PANIC : LOG_PANIC_DIE),
Note: this must be _exit(), not exit(). */
_exit(EX_EXECFAILED);
+#endif
}
/* vi: aw ai sw=2