about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-02-09 16:25:52 +0100
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-03-09 13:44:15 +0100
commit158d97b9dd08a0e378152224681294916c825fef (patch)
tree47359adb98ccd903b1fa8b45a57f2af5ac9948db
parentmodule/stalwart-mail: Init initial version (diff)
downloadnixos-server-158d97b9dd08a0e378152224681294916c825fef.zip
tests/email: Test the mvp
-rw-r--r--tests/by-name/em/email/test.nix173
1 files changed, 173 insertions, 0 deletions
diff --git a/tests/by-name/em/email/test.nix b/tests/by-name/em/email/test.nix
new file mode 100644
index 0000000..590136e
--- /dev/null
+++ b/tests/by-name/em/email/test.nix
@@ -0,0 +1,173 @@
+{
+  nixos-lib,
+  pkgsUnstable,
+  nixpkgs-unstable,
+  vhackPackages,
+  pkgs,
+  extraModules,
+  nixLib,
+  ...
+}: let
+  domain = "mail.server.test";
+
+  scripts = {
+    checkEmailEmpty = pkgs.writeShellScript "assert-empty-emails" ''
+      set -xe
+
+      # fetchmail returns EXIT_CODE 1 when no new mail
+      fetchmail --nosslcertck --verbose >&2 || [ "$?" -eq 1 ] || {
+        echo "Expected exit code 1, but got '$exit_code'"
+        exit 1
+      }
+    '';
+  };
+
+  mkUser = user: {nodes, ...}: let
+    domainIp = nodes.server.networking.primaryIPAddress;
+  in {
+    environment.systemPackages = with pkgs; [
+      fetchmail
+      msmtp
+      procmail
+    ];
+
+    users.users."${user}" = {isNormalUser = true;};
+
+    systemd.tmpfiles.rules = [
+      "d /home/${user}/mail         0700 ${user} users - -"
+      "L /home/${user}/.fetchmailrc -    -       -     - /etc/homeSetup/.fetchmailrc"
+      "L /home/${user}/.procmailrc  -    -       -     - /etc/homeSetup/.procmailrc"
+      "L /home/${user}/.msmtprc     -    -       -     - /etc/homeSetup/.msmtprc"
+    ];
+
+    environment.etc = {
+      "homeSetup/.fetchmailrc" = {
+        text = ''
+          poll "${domainIp}" protocol IMAP
+            username "${user}"
+            password "${user}-password"
+            ssl
+            mda procmail;
+        '';
+        mode = "0600";
+        inherit user;
+      };
+      "homeSetup/.procmailrc" = {
+        text = ''
+          DEFAULT=$HOME/mail
+        '';
+        mode = "0600";
+        inherit user;
+      };
+      "homeSetup/.msmtprc" = {
+        text = ''
+          account        ${user}
+          host           ${domainIp}
+          port           465
+          from           ${user}@${domain}
+          user           ${user}
+          password       ${user}-password
+          auth           on
+          tls            on
+          tls_starttls   off
+        '';
+        mode = "0600";
+        inherit user;
+      };
+    };
+  };
+in
+  nixos-lib.runTest {
+    hostPkgs = pkgs; # the Nixpkgs package set used outside the VMs
+
+    name = "email";
+
+    node = {
+      specialArgs = {inherit pkgsUnstable vhackPackages nixpkgs-unstable nixLib;};
+
+      # Use the nixpkgs as constructed by the `nixpkgs.*` options
+      pkgs = null;
+    };
+
+    nodes = {
+      server = {config, ...}: {
+        imports =
+          extraModules
+          ++ [
+            ../../../../modules
+          ];
+
+        vhack = {
+          nginx = {
+            enable = true;
+            selfsign = true;
+          };
+
+          stalwart-mail = {
+            enable = true;
+            fqdn = domain;
+            security = null;
+            openFirewall = true;
+            principals = [
+              {
+                class = "individual";
+                name = "alice";
+                secret = "alice-password";
+                email = ["alice@${domain}"];
+              }
+              {
+                class = "individual";
+                name = "bob";
+                secret = "bob-password";
+                email = ["bob@${domain}"];
+              }
+            ];
+          };
+        };
+      };
+
+      alice = mkUser "alice";
+      bob = mkUser "bob";
+    };
+
+    testScript = {...}:
+    /*
+    python
+    */
+    ''
+      start_all()
+
+      server.wait_for_unit("stalwart-mail.service")
+      server.wait_for_open_port(993) # imap
+      server.wait_for_open_port(465) # smtp
+
+      with subtest("Both start without mail"):
+        alice.succeed("sudo -u alice ${scripts.checkEmailEmpty}")
+        bob.succeed("sudo -u bob ${scripts.checkEmailEmpty}")
+
+      with subtest("Alice can send an email to bob"):
+        alice.succeed("sudo -u alice ${pkgs.writeShellScript "alice-send" ''
+        set -xe
+
+        cat << EOF | msmtp --debug --account alice --tls-certcheck=off bob@${domain} >&2
+        Hi Bob!
+
+        This is an email.
+        It contains a subject and a body.
+
+        ALICE
+        EOF
+      ''}")
+        bob.succeed("sudo -u bob ${pkgs.writeShellScript "bob-receive" ''
+        set -xe
+
+        fetchmail --nosslcertck --verbose >&2 || {
+          echo New Mail did not arrive
+          exit 1
+        }
+      ''}")
+
+      server.copy_from_vm("/var/lib/", "server")
+      bob.copy_from_vm("/home/bob/mail", "bob")
+    '';
+  }