]> git.pld-linux.org Git - packages/exim.git/blame - seen.patch
Rel 4; backport seeen from upcoming 4.95. Also show line length
[packages/exim.git] / seen.patch
CommitLineData
2d65235e
AM
1commit 2357aa78ccd7182cad14307eb89cb1065f078356
2Author: Jeremy Harris <jgh146exb@wizmail.org>
3Date: Sun Aug 1 18:15:39 2021 +0100
4
5 ACL: "seen" condition
6
7diff --git a/src/src/acl.c b/src/src/acl.c
8index f47259ca0..be17b5768 100644
9--- a/src/src/acl.c
10+++ b/src/src/acl.c
11@@ -103,6 +103,7 @@ enum { ACLC_ACL,
12 ACLC_REGEX,
13 #endif
14 ACLC_REMOVE_HEADER,
15+ ACLC_SEEN,
16 ACLC_SENDER_DOMAINS,
17 ACLC_SENDERS,
18 ACLC_SET,
19@@ -288,6 +289,7 @@ static condition_def conditions[] = {
20 ACL_BIT_MIME | ACL_BIT_NOTSMTP |
21 ACL_BIT_NOTSMTP_START),
22 },
23+ [ACLC_SEEN] = { US"seen", TRUE, FALSE, 0 },
24 [ACLC_SENDER_DOMAINS] = { US"sender_domains", FALSE, FALSE,
25 ACL_BIT_AUTH | ACL_BIT_CONNECT |
26 ACL_BIT_HELO |
27@@ -2815,6 +2817,143 @@ return rc;
28
29
30
31+/*************************************************
32+* Handle a check for previously-seen *
33+*************************************************/
34+
35+/*
36+ACL clauses like: seen = -5m / key=$foo / readonly
37+
38+Return is true for condition-true - but the semantics
39+depend heavily on the actual use-case.
40+
41+Negative times test for seen-before, positive for seen-more-recently-than
42+(the given interval before current time).
43+
44+All are subject to history not having been cleaned from the DB.
45+
46+Default for seen-before is to create if not present, and to
47+update if older than 10d (with the seen-test time).
48+Default for seen-since is to always create or update.
49+
50+Options:
51+ key=value. Default key is $sender_host_address
52+ readonly
53+ write
54+ refresh=<interval>: update an existing DB entry older than given
55+ amount. Default refresh lacking this option is 10d.
56+ The update sets the record timestamp to the seen-test time.
57+
58+XXX do we need separate nocreate, noupdate controls?
59+
60+Arguments:
61+ arg the option string for seen=
62+ where ACL_WHERE_xxxx indicating which ACL this is
63+ log_msgptr for error messages
64+
65+Returns: OK - Condition is true
66+ FAIL - Condition is false
67+ DEFER - Problem opening history database
68+ ERROR - Syntax error in options
69+*/
70+
71+static int
72+acl_seen(const uschar * arg, int where, uschar ** log_msgptr)
73+{
74+enum { SEEN_DEFAULT, SEEN_READONLY, SEEN_WRITE };
75+
76+const uschar * list = arg;
77+int slash = '/', equal = '=', interval, mode = SEEN_DEFAULT, yield = FAIL;
78+BOOL before;
79+int refresh = 10 * 24 * 60 * 60; /* 10 days */
80+const uschar * ele, * key = sender_host_address;
81+open_db dbblock, * dbm;
82+dbdata_seen * dbd;
83+time_t now;
84+
85+/* Parse the first element, the time-relation. */
86+
87+if (!(ele = string_nextinlist(&list, &slash, NULL, 0)))
88+ goto badparse;
89+if ((before = *ele == '-'))
90+ ele++;
91+if ((interval = readconf_readtime(ele, 0, FALSE)) < 0)
92+ goto badparse;
93+
94+/* Remaining elements are options */
95+
96+while ((ele = string_nextinlist(&list, &slash, NULL, 0)))
97+ if (Ustrncmp(ele, "key=", 4) == 0)
98+ key = ele + 4;
99+ else if (Ustrcmp(ele, "readonly") == 0)
100+ mode = SEEN_READONLY;
101+ else if (Ustrcmp(ele, "write") == 0)
102+ mode = SEEN_WRITE;
103+ else if (Ustrncmp(ele, "refresh=", 8) == 0)
104+ {
105+ if ((refresh = readconf_readtime(ele + 8, 0, FALSE)) < 0)
106+ goto badparse;
107+ }
108+ else
109+ goto badopt;
110+
111+if (!(dbm = dbfn_open(US"seen", O_RDWR, &dbblock, TRUE, TRUE)))
112+ {
113+ HDEBUG(D_acl) debug_printf_indent("database for 'seen' not available\n");
114+ *log_msgptr = US"database for 'seen' not available";
115+ return DEFER;
116+ }
117+
118+dbd = dbfn_read_with_length(dbm, key, NULL);
119+now = time(NULL);
120+if (dbd) /* an existing record */
121+ {
122+ time_t diff = now - dbd->time_stamp; /* time since the record was written */
123+
124+ if (before ? diff >= interval : diff < interval)
125+ yield = OK;
126+
127+ if (mode == SEEN_READONLY)
128+ { HDEBUG(D_acl) debug_printf_indent("seen db not written (readonly)\n"); }
129+ else if (mode == SEEN_WRITE || !before)
130+ {
131+ dbd->time_stamp = now;
132+ dbfn_write(dbm, key, dbd, sizeof(*dbd));
133+ HDEBUG(D_acl) debug_printf_indent("seen db written (update)\n");
134+ }
135+ else if (diff >= refresh)
136+ {
137+ dbd->time_stamp = now - interval;
138+ dbfn_write(dbm, key, dbd, sizeof(*dbd));
139+ HDEBUG(D_acl) debug_printf_indent("seen db written (refresh)\n");
140+ }
141+ }
142+else
143+ { /* No record found, yield always FAIL */
144+ if (mode != SEEN_READONLY)
145+ {
146+ dbdata_seen d = {.time_stamp = now};
147+ dbfn_write(dbm, key, &d, sizeof(*dbd));
148+ HDEBUG(D_acl) debug_printf_indent("seen db written (create)\n");
149+ }
150+ else
151+ HDEBUG(D_acl) debug_printf_indent("seen db not written (readonly)\n");
152+ }
153+
154+dbfn_close(dbm);
155+return yield;
156+
157+
158+badparse:
159+ *log_msgptr = string_sprintf("failed to parse '%s'", arg);
160+ return ERROR;
161+badopt:
162+ *log_msgptr = string_sprintf("unrecognised option '%s' in '%s'", ele, arg);
163+ return ERROR;
164+}
165+
166+
167+
168 /*************************************************
169 * The udpsend ACL modifier *
170 *************************************************/
171@@ -3740,6 +3879,10 @@ for (; cb; cb = cb->next)
172 setup_remove_header(arg);
173 break;
174
175+ case ACLC_SEEN:
176+ rc = acl_seen(arg, where, log_msgptr);
177+ break;
178+
179 case ACLC_SENDER_DOMAINS:
180 {
181 uschar *sdomain;
182diff --git a/src/src/dbstuff.h b/src/src/dbstuff.h
183index 2f00dffb4..94db7f7fd 100644
184--- a/src/src/dbstuff.h
185+++ b/src/src/dbstuff.h
186@@ -788,6 +788,12 @@ typedef struct {
187 uschar bloom[40]; /* Bloom filter which may be larger than this */
188 } dbdata_ratelimit_unique;
189
190+
191+/* For "seen" ACL condition */
192+typedef struct {
193+ time_t time_stamp;
194+} dbdata_seen;
195+
196 #ifndef DISABLE_PIPE_CONNECT
197 /* This structure records the EHLO responses, cleartext and crypted,
198 for an IP, as bitmasks (cf. OPTION_TLS). For LIMITS, also values
199diff --git a/src/src/exim_dbutil.c b/src/src/exim_dbutil.c
200index 13f74540e..45b778fc0 100644
201--- a/src/src/exim_dbutil.c
202+++ b/src/src/exim_dbutil.c
203@@ -21,7 +21,9 @@ argument is the name of the database file. The available names are:
204 misc: miscellaneous hints data
205 wait-<t>: message waiting information; <t> is a transport name
206 callout: callout verification cache
207+ ratelimit: ACL 'ratelimit' condition
208 tls: TLS session resumption cache
209+ seen: ACL 'seen' condition
210
211 There are a number of common subroutines, followed by three main programs,
212 whose inclusion is controlled by -D on the compilation command. */
213@@ -38,6 +40,7 @@ whose inclusion is controlled by -D on the compilation command. */
214 #define type_callout 4
215 #define type_ratelimit 5
216 #define type_tls 6
217+#define type_seen 7
218
219
220 /* This is used by our cut-down dbfn_open(). */
221@@ -126,7 +129,7 @@ static void
222 usage(uschar *name, uschar *options)
223 {
224 printf("Usage: exim_%s%s <spool-directory> <database-name>\n", name, options);
225-printf(" <database-name> = retry | misc | wait-<transport-name> | callout | ratelimit | tls\n");
226+printf(" <database-name> = retry | misc | wait-<transport-name> | callout | ratelimit | tls | seen\n");
227 exit(1);
228 }
229
230@@ -150,6 +153,7 @@ if (argc == 3)
231 if (Ustrcmp(argv[2], "callout") == 0) return type_callout;
232 if (Ustrcmp(argv[2], "ratelimit") == 0) return type_ratelimit;
233 if (Ustrcmp(argv[2], "tls") == 0) return type_tls;
234+ if (Ustrcmp(argv[2], "seen") == 0) return type_seen;
235 }
236 usage(name, options);
237 return -1; /* Never obeyed */
238@@ -581,6 +585,7 @@ for (uschar * key = dbfn_scan(dbm, TRUE, &cursor);
239 dbdata_ratelimit *ratelimit;
240 dbdata_ratelimit_unique *rate_unique;
241 dbdata_tls_session *session;
242+ dbdata_seen *seen;
243 int count_bad = 0;
244 int length;
245 uschar *t;
246@@ -720,6 +725,11 @@ for (uschar * key = dbfn_scan(dbm, TRUE, &cursor);
247 session = (dbdata_tls_session *)value;
248 printf(" %s %.*s\n", keybuffer, length, session->session);
249 break;
250+
251+ case type_seen:
252+ seen = (dbdata_seen *)value;
253+ printf("%s\t%s\n", keybuffer, print_time(seen->time_stamp));
254+ break;
255 }
256 }
257 store_reset(reset_point);
258diff --git a/test/confs/0626 b/test/confs/0626
259new file mode 100644
260index 000000000..872c4b20a
261--- /dev/null
262+++ b/test/confs/0626
263@@ -0,0 +1,31 @@
264+# Exim test configuration 0626
265+# ACL seen condition
266+
267+.include DIR/aux-var/std_conf_prefix
268+
269+
270+# ----- Main settings -----
271+
272+primary_hostname = test.ex
273+queue_only
274+
275+acl_smtp_rcpt = chk_rcpt
276+
277+# ----- ACL -----
278+
279+begin acl
280+
281+chk_rcpt:
282+ accept seen = OPT
283+
284+# seen = never / $sender_host_addreee / per_call
285+# seen = before=10s
286+# seen = before=10s / write
287+# seen = since / readonly
288+#
289+# seen = -10s
290+# seen = -10s / readonly
291+# seen = 2s
292+# seen = 0s / update=20d
293+#
294+# End
295diff --git a/test/scripts/0000-Basic/0626 b/test/scripts/0000-Basic/0626
296new file mode 100644
297index 000000000..6da58ee48
298--- /dev/null
299+++ b/test/scripts/0000-Basic/0626
300@@ -0,0 +1,82 @@
301+# ACL 'seen' condition
302+#
303+exim -DOPT='-1s' -bh 127.0.0.1
304+HELO test
305+MAIL FROM:<tester@test.ex>
306+RCPT TO:<a1@test.ex>
307+QUIT
308+****
309+# Check that a hints DB was created.
310+# Only the key is useful thanks to munging; should match the IP used above.
311+dump seen
312+#
313+sleep 1
314+# should now see old-enough record
315+exim -DOPT='-1s' -bh 127.0.0.1
316+HELO test
317+MAIL FROM:<tester@test.ex>
318+RCPT TO:<a1@test.ex>
319+QUIT
320+****
321+# force an update (visible via debug output in stdout for -bh)
322+exim -DOPT='-1s / write' -bh 127.0.0.1
323+HELO test
324+MAIL FROM:<tester@test.ex>
325+RCPT TO:<a1@test.ex>
326+QUIT
327+****
328+# default key should change with ip
329+exim -DOPT='-1s' -bh HOSTIPV4
330+HELO test
331+MAIL FROM:<tester@test.ex>
332+RCPT TO:<a1@test.ex>
333+QUIT
334+****
335+dump seen
336+# explicit key (also checking expansion)
337+exim -DOPT='-1s / key=${sender_host_address}_foo' -bh 127.0.0.1
338+HELO test
339+MAIL FROM:<tester@test.ex>
340+RCPT TO:<a1@test.ex>
341+QUIT
342+****
343+dump seen
344+# check refresh
345+sleep 1
346+exim -DOPT='-1s / refresh=1s' -bh 127.0.0.1
347+HELO test
348+MAIL FROM:<tester@test.ex>
349+RCPT TO:<a1@test.ex>
350+QUIT
351+****
352+#
353+#
354+#
355+#
356+#
357+# test for seen-more-recently-than
358+# that previous one should be no older than 5s, so this should pass
359+# do not update
360+# check list-parsing spaceless while we're here
361+exim -DOPT='5s/key=${sender_host_address}_foo/readonly' -bh 127.0.0.1
362+HELO test
363+MAIL FROM:<tester@test.ex>
364+RCPT TO:<a1@test.ex>
365+QUIT
366+****
367+# check the above no-update by waiting longer than the later-than interval; should fail
368+# should update
369+sleep 2
370+exim -DOPT='1s / key=${sender_host_address}_foo' -bh 127.0.0.1
371+HELO test
372+MAIL FROM:<tester@test.ex>
373+RCPT TO:<a1@test.ex>
374+QUIT
375+****
376+# having updated, should pass
377+exim -DOPT='1s / key=${sender_host_address}_foo' -bh 127.0.0.1
378+HELO test
379+MAIL FROM:<tester@test.ex>
380+RCPT TO:<a1@test.ex>
381+QUIT
382+****
383diff --git a/test/stderr/0626 b/test/stderr/0626
384new file mode 100644
385index 000000000..25e96bc4e
386--- /dev/null
387+++ b/test/stderr/0626
388@@ -0,0 +1,142 @@
389+>>> host in hosts_connection_nolog? no (option unset)
390+>>> host in host_lookup? no (option unset)
391+>>> host in host_reject_connection? no (option unset)
392+>>> host in sender_unqualified_hosts? no (option unset)
393+>>> host in recipient_unqualified_hosts? no (option unset)
394+>>> host in helo_verify_hosts? no (option unset)
395+>>> host in helo_try_verify_hosts? no (option unset)
396+>>> host in helo_accept_junk_hosts? no (option unset)
397+>>> test in helo_lookup_domains? no (end of list)
398+>>> using ACL "chk_rcpt"
399+>>> processing "accept" (TESTSUITE/test-config 19)
400+>>> check seen = -1s
401+>>> seen db written (create)
402+>>> accept: condition test failed in ACL "chk_rcpt"
403+>>> end of ACL "chk_rcpt": implicit DENY
404+LOG: H=(test) [127.0.0.1] F=<tester@test.ex> rejected RCPT <a1@test.ex>
405+>>> host in hosts_connection_nolog? no (option unset)
406+>>> host in host_lookup? no (option unset)
407+>>> host in host_reject_connection? no (option unset)
408+>>> host in sender_unqualified_hosts? no (option unset)
409+>>> host in recipient_unqualified_hosts? no (option unset)
410+>>> host in helo_verify_hosts? no (option unset)
411+>>> host in helo_try_verify_hosts? no (option unset)
412+>>> host in helo_accept_junk_hosts? no (option unset)
413+>>> test in helo_lookup_domains? no (end of list)
414+>>> using ACL "chk_rcpt"
415+>>> processing "accept" (TESTSUITE/test-config 19)
416+>>> check seen = -1s
417+>>> accept: condition test succeeded in ACL "chk_rcpt"
418+>>> end of ACL "chk_rcpt": ACCEPT
419+>>> host in hosts_connection_nolog? no (option unset)
420+>>> host in host_lookup? no (option unset)
421+>>> host in host_reject_connection? no (option unset)
422+>>> host in sender_unqualified_hosts? no (option unset)
423+>>> host in recipient_unqualified_hosts? no (option unset)
424+>>> host in helo_verify_hosts? no (option unset)
425+>>> host in helo_try_verify_hosts? no (option unset)
426+>>> host in helo_accept_junk_hosts? no (option unset)
427+>>> test in helo_lookup_domains? no (end of list)
428+>>> using ACL "chk_rcpt"
429+>>> processing "accept" (TESTSUITE/test-config 19)
430+>>> check seen = -1s / write
431+>>> seen db written (update)
432+>>> accept: condition test succeeded in ACL "chk_rcpt"
433+>>> end of ACL "chk_rcpt": ACCEPT
434+>>> host in hosts_connection_nolog? no (option unset)
435+>>> host in host_lookup? no (option unset)
436+>>> host in host_reject_connection? no (option unset)
437+>>> host in sender_unqualified_hosts? no (option unset)
438+>>> host in recipient_unqualified_hosts? no (option unset)
439+>>> host in helo_verify_hosts? no (option unset)
440+>>> host in helo_try_verify_hosts? no (option unset)
441+>>> host in helo_accept_junk_hosts? no (option unset)
442+>>> test in helo_lookup_domains? no (end of list)
443+>>> using ACL "chk_rcpt"
444+>>> processing "accept" (TESTSUITE/test-config 19)
445+>>> check seen = -1s
446+>>> seen db written (create)
447+>>> accept: condition test failed in ACL "chk_rcpt"
448+>>> end of ACL "chk_rcpt": implicit DENY
449+LOG: H=(test) [ip4.ip4.ip4.ip4] F=<tester@test.ex> rejected RCPT <a1@test.ex>
450+>>> host in hosts_connection_nolog? no (option unset)
451+>>> host in host_lookup? no (option unset)
452+>>> host in host_reject_connection? no (option unset)
453+>>> host in sender_unqualified_hosts? no (option unset)
454+>>> host in recipient_unqualified_hosts? no (option unset)
455+>>> host in helo_verify_hosts? no (option unset)
456+>>> host in helo_try_verify_hosts? no (option unset)
457+>>> host in helo_accept_junk_hosts? no (option unset)
458+>>> test in helo_lookup_domains? no (end of list)
459+>>> using ACL "chk_rcpt"
460+>>> processing "accept" (TESTSUITE/test-config 19)
461+>>> check seen = -1s / key=${sender_host_address}_foo
462+>>> = -1s / key=127.0.0.1_foo
463+>>> seen db written (create)
464+>>> accept: condition test failed in ACL "chk_rcpt"
465+>>> end of ACL "chk_rcpt": implicit DENY
466+LOG: H=(test) [127.0.0.1] F=<tester@test.ex> rejected RCPT <a1@test.ex>
467+>>> host in hosts_connection_nolog? no (option unset)
468+>>> host in host_lookup? no (option unset)
469+>>> host in host_reject_connection? no (option unset)
470+>>> host in sender_unqualified_hosts? no (option unset)
471+>>> host in recipient_unqualified_hosts? no (option unset)
472+>>> host in helo_verify_hosts? no (option unset)
473+>>> host in helo_try_verify_hosts? no (option unset)
474+>>> host in helo_accept_junk_hosts? no (option unset)
475+>>> test in helo_lookup_domains? no (end of list)
476+>>> using ACL "chk_rcpt"
477+>>> processing "accept" (TESTSUITE/test-config 19)
478+>>> check seen = -1s / refresh=1s
479+>>> seen db written (refresh)
480+>>> accept: condition test succeeded in ACL "chk_rcpt"
481+>>> end of ACL "chk_rcpt": ACCEPT
482+>>> host in hosts_connection_nolog? no (option unset)
483+>>> host in host_lookup? no (option unset)
484+>>> host in host_reject_connection? no (option unset)
485+>>> host in sender_unqualified_hosts? no (option unset)
486+>>> host in recipient_unqualified_hosts? no (option unset)
487+>>> host in helo_verify_hosts? no (option unset)
488+>>> host in helo_try_verify_hosts? no (option unset)
489+>>> host in helo_accept_junk_hosts? no (option unset)
490+>>> test in helo_lookup_domains? no (end of list)
491+>>> using ACL "chk_rcpt"
492+>>> processing "accept" (TESTSUITE/test-config 19)
493+>>> check seen = 5s/key=${sender_host_address}_foo/readonly
494+>>> = 5s/key=127.0.0.1_foo/readonly
495+>>> seen db not written (readonly)
496+>>> accept: condition test succeeded in ACL "chk_rcpt"
497+>>> end of ACL "chk_rcpt": ACCEPT
498+>>> host in hosts_connection_nolog? no (option unset)
499+>>> host in host_lookup? no (option unset)
500+>>> host in host_reject_connection? no (option unset)
501+>>> host in sender_unqualified_hosts? no (option unset)
502+>>> host in recipient_unqualified_hosts? no (option unset)
503+>>> host in helo_verify_hosts? no (option unset)
504+>>> host in helo_try_verify_hosts? no (option unset)
505+>>> host in helo_accept_junk_hosts? no (option unset)
506+>>> test in helo_lookup_domains? no (end of list)
507+>>> using ACL "chk_rcpt"
508+>>> processing "accept" (TESTSUITE/test-config 19)
509+>>> check seen = 1s / key=${sender_host_address}_foo
510+>>> = 1s / key=127.0.0.1_foo
511+>>> seen db written (update)
512+>>> accept: condition test failed in ACL "chk_rcpt"
513+>>> end of ACL "chk_rcpt": implicit DENY
514+LOG: H=(test) [127.0.0.1] F=<tester@test.ex> rejected RCPT <a1@test.ex>
515+>>> host in hosts_connection_nolog? no (option unset)
516+>>> host in host_lookup? no (option unset)
517+>>> host in host_reject_connection? no (option unset)
518+>>> host in sender_unqualified_hosts? no (option unset)
519+>>> host in recipient_unqualified_hosts? no (option unset)
520+>>> host in helo_verify_hosts? no (option unset)
521+>>> host in helo_try_verify_hosts? no (option unset)
522+>>> host in helo_accept_junk_hosts? no (option unset)
523+>>> test in helo_lookup_domains? no (end of list)
524+>>> using ACL "chk_rcpt"
525+>>> processing "accept" (TESTSUITE/test-config 19)
526+>>> check seen = 1s / key=${sender_host_address}_foo
527+>>> = 1s / key=127.0.0.1_foo
528+>>> seen db written (update)
529+>>> accept: condition test succeeded in ACL "chk_rcpt"
530+>>> end of ACL "chk_rcpt": ACCEPT
531diff --git a/test/stdout/0626 b/test/stdout/0626
532new file mode 100644
533index 000000000..44b481f31
534--- /dev/null
535+++ b/test/stdout/0626
536@@ -0,0 +1,99 @@
537+
538+**** SMTP testing session as if from host 127.0.0.1
539+**** but without any ident (RFC 1413) callback.
540+**** This is not for real!
541+
542+220 test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
543+250 test.ex Hello test [127.0.0.1]\r
544+250 OK\r
545+550 Administrative prohibition\r
546+221 test.ex closing connection\r
547++++++++++++++++++++++++++++
548+127.0.0.1 07-Mar-2000 12:21:52
549+
550+**** SMTP testing session as if from host 127.0.0.1
551+**** but without any ident (RFC 1413) callback.
552+**** This is not for real!
553+
554+220 test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
555+250 test.ex Hello test [127.0.0.1]\r
556+250 OK\r
557+250 Accepted\r
558+221 test.ex closing connection\r
559+
560+**** SMTP testing session as if from host 127.0.0.1
561+**** but without any ident (RFC 1413) callback.
562+**** This is not for real!
563+
564+220 test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
565+250 test.ex Hello test [127.0.0.1]\r
566+250 OK\r
567+250 Accepted\r
568+221 test.ex closing connection\r
569+
570+**** SMTP testing session as if from host ip4.ip4.ip4.ip4
571+**** but without any ident (RFC 1413) callback.
572+**** This is not for real!
573+
574+220 test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
575+250 test.ex Hello test [ip4.ip4.ip4.ip4]\r
576+250 OK\r
577+550 Administrative prohibition\r
578+221 test.ex closing connection\r
579++++++++++++++++++++++++++++
580+ip4.ip4.ip4.ip4 07-Mar-2000 12:21:52
581+127.0.0.1 07-Mar-2000 12:21:52
582+
583+**** SMTP testing session as if from host 127.0.0.1
584+**** but without any ident (RFC 1413) callback.
585+**** This is not for real!
586+
587+220 test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
588+250 test.ex Hello test [127.0.0.1]\r
589+250 OK\r
590+550 Administrative prohibition\r
591+221 test.ex closing connection\r
592++++++++++++++++++++++++++++
593+127.0.0.1_foo 07-Mar-2000 12:21:52
594+ip4.ip4.ip4.ip4 07-Mar-2000 12:21:52
595+127.0.0.1 07-Mar-2000 12:21:52
596+
597+**** SMTP testing session as if from host 127.0.0.1
598+**** but without any ident (RFC 1413) callback.
599+**** This is not for real!
600+
601+220 test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
602+250 test.ex Hello test [127.0.0.1]\r
603+250 OK\r
604+250 Accepted\r
605+221 test.ex closing connection\r
606+
607+**** SMTP testing session as if from host 127.0.0.1
608+**** but without any ident (RFC 1413) callback.
609+**** This is not for real!
610+
611+220 test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
612+250 test.ex Hello test [127.0.0.1]\r
613+250 OK\r
614+250 Accepted\r
615+221 test.ex closing connection\r
616+
617+**** SMTP testing session as if from host 127.0.0.1
618+**** but without any ident (RFC 1413) callback.
619+**** This is not for real!
620+
621+220 test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
622+250 test.ex Hello test [127.0.0.1]\r
623+250 OK\r
624+550 Administrative prohibition\r
625+221 test.ex closing connection\r
626+
627+**** SMTP testing session as if from host 127.0.0.1
628+**** but without any ident (RFC 1413) callback.
629+**** This is not for real!
630+
631+220 test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
632+250 test.ex Hello test [127.0.0.1]\r
633+250 OK\r
634+250 Accepted\r
635+221 test.ex closing connection\r
This page took 0.122696 seconds and 4 git commands to generate.