1{ ... }:
2{
3 name = "mailman";
4
5 nodes.machine =
6 { pkgs, ... }:
7 {
8 environment.systemPackages = with pkgs; [ mailutils ];
9
10 services.mailman.enable = true;
11 services.mailman.serve.enable = true;
12 services.mailman.siteOwner = "postmaster@example.com";
13 services.mailman.webHosts = [ "example.com" ];
14
15 services.postfix.enable = true;
16 services.postfix.settings.main = {
17 mydestination = [
18 "example.com"
19 "example.net"
20 ];
21 relay_domains = [ "hash:/var/lib/mailman/data/postfix_domains" ];
22 local_recipient_maps = [
23 "hash:/var/lib/mailman/data/postfix_lmtp"
24 "proxy:unix:passwd.byname"
25 ];
26 transport_maps = [ "hash:/var/lib/mailman/data/postfix_lmtp" ];
27 };
28
29 users.users.user = {
30 isNormalUser = true;
31 };
32
33 virtualisation.memorySize = 2048;
34
35 specialisation.restApiPassFileSystem.configuration = {
36 services.mailman.restApiPassFile = "/var/lib/mailman/pass";
37 };
38 };
39
40 testScript =
41 { nodes, ... }:
42 let
43 restApiPassFileSystem = "${nodes.machine.system.build.toplevel}/specialisation/restApiPassFileSystem";
44 in
45 ''
46 def check_mail(_) -> bool:
47 status, _ = machine.execute("grep -q hello /var/spool/mail/user/new/*")
48 return status == 0
49
50 def try_api(_) -> bool:
51 status, _ = machine.execute("curl -s http://localhost:8001/")
52 return status == 0
53
54 def wait_for_api():
55 with machine.nested("waiting for Mailman REST API to be available"):
56 retry(try_api)
57
58 machine.wait_for_unit("mailman.service")
59 wait_for_api()
60
61 with subtest("subscription and delivery"):
62 creds = machine.succeed("su -s /bin/sh -c 'mailman info' mailman | grep '^REST credentials: ' | sed 's/^REST credentials: //'").strip()
63 machine.succeed(f"curl --fail-with-body -sLSu {creds} -d mail_host=example.com http://localhost:8001/3.1/domains")
64 machine.succeed(f"curl --fail-with-body -sLSu {creds} -d fqdn_listname=list@example.com http://localhost:8001/3.1/lists")
65 machine.succeed(f"curl --fail-with-body -sLSu {creds} -d list_id=list.example.com -d subscriber=root@example.com -d pre_confirmed=True -d pre_verified=True -d send_welcome_message=False http://localhost:8001/3.1/members")
66 machine.succeed(f"curl --fail-with-body -sLSu {creds} -d list_id=list.example.com -d subscriber=user@example.net -d pre_confirmed=True -d pre_verified=True -d send_welcome_message=False http://localhost:8001/3.1/members")
67 machine.succeed("mail -a 'From: root@example.com' -s hello list@example.com < /dev/null")
68 with machine.nested("waiting for mail from list"):
69 retry(check_mail)
70
71 with subtest("Postorius"):
72 machine.succeed("curl --fail-with-body -sILS http://localhost/")
73
74 with subtest("restApiPassFile"):
75 machine.succeed("echo secretpassword > /var/lib/mailman/pass")
76 machine.succeed("${restApiPassFileSystem}/bin/switch-to-configuration test >&2")
77 machine.succeed("grep secretpassword /etc/mailman.cfg")
78 machine.succeed("su -s /bin/sh -c 'mailman info' mailman | grep secretpassword")
79 wait_for_api()
80 machine.succeed("curl --fail-with-body -sLSu restadmin:secretpassword http://localhost:8001/3.1/domains")
81 machine.succeed("curl --fail-with-body -sILS http://localhost/")
82
83 with subtest("service locking"):
84 machine.fail("su -s /bin/sh -c 'mailman start' mailman")
85 machine.execute("systemctl kill --signal=SIGKILL mailman")
86 machine.succeed("systemctl restart mailman")
87 wait_for_api()
88 '';
89}