1# Rudimentary test checking that the Stalwart email server can:
2# - receive some message through SMTP submission, then
3# - serve this message through IMAP.
4
5let
6 certs = import ./common/acme/server/snakeoil-certs.nix;
7 domain = certs.domain;
8
9in
10import ./make-test-python.nix (
11 { lib, ... }:
12 {
13 name = "stalwart-mail";
14
15 nodes.main =
16 { pkgs, ... }:
17 {
18 security.pki.certificateFiles = [ certs.ca.cert ];
19
20 services.stalwart-mail = {
21 enable = true;
22 settings = {
23 server.hostname = domain;
24
25 certificate."snakeoil" = {
26 cert = "%{file:${certs.${domain}.cert}}%";
27 private-key = "%{file:${certs.${domain}.key}}%";
28 };
29
30 server.tls = {
31 certificate = "snakeoil";
32 enable = true;
33 implicit = false;
34 };
35
36 server.listener = {
37 "smtp-submission" = {
38 bind = [ "[::]:587" ];
39 protocol = "smtp";
40 };
41
42 "imap" = {
43 bind = [ "[::]:143" ];
44 protocol = "imap";
45 };
46 };
47
48 session.auth.mechanisms = "[plain]";
49 session.auth.directory = "'in-memory'";
50 storage.directory = "in-memory";
51
52 session.rcpt.directory = "'in-memory'";
53 queue.outbound.next-hop = "'local'";
54
55 directory."in-memory" = {
56 type = "memory";
57 principals = [
58 {
59 class = "individual";
60 name = "alice";
61 secret = "foobar";
62 email = [ "alice@${domain}" ];
63 }
64 {
65 class = "individual";
66 name = "bob";
67 secret = "foobar";
68 email = [ "bob@${domain}" ];
69 }
70 ];
71 };
72 };
73 };
74
75 environment.systemPackages = [
76 (pkgs.writers.writePython3Bin "test-smtp-submission" { } ''
77 from smtplib import SMTP
78
79 with SMTP('localhost', 587) as smtp:
80 smtp.starttls()
81 smtp.login('alice', 'foobar')
82 smtp.sendmail(
83 'alice@${domain}',
84 'bob@${domain}',
85 """
86 From: alice@${domain}
87 To: bob@${domain}
88 Subject: Some test message
89
90 This is a test message.
91 """.strip()
92 )
93 '')
94
95 (pkgs.writers.writePython3Bin "test-imap-read" { } ''
96 from imaplib import IMAP4
97
98 with IMAP4('localhost') as imap:
99 imap.starttls()
100 status, [caps] = imap.login('bob', 'foobar')
101 assert status == 'OK'
102 imap.select()
103 status, [ref] = imap.search(None, 'ALL')
104 assert status == 'OK'
105 [msgId] = ref.split()
106 status, msg = imap.fetch(msgId, 'BODY[TEXT]')
107 assert status == 'OK'
108 assert msg[0][1].strip() == b'This is a test message.'
109 '')
110 ];
111 };
112
113 testScript = # python
114 ''
115 main.wait_for_unit("stalwart-mail.service")
116 main.wait_for_open_port(587)
117 main.wait_for_open_port(143)
118
119 main.succeed("test-smtp-submission")
120 main.succeed("test-imap-read")
121 '';
122
123 meta = {
124 maintainers = with lib.maintainers; [
125 happysalada
126 euxane
127 onny
128 ];
129 };
130 }
131)