Logging: ensure that an error for a mistyped IPv6 address in a search
authorJeremy Harris <jgh146exb@wizmail.org>
Wed, 6 Dec 2023 19:54:40 +0000 (19:54 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Wed, 6 Dec 2023 19:54:40 +0000 (19:54 +0000)
list is available for logging.  Bug 3057

12 files changed:
doc/doc-docbook/spec.xfpt
doc/doc-txt/ChangeLog
src/src/match.c
src/src/string.c
src/src/verify.c
test/confs/0475
test/scripts/0000-Basic/0002
test/scripts/0000-Basic/0475
test/stderr/0002
test/stderr/0475
test/stdout/0002
test/stdout/0475

index 6022d7642ea0761ddf63ff89d83e2dce7e9d718c..dc8f5cc4d0347419fdfed60b57d6d235d24ee8a8 100644 (file)
@@ -39097,7 +39097,7 @@ selection marked by asterisks:
 .irow &`tls_peerdn`&                   &nbsp; "TLS peer DN on <= and => lines"
 .irow &`tls_resumption`&               &nbsp; "append * to cipher field"
 .irow &`tls_sni`&                      &nbsp; "TLS SNI on <= lines"
 .irow &`tls_peerdn`&                   &nbsp; "TLS peer DN on <= and => lines"
 .irow &`tls_resumption`&               &nbsp; "append * to cipher field"
 .irow &`tls_sni`&                      &nbsp; "TLS SNI on <= lines"
-.irow &`unknown_in_list`&              &nbsp; "DNS lookup failed in list match"
+.irow &`unknown_in_list`&              &nbsp; "lookup failed in list match"
 .irow &`all`&                          &nbsp; "&*all of the above*&"
 .endtable
 See also the &%slow_lookup_log%& main configuration option,
 .irow &`all`&                          &nbsp; "&*all of the above*&"
 .endtable
 See also the &%slow_lookup_log%& main configuration option,
@@ -39516,7 +39516,8 @@ added to the log line, preceded by SNI=.
 .next
 .cindex "log" "DNS failure in list"
 &%unknown_in_list%&: This setting causes a log entry to be written when the
 .next
 .cindex "log" "DNS failure in list"
 &%unknown_in_list%&: This setting causes a log entry to be written when the
-result of a list match is failure because a DNS lookup failed.
+result of a list match is failure because a DNS lookup failed, or because
+a bad IP address was in the list.
 .endlist
 
 
 .endlist
 
 
index 369e951202603160a76d3e64467b4a847a6cb872..2d82df43d8010a67794413ad532eb6ead75cab74 100644 (file)
@@ -44,6 +44,11 @@ JH/08 Bug 3056: Tighten up parsing of DKIM DNS records.  Previously, whitespace
       Tighten parsing of DKIM header records.  Previously, all but lowercase
       alpha chars would be ignored in potential tag names.
 
       Tighten parsing of DKIM header records.  Previously, all but lowercase
       alpha chars would be ignored in potential tag names.
 
+JH/09 Bug 3057: Add heuristic for spotting mistyped IPv6 addresses in lists
+      being searched.  Previously we only had one for IPv4 addresses. Per the
+      documentation, the error results by default in a no-match result for the
+      list.  It is logged if the unknown_in_list log_selector is used.
+
 
 
 Exim version 4.97
 
 
 Exim version 4.97
index df440108e01085c45d558e431d894418518b6846..8b1a3bef6cc88e44326818aa21b7d792993b0748 100644 (file)
@@ -886,14 +886,19 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0)))
          log_write(0, LOG_MAIN, "%s: accepted by +include_defer", error);
          goto OK_RETURN;
 
          log_write(0, LOG_MAIN, "%s: accepted by +include_defer", error);
          goto OK_RETURN;
 
-        case ERROR:            /* host name lookup failed - this can only */
-         if (ignore_unknown)   /* be for an incoming host (not outgoing) */
+        /* The ERROR return occurs when checking hosts, when either a forward
+        or reverse lookup has failed. It can also occur in a match_ip list if a
+        non-IP address item is encountered. The error string gives details of
+        which it was. */
+
+        case ERROR:
+         if (ignore_unknown)
            {
            HDEBUG(D_lists) debug_printf_indent("%s: item ignored by +ignore_unknown\n",
              error);
            }
          else
            {
            HDEBUG(D_lists) debug_printf_indent("%s: item ignored by +ignore_unknown\n",
              error);
            }
          else
-          {
+           {
            HDEBUG(D_lists) debug_printf_indent("%s %s (%s)\n", ot,
              include_unknown? "yes":"no", error);
            (void)fclose(f);
            HDEBUG(D_lists) debug_printf_indent("%s %s (%s)\n", ot,
              include_unknown? "yes":"no", error);
            (void)fclose(f);
index dfe0f24519f20d7cacf84971285e8c9d06c09e29..3bf2f1df780eb04dfc6de691195816e4b4ee210e 100644 (file)
@@ -57,6 +57,7 @@ union { /* we do not need this, but inet_pton() needs a place for storage */
 we return failure, as we do if the mask isn't a pure numerical value,
 or if it is negative. The actual length is checked later, once we know
 the address family. */
 we return failure, as we do if the mask isn't a pure numerical value,
 or if it is negative. The actual length is checked later, once we know
 the address family. */
+
 if (slash = Ustrchr(ip_addr, '/'))
   {
   uschar * rest;
 if (slash = Ustrchr(ip_addr, '/'))
   {
   uschar * rest;
@@ -74,10 +75,11 @@ if (slash = Ustrchr(ip_addr, '/'))
     return 0;
     }
 
     return 0;
     }
 
-  *maskptr = slash - ip_addr;     /* offset of the slash */
+  *maskptr = slash - ip_addr;  /* offset of the slash */
   endp = slash;
   }
   endp = slash;
   }
-else if (maskptr) *maskptr = 0; /* no slash found */
+else if (maskptr)
+  *maskptr = 0;                        /* no slash found */
 
 /* The interface-ID suffix (%<id>) is optional (for IPv6). If it
 exists, we check it syntactically. Later, if we know the address
 
 /* The interface-ID suffix (%<id>) is optional (for IPv6). If it
 exists, we check it syntactically. Later, if we know the address
@@ -160,7 +162,7 @@ switch (af)
 int
 string_is_ip_address(const uschar * ip_addr, int * maskptr)
 {
 int
 string_is_ip_address(const uschar * ip_addr, int * maskptr)
 {
-return string_is_ip_addressX(ip_addr, maskptr, 0);
+return string_is_ip_addressX(ip_addr, maskptr, NULL);
 }
 
 #endif  /* COMPILE_UTILITY */
 }
 
 #endif  /* COMPILE_UTILITY */
