mailserver: update to e33fbde and add test
This commit is contained in:
parent
c7e404f8be
commit
503f1c31ea
6 changed files with 368 additions and 36 deletions
13
CHANGELOG.md
13
CHANGELOG.md
|
|
@ -16,6 +16,19 @@ Template:
|
|||
|
||||
# Upcoming Release
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- Updated simple-nixos-mailserver. Update all options following this pattern:
|
||||
|
||||
```diff
|
||||
- mailserver.mailboxes.<name>.specialUse = "value"
|
||||
+ mailserver.mailboxes.<name>.special_use = "\\value"
|
||||
```
|
||||
|
||||
Note that simple-nixos-mailserver wanted to upgrade the location of the storage path
|
||||
to include the ldap UID instead of the email but I kept the email address.
|
||||
This means there is no migration to do.
|
||||
|
||||
# v0.8.0
|
||||
|
||||
## Breaking Changes
|
||||
|
|
|
|||
|
|
@ -5009,6 +5009,9 @@
|
|||
"services-mailserver-options-shb.mailserver.ssl.systemdService": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ssl.systemdService"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.stateVersion": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.stateVersion"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.subdomain": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.subdomain"
|
||||
],
|
||||
|
|
|
|||
|
|
@ -403,6 +403,7 @@
|
|||
// (vm_test "homepage" ./test/services/homepage.nix)
|
||||
// (vm_test "jellyfin" ./test/services/jellyfin.nix)
|
||||
// (vm_test "karakeep" ./test/services/karakeep.nix)
|
||||
// (vm_test "mailserver" ./test/services/mailserver.nix)
|
||||
// (vm_test "nextcloud" ./test/services/nextcloud.nix)
|
||||
// (vm_test "open-webui" ./test/services/open-webui.nix)
|
||||
// (vm_test "paperless" ./test/services/paperless.nix)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ in
|
|||
builtins.fetchGit {
|
||||
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver.git";
|
||||
ref = "master";
|
||||
rev = "7d433bf89882f61621f95082e90a4ab91eb0bdd3";
|
||||
rev = "e33fbde199eaad513ef5d0746db19d5878150232";
|
||||
}
|
||||
+ "/default.nix"
|
||||
)
|
||||
|
|
@ -105,7 +105,7 @@ in
|
|||
description = ''
|
||||
Accounts to sync emails from using IMAP.
|
||||
|
||||
Emails will be stored under `''${config.mailserver.mailDirectory}/''${name}/''${username}`
|
||||
Emails will be stored under `''${config.mailserver.storage.path}/''${name}/''${username}`
|
||||
'';
|
||||
type = lib.types.attrsOf (
|
||||
lib.types.submodule {
|
||||
|
|
@ -137,7 +137,7 @@ in
|
|||
type = lib.types.submodule {
|
||||
options = shb.contracts.secret.mkRequester {
|
||||
mode = "0400";
|
||||
owner = config.mailserver.vmailUserName;
|
||||
owner = config.mailserver.storage.owner;
|
||||
restartUnits = [ "mbsync.service" ];
|
||||
};
|
||||
};
|
||||
|
|
@ -267,7 +267,7 @@ in
|
|||
Enabling this app will create a new LDAP configuration or update one that exists with
|
||||
the given host.
|
||||
'';
|
||||
default = { };
|
||||
default = null;
|
||||
type = lib.types.nullOr (
|
||||
lib.types.submodule {
|
||||
options = {
|
||||
|
|
@ -333,6 +333,26 @@ in
|
|||
);
|
||||
};
|
||||
|
||||
stateVersion = lib.mkOption {
|
||||
type = lib.types.ints.positive;
|
||||
# SHB started at stateVersion 3.
|
||||
default = 4;
|
||||
description = ''
|
||||
Tracking stateful version changes as an incrementing number.
|
||||
|
||||
When a new release comes out we may require manual migration steps to
|
||||
be completed, before the new version can be put into production.
|
||||
|
||||
If your `stateVersion` is too low one or multiple assertions may
|
||||
trigger to give you instructions on what migrations steps are required
|
||||
to continue. Increase the `stateVersion` as instructed by the assertion
|
||||
message.
|
||||
|
||||
See https://nixos-mailserver.readthedocs.io/en/latest/release-notes.html
|
||||
and https://nixos-mailserver.readthedocs.io/en/latest/migrations.html
|
||||
'';
|
||||
};
|
||||
|
||||
backup = lib.mkOption {
|
||||
description = ''
|
||||
Backup emails, index and sieve.
|
||||
|
|
@ -340,16 +360,16 @@ in
|
|||
default = { };
|
||||
type = lib.types.submodule {
|
||||
options = shb.contracts.backup.mkRequester {
|
||||
user = config.mailserver.vmailUserName;
|
||||
user = config.mailserver.storage.owner;
|
||||
sourceDirectories = builtins.filter (x: x != null) [
|
||||
config.mailserver.indexDir
|
||||
config.mailserver.mailDirectory
|
||||
config.mailserver.storage.path
|
||||
config.mailserver.sieveDirectory
|
||||
];
|
||||
sourceDirectoriesText = ''
|
||||
[
|
||||
config.mailserver.indexDir
|
||||
config.mailserver.mailDirectory
|
||||
config.mailserver.storage.path
|
||||
config.mailserver.sieveDirectory
|
||||
]
|
||||
'';
|
||||
|
|
@ -367,7 +387,7 @@ in
|
|||
user = config.services.rspamd.user;
|
||||
userText = "services.rspamd.user";
|
||||
sourceDirectories = builtins.filter (x: x != null) [
|
||||
config.mailserver.dkimKeyDirectory
|
||||
config.mailserver.dkim.keyDirectory
|
||||
];
|
||||
sourceDirectoriesText = ''
|
||||
[
|
||||
|
|
@ -385,14 +405,14 @@ in
|
|||
type = lib.types.attrsOf lib.types.str;
|
||||
default = {
|
||||
index = config.mailserver.indexDir;
|
||||
mail = config.mailserver.mailDirectory;
|
||||
mail = config.mailserver.storage.path;
|
||||
sieve = config.mailserver.sieveDirectory;
|
||||
dkim = config.mailserver.dkimKeyDirectory;
|
||||
};
|
||||
defaultText = lib.literalExpression ''
|
||||
{
|
||||
index = config.mailserver.indexDir;
|
||||
mail = config.mailserver.mailDirectory;
|
||||
mail = config.mailserver.storage.path;
|
||||
sieve = config.mailserver.sieveDirectory;
|
||||
dkim = config.mailserver.dkimKeyDirectory;
|
||||
}
|
||||
|
|
@ -417,8 +437,8 @@ in
|
|||
(lib.mkIf cfg.enable {
|
||||
mailserver = {
|
||||
enable = true;
|
||||
stateVersion = 3;
|
||||
fqdn = "${cfg.subdomain}.${cfg.domain}";
|
||||
inherit (cfg) stateVersion;
|
||||
domains = [ cfg.domain ];
|
||||
|
||||
localDnsResolver = false;
|
||||
|
|
@ -433,18 +453,22 @@ in
|
|||
# Using / is needed for iOS mail.
|
||||
# Both following options are used to organize subfolders in subdirectories.
|
||||
hierarchySeparator = "/";
|
||||
useFsLayout = true;
|
||||
storage = {
|
||||
directoryLayout = "fs";
|
||||
};
|
||||
};
|
||||
|
||||
services.postfix.config = {
|
||||
services.postfix.settings.main = {
|
||||
smtpd_tls_security_level = lib.mkForce "encrypt";
|
||||
};
|
||||
|
||||
# Is probably needed for iOS mail.
|
||||
services.dovecot2.extraConfig = ''
|
||||
ssl_min_protocol = TLSv1.2
|
||||
ssl_cipher_list = HIGH:!aNULL:!MD5
|
||||
'';
|
||||
services.dovecot2.settings = {
|
||||
ssl_min_protocol = "TLSv1.2";
|
||||
# This conflicts with the default setting which seems much better than this one.
|
||||
# So I'm leaving the default settings and we'll see if something breaks.
|
||||
# ssl_cipher_list = "HIGH:!aNULL:!MD5";
|
||||
};
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
|
|
@ -482,6 +506,8 @@ in
|
|||
in
|
||||
{
|
||||
forceSSL = true; # Redirect HTTP → HTTPS
|
||||
sslCertificate = cfg.ssl.paths.cert;
|
||||
sslCertificateKey = cfg.ssl.paths.key;
|
||||
root = "/var/www"; # Dummy root
|
||||
locations."/.well-known/autoconfig/mail/" = {
|
||||
alias = "${announce}/";
|
||||
|
|
@ -501,6 +527,8 @@ in
|
|||
in
|
||||
{
|
||||
forceSSL = true; # Redirect HTTP → HTTPS
|
||||
sslCertificate = cfg.ssl.paths.cert;
|
||||
sslCertificateKey = cfg.ssl.paths.key;
|
||||
root = "/var/www"; # Dummy root
|
||||
locations."/" = {
|
||||
alias = "${landingPage}/";
|
||||
|
|
@ -548,37 +576,44 @@ in
|
|||
uris = [
|
||||
"ldap://${cfg.ldap.host}:${toString cfg.ldap.port}"
|
||||
];
|
||||
searchBase = "ou=people,${cfg.ldap.dcdomain}";
|
||||
searchScope = "sub";
|
||||
base = "ou=people,${cfg.ldap.dcdomain}";
|
||||
scope = "sub";
|
||||
bind = {
|
||||
dn = "uid=${cfg.ldap.adminName},ou=people,${cfg.ldap.dcdomain}";
|
||||
passwordFile = cfg.ldap.adminPassword.result.path;
|
||||
};
|
||||
# Note that nixos simple mailserver sets auth_bind=yes
|
||||
# which means authentication binds are used.
|
||||
# https://doc.dovecot.org/2.3/configuration_manual/authentication/ldap_bind/#authentication-ldap-bind
|
||||
dovecot =
|
||||
let
|
||||
filter = "(&(objectClass=inetOrgPerson)(mail=%{user})(memberOf=cn=${cfg.ldap.userGroup},ou=groups,${cfg.ldap.dcdomain}))";
|
||||
in
|
||||
{
|
||||
passAttrs = "user=user";
|
||||
passFilter = filter;
|
||||
userAttrs = lib.concatStringsSep "," [
|
||||
"=home=${config.mailserver.mailDirectory}/${cfg.ldap.account}/%u"
|
||||
# "mail=maildir:${config.mailserver.mailDirectory}/${cfg.ldap.account}/%u/mail"
|
||||
"uid=${config.mailserver.vmailUserName}"
|
||||
"gid=${config.mailserver.vmailGroupName}"
|
||||
];
|
||||
userFilter = filter;
|
||||
};
|
||||
# username needs to be set to mail so postfix maps correctly the mail address.
|
||||
# Otherwise we get error messages when sending
|
||||
# Sender address rejected: not owned by user
|
||||
attributes = {
|
||||
username = "mail";
|
||||
};
|
||||
postfix = {
|
||||
filter = "(&(objectClass=inetOrgPerson)(mail=%s)(memberOf=cn=${cfg.ldap.userGroup},ou=groups,${cfg.ldap.dcdomain}))";
|
||||
mailAttribute = "mail";
|
||||
uidAttribute = "mail";
|
||||
};
|
||||
};
|
||||
};
|
||||
services.dovecot2.settings = {
|
||||
"userdb ldap" = {
|
||||
fields.home = lib.mkForce "${config.mailserver.storage.path}/${cfg.ldap.account}/%{user}";
|
||||
fields.mail_index_path = lib.mkForce "${config.mailserver.storage.path}/${cfg.ldap.account}/%{user}";
|
||||
};
|
||||
"passdb ldap" = {
|
||||
# LLDAP does not understand ldap user password setup.
|
||||
fields.password = lib.mkForce null;
|
||||
# We use bind DN auth.
|
||||
# https://doc.dovecot.org/2.3/configuration_manual/authentication/ldap_bind/#authentication-ldap-bind
|
||||
bind = true;
|
||||
};
|
||||
};
|
||||
})
|
||||
(lib.mkIf (cfg.enable && cfg.imapSync != null) {
|
||||
systemd.services.mbsync =
|
||||
|
|
@ -601,11 +636,11 @@ in
|
|||
Account ${name}
|
||||
|
||||
MaildirStore ${name}-local
|
||||
INBOX ${config.mailserver.mailDirectory}/${name}/${acct.username}/mail/
|
||||
INBOX ${config.mailserver.storage.path}/${name}/${acct.username}/mail/
|
||||
# Maps subfolders on far side to actual subfolders on disk.
|
||||
# The other option is Maildir++ but then the mailserver.hierarchySeparator must be set to a dot '.'
|
||||
SubFolders Verbatim
|
||||
Path ${config.mailserver.mailDirectory}/${name}/${acct.username}/mail/
|
||||
Path ${config.mailserver.storage.path}/${name}/${acct.username}/mail/
|
||||
|
||||
Channel ${name}-main
|
||||
Far :${name}-remote:
|
||||
|
|
@ -672,7 +707,7 @@ in
|
|||
description = "Sync mailbox";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = config.mailserver.vmailUserName;
|
||||
User = config.mailserver.storage.owner;
|
||||
};
|
||||
script =
|
||||
let
|
||||
|
|
@ -689,8 +724,8 @@ in
|
|||
name: acct:
|
||||
# The equal sign makes sure parent directories have the corret user and group too.
|
||||
[
|
||||
"d '${config.mailserver.mailDirectory}/${name}' 0750 ${config.mailserver.vmailUserName} ${config.mailserver.vmailGroupName} - -"
|
||||
"d '${config.mailserver.mailDirectory}/${name}/${acct.username}' 0750 ${config.mailserver.vmailUserName} ${config.mailserver.vmailGroupName} - -"
|
||||
"d '${config.mailserver.storage.path}/${name}' 0750 ${config.mailserver.storage.owner} ${config.mailserver.storage.group} - -"
|
||||
"d '${config.mailserver.storage.path}/${name}/${acct.username}' 0750 ${config.mailserver.storage.owner} ${config.mailserver.storage.group} - -"
|
||||
];
|
||||
in
|
||||
lib.flatten (lib.mapAttrsToList mkAccount cfg.imapSync.accounts);
|
||||
|
|
|
|||
|
|
@ -128,6 +128,8 @@ in
|
|||
}
|
||||
```
|
||||
|
||||
With the example above, the mails are stored under `/var/vmail/fastmail/<email address>`.
|
||||
|
||||
### Secrets {#services-mailserver-usage-secrets}
|
||||
|
||||
Secrets can be randomly generated with `nix run nixpkgs#openssl -- rand -hex 64`.
|
||||
|
|
|
|||
278
test/services/mailserver.nix
Normal file
278
test/services/mailserver.nix
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
shb,
|
||||
...
|
||||
}:
|
||||
let
|
||||
domain = "example.com";
|
||||
subdomain = "imap";
|
||||
fqdn = "${subdomain}.${domain}";
|
||||
|
||||
trySendMail = pkgs.writeShellApplication {
|
||||
name = "trySendMail";
|
||||
runtimeInputs = [
|
||||
pkgs.swaks
|
||||
];
|
||||
text = ''
|
||||
USER="''${1:-}"
|
||||
PASSWORD="''${2:-}"
|
||||
|
||||
if [ -z "$USER" ]; then
|
||||
echo "No user given"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$PASSWORD" ]; then
|
||||
swaks \
|
||||
--server ${fqdn} \
|
||||
--port 465 \
|
||||
--tls-on-connect \
|
||||
--from "$USER" \
|
||||
--to "$USER"
|
||||
else
|
||||
swaks \
|
||||
--server ${fqdn} \
|
||||
--port 465 \
|
||||
--tls-on-connect \
|
||||
--auth LOGIN \
|
||||
--auth-user "$USER" \
|
||||
--auth-password "$PASSWORD" \
|
||||
--from "$USER" \
|
||||
--to "$USER"
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
tryRcvMail = pkgs.writeShellApplication {
|
||||
name = "tryRcvMail";
|
||||
runtimeInputs = [
|
||||
pkgs.curl
|
||||
];
|
||||
text = ''
|
||||
USER="''${1:-}"
|
||||
PASSWORD="''${2:-}"
|
||||
|
||||
if [ -z "$USER" ]; then
|
||||
echo "No user given"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$PASSWORD" ]; then
|
||||
echo "No password given"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
curl -s --url "imaps://imap.example.com/INBOX;UID=1" \
|
||||
--user "$USER:$PASSWORD"
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
basic = shb.test.runNixOSTest {
|
||||
name = "mailserver_basic";
|
||||
|
||||
# Connect to the running VM started with driverInteractive:
|
||||
# ssh-keygen -R 'vsock-mux//run/user/1000/tmpcf3hs4yp/server_host.socket'; ssh -o User=root vsock-mux//run/user/1000/tmpcf3hs4yp/server_host.socket
|
||||
interactive.sshBackdoor.enable = true;
|
||||
|
||||
nodes.server =
|
||||
{ config, ... }:
|
||||
{
|
||||
imports = [
|
||||
../../modules/blocks/ssl.nix
|
||||
../../modules/services/mailserver.nix
|
||||
];
|
||||
|
||||
networking.hosts = {
|
||||
"127.0.0.1" = [ fqdn ];
|
||||
};
|
||||
|
||||
shb.certs.cas.selfsigned.myca = {
|
||||
name = "My CA";
|
||||
};
|
||||
shb.certs.certs.selfsigned = {
|
||||
${domain} = {
|
||||
ca = config.shb.certs.cas.selfsigned.myca;
|
||||
|
||||
domain = "*.${domain}";
|
||||
group = "nginx";
|
||||
};
|
||||
};
|
||||
|
||||
shb.mailserver = {
|
||||
enable = true;
|
||||
inherit subdomain domain;
|
||||
stateVersion = 4;
|
||||
ssl = config.shb.certs.certs.selfsigned.${domain};
|
||||
|
||||
# imapSync = {
|
||||
# # syncTimer = "10s";
|
||||
# # debug = false;
|
||||
# # accounts.fastmail = {
|
||||
# # host = "imap.fastmail.com";
|
||||
# # port = 993;
|
||||
# # username = email;
|
||||
# # password.result = config.shb.sops.secret."mailserver/imap/fastmail/password".result;
|
||||
# # mapSpecialJunk = "Spam";
|
||||
# # };
|
||||
# };
|
||||
|
||||
# smtpRelay = {
|
||||
# host = "smtp.fastmail.com";
|
||||
# port = 587;
|
||||
# username = email;
|
||||
# password.result = config.shb.sops.secret."mailserver/smtp/fastmail/password".result;
|
||||
# };
|
||||
|
||||
};
|
||||
|
||||
mailserver.mailboxes = {
|
||||
Junk = {
|
||||
auto = "subscribe";
|
||||
special_use = "\\Junk";
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = [
|
||||
pkgs.openssl
|
||||
pkgs.swaks
|
||||
trySendMail
|
||||
tryRcvMail
|
||||
];
|
||||
|
||||
specialisation = {
|
||||
ldap.configuration =
|
||||
{ config, ... }:
|
||||
{
|
||||
imports = [
|
||||
../../modules/blocks/hardcodedsecret.nix
|
||||
../../modules/blocks/lldap.nix
|
||||
];
|
||||
|
||||
networking.hosts = {
|
||||
"127.0.0.1" = [ "ldap.${domain}" ];
|
||||
};
|
||||
|
||||
environment.systemPackages = [
|
||||
pkgs.openldap
|
||||
];
|
||||
|
||||
shb.hardcodedsecret.ldapUserPassword = {
|
||||
request = config.shb.lldap.ldapUserPassword.request;
|
||||
settings.content = "ldapUserPassword";
|
||||
};
|
||||
shb.hardcodedsecret.jwtSecret = {
|
||||
request = config.shb.lldap.jwtSecret.request;
|
||||
settings.content = "jwtSecrets";
|
||||
};
|
||||
shb.hardcodedsecret.alice = {
|
||||
request = config.shb.lldap.ensureUsers.alice.password.request;
|
||||
settings.content = "alicePassword";
|
||||
};
|
||||
shb.hardcodedsecret.charlie = {
|
||||
request = config.shb.lldap.ensureUsers.charlie.password.request;
|
||||
settings.content = "charliePassword";
|
||||
};
|
||||
|
||||
shb.lldap = {
|
||||
enable = true;
|
||||
inherit domain;
|
||||
subdomain = "ldap";
|
||||
ldapPort = 3890;
|
||||
webUIListenPort = 17170;
|
||||
dcdomain = "dc=example,dc=com";
|
||||
ldapUserPassword.result = config.shb.hardcodedsecret.ldapUserPassword.result;
|
||||
jwtSecret.result = config.shb.hardcodedsecret.jwtSecret.result;
|
||||
debug = true;
|
||||
|
||||
ensureUsers = {
|
||||
alice = {
|
||||
email = "alice@example.com";
|
||||
groups = [ "user_group" ];
|
||||
password.result = config.shb.hardcodedsecret.alice.result;
|
||||
};
|
||||
charlie = {
|
||||
email = "charlie@example.com";
|
||||
groups = [ "other_group" ];
|
||||
password.result = config.shb.hardcodedsecret.charlie.result;
|
||||
};
|
||||
};
|
||||
|
||||
ensureGroups = {
|
||||
user_group = { };
|
||||
admin_group = { };
|
||||
other_group = { };
|
||||
};
|
||||
};
|
||||
|
||||
shb.mailserver = {
|
||||
ldap = {
|
||||
enable = true;
|
||||
host = "127.0.0.1";
|
||||
port = config.shb.lldap.ldapPort;
|
||||
dcdomain = config.shb.lldap.dcdomain;
|
||||
adminName = "admin";
|
||||
adminPassword.result = config.shb.hardcodedsecret.ldapUserPassword.result;
|
||||
account = "fastmail";
|
||||
userGroup = "user_group";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript =
|
||||
{ nodes, ... }:
|
||||
let
|
||||
specialisations = "${nodes.server.system.build.toplevel}/specialisation";
|
||||
switch = name: "${specialisations}/${name}/bin/switch-to-configuration test";
|
||||
|
||||
ldapSearch =
|
||||
let
|
||||
config = nodes.server.specialisation.ldap.configuration;
|
||||
in
|
||||
lib.concatStringsSep " " [
|
||||
"ldapsearch"
|
||||
"-H ldap://ldap.example.com:${toString config.shb.lldap.ldapPort}"
|
||||
];
|
||||
ldapSearchAdmin =
|
||||
let
|
||||
config = nodes.server.specialisation.ldap.configuration;
|
||||
in
|
||||
lib.concatStringsSep " " [
|
||||
"ldapsearch"
|
||||
"-H ldap://ldap.example.com:${toString config.shb.lldap.ldapPort}"
|
||||
"-D uid=admin,ou=people,${config.shb.lldap.dcdomain}"
|
||||
"-w ${config.shb.hardcodedsecret.ldapUserPassword.settings.content}"
|
||||
];
|
||||
in
|
||||
''
|
||||
server.wait_for_unit("multi-user.target")
|
||||
server.wait_for_unit("dovecot")
|
||||
|
||||
with subtest("ldap"):
|
||||
server.succeed("${switch "ldap"}")
|
||||
|
||||
server.wait_for_unit("lldap")
|
||||
print(server.succeed("${ldapSearch} -LLL -D uid=alice,ou=people,dc=example,dc=com -w alicePassword -b cn=user_group,ou=groups,dc=example,dc=com | grep uniquemember | grep alice"))
|
||||
print(server.succeed("${ldapSearchAdmin} -LLL -b cn=user_group,ou=groups,dc=example,dc=com | grep uniquemember | grep alice"))
|
||||
|
||||
server.wait_for_unit("dovecot")
|
||||
print(server.fail("doveadm auth test auser@example.com apassword"))
|
||||
print(server.fail("doveadm auth test charlie@example.com charliePassword"))
|
||||
print(server.succeed("doveadm auth test alice@example.com alicePassword"))
|
||||
|
||||
server.wait_for_unit("postfix")
|
||||
print(server.fail("trySendMail alice@example.com"))
|
||||
print(server.fail("trySendMail auser@example.com apassword"))
|
||||
print(server.fail("trySendMail charlie@example.com charliePassword"))
|
||||
print(server.succeed("trySendMail alice@example.com alicePassword"))
|
||||
|
||||
print(server.fail("tryRcvMail charlie@example.com charliePassword"))
|
||||
print(server.succeed("tryRcvMail alice@example.com alicePassword"))
|
||||
|
||||
print(server.succeed("find /var/vmail"))
|
||||
print(server.succeed("find /var/vmail/fastmail/alice@example.com"))
|
||||
'';
|
||||
};
|
||||
}
|
||||
Loading…
Reference in a new issue