From 2d65235ef91882fbdae07310ea21424dbfb9b32d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Arkadiusz=20Mi=C5=9Bkiewicz?= Date: Mon, 25 Apr 2022 11:55:24 +0200 Subject: [PATCH] Rel 4; backport seeen from upcoming 4.95. Also show line length breaches. --- exim.spec | 8 +- linelength-show.patch | 15 + seen.patch | 635 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 655 insertions(+), 3 deletions(-) create mode 100644 linelength-show.patch create mode 100644 seen.patch diff --git a/exim.spec b/exim.spec index 31b48ad..16de1bb 100644 --- a/exim.spec +++ b/exim.spec @@ -24,7 +24,7 @@ Summary(pl.UTF-8): Agent Transferu Poczty Uniwersytetu w Cambridge Summary(pt_BR.UTF-8): Servidor de correio eletrônico exim Name: exim Version: 4.95 -Release: 3 +Release: 4 Epoch: 2 License: GPL v2+ Group: Networking/Daemons/SMTP @@ -59,8 +59,9 @@ Patch4: %{name}4-Makefile-Default.patch # http://marc.merlins.org/linux/exim/files/sa-exim-cvs/localscan_dlopen_exim_4.20_or_better.patch Patch5: localscan_dlopen_%{name}_4.20_or_better.patch Patch6: ssl.patch - +Patch7: linelength-show.patch Patch8: %{name}-spam-timeout.patch +Patch9: seen.patch Patch20: %{name}4-disableSSLv3.patch URL: http://www.exim.org/ @@ -184,8 +185,9 @@ Pliki nagłówkowe dla Exima. %patch4 -p1 %patch5 -p1 %patch6 -p1 - +%patch7 -p1 %patch8 -p1 +%patch9 -p2 install %{SOURCE4} exim4.conf install %{SOURCE14} doc/config.samples.tar.bz2 diff --git a/linelength-show.patch b/linelength-show.patch new file mode 100644 index 0000000..19b8765 --- /dev/null +++ b/linelength-show.patch @@ -0,0 +1,15 @@ +diff --git a/src/transports/smtp.c b/src/transports/smtp.c +index 59abb9ef8..ad648755f 100644 +--- a/src/transports/smtp.c ++++ b/src/transports/smtp.c +@@ -5059,7 +5053,8 @@ if (max_received_linelength > ob->message_linelength_limit) + addr->transport_return = PENDING_DEFER; + + set_errno_nohost(addrlist, ERRNO_SMTPFORMAT, +- US"message has lines too long for transport", FAIL, TRUE, &now); ++ string_sprintf("message has lines too long for transport (received line length %d while limit is %d)", ++ max_received_linelength, ob->message_linelength_limit), FAIL, TRUE, &now); + goto END_TRANSPORT; + } + + diff --git a/seen.patch b/seen.patch new file mode 100644 index 0000000..7a2a7fa --- /dev/null +++ b/seen.patch @@ -0,0 +1,635 @@ +commit 2357aa78ccd7182cad14307eb89cb1065f078356 +Author: Jeremy Harris +Date: Sun Aug 1 18:15:39 2021 +0100 + + ACL: "seen" condition + +diff --git a/src/src/acl.c b/src/src/acl.c +index f47259ca0..be17b5768 100644 +--- a/src/src/acl.c ++++ b/src/src/acl.c +@@ -103,6 +103,7 @@ enum { ACLC_ACL, + ACLC_REGEX, + #endif + ACLC_REMOVE_HEADER, ++ ACLC_SEEN, + ACLC_SENDER_DOMAINS, + ACLC_SENDERS, + ACLC_SET, +@@ -288,6 +289,7 @@ static condition_def conditions[] = { + ACL_BIT_MIME | ACL_BIT_NOTSMTP | + ACL_BIT_NOTSMTP_START), + }, ++ [ACLC_SEEN] = { US"seen", TRUE, FALSE, 0 }, + [ACLC_SENDER_DOMAINS] = { US"sender_domains", FALSE, FALSE, + ACL_BIT_AUTH | ACL_BIT_CONNECT | + ACL_BIT_HELO | +@@ -2815,6 +2817,143 @@ return rc; + + + ++/************************************************* ++* Handle a check for previously-seen * ++*************************************************/ ++ ++/* ++ACL clauses like: seen = -5m / key=$foo / readonly ++ ++Return is true for condition-true - but the semantics ++depend heavily on the actual use-case. ++ ++Negative times test for seen-before, positive for seen-more-recently-than ++(the given interval before current time). ++ ++All are subject to history not having been cleaned from the DB. ++ ++Default for seen-before is to create if not present, and to ++update if older than 10d (with the seen-test time). ++Default for seen-since is to always create or update. ++ ++Options: ++ key=value. Default key is $sender_host_address ++ readonly ++ write ++ refresh=: update an existing DB entry older than given ++ amount. Default refresh lacking this option is 10d. ++ The update sets the record timestamp to the seen-test time. ++ ++XXX do we need separate nocreate, noupdate controls? ++ ++Arguments: ++ arg the option string for seen= ++ where ACL_WHERE_xxxx indicating which ACL this is ++ log_msgptr for error messages ++ ++Returns: OK - Condition is true ++ FAIL - Condition is false ++ DEFER - Problem opening history database ++ ERROR - Syntax error in options ++*/ ++ ++static int ++acl_seen(const uschar * arg, int where, uschar ** log_msgptr) ++{ ++enum { SEEN_DEFAULT, SEEN_READONLY, SEEN_WRITE }; ++ ++const uschar * list = arg; ++int slash = '/', equal = '=', interval, mode = SEEN_DEFAULT, yield = FAIL; ++BOOL before; ++int refresh = 10 * 24 * 60 * 60; /* 10 days */ ++const uschar * ele, * key = sender_host_address; ++open_db dbblock, * dbm; ++dbdata_seen * dbd; ++time_t now; ++ ++/* Parse the first element, the time-relation. */ ++ ++if (!(ele = string_nextinlist(&list, &slash, NULL, 0))) ++ goto badparse; ++if ((before = *ele == '-')) ++ ele++; ++if ((interval = readconf_readtime(ele, 0, FALSE)) < 0) ++ goto badparse; ++ ++/* Remaining elements are options */ ++ ++while ((ele = string_nextinlist(&list, &slash, NULL, 0))) ++ if (Ustrncmp(ele, "key=", 4) == 0) ++ key = ele + 4; ++ else if (Ustrcmp(ele, "readonly") == 0) ++ mode = SEEN_READONLY; ++ else if (Ustrcmp(ele, "write") == 0) ++ mode = SEEN_WRITE; ++ else if (Ustrncmp(ele, "refresh=", 8) == 0) ++ { ++ if ((refresh = readconf_readtime(ele + 8, 0, FALSE)) < 0) ++ goto badparse; ++ } ++ else ++ goto badopt; ++ ++if (!(dbm = dbfn_open(US"seen", O_RDWR, &dbblock, TRUE, TRUE))) ++ { ++ HDEBUG(D_acl) debug_printf_indent("database for 'seen' not available\n"); ++ *log_msgptr = US"database for 'seen' not available"; ++ return DEFER; ++ } ++ ++dbd = dbfn_read_with_length(dbm, key, NULL); ++now = time(NULL); ++if (dbd) /* an existing record */ ++ { ++ time_t diff = now - dbd->time_stamp; /* time since the record was written */ ++ ++ if (before ? diff >= interval : diff < interval) ++ yield = OK; ++ ++ if (mode == SEEN_READONLY) ++ { HDEBUG(D_acl) debug_printf_indent("seen db not written (readonly)\n"); } ++ else if (mode == SEEN_WRITE || !before) ++ { ++ dbd->time_stamp = now; ++ dbfn_write(dbm, key, dbd, sizeof(*dbd)); ++ HDEBUG(D_acl) debug_printf_indent("seen db written (update)\n"); ++ } ++ else if (diff >= refresh) ++ { ++ dbd->time_stamp = now - interval; ++ dbfn_write(dbm, key, dbd, sizeof(*dbd)); ++ HDEBUG(D_acl) debug_printf_indent("seen db written (refresh)\n"); ++ } ++ } ++else ++ { /* No record found, yield always FAIL */ ++ if (mode != SEEN_READONLY) ++ { ++ dbdata_seen d = {.time_stamp = now}; ++ dbfn_write(dbm, key, &d, sizeof(*dbd)); ++ HDEBUG(D_acl) debug_printf_indent("seen db written (create)\n"); ++ } ++ else ++ HDEBUG(D_acl) debug_printf_indent("seen db not written (readonly)\n"); ++ } ++ ++dbfn_close(dbm); ++return yield; ++ ++ ++badparse: ++ *log_msgptr = string_sprintf("failed to parse '%s'", arg); ++ return ERROR; ++badopt: ++ *log_msgptr = string_sprintf("unrecognised option '%s' in '%s'", ele, arg); ++ return ERROR; ++} ++ ++ ++ + /************************************************* + * The udpsend ACL modifier * + *************************************************/ +@@ -3740,6 +3879,10 @@ for (; cb; cb = cb->next) + setup_remove_header(arg); + break; + ++ case ACLC_SEEN: ++ rc = acl_seen(arg, where, log_msgptr); ++ break; ++ + case ACLC_SENDER_DOMAINS: + { + uschar *sdomain; +diff --git a/src/src/dbstuff.h b/src/src/dbstuff.h +index 2f00dffb4..94db7f7fd 100644 +--- a/src/src/dbstuff.h ++++ b/src/src/dbstuff.h +@@ -788,6 +788,12 @@ typedef struct { + uschar bloom[40]; /* Bloom filter which may be larger than this */ + } dbdata_ratelimit_unique; + ++ ++/* For "seen" ACL condition */ ++typedef struct { ++ time_t time_stamp; ++} dbdata_seen; ++ + #ifndef DISABLE_PIPE_CONNECT + /* This structure records the EHLO responses, cleartext and crypted, + for an IP, as bitmasks (cf. OPTION_TLS). For LIMITS, also values +diff --git a/src/src/exim_dbutil.c b/src/src/exim_dbutil.c +index 13f74540e..45b778fc0 100644 +--- a/src/src/exim_dbutil.c ++++ b/src/src/exim_dbutil.c +@@ -21,7 +21,9 @@ argument is the name of the database file. The available names are: + misc: miscellaneous hints data + wait-: message waiting information; is a transport name + callout: callout verification cache ++ ratelimit: ACL 'ratelimit' condition + tls: TLS session resumption cache ++ seen: ACL 'seen' condition + + There are a number of common subroutines, followed by three main programs, + whose inclusion is controlled by -D on the compilation command. */ +@@ -38,6 +40,7 @@ whose inclusion is controlled by -D on the compilation command. */ + #define type_callout 4 + #define type_ratelimit 5 + #define type_tls 6 ++#define type_seen 7 + + + /* This is used by our cut-down dbfn_open(). */ +@@ -126,7 +129,7 @@ static void + usage(uschar *name, uschar *options) + { + printf("Usage: exim_%s%s \n", name, options); +-printf(" = retry | misc | wait- | callout | ratelimit | tls\n"); ++printf(" = retry | misc | wait- | callout | ratelimit | tls | seen\n"); + exit(1); + } + +@@ -150,6 +153,7 @@ if (argc == 3) + if (Ustrcmp(argv[2], "callout") == 0) return type_callout; + if (Ustrcmp(argv[2], "ratelimit") == 0) return type_ratelimit; + if (Ustrcmp(argv[2], "tls") == 0) return type_tls; ++ if (Ustrcmp(argv[2], "seen") == 0) return type_seen; + } + usage(name, options); + return -1; /* Never obeyed */ +@@ -581,6 +585,7 @@ for (uschar * key = dbfn_scan(dbm, TRUE, &cursor); + dbdata_ratelimit *ratelimit; + dbdata_ratelimit_unique *rate_unique; + dbdata_tls_session *session; ++ dbdata_seen *seen; + int count_bad = 0; + int length; + uschar *t; +@@ -720,6 +725,11 @@ for (uschar * key = dbfn_scan(dbm, TRUE, &cursor); + session = (dbdata_tls_session *)value; + printf(" %s %.*s\n", keybuffer, length, session->session); + break; ++ ++ case type_seen: ++ seen = (dbdata_seen *)value; ++ printf("%s\t%s\n", keybuffer, print_time(seen->time_stamp)); ++ break; + } + } + store_reset(reset_point); +diff --git a/test/confs/0626 b/test/confs/0626 +new file mode 100644 +index 000000000..872c4b20a +--- /dev/null ++++ b/test/confs/0626 +@@ -0,0 +1,31 @@ ++# Exim test configuration 0626 ++# ACL seen condition ++ ++.include DIR/aux-var/std_conf_prefix ++ ++ ++# ----- Main settings ----- ++ ++primary_hostname = test.ex ++queue_only ++ ++acl_smtp_rcpt = chk_rcpt ++ ++# ----- ACL ----- ++ ++begin acl ++ ++chk_rcpt: ++ accept seen = OPT ++ ++# seen = never / $sender_host_addreee / per_call ++# seen = before=10s ++# seen = before=10s / write ++# seen = since / readonly ++# ++# seen = -10s ++# seen = -10s / readonly ++# seen = 2s ++# seen = 0s / update=20d ++# ++# End +diff --git a/test/scripts/0000-Basic/0626 b/test/scripts/0000-Basic/0626 +new file mode 100644 +index 000000000..6da58ee48 +--- /dev/null ++++ b/test/scripts/0000-Basic/0626 +@@ -0,0 +1,82 @@ ++# ACL 'seen' condition ++# ++exim -DOPT='-1s' -bh 127.0.0.1 ++HELO test ++MAIL FROM: ++RCPT TO: ++QUIT ++**** ++# Check that a hints DB was created. ++# Only the key is useful thanks to munging; should match the IP used above. ++dump seen ++# ++sleep 1 ++# should now see old-enough record ++exim -DOPT='-1s' -bh 127.0.0.1 ++HELO test ++MAIL FROM: ++RCPT TO: ++QUIT ++**** ++# force an update (visible via debug output in stdout for -bh) ++exim -DOPT='-1s / write' -bh 127.0.0.1 ++HELO test ++MAIL FROM: ++RCPT TO: ++QUIT ++**** ++# default key should change with ip ++exim -DOPT='-1s' -bh HOSTIPV4 ++HELO test ++MAIL FROM: ++RCPT TO: ++QUIT ++**** ++dump seen ++# explicit key (also checking expansion) ++exim -DOPT='-1s / key=${sender_host_address}_foo' -bh 127.0.0.1 ++HELO test ++MAIL FROM: ++RCPT TO: ++QUIT ++**** ++dump seen ++# check refresh ++sleep 1 ++exim -DOPT='-1s / refresh=1s' -bh 127.0.0.1 ++HELO test ++MAIL FROM: ++RCPT TO: ++QUIT ++**** ++# ++# ++# ++# ++# ++# test for seen-more-recently-than ++# that previous one should be no older than 5s, so this should pass ++# do not update ++# check list-parsing spaceless while we're here ++exim -DOPT='5s/key=${sender_host_address}_foo/readonly' -bh 127.0.0.1 ++HELO test ++MAIL FROM: ++RCPT TO: ++QUIT ++**** ++# check the above no-update by waiting longer than the later-than interval; should fail ++# should update ++sleep 2 ++exim -DOPT='1s / key=${sender_host_address}_foo' -bh 127.0.0.1 ++HELO test ++MAIL FROM: ++RCPT TO: ++QUIT ++**** ++# having updated, should pass ++exim -DOPT='1s / key=${sender_host_address}_foo' -bh 127.0.0.1 ++HELO test ++MAIL FROM: ++RCPT TO: ++QUIT ++**** +diff --git a/test/stderr/0626 b/test/stderr/0626 +new file mode 100644 +index 000000000..25e96bc4e +--- /dev/null ++++ b/test/stderr/0626 +@@ -0,0 +1,142 @@ ++>>> host in hosts_connection_nolog? no (option unset) ++>>> host in host_lookup? no (option unset) ++>>> host in host_reject_connection? no (option unset) ++>>> host in sender_unqualified_hosts? no (option unset) ++>>> host in recipient_unqualified_hosts? no (option unset) ++>>> host in helo_verify_hosts? no (option unset) ++>>> host in helo_try_verify_hosts? no (option unset) ++>>> host in helo_accept_junk_hosts? no (option unset) ++>>> test in helo_lookup_domains? no (end of list) ++>>> using ACL "chk_rcpt" ++>>> processing "accept" (TESTSUITE/test-config 19) ++>>> check seen = -1s ++>>> seen db written (create) ++>>> accept: condition test failed in ACL "chk_rcpt" ++>>> end of ACL "chk_rcpt": implicit DENY ++LOG: H=(test) [127.0.0.1] F= rejected RCPT ++>>> host in hosts_connection_nolog? no (option unset) ++>>> host in host_lookup? no (option unset) ++>>> host in host_reject_connection? no (option unset) ++>>> host in sender_unqualified_hosts? no (option unset) ++>>> host in recipient_unqualified_hosts? no (option unset) ++>>> host in helo_verify_hosts? no (option unset) ++>>> host in helo_try_verify_hosts? no (option unset) ++>>> host in helo_accept_junk_hosts? no (option unset) ++>>> test in helo_lookup_domains? no (end of list) ++>>> using ACL "chk_rcpt" ++>>> processing "accept" (TESTSUITE/test-config 19) ++>>> check seen = -1s ++>>> accept: condition test succeeded in ACL "chk_rcpt" ++>>> end of ACL "chk_rcpt": ACCEPT ++>>> host in hosts_connection_nolog? no (option unset) ++>>> host in host_lookup? no (option unset) ++>>> host in host_reject_connection? no (option unset) ++>>> host in sender_unqualified_hosts? no (option unset) ++>>> host in recipient_unqualified_hosts? no (option unset) ++>>> host in helo_verify_hosts? no (option unset) ++>>> host in helo_try_verify_hosts? no (option unset) ++>>> host in helo_accept_junk_hosts? no (option unset) ++>>> test in helo_lookup_domains? no (end of list) ++>>> using ACL "chk_rcpt" ++>>> processing "accept" (TESTSUITE/test-config 19) ++>>> check seen = -1s / write ++>>> seen db written (update) ++>>> accept: condition test succeeded in ACL "chk_rcpt" ++>>> end of ACL "chk_rcpt": ACCEPT ++>>> host in hosts_connection_nolog? no (option unset) ++>>> host in host_lookup? no (option unset) ++>>> host in host_reject_connection? no (option unset) ++>>> host in sender_unqualified_hosts? no (option unset) ++>>> host in recipient_unqualified_hosts? no (option unset) ++>>> host in helo_verify_hosts? no (option unset) ++>>> host in helo_try_verify_hosts? no (option unset) ++>>> host in helo_accept_junk_hosts? no (option unset) ++>>> test in helo_lookup_domains? no (end of list) ++>>> using ACL "chk_rcpt" ++>>> processing "accept" (TESTSUITE/test-config 19) ++>>> check seen = -1s ++>>> seen db written (create) ++>>> accept: condition test failed in ACL "chk_rcpt" ++>>> end of ACL "chk_rcpt": implicit DENY ++LOG: H=(test) [ip4.ip4.ip4.ip4] F= rejected RCPT ++>>> host in hosts_connection_nolog? no (option unset) ++>>> host in host_lookup? no (option unset) ++>>> host in host_reject_connection? no (option unset) ++>>> host in sender_unqualified_hosts? no (option unset) ++>>> host in recipient_unqualified_hosts? no (option unset) ++>>> host in helo_verify_hosts? no (option unset) ++>>> host in helo_try_verify_hosts? no (option unset) ++>>> host in helo_accept_junk_hosts? no (option unset) ++>>> test in helo_lookup_domains? no (end of list) ++>>> using ACL "chk_rcpt" ++>>> processing "accept" (TESTSUITE/test-config 19) ++>>> check seen = -1s / key=${sender_host_address}_foo ++>>> = -1s / key=127.0.0.1_foo ++>>> seen db written (create) ++>>> accept: condition test failed in ACL "chk_rcpt" ++>>> end of ACL "chk_rcpt": implicit DENY ++LOG: H=(test) [127.0.0.1] F= rejected RCPT ++>>> host in hosts_connection_nolog? no (option unset) ++>>> host in host_lookup? no (option unset) ++>>> host in host_reject_connection? no (option unset) ++>>> host in sender_unqualified_hosts? no (option unset) ++>>> host in recipient_unqualified_hosts? no (option unset) ++>>> host in helo_verify_hosts? no (option unset) ++>>> host in helo_try_verify_hosts? no (option unset) ++>>> host in helo_accept_junk_hosts? no (option unset) ++>>> test in helo_lookup_domains? no (end of list) ++>>> using ACL "chk_rcpt" ++>>> processing "accept" (TESTSUITE/test-config 19) ++>>> check seen = -1s / refresh=1s ++>>> seen db written (refresh) ++>>> accept: condition test succeeded in ACL "chk_rcpt" ++>>> end of ACL "chk_rcpt": ACCEPT ++>>> host in hosts_connection_nolog? no (option unset) ++>>> host in host_lookup? no (option unset) ++>>> host in host_reject_connection? no (option unset) ++>>> host in sender_unqualified_hosts? no (option unset) ++>>> host in recipient_unqualified_hosts? no (option unset) ++>>> host in helo_verify_hosts? no (option unset) ++>>> host in helo_try_verify_hosts? no (option unset) ++>>> host in helo_accept_junk_hosts? no (option unset) ++>>> test in helo_lookup_domains? no (end of list) ++>>> using ACL "chk_rcpt" ++>>> processing "accept" (TESTSUITE/test-config 19) ++>>> check seen = 5s/key=${sender_host_address}_foo/readonly ++>>> = 5s/key=127.0.0.1_foo/readonly ++>>> seen db not written (readonly) ++>>> accept: condition test succeeded in ACL "chk_rcpt" ++>>> end of ACL "chk_rcpt": ACCEPT ++>>> host in hosts_connection_nolog? no (option unset) ++>>> host in host_lookup? no (option unset) ++>>> host in host_reject_connection? no (option unset) ++>>> host in sender_unqualified_hosts? no (option unset) ++>>> host in recipient_unqualified_hosts? no (option unset) ++>>> host in helo_verify_hosts? no (option unset) ++>>> host in helo_try_verify_hosts? no (option unset) ++>>> host in helo_accept_junk_hosts? no (option unset) ++>>> test in helo_lookup_domains? no (end of list) ++>>> using ACL "chk_rcpt" ++>>> processing "accept" (TESTSUITE/test-config 19) ++>>> check seen = 1s / key=${sender_host_address}_foo ++>>> = 1s / key=127.0.0.1_foo ++>>> seen db written (update) ++>>> accept: condition test failed in ACL "chk_rcpt" ++>>> end of ACL "chk_rcpt": implicit DENY ++LOG: H=(test) [127.0.0.1] F= rejected RCPT ++>>> host in hosts_connection_nolog? no (option unset) ++>>> host in host_lookup? no (option unset) ++>>> host in host_reject_connection? no (option unset) ++>>> host in sender_unqualified_hosts? no (option unset) ++>>> host in recipient_unqualified_hosts? no (option unset) ++>>> host in helo_verify_hosts? no (option unset) ++>>> host in helo_try_verify_hosts? no (option unset) ++>>> host in helo_accept_junk_hosts? no (option unset) ++>>> test in helo_lookup_domains? no (end of list) ++>>> using ACL "chk_rcpt" ++>>> processing "accept" (TESTSUITE/test-config 19) ++>>> check seen = 1s / key=${sender_host_address}_foo ++>>> = 1s / key=127.0.0.1_foo ++>>> seen db written (update) ++>>> accept: condition test succeeded in ACL "chk_rcpt" ++>>> end of ACL "chk_rcpt": ACCEPT +diff --git a/test/stdout/0626 b/test/stdout/0626 +new file mode 100644 +index 000000000..44b481f31 +--- /dev/null ++++ b/test/stdout/0626 +@@ -0,0 +1,99 @@ ++ ++**** SMTP testing session as if from host 127.0.0.1 ++**** but without any ident (RFC 1413) callback. ++**** This is not for real! ++ ++220 test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 ++250 test.ex Hello test [127.0.0.1] ++250 OK ++550 Administrative prohibition ++221 test.ex closing connection +++++++++++++++++++++++++++++ ++127.0.0.1 07-Mar-2000 12:21:52 ++ ++**** SMTP testing session as if from host 127.0.0.1 ++**** but without any ident (RFC 1413) callback. ++**** This is not for real! ++ ++220 test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 ++250 test.ex Hello test [127.0.0.1] ++250 OK ++250 Accepted ++221 test.ex closing connection ++ ++**** SMTP testing session as if from host 127.0.0.1 ++**** but without any ident (RFC 1413) callback. ++**** This is not for real! ++ ++220 test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 ++250 test.ex Hello test [127.0.0.1] ++250 OK ++250 Accepted ++221 test.ex closing connection ++ ++**** SMTP testing session as if from host ip4.ip4.ip4.ip4 ++**** but without any ident (RFC 1413) callback. ++**** This is not for real! ++ ++220 test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 ++250 test.ex Hello test [ip4.ip4.ip4.ip4] ++250 OK ++550 Administrative prohibition ++221 test.ex closing connection +++++++++++++++++++++++++++++ ++ip4.ip4.ip4.ip4 07-Mar-2000 12:21:52 ++127.0.0.1 07-Mar-2000 12:21:52 ++ ++**** SMTP testing session as if from host 127.0.0.1 ++**** but without any ident (RFC 1413) callback. ++**** This is not for real! ++ ++220 test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 ++250 test.ex Hello test [127.0.0.1] ++250 OK ++550 Administrative prohibition ++221 test.ex closing connection +++++++++++++++++++++++++++++ ++127.0.0.1_foo 07-Mar-2000 12:21:52 ++ip4.ip4.ip4.ip4 07-Mar-2000 12:21:52 ++127.0.0.1 07-Mar-2000 12:21:52 ++ ++**** SMTP testing session as if from host 127.0.0.1 ++**** but without any ident (RFC 1413) callback. ++**** This is not for real! ++ ++220 test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 ++250 test.ex Hello test [127.0.0.1] ++250 OK ++250 Accepted ++221 test.ex closing connection ++ ++**** SMTP testing session as if from host 127.0.0.1 ++**** but without any ident (RFC 1413) callback. ++**** This is not for real! ++ ++220 test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 ++250 test.ex Hello test [127.0.0.1] ++250 OK ++250 Accepted ++221 test.ex closing connection ++ ++**** SMTP testing session as if from host 127.0.0.1 ++**** but without any ident (RFC 1413) callback. ++**** This is not for real! ++ ++220 test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 ++250 test.ex Hello test [127.0.0.1] ++250 OK ++550 Administrative prohibition ++221 test.ex closing connection ++ ++**** SMTP testing session as if from host 127.0.0.1 ++**** but without any ident (RFC 1413) callback. ++**** This is not for real! ++ ++220 test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 ++250 test.ex Hello test [127.0.0.1] ++250 OK ++250 Accepted ++221 test.ex closing connection -- 2.43.0