1import ./make-test-python.nix {
2 name = "opensmtpd-rspamd";
3
4 nodes = {
5 smtp1 = { pkgs, ... }: {
6 imports = [ common/user-account.nix ];
7 networking = {
8 firewall.allowedTCPPorts = [ 25 143 ];
9 useDHCP = false;
10 interfaces.eth1.ipv4.addresses = pkgs.lib.mkOverride 0 [
11 { address = "192.168.1.1"; prefixLength = 24; }
12 ];
13 };
14 environment.systemPackages = [ pkgs.opensmtpd ];
15 services.opensmtpd = {
16 enable = true;
17 extraServerArgs = [ "-v" ];
18 serverConfiguration = ''
19 listen on 0.0.0.0
20 action dovecot_deliver mda \
21 "${pkgs.dovecot}/libexec/dovecot/deliver -d %{user.username}"
22 match from any for local action dovecot_deliver
23
24 action do_relay relay
25 # DO NOT DO THIS IN PRODUCTION!
26 # Setting up authentication requires a certificate which is painful in
27 # a test environment, but THIS WOULD BE DANGEROUS OUTSIDE OF A
28 # WELL-CONTROLLED ENVIRONMENT!
29 match from any for any action do_relay
30 '';
31 };
32 services.dovecot2 = {
33 enable = true;
34 enableImap = true;
35 mailLocation = "maildir:~/mail";
36 protocols = [ "imap" ];
37 };
38 };
39
40 smtp2 = { pkgs, ... }: {
41 imports = [ common/user-account.nix ];
42 virtualisation.memorySize = 512;
43 networking = {
44 firewall.allowedTCPPorts = [ 25 143 ];
45 useDHCP = false;
46 interfaces.eth1.ipv4.addresses = pkgs.lib.mkOverride 0 [
47 { address = "192.168.1.2"; prefixLength = 24; }
48 ];
49 };
50 environment.systemPackages = [ pkgs.opensmtpd ];
51 services.rspamd = {
52 enable = true;
53 locals."worker-normal.inc".text = ''
54 bind_socket = "127.0.0.1:11333";
55 '';
56 };
57 services.opensmtpd = {
58 enable = true;
59 extraServerArgs = [ "-v" ];
60 serverConfiguration = ''
61 filter rspamd proc-exec "${pkgs.opensmtpd-filter-rspamd}/bin/filter-rspamd"
62 listen on 0.0.0.0 filter rspamd
63 action dovecot_deliver mda \
64 "${pkgs.dovecot}/libexec/dovecot/deliver -d %{user.username}"
65 match from any for local action dovecot_deliver
66 '';
67 };
68 services.dovecot2 = {
69 enable = true;
70 enableImap = true;
71 mailLocation = "maildir:~/mail";
72 protocols = [ "imap" ];
73 };
74 };
75
76 client = { pkgs, ... }: {
77 networking = {
78 useDHCP = false;
79 interfaces.eth1.ipv4.addresses = pkgs.lib.mkOverride 0 [
80 { address = "192.168.1.3"; prefixLength = 24; }
81 ];
82 };
83 environment.systemPackages = let
84 sendTestMail = pkgs.writeScriptBin "send-a-test-mail" ''
85 #!${pkgs.python3.interpreter}
86 import smtplib, sys
87
88 with smtplib.SMTP('192.168.1.1') as smtp:
89 smtp.sendmail('alice@[192.168.1.1]', 'bob@[192.168.1.2]', """
90 From: alice@smtp1
91 To: bob@smtp2
92 Subject: Test
93
94 Hello World
95 Here goes the spam test
96 XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
97 """)
98 '';
99
100 checkMailBounced = pkgs.writeScriptBin "check-mail-bounced" ''
101 #!${pkgs.python3.interpreter}
102 import imaplib
103
104 with imaplib.IMAP4('192.168.1.1', 143) as imap:
105 imap.login('alice', 'foobar')
106 imap.select()
107 status, refs = imap.search(None, 'ALL')
108 assert status == 'OK'
109 assert len(refs) == 1
110 status, msg = imap.fetch(refs[0], 'BODY[TEXT]')
111 assert status == 'OK'
112 content = msg[0][1]
113 print("===> content:", content)
114 assert b"An error has occurred while attempting to deliver a message" in content
115 '';
116 in [ sendTestMail checkMailBounced ];
117 };
118 };
119
120 testScript = ''
121 start_all()
122
123 client.wait_for_unit("network-online.target")
124 smtp1.wait_for_unit("opensmtpd")
125 smtp2.wait_for_unit("opensmtpd")
126 smtp2.wait_for_unit("rspamd")
127 smtp2.wait_for_unit("dovecot2")
128
129 # To prevent sporadic failures during daemon startup, make sure
130 # services are listening on their ports before sending requests
131 smtp1.wait_for_open_port(25)
132 smtp2.wait_for_open_port(25)
133 smtp2.wait_for_open_port(143)
134 smtp2.wait_for_open_port(11333)
135
136 client.succeed("send-a-test-mail")
137 smtp1.wait_until_fails("smtpctl show queue | egrep .")
138 client.succeed("check-mail-bounced >&2")
139 '';
140
141 meta.timeout = 1800;
142}