1import ./make-test.nix {
2 name = "opensmtpd";
3
4 nodes = {
5 smtp1 = { pkgs, ... }: {
6 imports = [ common/user-account.nix ];
7 networking = {
8 firewall.allowedTCPPorts = [ 25 ];
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 # DO NOT DO THIS IN PRODUCTION!
21 # Setting up authentication requires a certificate which is painful in
22 # a test environment, but THIS WOULD BE DANGEROUS OUTSIDE OF A
23 # WELL-CONTROLLED ENVIRONMENT!
24 accept from any for any relay
25 '';
26 };
27 };
28
29 smtp2 = { pkgs, ... }: {
30 imports = [ common/user-account.nix ];
31 networking = {
32 firewall.allowedTCPPorts = [ 25 143 ];
33 useDHCP = false;
34 interfaces.eth1.ipv4.addresses = pkgs.lib.mkOverride 0 [
35 { address = "192.168.1.2"; prefixLength = 24; }
36 ];
37 };
38 environment.systemPackages = [ pkgs.opensmtpd ];
39 services.opensmtpd = {
40 enable = true;
41 extraServerArgs = [ "-v" ];
42 serverConfiguration = ''
43 listen on 0.0.0.0
44 accept from any for local deliver to mda \
45 "${pkgs.dovecot}/libexec/dovecot/deliver -d %{user.username}"
46 '';
47 };
48 services.dovecot2 = {
49 enable = true;
50 enableImap = true;
51 mailLocation = "maildir:~/mail";
52 protocols = [ "imap" ];
53 };
54 };
55
56 client = { pkgs, ... }: {
57 networking = {
58 useDHCP = false;
59 interfaces.eth1.ipv4.addresses = pkgs.lib.mkOverride 0 [
60 { address = "192.168.1.3"; prefixLength = 24; }
61 ];
62 };
63 environment.systemPackages = let
64 sendTestMail = pkgs.writeScriptBin "send-a-test-mail" ''
65 #!${pkgs.python3.interpreter}
66 import smtplib, sys
67
68 with smtplib.SMTP('192.168.1.1') as smtp:
69 smtp.sendmail('alice@[192.168.1.1]', 'bob@[192.168.1.2]', """
70 From: alice@smtp1
71 To: bob@smtp2
72 Subject: Test
73
74 Hello World
75 """)
76 '';
77
78 checkMailLanded = pkgs.writeScriptBin "check-mail-landed" ''
79 #!${pkgs.python3.interpreter}
80 import imaplib
81
82 with imaplib.IMAP4('192.168.1.2', 143) as imap:
83 imap.login('bob', 'foobar')
84 imap.select()
85 status, refs = imap.search(None, 'ALL')
86 assert status == 'OK'
87 assert len(refs) == 1
88 status, msg = imap.fetch(refs[0], 'BODY[TEXT]')
89 assert status == 'OK'
90 content = msg[0][1]
91 print("===> content:", content)
92 split = content.split(b'\r\n')
93 print("===> split:", split)
94 lastline = split[-3]
95 print("===> lastline:", lastline)
96 assert lastline.strip() == b'Hello World'
97 '';
98 in [ sendTestMail checkMailLanded ];
99 };
100 };
101
102 testScript = ''
103 startAll;
104
105 $client->waitForUnit("network.target");
106 $smtp1->waitForUnit('opensmtpd');
107 $smtp2->waitForUnit('opensmtpd');
108 $smtp2->waitForUnit('dovecot2');
109
110 $client->succeed('send-a-test-mail');
111 $smtp1->waitUntilFails('smtpctl show queue | egrep .');
112 $smtp2->waitUntilFails('smtpctl show queue | egrep .');
113 $client->succeed('check-mail-landed >&2');
114 '';
115}