summary refs log tree commit diff
path: root/nixos/tests/opensmtpd-rspamd.nix
blob: 19969a7b47dddf002ffca85b76306c1977ff0d34 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import ./make-test-python.nix {
  name = "opensmtpd-rspamd";

  nodes = {
    smtp1 = { pkgs, ... }: {
      imports = [ common/user-account.nix ];
      networking = {
        firewall.allowedTCPPorts = [ 25 143 ];
        useDHCP = false;
        interfaces.eth1.ipv4.addresses = pkgs.lib.mkOverride 0 [
          { address = "192.168.1.1"; prefixLength = 24; }
        ];
      };
      environment.systemPackages = [ pkgs.opensmtpd ];
      services.opensmtpd = {
        enable = true;
        extraServerArgs = [ "-v" ];
        serverConfiguration = ''
          listen on 0.0.0.0
          action dovecot_deliver mda \
            "${pkgs.dovecot}/libexec/dovecot/deliver -d %{user.username}"
          match from any for local action dovecot_deliver

          action do_relay relay
          # DO NOT DO THIS IN PRODUCTION!
          # Setting up authentication requires a certificate which is painful in
          # a test environment, but THIS WOULD BE DANGEROUS OUTSIDE OF A
          # WELL-CONTROLLED ENVIRONMENT!
          match from any for any action do_relay
        '';
      };
      services.dovecot2 = {
        enable = true;
        enableImap = true;
        mailLocation = "maildir:~/mail";
        protocols = [ "imap" ];
      };
    };

    smtp2 = { pkgs, ... }: {
      imports = [ common/user-account.nix ];
      networking = {
        firewall.allowedTCPPorts = [ 25 143 ];
        useDHCP = false;
        interfaces.eth1.ipv4.addresses = pkgs.lib.mkOverride 0 [
          { address = "192.168.1.2"; prefixLength = 24; }
        ];
      };
      environment.systemPackages = [ pkgs.opensmtpd ];
      services.rspamd = {
        enable = true;
        locals."worker-normal.inc".text = ''
          bind_socket = "127.0.0.1:11333";
        '';
      };
      services.opensmtpd = {
        enable = true;
        extraServerArgs = [ "-v" ];
        serverConfiguration = ''
          filter rspamd proc-exec "${pkgs.opensmtpd-filter-rspamd}/bin/filter-rspamd"
          listen on 0.0.0.0 filter rspamd
          action dovecot_deliver mda \
            "${pkgs.dovecot}/libexec/dovecot/deliver -d %{user.username}"
          match from any for local action dovecot_deliver
        '';
      };
      services.dovecot2 = {
        enable = true;
        enableImap = true;
        mailLocation = "maildir:~/mail";
        protocols = [ "imap" ];
      };
    };

    client = { pkgs, ... }: {
      networking = {
        useDHCP = false;
        interfaces.eth1.ipv4.addresses = pkgs.lib.mkOverride 0 [
          { address = "192.168.1.3"; prefixLength = 24; }
        ];
      };
      environment.systemPackages = let
        sendTestMail = pkgs.writeScriptBin "send-a-test-mail" ''
          #!${pkgs.python3.interpreter}
          import smtplib, sys

          with smtplib.SMTP('192.168.1.1') as smtp:
            smtp.sendmail('alice@[192.168.1.1]', 'bob@[192.168.1.2]', """
              From: alice@smtp1
              To: bob@smtp2
              Subject: Test

              Hello World
              Here goes the spam test
              XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
            """)
        '';

        checkMailBounced = pkgs.writeScriptBin "check-mail-bounced" ''
          #!${pkgs.python3.interpreter}
          import imaplib

          with imaplib.IMAP4('192.168.1.1', 143) as imap:
            imap.login('alice', 'foobar')
            imap.select()
            status, refs = imap.search(None, 'ALL')
            assert status == 'OK'
            assert len(refs) == 1
            status, msg = imap.fetch(refs[0], 'BODY[TEXT]')
            assert status == 'OK'
            content = msg[0][1]
            print("===> content:", content)
            assert b"An error has occurred while attempting to deliver a message" in content
        '';
      in [ sendTestMail checkMailBounced ];
    };
  };

  testScript = ''
    start_all()

    client.wait_for_unit("network-online.target")
    smtp1.wait_for_unit("opensmtpd")
    smtp2.wait_for_unit("opensmtpd")
    smtp2.wait_for_unit("rspamd")
    smtp2.wait_for_unit("dovecot2")

    # To prevent sporadic failures during daemon startup, make sure
    # services are listening on their ports before sending requests
    smtp1.wait_for_open_port(25)
    smtp2.wait_for_open_port(25)
    smtp2.wait_for_open_port(143)
    smtp2.wait_for_open_port(11333)

    client.succeed("send-a-test-mail")
    smtp1.wait_until_fails("smtpctl show queue | egrep .")
    client.succeed("check-mail-bounced >&2")
  '';

  meta.timeout = 1800;
}