{
  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." >&2
        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;
            admin = "mailto:admin@${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")
    '';
  }