index d080ddd631bd8f2985b1c26f71bc2a92f51ad298..194e9a76a8896e27c1daeceb60fcdeed32fa0b1c 100644 (file)
@@ -2971,7 +2971,7 @@ if (*ss == '@')
 a (possibly masked) comparison with the current IP address. */
 
 if (string_is_ip_address(ss, &maskoffset) != 0)
 a (possibly masked) comparison with the current IP address. */
 
 if (string_is_ip_address(ss, &maskoffset) != 0)
-  return (host_is_in_net(cb->host_address, ss, maskoffset)? OK : FAIL);
+  return host_is_in_net(cb->host_address, ss, maskoffset) ? OK : FAIL;
 
 /* The pattern is not an IP address. A common error that people make is to omit
 one component of an IPv4 address, either by accident, or believing that, for
 
 /* The pattern is not an IP address. A common error that people make is to omit
 one component of an IPv4 address, either by accident, or believing that, for
@@ -2982,13 +2982,25 @@ ancient specification.) To aid in debugging these cases, we give a specific
 error if the pattern contains only digits and dots or contains a slash preceded
 only by digits and dots (a slash at the start indicates a file name and of
 course slashes may be present in lookups, but not preceded only by digits and
 error if the pattern contains only digits and dots or contains a slash preceded
 only by digits and dots (a slash at the start indicates a file name and of
 course slashes may be present in lookups, but not preceded only by digits and
-dots). */
+dots).  Then the equivalent for IPv6 (roughly). */
 
 
-for (t = ss; isdigit(*t) || *t == '.'; ) t++;
-if (!*t  || (*t == '/' && t != ss))
+if (Ustrchr(ss, ':'))
   {
   {
-  *error = string_sprintf("malformed IPv4 address or address mask: %.*s", (int)(t - ss), ss);
-  return ERROR;
+  for (t = ss; isxdigit(*t) || *t == ':' || *t == '.'; ) t++;
+  if (!*t  ||  (*t == '/' || *t == '%') && t != ss)
+    {
+    *error = string_sprintf("malformed IPv6 address or address mask: %.*s", (int)(t - ss), ss);
+    return ERROR;
+    }
+  }
+else
+  {
+  for (t = ss; isdigit(*t) || *t == '.'; ) t++;
+  if (!*t  || (*t == '/' && t != ss))
+    {
+    *error = string_sprintf("malformed IPv4 address or address mask: %.*s", (int)(t - ss), ss);
+    return ERROR;
+    }
   }
 
 /* See if there is a semicolon in the pattern, separating a searchtype
   }
 
 /* See if there is a semicolon in the pattern, separating a searchtype
index dfca55c7857054186570e4939dbf5e1b0b3ce711..58eb420523ffb690f75fbba037f68509e750ca3c 100644 (file)
@@ -7,6 +7,7 @@
 
 acl_smtp_rcpt = $local_part
 
 
 acl_smtp_rcpt = $local_part
 
+log_selector = +unknown_in_list
 
 # ----- ACL -----
 
 
 # ----- ACL -----
 
@@ -18,4 +19,10 @@ a1:
 a2:
   deny hosts = 1.2.3/24
 
 a2:
   deny hosts = 1.2.3/24
 
+a3:
+  deny hosts = <; fe80::1
+
+a4:
+  deny hosts = <; fe80:1
+
 # End
 # End
index c1fa1bdb514a48ad185d3485edae79f03bb6a8a3..9b1e5120ed15d6125bd101f711874d2edec28a32 100644 (file)
@@ -418,7 +418,7 @@ mask:   ${if eq {1}{2}{${mask:invalid}}{NO}}
 5>3m:   ${if >{5 } {3m }{y}{n}}
 5>3z:   ${if >{5 } {3z }{y}{n}}
 5>a:    ${if >{ 5 } {a}{y}{n}}
 5>3m:   ${if >{5 } {3m }{y}{n}}
 5>3z:   ${if >{5 } {3z }{y}{n}}
 5>a:    ${if >{ 5 } {a}{y}{n}}
-5>bad:  ${if >{5 } {${lookup{trick}lsearch{DIR/aux-fixed/0002.lsearch}}} {y}{n}}
+5>bad:  ${if >{5 } {${lookup{trick}lsearch{DIR/aux-fixed/TESTNUM.lsearch}}} {y}{n}}
 
 >0:     ${if > {}{0}{y}{n}}
 =:      ${if = {}{}{y}{n}}
 
 >0:     ${if > {}{0}{y}{n}}
 =:      ${if = {}{}{y}{n}}
@@ -472,6 +472,7 @@ isip6:  ${if isip6{::1}{y}{n}}      ::1
 isip:   ${if isip {fe80::a00:20ff:fe86:a061}{y}{n}}  fe80::a00:20ff:fe86:a061
 isip4:  ${if isip4{fe80::a00:20ff:fe86:a061}{y}{n}}  fe80::a00:20ff:fe86:a061
 isip6:  ${if isip6{fe80::a00:20ff:fe86:a061}{y}{n}}  fe80::a00:20ff:fe86:a061
 isip:   ${if isip {fe80::a00:20ff:fe86:a061}{y}{n}}  fe80::a00:20ff:fe86:a061
 isip4:  ${if isip4{fe80::a00:20ff:fe86:a061}{y}{n}}  fe80::a00:20ff:fe86:a061
 isip6:  ${if isip6{fe80::a00:20ff:fe86:a061}{y}{n}}  fe80::a00:20ff:fe86:a061
+isip6:  ${if isip6{fe80:a00:20ff:fe86:a061}{y}{n}}   fe80:a00:20ff:fe86:a061
 isip:   ${if isip {fe80::1.2.3.4}{y}{n}}  fe80::1.2.3.4
 isip:   ${if isip {rhubarb}{y}{n}}  rhubarb
 isip4:  ${if isip4{rhubarb}{y}{n}}  rhubarb
 isip:   ${if isip {fe80::1.2.3.4}{y}{n}}  fe80::1.2.3.4
 isip:   ${if isip {rhubarb}{y}{n}}  rhubarb
 isip4:  ${if isip4{rhubarb}{y}{n}}  rhubarb
@@ -527,10 +528,10 @@ match_ip:        08 ${if match_ip{V4NET.11.12.13}{+hlist}}
 match_ip:        09 ${if match_ip{V4NET.11.12.14}{+hlist}}
 match_ip:        10 ${if match_ip{192.168.3.4}{+hlist}}
 match_ip:        11 ${if match_ip{somename}{+hlist}}
 match_ip:        09 ${if match_ip{V4NET.11.12.14}{+hlist}}
 match_ip:        10 ${if match_ip{192.168.3.4}{+hlist}}
 match_ip:        11 ${if match_ip{somename}{+hlist}}
-match_ip:        12 ${if match_ip{1.2.3.4}{lsearch;DIR/aux-fixed/0002.matchip}}
-match_ip:        13 ${if match_ip{1.2.3.4}{net-lsearch;DIR/aux-fixed/0002.matchip}}
-match_ip:        14 ${if match_ip{5.6.7.8}{net24-lsearch;DIR/aux-fixed/0002.matchip}}
-match_ip:        15 ${if match_ip{abcd::dcba}{net-iplsearch;DIR/aux-fixed/0002.matchip}}
+match_ip:        12 ${if match_ip{1.2.3.4}{lsearch;DIR/aux-fixed/TESTNUM.matchip}}
+match_ip:        13 ${if match_ip{1.2.3.4}{net-lsearch;DIR/aux-fixed/TESTNUM.matchip}}
+match_ip:        14 ${if match_ip{5.6.7.8}{net24-lsearch;DIR/aux-fixed/TESTNUM.matchip}}
+match_ip:        15 ${if match_ip{abcd::dcba}{net-iplsearch;DIR/aux-fixed/TESTNUM.matchip}}
 
 queue_running:  ${if queue_running{y}{n}}
 first_delivery: ${if first_delivery{y}{n}}
 
 queue_running:  ${if queue_running{y}{n}}
 first_delivery: ${if first_delivery{y}{n}}
@@ -552,126 +553,126 @@ acl if: ${if acl {{a_defer}{argN}{arg2}} {Y:$value}{N:$value}}
 # Lookups: DIR is the testing directory. In this test we can only use the
 # lookups that are required in all cases.
 
 # Lookups: DIR is the testing directory. In this test we can only use the
 # lookups that are required in all cases.
 
-${lookup{postmaster}lsearch         {DIR/aux-fixed/0002.aliases}{$value}fail}
-${lookup{postmaster}lsearch,ret=full{DIR/aux-fixed/0002.aliases}{$value}fail}
-
-${lookup{x@y}lsearch*@{DIR/aux-fixed/0002.starat}{$value}fail}
-${lookup{x@z}lsearch* {DIR/aux-fixed/0002.starat}{$value}fail}
-${lookup{x@z}lsearch*@{DIR/aux-fixed/0002.starat}{$value}fail}
-${lookup{x@w}lsearch*@{DIR/aux-fixed/0002.starat}{$value}fail}
-
-${lookup{x@y}lsearch*@,ret=full {DIR/aux-fixed/0002.starat}{$value}fail}
-${lookup{x@z}lsearch*,ret=full  {DIR/aux-fixed/0002.starat}{$value}fail}
-${lookup{x@z}lsearch*@,ret=full {DIR/aux-fixed/0002.starat}{$value}fail}
-${lookup{x@w}lsearch*@,ret=full {DIR/aux-fixed/0002.starat}{$value}fail}
-
-${lookup{a.b.c.d}  partial-lsearch {DIR/aux-fixed/0002.domains}{$value}fail}
-${lookup{x.y.z}    partial-lsearch {DIR/aux-fixed/0002.domains}{$value}{failed x.y.z}}
-${lookup{p.q}      partial-lsearch {DIR/aux-fixed/0002.domains}{$value}fail}
-${lookup{o.p.q}    partial-lsearch {DIR/aux-fixed/0002.domains}{$value}fail}
-${lookup{m.n.o.p.q}partial-lsearch {DIR/aux-fixed/0002.domains}{$value}fail}
-${lookup{x.y.z}    partial1-lsearch{DIR/aux-fixed/0002.domains}{$value}fail}
-${lookup{x.y.z}    partial0-lsearch{DIR/aux-fixed/0002.domains}{$value}fail}
-
-${lookup{a.b.c.d}  partial-lsearch,ret=full {DIR/aux-fixed/0002.domains}{$value}fail}
-${lookup{x.y.z}    partial-lsearch,ret=full {DIR/aux-fixed/0002.domains}{$value}{failed x.y.z}}
-${lookup{p.q}      partial-lsearch,ret=full {DIR/aux-fixed/0002.domains}{$value}fail}
-${lookup{o.p.q}    partial-lsearch,ret=full {DIR/aux-fixed/0002.domains}{$value}fail}
-${lookup{m.n.o.p.q}partial-lsearch,ret=full {DIR/aux-fixed/0002.domains}{$value}fail}
-${lookup{x.y.z}    partial1-lsearch,ret=full{DIR/aux-fixed/0002.domains}{$value}fail}
-${lookup{x.y.z}    partial0-lsearch,ret=full{DIR/aux-fixed/0002.domains}{$value}fail}
-
-q1:  ${lookup{abc}        lsearch{DIR/aux-fixed/0002.quoted}}
-q2:  ${lookup{xyz}        lsearch{DIR/aux-fixed/0002.quoted}}
-q3:  ${lookup{pqr}        lsearch{DIR/aux-fixed/0002.quoted}}
-q4:  ${lookup{a:b}        lsearch{DIR/aux-fixed/0002.quoted}}
-q5:  ${lookup{"quoted"}   lsearch{DIR/aux-fixed/0002.quoted}}
-q6:  ${lookup{white space}lsearch{DIR/aux-fixed/0002.quoted}}
-q7:  ${lookup{b\\s}       lsearch{DIR/aux-fixed/0002.quoted}}
-
-q1f: ${lookup{abc}        lsearch,ret=full{DIR/aux-fixed/0002.quoted}}
-q2f: ${lookup{xyz}        lsearch,ret=full{DIR/aux-fixed/0002.quoted}}
-q3f: ${lookup{pqr}        lsearch,ret=full{DIR/aux-fixed/0002.quoted}}
-q4f: ${lookup{a:b}        lsearch,ret=full{DIR/aux-fixed/0002.quoted}}
-q5f: ${lookup{"quoted"}   lsearch,ret=full{DIR/aux-fixed/0002.quoted}}
-q6f: ${lookup{white space}lsearch,ret=full{DIR/aux-fixed/0002.quoted}}
-q7f: ${lookup{b\\s}       lsearch,ret=full{DIR/aux-fixed/0002.quoted}}
-
-abc:   ${lookup{abc}wildlsearch{DIR/aux-var/0002.wild}}
-a.b.c: ${lookup{a.b.c}wildlsearch{DIR/aux-var/0002.wild}}
-ab.c:  ${lookup{ab.c}wildlsearch{DIR/aux-var/0002.wild}}
-xyz:   ${lookup{xyz}wildlsearch{DIR/aux-var/0002.wild}}
-.Xyz:   ${lookup{Xyz}wildlsearch{DIR/aux-var/0002.wild}}
-.Zyz:   ${lookup{Zyz}wildlsearch{DIR/aux-var/0002.wild}}
-a b:   ${lookup{a b}wildlsearch{DIR/aux-var/0002.wild}}
-a  b:  ${lookup{a  b}wildlsearch{DIR/aux-var/0002.wild}}
-a:b:   ${lookup{a:b}wildlsearch{DIR/aux-var/0002.wild}}
-a.b:   ${lookup{a.b}wildlsearch{DIR/aux-var/0002.wild}}
-a..b:  ${lookup{a..b}wildlsearch{DIR/aux-var/0002.wild}}
-a9b:   ${lookup{a9b}wildlsearch{DIR/aux-var/0002.wild}}
-a99b:  ${lookup{a99b}wildlsearch{DIR/aux-var/0002.wild}}
+${lookup{postmaster}lsearch         {DIR/aux-fixed/TESTNUM.aliases}{$value}fail}
+${lookup{postmaster}lsearch,ret=full{DIR/aux-fixed/TESTNUM.aliases}{$value}fail}
+
+${lookup{x@y}lsearch*@{DIR/aux-fixed/TESTNUM.starat}{$value}fail}
+${lookup{x@z}lsearch* {DIR/aux-fixed/TESTNUM.starat}{$value}fail}
+${lookup{x@z}lsearch*@{DIR/aux-fixed/TESTNUM.starat}{$value}fail}
+${lookup{x@w}lsearch*@{DIR/aux-fixed/TESTNUM.starat}{$value}fail}
+
+${lookup{x@y}lsearch*@,ret=full {DIR/aux-fixed/TESTNUM.starat}{$value}fail}
+${lookup{x@z}lsearch*,ret=full  {DIR/aux-fixed/TESTNUM.starat}{$value}fail}
+${lookup{x@z}lsearch*@,ret=full {DIR/aux-fixed/TESTNUM.starat}{$value}fail}
+${lookup{x@w}lsearch*@,ret=full {DIR/aux-fixed/TESTNUM.starat}{$value}fail}
+
+${lookup{a.b.c.d}  partial-lsearch {DIR/aux-fixed/TESTNUM.domains}{$value}fail}
+${lookup{x.y.z}    partial-lsearch {DIR/aux-fixed/TESTNUM.domains}{$value}{failed x.y.z}}
+${lookup{p.q}      partial-lsearch {DIR/aux-fixed/TESTNUM.domains}{$value}fail}
+${lookup{o.p.q}    partial-lsearch {DIR/aux-fixed/TESTNUM.domains}{$value}fail}
+${lookup{m.n.o.p.q}partial-lsearch {DIR/aux-fixed/TESTNUM.domains}{$value}fail}
+${lookup{x.y.z}    partial1-lsearch{DIR/aux-fixed/TESTNUM.domains}{$value}fail}
+${lookup{x.y.z}    partial0-lsearch{DIR/aux-fixed/TESTNUM.domains}{$value}fail}
+
+${lookup{a.b.c.d}  partial-lsearch,ret=full {DIR/aux-fixed/TESTNUM.domains}{$value}fail}
+${lookup{x.y.z}    partial-lsearch,ret=full {DIR/aux-fixed/TESTNUM.domains}{$value}{failed x.y.z}}
+${lookup{p.q}      partial-lsearch,ret=full {DIR/aux-fixed/TESTNUM.domains}{$value}fail}
+${lookup{o.p.q}    partial-lsearch,ret=full {DIR/aux-fixed/TESTNUM.domains}{$value}fail}
+${lookup{m.n.o.p.q}partial-lsearch,ret=full {DIR/aux-fixed/TESTNUM.domains}{$value}fail}
+${lookup{x.y.z}    partial1-lsearch,ret=full{DIR/aux-fixed/TESTNUM.domains}{$value}fail}
+${lookup{x.y.z}    partial0-lsearch,ret=full{DIR/aux-fixed/TESTNUM.domains}{$value}fail}
+
+q1:  ${lookup{abc}        lsearch{DIR/aux-fixed/TESTNUM.quoted}}
+q2:  ${lookup{xyz}        lsearch{DIR/aux-fixed/TESTNUM.quoted}}
+q3:  ${lookup{pqr}        lsearch{DIR/aux-fixed/TESTNUM.quoted}}
+q4:  ${lookup{a:b}        lsearch{DIR/aux-fixed/TESTNUM.quoted}}
+q5:  ${lookup{"quoted"}   lsearch{DIR/aux-fixed/TESTNUM.quoted}}
+q6:  ${lookup{white space}lsearch{DIR/aux-fixed/TESTNUM.quoted}}
+q7:  ${lookup{b\\s}       lsearch{DIR/aux-fixed/TESTNUM.quoted}}
+
+q1f: ${lookup{abc}        lsearch,ret=full{DIR/aux-fixed/TESTNUM.quoted}}
+q2f: ${lookup{xyz}        lsearch,ret=full{DIR/aux-fixed/TESTNUM.quoted}}
+q3f: ${lookup{pqr}        lsearch,ret=full{DIR/aux-fixed/TESTNUM.quoted}}
+q4f: ${lookup{a:b}        lsearch,ret=full{DIR/aux-fixed/TESTNUM.quoted}}
+q5f: ${lookup{"quoted"}   lsearch,ret=full{DIR/aux-fixed/TESTNUM.quoted}}
+q6f: ${lookup{white space}lsearch,ret=full{DIR/aux-fixed/TESTNUM.quoted}}
+q7f: ${lookup{b\\s}       lsearch,ret=full{DIR/aux-fixed/TESTNUM.quoted}}
+
+abc:   ${lookup{abc}wildlsearch{DIR/aux-var/TESTNUM.wild}}
+a.b.c: ${lookup{a.b.c}wildlsearch{DIR/aux-var/TESTNUM.wild}}
+ab.c:  ${lookup{ab.c}wildlsearch{DIR/aux-var/TESTNUM.wild}}
+xyz:   ${lookup{xyz}wildlsearch{DIR/aux-var/TESTNUM.wild}}
+.Xyz:   ${lookup{Xyz}wildlsearch{DIR/aux-var/TESTNUM.wild}}
+.Zyz:   ${lookup{Zyz}wildlsearch{DIR/aux-var/TESTNUM.wild}}
+a b:   ${lookup{a b}wildlsearch{DIR/aux-var/TESTNUM.wild}}
+a  b:  ${lookup{a  b}wildlsearch{DIR/aux-var/TESTNUM.wild}}
+a:b:   ${lookup{a:b}wildlsearch{DIR/aux-var/TESTNUM.wild}}
+a.b:   ${lookup{a.b}wildlsearch{DIR/aux-var/TESTNUM.wild}}
+a..b:  ${lookup{a..b}wildlsearch{DIR/aux-var/TESTNUM.wild}}
+a9b:   ${lookup{a9b}wildlsearch{DIR/aux-var/TESTNUM.wild}}
+a99b:  ${lookup{a99b}wildlsearch{DIR/aux-var/TESTNUM.wild}}
 
 # Should give the same results as above because expansion does nothing
 
 
 # Should give the same results as above because expansion does nothing
 
-abc:   ${lookup{abc}nwildlsearch{DIR/aux-var/0002.wild}}
-a.b.c: ${lookup{a.b.c}nwildlsearch{DIR/aux-var/0002.wild}}
-ab.c:  ${lookup{ab.c}nwildlsearch{DIR/aux-var/0002.wild}}
-xyz:   ${lookup{xyz}nwildlsearch{DIR/aux-var/0002.wild}}
-.Xyz:   ${lookup{Xyz}nwildlsearch{DIR/aux-var/0002.wild}}
-.Zyz:   ${lookup{Zyz}nwildlsearch{DIR/aux-var/0002.wild}}
-a b:   ${lookup{a b}nwildlsearch{DIR/aux-var/0002.wild}}
-a  b:  ${lookup{a  b}nwildlsearch{DIR/aux-var/0002.wild}}
-a:b:   ${lookup{a:b}nwildlsearch{DIR/aux-var/0002.wild}}
+abc:   ${lookup{abc}nwildlsearch{DIR/aux-var/TESTNUM.wild}}
+a.b.c: ${lookup{a.b.c}nwildlsearch{DIR/aux-var/TESTNUM.wild}}
+ab.c:  ${lookup{ab.c}nwildlsearch{DIR/aux-var/TESTNUM.wild}}
+xyz:   ${lookup{xyz}nwildlsearch{DIR/aux-var/TESTNUM.wild}}
+.Xyz:   ${lookup{Xyz}nwildlsearch{DIR/aux-var/TESTNUM.wild}}
+.Zyz:   ${lookup{Zyz}nwildlsearch{DIR/aux-var/TESTNUM.wild}}
+a b:   ${lookup{a b}nwildlsearch{DIR/aux-var/TESTNUM.wild}}
+a  b:  ${lookup{a  b}nwildlsearch{DIR/aux-var/TESTNUM.wild}}
+a:b:   ${lookup{a:b}nwildlsearch{DIR/aux-var/TESTNUM.wild}}
 
 # Should fail because of no expansion
 
 
 # Should fail because of no expansion
 
-a.b:   ${lookup{a.b}nwildlsearch{DIR/aux-var/0002.wild}{$value}{NO}}
-a..b:  ${lookup{a..b}nwildlsearch{DIR/aux-var/0002.wild}{$value}{NO}}
-a9b:   ${lookup{a9b}nwildlsearch{DIR/aux-var/0002.wild}{$value}{NO}}
-a99b:  ${lookup{a99b}nwildlsearch{DIR/aux-var/0002.wild}{$value}{NO}}
+a.b:   ${lookup{a.b}nwildlsearch{DIR/aux-var/TESTNUM.wild}{$value}{NO}}
+a..b:  ${lookup{a..b}nwildlsearch{DIR/aux-var/TESTNUM.wild}{$value}{NO}}
+a9b:   ${lookup{a9b}nwildlsearch{DIR/aux-var/TESTNUM.wild}{$value}{NO}}
+a99b:  ${lookup{a99b}nwildlsearch{DIR/aux-var/TESTNUM.wild}{$value}{NO}}
 
 # But these should succeed
 
 
 # But these should succeed
 
-a\\:b:  ${lookup{a\\:b}nwildlsearch{DIR/aux-var/0002.wild}}
-a\\:Xb: ${lookup{a\\:Xb}nwildlsearch{DIR/aux-var/0002.wild}}
+a\\:b:  ${lookup{a\\:b}nwildlsearch{DIR/aux-var/TESTNUM.wild}}
+a\\:Xb: ${lookup{a\\:Xb}nwildlsearch{DIR/aux-var/TESTNUM.wild}}
 
 # Some tests of case-(in)dependence
 
 
 # Some tests of case-(in)dependence
 
-.MiXeD-CD:  ${lookup{MiXeD-CD}nwildlsearch{DIR/aux-var/0002.wild}{$value}{NOT FOUND}}
-.MixeD-CD:  ${lookup{MixeD-CD}nwildlsearch{DIR/aux-var/0002.wild}{$value}{NOT FOUND}}
-.MiXeD-Ncd: ${lookup{MiXeD-Ncd}nwildlsearch{DIR/aux-var/0002.wild}{$value}{NOT FOUND}}
-.MixeD-Ncd: ${lookup{MixeD-Ncd}nwildlsearch{DIR/aux-var/0002.wild}{$value}{NOT FOUND}}
+.MiXeD-CD:  ${lookup{MiXeD-CD}nwildlsearch{DIR/aux-var/TESTNUM.wild}{$value}{NOT FOUND}}
+.MixeD-CD:  ${lookup{MixeD-CD}nwildlsearch{DIR/aux-var/TESTNUM.wild}{$value}{NOT FOUND}}
+.MiXeD-Ncd: ${lookup{MiXeD-Ncd}nwildlsearch{DIR/aux-var/TESTNUM.wild}{$value}{NOT FOUND}}
+.MixeD-Ncd: ${lookup{MixeD-Ncd}nwildlsearch{DIR/aux-var/TESTNUM.wild}{$value}{NOT FOUND}}
 
 # IP address (CIDR) lookups
 
 
 # IP address (CIDR) lookups
 
-1.2.3.4:      ${lookup{1.2.3.4}iplsearch{DIR/aux-fixed/0002.iplsearch}}
-1.2.3.5:      ${lookup{1.2.3.5}iplsearch{DIR/aux-fixed/0002.iplsearch}}
-1.2.3.5:      ${lookup{1.2.3.5}iplsearch*{DIR/aux-fixed/0002.iplsearch}}
-abcd::cdab:   ${lookup{abcd::cdab}iplsearch{DIR/aux-fixed/0002.iplsearch}}
-192.168.1.2:  ${lookup{192.168.1.2}iplsearch{DIR/aux-fixed/0002.iplsearch}}
-192.168.5.6:  ${lookup{192.168.5.6}iplsearch{DIR/aux-fixed/0002.iplsearch}}
-abcd:abcd::   ${lookup{abcd:abcd::}iplsearch{DIR/aux-fixed/0002.iplsearch}}
-abcd:abcd:1:: ${lookup{abcd:abcd:1::}iplsearch{DIR/aux-fixed/0002.iplsearch}}
-abcd:abcd::3  ${lookup{abcd:abcd::3}iplsearch{DIR/aux-fixed/0002.iplsearch}}
-rhubarb       ${lookup{rhubarb}iplsearch{DIR/aux-fixed/0002.iplsearch}}
+1.2.3.4:      ${lookup{1.2.3.4}iplsearch{DIR/aux-fixed/TESTNUM.iplsearch}}
+1.2.3.5:      ${lookup{1.2.3.5}iplsearch{DIR/aux-fixed/TESTNUM.iplsearch}}
+1.2.3.5:      ${lookup{1.2.3.5}iplsearch*{DIR/aux-fixed/TESTNUM.iplsearch}}
+abcd::cdab:   ${lookup{abcd::cdab}iplsearch{DIR/aux-fixed/TESTNUM.iplsearch}}
+192.168.1.2:  ${lookup{192.168.1.2}iplsearch{DIR/aux-fixed/TESTNUM.iplsearch}}
+192.168.5.6:  ${lookup{192.168.5.6}iplsearch{DIR/aux-fixed/TESTNUM.iplsearch}}
+abcd:abcd::   ${lookup{abcd:abcd::}iplsearch{DIR/aux-fixed/TESTNUM.iplsearch}}
+abcd:abcd:1:: ${lookup{abcd:abcd:1::}iplsearch{DIR/aux-fixed/TESTNUM.iplsearch}}
+abcd:abcd::3  ${lookup{abcd:abcd::3}iplsearch{DIR/aux-fixed/TESTNUM.iplsearch}}
+rhubarb       ${lookup{rhubarb}iplsearch{DIR/aux-fixed/TESTNUM.iplsearch}}
 
 
 # Nested Lookups - style 1
 
 
 
 # Nested Lookups - style 1
 
-${lookup{${lookup{key1}lsearch{DIR/aux-fixed/0002.rec}{$value}{key1f}}}lsearch{DIR/aux-fixed/0002.rec}{$value}fail}
-${lookup{${lookup{key3}lsearch{DIR/aux-fixed/0002.rec}{$value}{key1f}}}lsearch{DIR/aux-fixed/0002.rec}{$value}fail}
+${lookup{${lookup{key1}lsearch{DIR/aux-fixed/TESTNUM.rec}{$value}{key1f}}}lsearch{DIR/aux-fixed/TESTNUM.rec}{$value}fail}
+${lookup{${lookup{key3}lsearch{DIR/aux-fixed/TESTNUM.rec}{$value}{key1f}}}lsearch{DIR/aux-fixed/TESTNUM.rec}{$value}fail}
 
 # Nested Lookups - style 2
 
 
 # Nested Lookups - style 2
 
-${lookup{key1}lsearch{DIR/aux-fixed/0002.rec}{${lookup{$value}lsearch{DIR/aux-fixed/0002.rec}{$value}{failed for $value}}}{failed for key1}}
-${lookup{key3}lsearch{DIR/aux-fixed/0002.rec}{${lookup{$value}lsearch{DIR/aux-fixed/0002.rec}{$value}{failed for $value}}}{failed for key1}}
+${lookup{key1}lsearch{DIR/aux-fixed/TESTNUM.rec}{${lookup{$value}lsearch{DIR/aux-fixed/TESTNUM.rec}{$value}{failed for $value}}}{failed for key1}}
+${lookup{key3}lsearch{DIR/aux-fixed/TESTNUM.rec}{${lookup{$value}lsearch{DIR/aux-fixed/TESTNUM.rec}{$value}{failed for $value}}}{failed for key1}}
 
 # Other nesting tests
 
 
 # Other nesting tests
 
-${lookup{one}lsearch{DIR/aux-fixed/0002.alias1}{$value${lookup{one}lsearch{DIR/aux-fixed/0002.alias2}{,$value}}}{${lookup{one}lsearch{DIR/aux-fixed/0002.alias2}{$value}fail}}}
-${lookup{two}lsearch{DIR/aux-fixed/0002.alias1}{$value${lookup{two}lsearch{DIR/aux-fixed/0002.alias2}{,$value}}}{${lookup{two}lsearch{DIR/aux-fixed/0002.alias2}{$value}fail}}}
-${lookup{both}lsearch{DIR/aux-fixed/0002.alias1}{$value${lookup{both}lsearch{DIR/aux-fixed/0002.alias2}{,$value}}}{${lookup{both}lsearch{DIR/aux-fixed/0002.alias2}{$value}fail}}}
-${lookup{neither}lsearch{DIR/aux-fixed/0002.alias1}{$value${lookup{neither}lsearch{DIR/aux-fixed/0002.alias2}{,$value}}}{${lookup{neither}lsearch{DIR/aux-fixed/0002.alias2}{$value}fail}}}
+${lookup{one}lsearch{DIR/aux-fixed/TESTNUM.alias1}{$value${lookup{one}lsearch{DIR/aux-fixed/TESTNUM.alias2}{,$value}}}{${lookup{one}lsearch{DIR/aux-fixed/TESTNUM.alias2}{$value}fail}}}
+${lookup{two}lsearch{DIR/aux-fixed/TESTNUM.alias1}{$value${lookup{two}lsearch{DIR/aux-fixed/TESTNUM.alias2}{,$value}}}{${lookup{two}lsearch{DIR/aux-fixed/TESTNUM.alias2}{$value}fail}}}
+${lookup{both}lsearch{DIR/aux-fixed/TESTNUM.alias1}{$value${lookup{both}lsearch{DIR/aux-fixed/TESTNUM.alias2}{,$value}}}{${lookup{both}lsearch{DIR/aux-fixed/TESTNUM.alias2}{$value}fail}}}
+${lookup{neither}lsearch{DIR/aux-fixed/TESTNUM.alias1}{$value${lookup{neither}lsearch{DIR/aux-fixed/TESTNUM.alias2}{,$value}}}{${lookup{neither}lsearch{DIR/aux-fixed/TESTNUM.alias2}{$value}fail}}}
 
 # Lookup quotes for standardly expected lookups
 
 
 # Lookup quotes for standardly expected lookups
 
@@ -798,26 +799,26 @@ toobig    ${from_utf8:aĀd}
 # File insertion
 
 ${readfile}
 # File insertion
 
 ${readfile}
-${readfile{DIR/aux-fixed/0002.readfile}}
-${readfile{DIR/aux-fixed/0002.readfile}{}}
-${readfile{DIR/aux-fixed/0002.readfile}{:}}
-${readfile{DIR/aux-fixed/0002.readfile}{ - }}
+${readfile{DIR/aux-fixed/TESTNUM.readfile}}
+${readfile{DIR/aux-fixed/TESTNUM.readfile}{}}
+${readfile{DIR/aux-fixed/TESTNUM.readfile}{:}}
+${readfile{DIR/aux-fixed/TESTNUM.readfile}{ - }}
 ${readfile{/non/exist/file}}
 ${if exists{/non/exist/file}{${readfile{/non/exist/file}}}{non-exist}}
 ${readfile{/non/exist/file}}
 ${if exists{/non/exist/file}{${readfile{/non/exist/file}}}{non-exist}}
->${readfile{DIR/aux-fixed/0002.readfile}{!}}\
+>${readfile{DIR/aux-fixed/TESTNUM.readfile}{!}}\
     <
 
 # Calling a command
 
     <
 
 # Calling a command
 
-${run{DIR/aux-fixed/0002.runfile 0}}
+${run{DIR/aux-fixed/TESTNUM.runfile 0}}
 rc=$runrc
 rc=$runrc
-${run{DIR/aux-fixed/0002.runfile 0}{1}{2}}
+${run{DIR/aux-fixed/TESTNUM.runfile 0}{1}{2}}
 rc=$runrc
 rc=$runrc
-${run{DIR/aux-fixed/0002.runfile 0}{$value}{2}}
+${run{DIR/aux-fixed/TESTNUM.runfile 0}{$value}{2}}
 rc=$runrc
 rc=$runrc
-${run{DIR/aux-fixed/0002.runfile 1}{$value}{2}}
+${run{DIR/aux-fixed/TESTNUM.runfile 1}{$value}{2}}
 rc=$runrc
 rc=$runrc
-${run{DIR/aux-fixed/0002.runfile 1}{$value}{$value}}
+${run{DIR/aux-fixed/TESTNUM.runfile 1}{$value}{$value}}
 rc=$runrc
 ${run{DIR/test-nonexist}{Y}{N}}
 rc=$runrc
 rc=$runrc
 ${run{DIR/test-nonexist}{Y}{N}}
 rc=$runrc
@@ -825,9 +826,9 @@ rc=$runrc
 rc=$runrc
 ${if eq{1}{2}{${run{/non/exist}}}{1!=2}}
 rc=$runrc
 rc=$runrc
 ${if eq{1}{2}{${run{/non/exist}}}{1!=2}}
 rc=$runrc
-${run,preexpand {DIR/aux-fixed/0002.runfile 0}}
+${run,preexpand {DIR/aux-fixed/TESTNUM.runfile 0}}
 rc=$runrc
 rc=$runrc
-${run{DIR/aux-fixed/0002.runfile ${quote:1}}{$value}{2}}
+${run{DIR/aux-fixed/TESTNUM.runfile ${quote:1}}{$value}{2}}
 rc=$runrc
 
 # PRVS
 rc=$runrc
 
 # PRVS
@@ -1138,10 +1139,11 @@ Subject: =?iso-8859-8?Q?_here_we_go=3A_a_string_that_is_going_to_be_encoded=3A_i
 .
 quit
 ****
 .
 quit
 ****
-# Certain kind of error
+# Bad IP addresses
 exim -d -be
 match_ip:        15 ${if match_ip{1.2.3.4}{1.2.3}}
 match_ip:        16 ${if match_ip{1.2.3.4}{1.2.3.4/abc}}
 exim -d -be
 match_ip:        15 ${if match_ip{1.2.3.4}{1.2.3}}
 match_ip:        16 ${if match_ip{1.2.3.4}{1.2.3.4/abc}}
+match_ip:        17 ${if match_ip{::1}{<; aaaa:bbbb}}
 ****
 # Operation of inlist and negated inlist
 exim -be
 ****
 # Operation of inlist and negated inlist
 exim -be
index 5008c8768b0017950451f022524d51c1aed50d0a..05f3a70e40c1617f470b730c3e52c96ec080782d 100644 (file)
@@ -4,5 +4,7 @@ helo test
 mail from:<>
 rcpt to:<a1@b>
 rcpt to:<a2@b>
 mail from:<>
 rcpt to:<a1@b>
 rcpt to:<a2@b>
+rcpt to:<a3@b>
+rcpt to:<a4@b>
 quit
 ****
 quit
 ****
index a74e98c11f4f7478f8ae719f45157466dc192f00..087b58f60615bc3aa1829a39e8ed9046152bbf7f 100644 (file)
@@ -746,5 +746,8 @@ sender address = CALLER@myhost.test.ex
   1.2.3.4 in "1.2.3.4/abc"?
    list element: 1.2.3.4/abc
    1.2.3.4 in "1.2.3.4/abc"? no (malformed IPv4 address or address mask: 1.2.3.4)
   1.2.3.4 in "1.2.3.4/abc"?
    list element: 1.2.3.4/abc
    1.2.3.4 in "1.2.3.4/abc"? no (malformed IPv4 address or address mask: 1.2.3.4)
-  search_tidyup called
+   ::1 in "<; aaaa:bbbb"?
+   ╎list element: aaaa:bbbb
+   ╎::1 in "<; aaaa:bbbb"? no (malformed IPv6 address or address mask: aaaa:bbbb)
+   search_tidyup called
 >>>>>>>>>>>>>>>> Exim pid=p1240 (fresh-exec) terminating with rc=0 >>>>>>>>>>>>>>>>
 >>>>>>>>>>>>>>>> Exim pid=p1240 (fresh-exec) terminating with rc=0 >>>>>>>>>>>>>>>>
index 4626506f53a9d395f47b00dc8765b4190febc663..f080bfc0ee72b3240b31043b56c091458a785715 100644 (file)
@@ -11,7 +11,7 @@
 >>>  list element: @[]
 >>> test in helo_lookup_domains? no (end of list)
 >>> using ACL "a1"
 >>>  list element: @[]
 >>> test in helo_lookup_domains? no (end of list)
 >>> using ACL "a1"
->>> processing "deny" (TESTSUITE/test-config 16)
+>>> processing "deny" (TESTSUITE/test-config 17)
 >>> check hosts = 1.2.3.4 : <; 1.2.3.4::5.6.7.8
 >>> host in "1.2.3.4 : <; 1.2.3.4::5.6.7.8"?
 >>>  list element: 1.2.3.4
 >>> check hosts = 1.2.3.4 : <; 1.2.3.4::5.6.7.8
 >>> host in "1.2.3.4 : <; 1.2.3.4::5.6.7.8"?
 >>>  list element: 1.2.3.4
@@ -21,11 +21,31 @@ LOG: unknown lookup type "<" in host list item "<; 1.2.3.4:5.6.7.8"
 >>> deny: condition test deferred in ACL "a1"
 LOG: H=(test) [V4NET.0.0.0] F=<> temporarily rejected RCPT <a1@b>: unknown lookup type "<"
 >>> using ACL "a2"
 >>> deny: condition test deferred in ACL "a1"
 LOG: H=(test) [V4NET.0.0.0] F=<> temporarily rejected RCPT <a1@b>: unknown lookup type "<"
 >>> using ACL "a2"
->>> processing "deny" (TESTSUITE/test-config 19)
+>>> processing "deny" (TESTSUITE/test-config 20)
 >>> check hosts = 1.2.3/24
 >>> host in "1.2.3/24"?
 >>>  list element: 1.2.3/24
 >>>  host in "1.2.3/24"? no (malformed IPv4 address or address mask: 1.2.3)
 >>> check hosts = 1.2.3/24
 >>> host in "1.2.3/24"?
 >>>  list element: 1.2.3/24
 >>>  host in "1.2.3/24"? no (malformed IPv4 address or address mask: 1.2.3)
+LOG: list matching forced to fail: malformed IPv4 address or address mask: 1.2.3
 >>>  deny: condition test failed in ACL "a2"
 >>>  end of ACL "a2": implicit DENY
 LOG: H=(test) [V4NET.0.0.0] F=<> rejected RCPT <a2@b>
 >>>  deny: condition test failed in ACL "a2"
 >>>  end of ACL "a2": implicit DENY
 LOG: H=(test) [V4NET.0.0.0] F=<> rejected RCPT <a2@b>
+>>>  using ACL "a3"
+>>>  processing "deny" (TESTSUITE/test-config 23)
+>>>  check hosts = <; fe80::1
+>>>  host in "<; fe80::1"?
+>>>   list element: fe80::1
+>>>  host in "<; fe80::1"? no (end of list)
+>>>  deny: condition test failed in ACL "a3"
+>>>  end of ACL "a3": implicit DENY
+LOG: H=(test) [V4NET.0.0.0] F=<> rejected RCPT <a3@b>
+>>>  using ACL "a4"
+>>>  processing "deny" (TESTSUITE/test-config 26)
+>>>  check hosts = <; fe80:1
+>>>  host in "<; fe80:1"?
+>>>   list element: fe80:1
+>>>   host in "<; fe80:1"? no (malformed IPv6 address or address mask: fe80:1)
+LOG: list matching forced to fail: malformed IPv6 address or address mask: fe80:1
+>>>   deny: condition test failed in ACL "a4"
+>>>   end of ACL "a4": implicit DENY
+LOG: H=(test) [V4NET.0.0.0] F=<> rejected RCPT <a4@b>
index d5bb0605c5fac58628816137f1b82047fb21a368..a79a5c733e66e4d8aef79316da65d54ab10b5985 100644 (file)
@@ -466,6 +466,7 @@ newline     tab\134backslash ~tilde\177DEL\200\201.
 > isip:   y  fe80::a00:20ff:fe86:a061
 > isip4:  n  fe80::a00:20ff:fe86:a061
 > isip6:  y  fe80::a00:20ff:fe86:a061
 > isip:   y  fe80::a00:20ff:fe86:a061
 > isip4:  n  fe80::a00:20ff:fe86:a061
 > isip6:  y  fe80::a00:20ff:fe86:a061
+> isip6:  n   fe80:a00:20ff:fe86:a061
 > isip:   y  fe80::1.2.3.4
 > isip:   n  rhubarb
 > isip4:  n  rhubarb
 > isip:   y  fe80::1.2.3.4
 > isip:   n  rhubarb
 > isip4:  n  rhubarb
@@ -1091,6 +1092,7 @@ xyz
 221 myhost.test.ex closing connection\r
 > match_ip:        15 
 > match_ip:        16 
 221 myhost.test.ex closing connection\r
 > match_ip:        15 
 > match_ip:        16 
+> match_ip:        17 
 > 
 > in list
 > in list
 > 
 > in list
 > in list
index 819cea3bcc8e57ee1301d9daca823c099cd539e1..d1f718997a22e171863ed4d7d5d64b51b78aaf0d 100644 (file)
@@ -8,4 +8,6 @@
 250 OK\r
 451 Temporary local problem - please try later\r
 550 Administrative prohibition\r
 250 OK\r
 451 Temporary local problem - please try later\r
 550 Administrative prohibition\r
+550 Administrative prohibition\r
+550 Administrative prohibition\r
 221 the.local.host.name closing connection\r
 221 the.local.host.name closing connection\r