2019-12-14 22:19:57 +01:00
|
|
|
# nixos-mailserver: a simple mail server
|
|
|
|
# Copyright (C) 2016-2018 Robin Raymond
|
|
|
|
#
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
|
|
|
2021-07-10 16:05:25 +02:00
|
|
|
{ pkgs ? import <nixpkgs> {}, ...}:
|
2020-04-11 15:38:52 +02:00
|
|
|
|
2020-04-25 23:34:22 +02:00
|
|
|
let
|
|
|
|
sendMail = pkgs.writeTextFile {
|
|
|
|
"name" = "send-mail-to-send-only-account";
|
|
|
|
"text" = ''
|
|
|
|
EHLO mail.example.com
|
|
|
|
MAIL FROM: none@example.com
|
|
|
|
RCPT TO: send-only@example.com
|
|
|
|
QUIT
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
hashPassword = password: pkgs.runCommand
|
|
|
|
"password-${password}-hashed"
|
2022-11-27 20:14:22 +01:00
|
|
|
{ buildInputs = [ pkgs.mkpasswd ]; inherit password; } ''
|
|
|
|
mkpasswd -sm bcrypt <<<"$password" > $out
|
2020-04-25 23:34:22 +02:00
|
|
|
'';
|
|
|
|
|
2021-01-28 23:58:08 +01:00
|
|
|
hashedPasswordFile = hashPassword "my-password";
|
|
|
|
passwordFile = pkgs.writeText "password" "my-password";
|
2020-04-25 23:34:22 +02:00
|
|
|
in
|
2020-07-27 22:50:27 +02:00
|
|
|
pkgs.nixosTest {
|
2021-05-01 08:21:27 +02:00
|
|
|
name = "internal";
|
2020-07-27 22:50:27 +02:00
|
|
|
nodes = {
|
|
|
|
machine = { config, pkgs, ... }: {
|
|
|
|
imports = [
|
|
|
|
./../default.nix
|
|
|
|
./lib/config.nix
|
|
|
|
];
|
2019-12-14 22:19:57 +01:00
|
|
|
|
2020-07-27 22:50:27 +02:00
|
|
|
virtualisation.memorySize = 1024;
|
2019-12-14 22:19:57 +01:00
|
|
|
|
2021-01-28 23:58:08 +01:00
|
|
|
environment.systemPackages = [
|
|
|
|
(pkgs.writeScriptBin "mail-check" ''
|
|
|
|
${pkgs.python3}/bin/python ${../scripts/mail-check.py} $@
|
|
|
|
'')];
|
|
|
|
|
2020-07-27 22:50:27 +02:00
|
|
|
mailserver = {
|
|
|
|
enable = true;
|
|
|
|
fqdn = "mail.example.com";
|
2023-09-28 16:13:00 +02:00
|
|
|
domains = [ "example.com" "domain.com" ];
|
2021-01-28 23:58:08 +01:00
|
|
|
localDnsResolver = false;
|
2020-04-26 09:32:07 +02:00
|
|
|
|
2020-07-27 22:50:27 +02:00
|
|
|
loginAccounts = {
|
|
|
|
"user1@example.com" = {
|
2021-01-28 23:58:08 +01:00
|
|
|
hashedPasswordFile = hashedPasswordFile;
|
|
|
|
};
|
|
|
|
"user2@example.com" = {
|
|
|
|
hashedPasswordFile = hashedPasswordFile;
|
2023-09-28 16:13:00 +02:00
|
|
|
aliasesRegexp = [''/^user2.*@domain\.com$/''];
|
2020-07-27 22:50:27 +02:00
|
|
|
};
|
|
|
|
"send-only@example.com" = {
|
|
|
|
hashedPasswordFile = hashPassword "send-only";
|
|
|
|
sendOnly = true;
|
2019-12-14 22:19:57 +01:00
|
|
|
};
|
|
|
|
};
|
2021-01-28 23:58:08 +01:00
|
|
|
forwards = {
|
|
|
|
# user2@example.com is a local account and its mails are
|
|
|
|
# also forwarded to user1@example.com
|
|
|
|
"user2@example.com" = "user1@example.com";
|
|
|
|
};
|
2019-12-14 22:19:57 +01:00
|
|
|
|
2020-07-27 22:50:27 +02:00
|
|
|
vmailGroupName = "vmail";
|
|
|
|
vmailUID = 5000;
|
2020-10-05 21:18:36 +02:00
|
|
|
|
|
|
|
enableImap = false;
|
2019-12-14 22:19:57 +01:00
|
|
|
};
|
2020-07-27 22:50:27 +02:00
|
|
|
};
|
|
|
|
};
|
|
|
|
testScript = ''
|
|
|
|
machine.start()
|
|
|
|
machine.wait_for_unit("multi-user.target")
|
2019-12-14 22:19:57 +01:00
|
|
|
|
2021-01-28 23:58:08 +01:00
|
|
|
# Regression test for https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/issues/205
|
|
|
|
with subtest("mail forwarded can are locally kept"):
|
|
|
|
# A mail sent to user2@example.com is in the user1@example.com mailbox
|
|
|
|
machine.succeed(
|
|
|
|
" ".join(
|
|
|
|
[
|
|
|
|
"mail-check send-and-read",
|
|
|
|
"--smtp-port 587",
|
|
|
|
"--smtp-starttls",
|
|
|
|
"--smtp-host localhost",
|
|
|
|
"--imap-host localhost",
|
|
|
|
"--imap-username user1@example.com",
|
|
|
|
"--from-addr user1@example.com",
|
|
|
|
"--to-addr user2@example.com",
|
|
|
|
"--src-password-file ${passwordFile}",
|
|
|
|
"--dst-password-file ${passwordFile}",
|
|
|
|
"--ignore-dkim-spf",
|
|
|
|
]
|
|
|
|
)
|
|
|
|
)
|
|
|
|
# A mail sent to user2@example.com is in the user2@example.com mailbox
|
|
|
|
machine.succeed(
|
|
|
|
" ".join(
|
|
|
|
[
|
|
|
|
"mail-check send-and-read",
|
|
|
|
"--smtp-port 587",
|
|
|
|
"--smtp-starttls",
|
|
|
|
"--smtp-host localhost",
|
|
|
|
"--imap-host localhost",
|
|
|
|
"--imap-username user2@example.com",
|
|
|
|
"--from-addr user1@example.com",
|
|
|
|
"--to-addr user2@example.com",
|
|
|
|
"--src-password-file ${passwordFile}",
|
|
|
|
"--dst-password-file ${passwordFile}",
|
|
|
|
"--ignore-dkim-spf",
|
|
|
|
]
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2023-09-28 16:13:00 +02:00
|
|
|
with subtest("regex email alias are received"):
|
|
|
|
# A mail sent to user2-regex-alias@domain.com is in the user2@example.com mailbox
|
|
|
|
machine.succeed(
|
|
|
|
" ".join(
|
|
|
|
[
|
|
|
|
"mail-check send-and-read",
|
|
|
|
"--smtp-port 587",
|
|
|
|
"--smtp-starttls",
|
|
|
|
"--smtp-host localhost",
|
|
|
|
"--imap-host localhost",
|
|
|
|
"--imap-username user2@example.com",
|
|
|
|
"--from-addr user1@example.com",
|
|
|
|
"--to-addr user2-regex-alias@domain.com",
|
|
|
|
"--src-password-file ${passwordFile}",
|
|
|
|
"--dst-password-file ${passwordFile}",
|
|
|
|
"--ignore-dkim-spf",
|
|
|
|
]
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
with subtest("user can send from regex email alias"):
|
|
|
|
# A mail sent from user2-regex-alias@domain.com, using user2@example.com credentials is received
|
|
|
|
machine.succeed(
|
|
|
|
" ".join(
|
|
|
|
[
|
|
|
|
"mail-check send-and-read",
|
|
|
|
"--smtp-port 587",
|
|
|
|
"--smtp-starttls",
|
|
|
|
"--smtp-host localhost",
|
|
|
|
"--imap-host localhost",
|
|
|
|
"--smtp-username user2@example.com",
|
|
|
|
"--from-addr user2-regex-alias@domain.com",
|
|
|
|
"--to-addr user1@example.com",
|
|
|
|
"--src-password-file ${passwordFile}",
|
|
|
|
"--dst-password-file ${passwordFile}",
|
|
|
|
"--ignore-dkim-spf",
|
|
|
|
]
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2020-07-27 22:50:27 +02:00
|
|
|
with subtest("vmail gid is set correctly"):
|
|
|
|
machine.succeed("getent group vmail | grep 5000")
|
2020-06-27 21:20:16 +02:00
|
|
|
|
2020-07-27 22:50:27 +02:00
|
|
|
with subtest("mail to send only accounts is rejected"):
|
|
|
|
machine.wait_for_open_port(25)
|
|
|
|
# TODO put this blocking into the systemd units
|
|
|
|
machine.wait_until_succeeds(
|
2021-06-24 21:29:23 +02:00
|
|
|
"set +e; timeout 1 ${pkgs.netcat}/bin/nc -U /run/rspamd/rspamd-milter.sock < /dev/null; [ $? -eq 124 ]"
|
2020-07-27 22:50:27 +02:00
|
|
|
)
|
|
|
|
machine.succeed(
|
|
|
|
"cat ${sendMail} | ${pkgs.netcat-gnu}/bin/nc localhost 25 | grep -q 'This account cannot receive emails'"
|
|
|
|
)
|
|
|
|
|
|
|
|
with subtest("rspamd controller serves web ui"):
|
|
|
|
machine.succeed(
|
2021-06-24 21:29:23 +02:00
|
|
|
"set +o pipefail; ${pkgs.curl}/bin/curl --unix-socket /run/rspamd/worker-controller.sock http://localhost/ | grep -q '<body>'"
|
2020-07-27 22:50:27 +02:00
|
|
|
)
|
2020-10-05 21:18:36 +02:00
|
|
|
|
|
|
|
with subtest("imap port 143 is closed and imaps is serving SSL"):
|
|
|
|
machine.wait_for_closed_port(143)
|
|
|
|
machine.wait_for_open_port(993)
|
|
|
|
machine.succeed(
|
|
|
|
"echo | ${pkgs.openssl}/bin/openssl s_client -connect localhost:993 | grep 'New, TLS'"
|
|
|
|
)
|
2020-07-27 22:50:27 +02:00
|
|
|
'';
|
2019-12-14 22:19:57 +01:00
|
|
|
}
|