From 4e9287801772d5aae181a9db0ef1dd1b514b2129 Mon Sep 17 00:00:00 2001
From: Matthias Kurz <m.kurz@irregular.at>
Date: Fri, 28 Sep 2018 23:05:02 +0100
Subject: [PATCH] Events:  Fire msg:fail:internal for a non-system filter
 "fail" command.  Bug 2322

---
 doc/doc-txt/ChangeLog         |  3 +++
 src/src/deliver.c             | 32 ++++++++++++++++++++++----------
 test/aux-fixed/5704.filter    |  4 ++++
 test/aux-fixed/5706.filter    |  3 +++
 test/confs/5704               | 28 ++++++++++++++++++++++++++++
 test/log/5704                 | 12 ++++++++++++
 test/scripts/5700-events/5704 |  5 +++++
 7 files changed, 77 insertions(+), 10 deletions(-)
 create mode 100644 test/aux-fixed/5704.filter
 create mode 100644 test/aux-fixed/5706.filter
 create mode 100644 test/confs/5704
 create mode 100644 test/log/5704
 create mode 100644 test/scripts/5700-events/5704

diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 0f50318f7..6f16fed82 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -134,6 +134,9 @@ JH/28 Bug 2314: Fire msg:fail:delivery event even when error is being ignored.
       move the existing event to fire before the normal logging of message
       failure so that custom logging is bracketed by normal logging.
 
+JH/29 Bug 2322: A "fail" command in a non-system filter (file) now fires the
+      msg:fail:internal event.  Developement by Matthias Kurz.
+
 
 Exim version 4.91
 -----------------
diff --git a/src/src/deliver.c b/src/src/deliver.c
index bba343c55..24c4048f6 100644
--- a/src/src/deliver.c
+++ b/src/src/deliver.c
@@ -877,21 +877,33 @@ const uschar * save_host = deliver_host;
 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
-	  || Ustrcmp(addr->transport->driver_name, "autoreply") == 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;
diff --git a/test/aux-fixed/5704.filter b/test/aux-fixed/5704.filter
new file mode 100644
index 000000000..7d01325a3
--- /dev/null
+++ b/test/aux-fixed/5704.filter
@@ -0,0 +1,4 @@
+# Exim filter
+
+if not error_message
+then fail text "failed in system filter file" endif
diff --git a/test/aux-fixed/5706.filter b/test/aux-fixed/5706.filter
new file mode 100644
index 000000000..b434b77c2
--- /dev/null
+++ b/test/aux-fixed/5706.filter
@@ -0,0 +1,3 @@
+# Exim filter
+
+fail "failed in filter file"
diff --git a/test/confs/5704 b/test/confs/5704
new file mode 100644
index 000000000..a1749442b
--- /dev/null
+++ b/test/confs/5704
@@ -0,0 +1,28 @@
+# Exim test configuration 5704
+
+.include DIR/aux-var/std_conf_prefix
+
+# ----- Main settings -----
+
+system_filter = DIR/aux-fixed/TESTNUM.filter
+
+event_action = ${acl {logger}}
+
+# ----- ACL -----
+
+begin acl
+
+.include DIR/aux-fixed/event-logger-acl
+
+# ----- Routers -----
+
+begin routers
+
+dump_bounces:
+  driver = redirect
+  senders = :
+  data = :blackhole:
+
+# ----- Transports -----
+
+# End
diff --git a/test/log/5704 b/test/log/5704
new file mode 100644
index 000000000..ac2d365e0
--- /dev/null
+++ b/test/log/5704
@@ -0,0 +1,12 @@
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmaX-0005vi-00 cancelled by system filter: failed in system filter file
+1999-03-02 09:44:33 10HmaX-0005vi-00 event msg:fail:internal
+1999-03-02 09:44:33 10HmaX-0005vi-00 . local_part <userx> domain <domain1> reason <failed in system filter file>
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= <> R=10HmaX-0005vi-00 U=EXIMUSER P=local S=sss
+1999-03-02 09:44:33 10HmaY-0005vi-00 => :blackhole: <CALLER@the.local.host.name> R=dump_bounces
+1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
+1999-03-02 09:44:33 10HmaY-0005vi-00 event msg:complete
+1999-03-02 09:44:33 10HmaY-0005vi-00 . finished: 10HmaY-0005vi-00
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 10HmaX-0005vi-00 event msg:complete
+1999-03-02 09:44:33 10HmaX-0005vi-00 . finished: 10HmaX-0005vi-00
diff --git a/test/scripts/5700-events/5704 b/test/scripts/5700-events/5704
new file mode 100644
index 000000000..3ed25aa74
--- /dev/null
+++ b/test/scripts/5700-events/5704
@@ -0,0 +1,5 @@
+# System filter which triggers fail command results in event.
+#
+exim -odi userx@domain1
+Processed by a system filter which triggers fail command.
+****
-- 
2.30.2