treewide: add language annotations for inline code
Instruct editors to correctly highlight and evaluate inline code blocks.
This commit is contained in:
+16
-14
@@ -69,21 +69,23 @@ rec {
|
||||
passwordFile,
|
||||
destination,
|
||||
}:
|
||||
pkgs.writeScript "append-ldap-bind-pwd-in-${name}" ''
|
||||
#!${pkgs.stdenv.shell}
|
||||
set -euo pipefail
|
||||
pkgs.writeScript "append-ldap-bind-pwd-in-${name}"
|
||||
# bash
|
||||
''
|
||||
#!${pkgs.stdenv.shell}
|
||||
set -euo pipefail
|
||||
|
||||
baseDir=$(dirname ${destination})
|
||||
if (! test -d "$baseDir"); then
|
||||
mkdir -p $baseDir
|
||||
chmod 755 $baseDir
|
||||
fi
|
||||
baseDir=$(dirname ${destination})
|
||||
if (! test -d "$baseDir"); then
|
||||
mkdir -p $baseDir
|
||||
chmod 755 $baseDir
|
||||
fi
|
||||
|
||||
cat ${file} > ${destination}
|
||||
echo -n '${prefix}' >> ${destination}
|
||||
cat ${passwordFile} | tr -d '\n' >> ${destination}
|
||||
echo -n '${suffix}' >> ${destination}
|
||||
chmod 600 ${destination}
|
||||
'';
|
||||
cat ${file} > ${destination}
|
||||
echo -n '${prefix}' >> ${destination}
|
||||
cat ${passwordFile} | tr -d '\n' >> ${destination}
|
||||
echo -n '${suffix}' >> ${destination}
|
||||
chmod 600 ${destination}
|
||||
'';
|
||||
|
||||
}
|
||||
|
||||
+41
-38
@@ -96,50 +96,53 @@ let
|
||||
destination = ldapConfFile;
|
||||
};
|
||||
|
||||
genPasswdScript = pkgs.writeScript "generate-password-file" ''
|
||||
#!${pkgs.stdenv.shell}
|
||||
genPasswdScript =
|
||||
pkgs.writeScript "generate-password-file"
|
||||
# bash
|
||||
''
|
||||
#!${pkgs.stdenv.shell}
|
||||
|
||||
set -euo pipefail
|
||||
set -euo pipefail
|
||||
|
||||
if (! test -d "${passwdDir}"); then
|
||||
mkdir "${passwdDir}"
|
||||
chmod 755 "${passwdDir}"
|
||||
fi
|
||||
if (! test -d "${passwdDir}"); then
|
||||
mkdir "${passwdDir}"
|
||||
chmod 755 "${passwdDir}"
|
||||
fi
|
||||
|
||||
# Prevent world-readable password files, even temporarily.
|
||||
umask 077
|
||||
# Prevent world-readable password files, even temporarily.
|
||||
umask 077
|
||||
|
||||
for f in ${
|
||||
builtins.toString (lib.mapAttrsToList (name: _: passwordFiles."${name}") cfg.loginAccounts)
|
||||
}; do
|
||||
if [ ! -f "$f" ]; then
|
||||
echo "Expected password hash file $f does not exist!"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
for f in ${
|
||||
builtins.toString (lib.mapAttrsToList (name: _: passwordFiles."${name}") cfg.loginAccounts)
|
||||
}; do
|
||||
if [ ! -f "$f" ]; then
|
||||
echo "Expected password hash file $f does not exist!"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
cat <<EOF > ${passwdFile}
|
||||
${lib.concatStringsSep "\n" (
|
||||
lib.mapAttrsToList (
|
||||
name: _:
|
||||
if lib.elem name accountsWithPlaintextPasswordFiles then
|
||||
"${name}:${"$(sed -n '1{p;p;q}' ${passwordFiles."${name}"} | ${lib.getExe' pkgs.dovecot "doveadm"} pw)"}::::::"
|
||||
else
|
||||
"${name}:${"$(head -n 1 ${passwordFiles."${name}"})"}::::::"
|
||||
) cfg.loginAccounts
|
||||
)}
|
||||
EOF
|
||||
cat <<EOF > ${passwdFile}
|
||||
${lib.concatStringsSep "\n" (
|
||||
lib.mapAttrsToList (
|
||||
name: _:
|
||||
if lib.elem name accountsWithPlaintextPasswordFiles then
|
||||
"${name}:${"$(sed -n '1{p;p;q}' ${passwordFiles."${name}"} | ${lib.getExe' pkgs.dovecot "doveadm"} pw)"}::::::"
|
||||
else
|
||||
"${name}:${"$(head -n 1 ${passwordFiles."${name}"})"}::::::"
|
||||
) cfg.loginAccounts
|
||||
)}
|
||||
EOF
|
||||
|
||||
cat <<EOF > ${userdbFile}
|
||||
${lib.concatStringsSep "\n" (
|
||||
lib.mapAttrsToList (
|
||||
name: value:
|
||||
"${name}:::::::"
|
||||
+ lib.optionalString (value.quota != null) "userdb_quota_rule=*:storage=${value.quota}"
|
||||
) cfg.loginAccounts
|
||||
)}
|
||||
EOF
|
||||
'';
|
||||
cat <<EOF > ${userdbFile}
|
||||
${lib.concatStringsSep "\n" (
|
||||
lib.mapAttrsToList (
|
||||
name: value:
|
||||
"${name}:::::::"
|
||||
+ lib.optionalString (value.quota != null) "userdb_quota_rule=*:storage=${value.quota}"
|
||||
) cfg.loginAccounts
|
||||
)}
|
||||
EOF
|
||||
'';
|
||||
|
||||
junkMailboxes = builtins.attrNames (
|
||||
lib.filterAttrs (_: v: v ? "specialUse" && v.specialUse == "Junk") cfg.mailboxes
|
||||
|
||||
+41
-38
@@ -43,48 +43,51 @@ let
|
||||
group = vmailGroupName;
|
||||
};
|
||||
|
||||
virtualMailUsersActivationScript = pkgs.writeScript "activate-virtual-mail-users" ''
|
||||
#!${pkgs.stdenv.shell}
|
||||
virtualMailUsersActivationScript =
|
||||
pkgs.writeScript "activate-virtual-mail-users"
|
||||
# bash
|
||||
''
|
||||
#!${pkgs.stdenv.shell}
|
||||
|
||||
set -euo pipefail
|
||||
set -euo pipefail
|
||||
|
||||
# Prevent world-readable paths, even temporarily.
|
||||
umask 007
|
||||
# Prevent world-readable paths, even temporarily.
|
||||
umask 007
|
||||
|
||||
# Create directory to store user sieve scripts if it doesn't exist
|
||||
if (! test -d "${sieveDirectory}"); then
|
||||
mkdir "${sieveDirectory}"
|
||||
chown "${vmailUserName}:${vmailGroupName}" "${sieveDirectory}"
|
||||
chmod 770 "${sieveDirectory}"
|
||||
fi
|
||||
# Create directory to store user sieve scripts if it doesn't exist
|
||||
if (! test -d "${sieveDirectory}"); then
|
||||
mkdir "${sieveDirectory}"
|
||||
chown "${vmailUserName}:${vmailGroupName}" "${sieveDirectory}"
|
||||
chmod 770 "${sieveDirectory}"
|
||||
fi
|
||||
|
||||
# Copy user's sieve script to the correct location (if it exists). If it
|
||||
# is null, remove the file.
|
||||
${lib.concatMapStringsSep "\n" (
|
||||
{ name, sieveScript }:
|
||||
if lib.isString sieveScript then
|
||||
''
|
||||
if (! test -d "${sieveDirectory}/${name}"); then
|
||||
mkdir -p "${sieveDirectory}/${name}"
|
||||
chown "${vmailUserName}:${vmailGroupName}" "${sieveDirectory}/${name}"
|
||||
chmod 770 "${sieveDirectory}/${name}"
|
||||
fi
|
||||
cat << 'EOF' > "${sieveDirectory}/${name}/default.sieve"
|
||||
${sieveScript}
|
||||
EOF
|
||||
chown "${vmailUserName}:${vmailGroupName}" "${sieveDirectory}/${name}/default.sieve"
|
||||
''
|
||||
else
|
||||
''
|
||||
if (test -f "${sieveDirectory}/${name}/default.sieve"); then
|
||||
rm "${sieveDirectory}/${name}/default.sieve"
|
||||
fi
|
||||
if (test -f "${sieveDirectory}/${name}.svbin"); then
|
||||
rm "${sieveDirectory}/${name}/default.svbin"
|
||||
fi
|
||||
''
|
||||
) (map (user: { inherit (user) name sieveScript; }) (lib.attrValues loginAccounts))}
|
||||
'';
|
||||
# Copy user's sieve script to the correct location (if it exists). If it
|
||||
# is null, remove the file.
|
||||
${lib.concatMapStringsSep "\n" (
|
||||
{ name, sieveScript }:
|
||||
if lib.isString sieveScript then
|
||||
''
|
||||
if (! test -d "${sieveDirectory}/${name}"); then
|
||||
mkdir -p "${sieveDirectory}/${name}"
|
||||
chown "${vmailUserName}:${vmailGroupName}" "${sieveDirectory}/${name}"
|
||||
chmod 770 "${sieveDirectory}/${name}"
|
||||
fi
|
||||
cat << 'EOF' > "${sieveDirectory}/${name}/default.sieve"
|
||||
${sieveScript}
|
||||
EOF
|
||||
chown "${vmailUserName}:${vmailGroupName}" "${sieveDirectory}/${name}/default.sieve"
|
||||
''
|
||||
else
|
||||
''
|
||||
if (test -f "${sieveDirectory}/${name}/default.sieve"); then
|
||||
rm "${sieveDirectory}/${name}/default.sieve"
|
||||
fi
|
||||
if (test -f "${sieveDirectory}/${name}.svbin"); then
|
||||
rm "${sieveDirectory}/${name}/default.svbin"
|
||||
fi
|
||||
''
|
||||
) (map (user: { inherit (user) name sieveScript; }) (lib.attrValues loginAccounts))}
|
||||
'';
|
||||
in
|
||||
{
|
||||
config = lib.mkIf enable {
|
||||
|
||||
+90
-84
@@ -144,111 +144,117 @@
|
||||
password user2
|
||||
'';
|
||||
};
|
||||
"root/virus-email".text = ''
|
||||
From: User2 <user@example2.com>
|
||||
Content-Type: multipart/mixed;
|
||||
boundary="Apple-Mail=_2689C63E-FD18-4E4D-8822-54797BDA9607"
|
||||
Mime-Version: 1.0 (Mac OS X Mail 11.3 \(3445.6.18\))
|
||||
Subject: Testy McTest
|
||||
Message-Id: <94550DD9-1FF1-4ED1-9F09-8812FF2E59AA@example.com>
|
||||
Date: Sat, 12 May 2018 14:15:44 +0200
|
||||
To: User1 <user1@example.com>
|
||||
X-Mailer: Apple Mail (2.3445.6.18)
|
||||
"root/virus-email".text =
|
||||
# mail
|
||||
''
|
||||
From: User2 <user@example2.com>
|
||||
Content-Type: multipart/mixed;
|
||||
boundary="Apple-Mail=_2689C63E-FD18-4E4D-8822-54797BDA9607"
|
||||
Mime-Version: 1.0 (Mac OS X Mail 11.3 \(3445.6.18\))
|
||||
Subject: Testy McTest
|
||||
Message-Id: <94550DD9-1FF1-4ED1-9F09-8812FF2E59AA@example.com>
|
||||
Date: Sat, 12 May 2018 14:15:44 +0200
|
||||
To: User1 <user1@example.com>
|
||||
X-Mailer: Apple Mail (2.3445.6.18)
|
||||
|
||||
|
||||
--Apple-Mail=_2689C63E-FD18-4E4D-8822-54797BDA9607
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Type: text/plain;
|
||||
charset=us-ascii
|
||||
--Apple-Mail=_2689C63E-FD18-4E4D-8822-54797BDA9607
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Type: text/plain;
|
||||
charset=us-ascii
|
||||
|
||||
Hello
|
||||
Hello
|
||||
|
||||
I have attached a dangerous virus.
|
||||
I have attached a dangerous virus.
|
||||
|
||||
Mfg.
|
||||
User2
|
||||
Mfg.
|
||||
User2
|
||||
|
||||
|
||||
--Apple-Mail=_2689C63E-FD18-4E4D-8822-54797BDA9607
|
||||
Content-Disposition: attachment;
|
||||
filename=eicar.com.txt
|
||||
Content-Type: text/plain;
|
||||
x-unix-mode=0644;
|
||||
name="eicar.com.txt"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
--Apple-Mail=_2689C63E-FD18-4E4D-8822-54797BDA9607
|
||||
Content-Disposition: attachment;
|
||||
filename=eicar.com.txt
|
||||
Content-Type: text/plain;
|
||||
x-unix-mode=0644;
|
||||
name="eicar.com.txt"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
|
||||
--Apple-Mail=_2689C63E-FD18-4E4D-8822-54797BDA9607--
|
||||
'';
|
||||
"root/safe-email".text = ''
|
||||
From: User <user@example2.com>
|
||||
To: User1 <user1@example.com>
|
||||
Cc:
|
||||
Bcc:
|
||||
Subject: This is a test Email from user@example2.com to user1
|
||||
Reply-To:
|
||||
X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
|
||||
--Apple-Mail=_2689C63E-FD18-4E4D-8822-54797BDA9607--
|
||||
'';
|
||||
"root/safe-email".text =
|
||||
# mail
|
||||
''
|
||||
From: User <user@example2.com>
|
||||
To: User1 <user1@example.com>
|
||||
Cc:
|
||||
Bcc:
|
||||
Subject: This is a test Email from user@example2.com to user1
|
||||
Reply-To:
|
||||
|
||||
Hello User1,
|
||||
Hello User1,
|
||||
|
||||
how are you doing today?
|
||||
how are you doing today?
|
||||
|
||||
XOXO User1
|
||||
'';
|
||||
XOXO User1
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
testScript =
|
||||
# python
|
||||
''
|
||||
start_all()
|
||||
|
||||
server.wait_for_unit("multi-user.target")
|
||||
client.wait_for_unit("multi-user.target")
|
||||
server.wait_for_unit("multi-user.target")
|
||||
client.wait_for_unit("multi-user.target")
|
||||
|
||||
# TODO put this blocking into the systemd units? I am not sure if rspamd already waits for the clamd socket.
|
||||
server.wait_until_succeeds(
|
||||
"set +e; timeout 1 nc -U /run/rspamd/rspamd-milter.sock < /dev/null; [ $? -eq 124 ]"
|
||||
)
|
||||
server.wait_until_succeeds(
|
||||
"set +e; timeout 1 nc -U /run/clamav/clamd.ctl < /dev/null; [ $? -eq 124 ]"
|
||||
)
|
||||
# TODO put this blocking into the systemd units? I am not sure if rspamd already waits for the clamd socket.
|
||||
server.wait_until_succeeds(
|
||||
"set +e; timeout 1 nc -U /run/rspamd/rspamd-milter.sock < /dev/null; [ $? -eq 124 ]"
|
||||
)
|
||||
server.wait_until_succeeds(
|
||||
"set +e; timeout 1 nc -U /run/clamav/clamd.ctl < /dev/null; [ $? -eq 124 ]"
|
||||
)
|
||||
|
||||
client.execute("cp -p /etc/root/.* ~/")
|
||||
client.succeed("mkdir -p ~/mail")
|
||||
client.succeed("ls -la ~/ >&2")
|
||||
client.succeed("cat ~/.fetchmailrc >&2")
|
||||
client.succeed("cat ~/.procmailrc >&2")
|
||||
client.succeed("cat ~/.msmtprc >&2")
|
||||
client.execute("cp -p /etc/root/.* ~/")
|
||||
client.succeed("mkdir -p ~/mail")
|
||||
client.succeed("ls -la ~/ >&2")
|
||||
client.succeed("cat ~/.fetchmailrc >&2")
|
||||
client.succeed("cat ~/.procmailrc >&2")
|
||||
client.succeed("cat ~/.msmtprc >&2")
|
||||
|
||||
# fetchmail returns EXIT_CODE 1 when no new mail
|
||||
client.succeed("fetchmail --nosslcertck -v || [ $? -eq 1 ] >&2")
|
||||
# fetchmail returns EXIT_CODE 1 when no new mail
|
||||
client.succeed("fetchmail --nosslcertck -v || [ $? -eq 1 ] >&2")
|
||||
|
||||
# Verify that mail can be sent and received before testing virus scanner
|
||||
client.execute("rm ~/mail/*")
|
||||
client.succeed("msmtp -a user2 user1@example.com < /etc/root/safe-email >&2")
|
||||
# give the mail server some time to process the mail
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
client.execute("rm ~/mail/*")
|
||||
# fetchmail returns EXIT_CODE 0 when it retrieves mail
|
||||
client.succeed("fetchmail --nosslcertck -v >&2")
|
||||
client.execute("rm ~/mail/*")
|
||||
# Verify that mail can be sent and received before testing virus scanner
|
||||
client.execute("rm ~/mail/*")
|
||||
client.succeed("msmtp -a user2 user1@example.com < /etc/root/safe-email >&2")
|
||||
# give the mail server some time to process the mail
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
client.execute("rm ~/mail/*")
|
||||
# fetchmail returns EXIT_CODE 0 when it retrieves mail
|
||||
client.succeed("fetchmail --nosslcertck -v >&2")
|
||||
client.execute("rm ~/mail/*")
|
||||
|
||||
with subtest("virus scan file"):
|
||||
server.succeed(
|
||||
'set +o pipefail; clamdscan $(readlink -f /etc/root/eicar.com.txt) | grep "Txt\\.Malware\\.Agent-1787597 FOUND" >&2'
|
||||
)
|
||||
with subtest("virus scan file"):
|
||||
server.succeed(
|
||||
'set +o pipefail; clamdscan $(readlink -f /etc/root/eicar.com.txt) | grep "Txt\\.Malware\\.Agent-1787597 FOUND" >&2'
|
||||
)
|
||||
|
||||
with subtest("virus scan email"):
|
||||
client.succeed(
|
||||
'set +o pipefail; msmtp -a user2 user1@example.com < /etc/root/virus-email 2>&1 | tee /dev/stderr | grep "server message: 554 5\\.7\\.1" >&2'
|
||||
)
|
||||
server.succeed("journalctl -u rspamd | grep -i eicar")
|
||||
# give the mail server some time to process the mail
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
with subtest("virus scan email"):
|
||||
client.succeed(
|
||||
'set +o pipefail; msmtp -a user2 user1@example.com < /etc/root/virus-email 2>&1 | tee /dev/stderr | grep "server message: 554 5\\.7\\.1" >&2'
|
||||
)
|
||||
server.succeed("journalctl -u rspamd | grep -i eicar")
|
||||
# give the mail server some time to process the mail
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
|
||||
with subtest("no warnings or errors"):
|
||||
server.fail("journalctl -u postfix | grep -i error >&2")
|
||||
server.fail("journalctl -u postfix | grep -i warning >&2")
|
||||
server.fail("journalctl -u dovecot | grep -i error >&2")
|
||||
server.fail("journalctl -u dovecot | grep -i warning >&2")
|
||||
'';
|
||||
with subtest("no warnings or errors"):
|
||||
server.fail("journalctl -u postfix | grep -i error >&2")
|
||||
server.fail("journalctl -u postfix | grep -i warning >&2")
|
||||
server.fail("journalctl -u dovecot | grep -i error >&2")
|
||||
server.fail("journalctl -u dovecot | grep -i warning >&2")
|
||||
'';
|
||||
}
|
||||
|
||||
+322
-297
@@ -121,80 +121,89 @@
|
||||
echo grep '^Message-ID:.*@mail.example.com>$' "$@" >&2
|
||||
exec grep '^Message-ID:.*@mail.example.com>$' "$@"
|
||||
'';
|
||||
test-imap-spam = pkgs.writeScriptBin "imap-mark-spam" ''
|
||||
#!${pkgs.python3.interpreter}
|
||||
import imaplib
|
||||
test-imap-spam =
|
||||
pkgs.writeScriptBin "imap-mark-spam"
|
||||
# python
|
||||
''
|
||||
#!${pkgs.python3.interpreter}
|
||||
import imaplib
|
||||
|
||||
with imaplib.IMAP4_SSL('${serverIP}') as imap:
|
||||
imap.login('user1@example.com', 'user1')
|
||||
imap.select()
|
||||
status, [response] = imap.search(None, 'ALL')
|
||||
msg_ids = response.decode("utf-8").split(' ')
|
||||
print(msg_ids)
|
||||
assert status == 'OK'
|
||||
assert len(msg_ids) == 1
|
||||
with imaplib.IMAP4_SSL('${serverIP}') as imap:
|
||||
imap.login('user1@example.com', 'user1')
|
||||
imap.select()
|
||||
status, [response] = imap.search(None, 'ALL')
|
||||
msg_ids = response.decode("utf-8").split(' ')
|
||||
print(msg_ids)
|
||||
assert status == 'OK'
|
||||
assert len(msg_ids) == 1
|
||||
|
||||
imap.copy(','.join(msg_ids), 'Junk')
|
||||
for num in msg_ids:
|
||||
imap.store(num, '+FLAGS', '\\Deleted')
|
||||
imap.expunge()
|
||||
imap.copy(','.join(msg_ids), 'Junk')
|
||||
for num in msg_ids:
|
||||
imap.store(num, '+FLAGS', '\\Deleted')
|
||||
imap.expunge()
|
||||
|
||||
imap.select('Junk')
|
||||
status, [response] = imap.search(None, 'ALL')
|
||||
msg_ids = response.decode("utf-8").split(' ')
|
||||
print(msg_ids)
|
||||
assert status == 'OK'
|
||||
assert len(msg_ids) == 1
|
||||
imap.select('Junk')
|
||||
status, [response] = imap.search(None, 'ALL')
|
||||
msg_ids = response.decode("utf-8").split(' ')
|
||||
print(msg_ids)
|
||||
assert status == 'OK'
|
||||
assert len(msg_ids) == 1
|
||||
|
||||
imap.close()
|
||||
'';
|
||||
test-imap-ham = pkgs.writeScriptBin "imap-mark-ham" ''
|
||||
#!${pkgs.python3.interpreter}
|
||||
import imaplib
|
||||
imap.close()
|
||||
'';
|
||||
test-imap-ham =
|
||||
pkgs.writeScriptBin "imap-mark-ham"
|
||||
# python
|
||||
''
|
||||
#!${pkgs.python3.interpreter}
|
||||
import imaplib
|
||||
|
||||
with imaplib.IMAP4_SSL('${serverIP}') as imap:
|
||||
imap.login('user1@example.com', 'user1')
|
||||
imap.select('Junk')
|
||||
status, [response] = imap.search(None, 'ALL')
|
||||
msg_ids = response.decode("utf-8").split(' ')
|
||||
print(msg_ids)
|
||||
assert status == 'OK'
|
||||
assert len(msg_ids) == 1
|
||||
with imaplib.IMAP4_SSL('${serverIP}') as imap:
|
||||
imap.login('user1@example.com', 'user1')
|
||||
imap.select('Junk')
|
||||
status, [response] = imap.search(None, 'ALL')
|
||||
msg_ids = response.decode("utf-8").split(' ')
|
||||
print(msg_ids)
|
||||
assert status == 'OK'
|
||||
assert len(msg_ids) == 1
|
||||
|
||||
imap.copy(','.join(msg_ids), 'INBOX')
|
||||
for num in msg_ids:
|
||||
imap.store(num, '+FLAGS', '\\Deleted')
|
||||
imap.expunge()
|
||||
imap.copy(','.join(msg_ids), 'INBOX')
|
||||
for num in msg_ids:
|
||||
imap.store(num, '+FLAGS', '\\Deleted')
|
||||
imap.expunge()
|
||||
|
||||
imap.select('INBOX')
|
||||
status, [response] = imap.search(None, 'ALL')
|
||||
msg_ids = response.decode("utf-8").split(' ')
|
||||
print(msg_ids)
|
||||
assert status == 'OK'
|
||||
assert len(msg_ids) == 1
|
||||
imap.select('INBOX')
|
||||
status, [response] = imap.search(None, 'ALL')
|
||||
msg_ids = response.decode("utf-8").split(' ')
|
||||
print(msg_ids)
|
||||
assert status == 'OK'
|
||||
assert len(msg_ids) == 1
|
||||
|
||||
imap.close()
|
||||
'';
|
||||
search = pkgs.writeScriptBin "search" ''
|
||||
#!${pkgs.python3.interpreter}
|
||||
import imaplib
|
||||
import sys
|
||||
imap.close()
|
||||
'';
|
||||
search =
|
||||
pkgs.writeScriptBin "search"
|
||||
# python
|
||||
''
|
||||
#!${pkgs.python3.interpreter}
|
||||
import imaplib
|
||||
import sys
|
||||
|
||||
[_, mailbox, needle] = sys.argv
|
||||
[_, mailbox, needle] = sys.argv
|
||||
|
||||
with imaplib.IMAP4_SSL('${serverIP}') as imap:
|
||||
imap.login('user1@example.com', 'user1')
|
||||
imap.select(mailbox)
|
||||
status, [response] = imap.search(None, 'BODY', repr(needle))
|
||||
msg_ids = [ i for i in response.decode("utf-8").split(' ') if i ]
|
||||
print(msg_ids)
|
||||
assert status == 'OK'
|
||||
assert len(msg_ids) == 1
|
||||
status, response = imap.fetch(msg_ids[0], '(RFC822)')
|
||||
assert status == "OK"
|
||||
assert needle in repr(response)
|
||||
imap.close()
|
||||
'';
|
||||
with imaplib.IMAP4_SSL('${serverIP}') as imap:
|
||||
imap.login('user1@example.com', 'user1')
|
||||
imap.select(mailbox)
|
||||
status, [response] = imap.search(None, 'BODY', repr(needle))
|
||||
msg_ids = [ i for i in response.decode("utf-8").split(' ') if i ]
|
||||
print(msg_ids)
|
||||
assert status == 'OK'
|
||||
assert len(msg_ids) == 1
|
||||
status, response = imap.fetch(msg_ids[0], '(RFC822)')
|
||||
assert status == "OK"
|
||||
assert needle in repr(response)
|
||||
imap.close()
|
||||
'';
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
@@ -269,282 +278,298 @@
|
||||
password user1
|
||||
'';
|
||||
};
|
||||
"root/email1".text = ''
|
||||
Message-ID: <12345qwerty@host.local.network>
|
||||
From: User2 <user2@example.com>
|
||||
To: User1 <user1@example.com>
|
||||
Cc:
|
||||
Bcc:
|
||||
Subject: This is a test Email from user2 to user1
|
||||
Reply-To:
|
||||
"root/email1".text =
|
||||
# mail
|
||||
''
|
||||
Message-ID: <12345qwerty@host.local.network>
|
||||
From: User2 <user2@example.com>
|
||||
To: User1 <user1@example.com>
|
||||
Cc:
|
||||
Bcc:
|
||||
Subject: This is a test Email from user2 to user1
|
||||
Reply-To:
|
||||
|
||||
Hello User1,
|
||||
Hello User1,
|
||||
|
||||
how are you doing today?
|
||||
'';
|
||||
"root/email2".text = ''
|
||||
Message-ID: <232323abc@host.local.network>
|
||||
From: User <user@example2.com>
|
||||
To: User1 <user1@example.com>
|
||||
Cc:
|
||||
Bcc:
|
||||
Subject: This is a test Email from user@example2.com to user1
|
||||
Reply-To:
|
||||
how are you doing today?
|
||||
'';
|
||||
"root/email2".text =
|
||||
# mail
|
||||
''
|
||||
Message-ID: <232323abc@host.local.network>
|
||||
From: User <user@example2.com>
|
||||
To: User1 <user1@example.com>
|
||||
Cc:
|
||||
Bcc:
|
||||
Subject: This is a test Email from user@example2.com to user1
|
||||
Reply-To:
|
||||
|
||||
Hello User1,
|
||||
Hello User1,
|
||||
|
||||
how are you doing today?
|
||||
how are you doing today?
|
||||
|
||||
XOXO User1
|
||||
'';
|
||||
"root/email3".text = ''
|
||||
Message-ID: <asdfghjkl42@host.local.network>
|
||||
From: Postmaster <postmaster@example.com>
|
||||
To: Chuck <chuck@example.com>
|
||||
Cc:
|
||||
Bcc:
|
||||
Subject: This is a test Email from postmaster@example.com to chuck
|
||||
Reply-To:
|
||||
XOXO User1
|
||||
'';
|
||||
"root/email3".text =
|
||||
# mail
|
||||
''
|
||||
Message-ID: <asdfghjkl42@host.local.network>
|
||||
From: Postmaster <postmaster@example.com>
|
||||
To: Chuck <chuck@example.com>
|
||||
Cc:
|
||||
Bcc:
|
||||
Subject: This is a test Email from postmaster@example.com to chuck
|
||||
Reply-To:
|
||||
|
||||
Hello Chuck,
|
||||
Hello Chuck,
|
||||
|
||||
I think I may have misconfigured the mail server
|
||||
XOXO Postmaster
|
||||
'';
|
||||
"root/email4".text = ''
|
||||
Message-ID: <sdfsdf@host.local.network>
|
||||
From: Single Alias <single-alias@example.com>
|
||||
To: User1 <user1@example.com>
|
||||
Cc:
|
||||
Bcc:
|
||||
Subject: This is a test Email from single-alias@example.com to user1
|
||||
Reply-To:
|
||||
I think I may have misconfigured the mail server
|
||||
XOXO Postmaster
|
||||
'';
|
||||
"root/email4".text =
|
||||
# mail
|
||||
''
|
||||
Message-ID: <sdfsdf@host.local.network>
|
||||
From: Single Alias <single-alias@example.com>
|
||||
To: User1 <user1@example.com>
|
||||
Cc:
|
||||
Bcc:
|
||||
Subject: This is a test Email from single-alias@example.com to user1
|
||||
Reply-To:
|
||||
|
||||
Hello User1,
|
||||
Hello User1,
|
||||
|
||||
how are you doing today?
|
||||
how are you doing today?
|
||||
|
||||
XOXO User1 aka Single Alias
|
||||
'';
|
||||
"root/email5".text = ''
|
||||
Message-ID: <789asdf@host.local.network>
|
||||
From: User2 <user2@example.com>
|
||||
To: Multi Alias <multi-alias@example.com>
|
||||
Cc:
|
||||
Bcc:
|
||||
Subject: This is a test Email from user2@example.com to multi-alias
|
||||
Reply-To:
|
||||
XOXO User1 aka Single Alias
|
||||
'';
|
||||
"root/email5".text =
|
||||
# mail
|
||||
''
|
||||
Message-ID: <789asdf@host.local.network>
|
||||
From: User2 <user2@example.com>
|
||||
To: Multi Alias <multi-alias@example.com>
|
||||
Cc:
|
||||
Bcc:
|
||||
Subject: This is a test Email from user2@example.com to multi-alias
|
||||
Reply-To:
|
||||
|
||||
Hello Multi Alias,
|
||||
Hello Multi Alias,
|
||||
|
||||
how are we doing today?
|
||||
how are we doing today?
|
||||
|
||||
XOXO User1
|
||||
'';
|
||||
"root/email6".text = ''
|
||||
Message-ID: <123457qwerty@host.local.network>
|
||||
From: User2 <user2@example.com>
|
||||
To: User1 <user1@example.com>
|
||||
Cc:
|
||||
Bcc:
|
||||
Subject: This is a test Email from user2 to user1
|
||||
Reply-To:
|
||||
XOXO User1
|
||||
'';
|
||||
"root/email6".text =
|
||||
# mail
|
||||
''
|
||||
Message-ID: <123457qwerty@host.local.network>
|
||||
From: User2 <user2@example.com>
|
||||
To: User1 <user1@example.com>
|
||||
Cc:
|
||||
Bcc:
|
||||
Subject: This is a test Email from user2 to user1
|
||||
Reply-To:
|
||||
|
||||
Hello User1,
|
||||
Hello User1,
|
||||
|
||||
this email contains the needle:
|
||||
576a4565b70f5a4c1a0925cabdb587a6
|
||||
'';
|
||||
"root/email7".text = ''
|
||||
Message-ID: <1234578qwerty@host.local.network>
|
||||
From: User2 <user2@example.com>
|
||||
To: User1 <user1@example.com>
|
||||
Cc:
|
||||
Bcc:
|
||||
Subject: This is a test Email from user2 to user1
|
||||
Reply-To:
|
||||
this email contains the needle:
|
||||
576a4565b70f5a4c1a0925cabdb587a6
|
||||
'';
|
||||
"root/email7".text =
|
||||
# mail
|
||||
''
|
||||
Message-ID: <1234578qwerty@host.local.network>
|
||||
From: User2 <user2@example.com>
|
||||
To: User1 <user1@example.com>
|
||||
Cc:
|
||||
Bcc:
|
||||
Subject: This is a test Email from user2 to user1
|
||||
Reply-To:
|
||||
|
||||
Hello User1,
|
||||
Hello User1,
|
||||
|
||||
this email does not contain the needle :(
|
||||
'';
|
||||
this email does not contain the needle :(
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
testScript =
|
||||
# python
|
||||
''
|
||||
start_all()
|
||||
|
||||
server.wait_for_unit("multi-user.target")
|
||||
client.wait_for_unit("multi-user.target")
|
||||
server.wait_for_unit("multi-user.target")
|
||||
client.wait_for_unit("multi-user.target")
|
||||
|
||||
# TODO put this blocking into the systemd units?
|
||||
server.wait_until_succeeds(
|
||||
"set +e; timeout 1 nc -U /run/rspamd/rspamd-milter.sock < /dev/null; [ $? -eq 124 ]"
|
||||
)
|
||||
# TODO put this blocking into the systemd units?
|
||||
server.wait_until_succeeds(
|
||||
"set +e; timeout 1 nc -U /run/rspamd/rspamd-milter.sock < /dev/null; [ $? -eq 124 ]"
|
||||
)
|
||||
|
||||
server.succeed("rspamadm dkim_keygen > /run/rspamd/dkim-test.key")
|
||||
server.succeed("chown rspamd: /run/rspamd/dkim-test.key")
|
||||
server.succeed("rspamadm dkim_keygen > /run/rspamd/dkim-test.key")
|
||||
server.succeed("chown rspamd: /run/rspamd/dkim-test.key")
|
||||
|
||||
client.execute("cp -p /etc/root/.* ~/")
|
||||
client.succeed("mkdir -p ~/mail")
|
||||
client.succeed("ls -la ~/ >&2")
|
||||
client.succeed("cat ~/.fetchmailrc >&2")
|
||||
client.succeed("cat ~/.procmailrc >&2")
|
||||
client.succeed("cat ~/.msmtprc >&2")
|
||||
client.execute("cp -p /etc/root/.* ~/")
|
||||
client.succeed("mkdir -p ~/mail")
|
||||
client.succeed("ls -la ~/ >&2")
|
||||
client.succeed("cat ~/.fetchmailrc >&2")
|
||||
client.succeed("cat ~/.procmailrc >&2")
|
||||
client.succeed("cat ~/.msmtprc >&2")
|
||||
|
||||
with subtest("imap retrieving mail"):
|
||||
# fetchmail returns EXIT_CODE 1 when no new mail
|
||||
client.succeed("fetchmail --nosslcertck -v || [ $? -eq 1 ] >&2")
|
||||
with subtest("imap retrieving mail"):
|
||||
# fetchmail returns EXIT_CODE 1 when no new mail
|
||||
client.succeed("fetchmail --nosslcertck -v || [ $? -eq 1 ] >&2")
|
||||
|
||||
with subtest("submission port send mail"):
|
||||
# send email from user2 to user1
|
||||
client.succeed(
|
||||
"msmtp -a test --tls=on --tls-certcheck=off --auth=on user1@example.com < /etc/root/email1 >&2"
|
||||
)
|
||||
# give the mail server some time to process the mail
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
with subtest("submission port send mail"):
|
||||
# send email from user2 to user1
|
||||
client.succeed(
|
||||
"msmtp -a test --tls=on --tls-certcheck=off --auth=on user1@example.com < /etc/root/email1 >&2"
|
||||
)
|
||||
# give the mail server some time to process the mail
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
|
||||
with subtest("imap retrieving mail 2"):
|
||||
client.execute("rm ~/mail/*")
|
||||
# fetchmail returns EXIT_CODE 0 when it retrieves mail
|
||||
client.succeed("fetchmail --nosslcertck -v >&2")
|
||||
with subtest("imap retrieving mail 2"):
|
||||
client.execute("rm ~/mail/*")
|
||||
# fetchmail returns EXIT_CODE 0 when it retrieves mail
|
||||
client.succeed("fetchmail --nosslcertck -v >&2")
|
||||
|
||||
with subtest("remove sensitive information on submission port"):
|
||||
client.succeed("cat ~/mail/* >&2")
|
||||
## make sure our IP is _not_ in the email header
|
||||
client.fail("grep-ip ~/mail/*")
|
||||
client.succeed("check-mail-id ~/mail/*")
|
||||
with subtest("remove sensitive information on submission port"):
|
||||
client.succeed("cat ~/mail/* >&2")
|
||||
## make sure our IP is _not_ in the email header
|
||||
client.fail("grep-ip ~/mail/*")
|
||||
client.succeed("check-mail-id ~/mail/*")
|
||||
|
||||
with subtest("have correct fqdn as sender"):
|
||||
client.succeed("grep 'Received: from mail.example.com' ~/mail/*")
|
||||
with subtest("have correct fqdn as sender"):
|
||||
client.succeed("grep 'Received: from mail.example.com' ~/mail/*")
|
||||
|
||||
with subtest("dkim has user-specified size"):
|
||||
server.succeed(
|
||||
"openssl rsa -in /var/dkim/example2.com.dkim-rsa.key -text -noout | grep 'Private-Key: (1535 bit'"
|
||||
)
|
||||
with subtest("dkim has user-specified size"):
|
||||
server.succeed(
|
||||
"openssl rsa -in /var/dkim/example2.com.dkim-rsa.key -text -noout | grep 'Private-Key: (1535 bit'"
|
||||
)
|
||||
|
||||
with subtest("dkim signing, multiple domains"):
|
||||
client.execute("rm ~/mail/*")
|
||||
# send email from user2 to user1
|
||||
client.succeed(
|
||||
"msmtp -a test2 --tls=on --tls-certcheck=off --auth=on user1@example.com < /etc/root/email2 >&2"
|
||||
)
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
# fetchmail returns EXIT_CODE 0 when it retrieves mail
|
||||
client.succeed("fetchmail --nosslcertck -v")
|
||||
client.succeed("cat ~/mail/* >&2")
|
||||
# make sure it is dkim signed
|
||||
client.succeed("grep 's=dkim-rsa' ~/mail/*")
|
||||
client.succeed("grep 's=dkim-ed25519' ~/mail/*")
|
||||
client.succeed("grep 's=dkim-file' ~/mail/*")
|
||||
with subtest("dkim signing, multiple domains"):
|
||||
client.execute("rm ~/mail/*")
|
||||
# send email from user2 to user1
|
||||
client.succeed(
|
||||
"msmtp -a test2 --tls=on --tls-certcheck=off --auth=on user1@example.com < /etc/root/email2 >&2"
|
||||
)
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
# fetchmail returns EXIT_CODE 0 when it retrieves mail
|
||||
client.succeed("fetchmail --nosslcertck -v")
|
||||
client.succeed("cat ~/mail/* >&2")
|
||||
# make sure it is dkim signed
|
||||
client.succeed("grep 's=dkim-rsa' ~/mail/*")
|
||||
client.succeed("grep 's=dkim-ed25519' ~/mail/*")
|
||||
client.succeed("grep 's=dkim-file' ~/mail/*")
|
||||
|
||||
with subtest("aliases"):
|
||||
client.execute("rm ~/mail/*")
|
||||
# send email from chuck to postmaster
|
||||
client.succeed(
|
||||
"msmtp -a test3 --tls=on --tls-certcheck=off --auth=on postmaster@example.com < /etc/root/email2 >&2"
|
||||
)
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
# fetchmail returns EXIT_CODE 0 when it retrieves mail
|
||||
client.succeed("fetchmail --nosslcertck -v")
|
||||
with subtest("aliases"):
|
||||
client.execute("rm ~/mail/*")
|
||||
# send email from chuck to postmaster
|
||||
client.succeed(
|
||||
"msmtp -a test3 --tls=on --tls-certcheck=off --auth=on postmaster@example.com < /etc/root/email2 >&2"
|
||||
)
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
# fetchmail returns EXIT_CODE 0 when it retrieves mail
|
||||
client.succeed("fetchmail --nosslcertck -v")
|
||||
|
||||
with subtest("domain catch-all"):
|
||||
client.execute("rm ~/mail/*")
|
||||
# send email from chuck to non-existent account
|
||||
client.succeed(
|
||||
"msmtp -a test3 --tls=on --tls-certcheck=off --auth=on lol@example.com < /etc/root/email2 >&2"
|
||||
)
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
# fetchmail returns EXIT_CODE 0 when it retrieves mail
|
||||
client.succeed("fetchmail --nosslcertck -v")
|
||||
with subtest("domain catch-all"):
|
||||
client.execute("rm ~/mail/*")
|
||||
# send email from chuck to non-existent account
|
||||
client.succeed(
|
||||
"msmtp -a test3 --tls=on --tls-certcheck=off --auth=on lol@example.com < /etc/root/email2 >&2"
|
||||
)
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
# fetchmail returns EXIT_CODE 0 when it retrieves mail
|
||||
client.succeed("fetchmail --nosslcertck -v")
|
||||
|
||||
client.execute("rm ~/mail/*")
|
||||
# send email from user1 to chuck
|
||||
client.succeed(
|
||||
"msmtp -a test4 --tls=on --tls-certcheck=off --auth=on chuck@example.com < /etc/root/email2 >&2"
|
||||
)
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
# fetchmail returns EXIT_CODE 1 when no new mail
|
||||
# if this succeeds, it means that user1 received the mail that was intended for chuck.
|
||||
client.fail("fetchmail --nosslcertck -v")
|
||||
client.execute("rm ~/mail/*")
|
||||
# send email from user1 to chuck
|
||||
client.succeed(
|
||||
"msmtp -a test4 --tls=on --tls-certcheck=off --auth=on chuck@example.com < /etc/root/email2 >&2"
|
||||
)
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
# fetchmail returns EXIT_CODE 1 when no new mail
|
||||
# if this succeeds, it means that user1 received the mail that was intended for chuck.
|
||||
client.fail("fetchmail --nosslcertck -v")
|
||||
|
||||
with subtest("extraVirtualAliases"):
|
||||
client.execute("rm ~/mail/*")
|
||||
# send email from single-alias to user1
|
||||
client.succeed(
|
||||
"msmtp -a test5 --tls=on --tls-certcheck=off --auth=on user1@example.com < /etc/root/email4 >&2"
|
||||
)
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
# fetchmail returns EXIT_CODE 0 when it retrieves mail
|
||||
client.succeed("fetchmail --nosslcertck -v")
|
||||
with subtest("extraVirtualAliases"):
|
||||
client.execute("rm ~/mail/*")
|
||||
# send email from single-alias to user1
|
||||
client.succeed(
|
||||
"msmtp -a test5 --tls=on --tls-certcheck=off --auth=on user1@example.com < /etc/root/email4 >&2"
|
||||
)
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
# fetchmail returns EXIT_CODE 0 when it retrieves mail
|
||||
client.succeed("fetchmail --nosslcertck -v")
|
||||
|
||||
client.execute("rm ~/mail/*")
|
||||
# send email from user1 to multi-alias (user{1,2}@example.com)
|
||||
client.succeed(
|
||||
"msmtp -a test --tls=on --tls-certcheck=off --auth=on multi-alias@example.com < /etc/root/email5 >&2"
|
||||
)
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
# fetchmail returns EXIT_CODE 0 when it retrieves mail
|
||||
client.succeed("fetchmail --nosslcertck -v")
|
||||
client.execute("rm ~/mail/*")
|
||||
# send email from user1 to multi-alias (user{1,2}@example.com)
|
||||
client.succeed(
|
||||
"msmtp -a test --tls=on --tls-certcheck=off --auth=on multi-alias@example.com < /etc/root/email5 >&2"
|
||||
)
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
# fetchmail returns EXIT_CODE 0 when it retrieves mail
|
||||
client.succeed("fetchmail --nosslcertck -v")
|
||||
|
||||
with subtest("quota"):
|
||||
client.execute("rm ~/mail/*")
|
||||
client.execute("mv ~/.fetchmailRcLowQuota ~/.fetchmailrc")
|
||||
with subtest("quota"):
|
||||
client.execute("rm ~/mail/*")
|
||||
client.execute("mv ~/.fetchmailRcLowQuota ~/.fetchmailrc")
|
||||
|
||||
client.succeed(
|
||||
"msmtp -a test3 --tls=on --tls-certcheck=off --auth=on lowquota@example.com < /etc/root/email2 >&2"
|
||||
)
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
# fetchmail returns EXIT_CODE 0 when it retrieves mail
|
||||
client.fail("fetchmail --nosslcertck -v")
|
||||
client.succeed(
|
||||
"msmtp -a test3 --tls=on --tls-certcheck=off --auth=on lowquota@example.com < /etc/root/email2 >&2"
|
||||
)
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
# fetchmail returns EXIT_CODE 0 when it retrieves mail
|
||||
client.fail("fetchmail --nosslcertck -v")
|
||||
|
||||
with subtest("imap sieve junk trainer"):
|
||||
# send email from user2 to user1
|
||||
client.succeed(
|
||||
"msmtp -a test --tls=on --tls-certcheck=off --auth=on user1@example.com < /etc/root/email1 >&2"
|
||||
)
|
||||
# give the mail server some time to process the mail
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
with subtest("imap sieve junk trainer"):
|
||||
# send email from user2 to user1
|
||||
client.succeed(
|
||||
"msmtp -a test --tls=on --tls-certcheck=off --auth=on user1@example.com < /etc/root/email1 >&2"
|
||||
)
|
||||
# give the mail server some time to process the mail
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
|
||||
client.succeed("imap-mark-spam >&2")
|
||||
server.wait_until_succeeds("journalctl -u dovecot | grep -i rspamd-learn-spam.sh >&2")
|
||||
client.succeed("imap-mark-ham >&2")
|
||||
server.wait_until_succeeds("journalctl -u dovecot | grep -i rspamd-learn-ham.sh >&2")
|
||||
client.succeed("imap-mark-spam >&2")
|
||||
server.wait_until_succeeds("journalctl -u dovecot | grep -i rspamd-learn-spam.sh >&2")
|
||||
client.succeed("imap-mark-ham >&2")
|
||||
server.wait_until_succeeds("journalctl -u dovecot | grep -i rspamd-learn-ham.sh >&2")
|
||||
|
||||
with subtest("full text search and indexation"):
|
||||
# send 2 email from user2 to user1
|
||||
client.succeed(
|
||||
"msmtp -a test --tls=on --tls-certcheck=off --auth=on user1@example.com < /etc/root/email6 >&2"
|
||||
)
|
||||
client.succeed(
|
||||
"msmtp -a test --tls=on --tls-certcheck=off --auth=on user1@example.com < /etc/root/email7 >&2"
|
||||
)
|
||||
# give the mail server some time to process the mail
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
with subtest("full text search and indexation"):
|
||||
# send 2 email from user2 to user1
|
||||
client.succeed(
|
||||
"msmtp -a test --tls=on --tls-certcheck=off --auth=on user1@example.com < /etc/root/email6 >&2"
|
||||
)
|
||||
client.succeed(
|
||||
"msmtp -a test --tls=on --tls-certcheck=off --auth=on user1@example.com < /etc/root/email7 >&2"
|
||||
)
|
||||
# give the mail server some time to process the mail
|
||||
server.wait_until_fails('[ "$(postqueue -p)" != "Mail queue is empty" ]')
|
||||
|
||||
# should find exactly one email containing this
|
||||
client.succeed("search INBOX 576a4565b70f5a4c1a0925cabdb587a6 >&2")
|
||||
# should fail because this folder is not indexed
|
||||
client.fail("search Junk a >&2")
|
||||
# check that search really goes through the indexer
|
||||
server.succeed("journalctl -u dovecot | grep 'fts-flatcurve(INBOX): Query ' >&2")
|
||||
# check that Junk is not indexed
|
||||
server.fail("journalctl -u dovecot | grep 'fts-flatcurve(JUNK): Indexing ' >&2")
|
||||
# should find exactly one email containing this
|
||||
client.succeed("search INBOX 576a4565b70f5a4c1a0925cabdb587a6 >&2")
|
||||
# should fail because this folder is not indexed
|
||||
client.fail("search Junk a >&2")
|
||||
# check that search really goes through the indexer
|
||||
server.succeed("journalctl -u dovecot | grep 'fts-flatcurve(INBOX): Query ' >&2")
|
||||
# check that Junk is not indexed
|
||||
server.fail("journalctl -u dovecot | grep 'fts-flatcurve(JUNK): Indexing ' >&2")
|
||||
|
||||
with subtest("dmarc reporting"):
|
||||
server.systemctl("start rspamd-dmarc-reporter.service")
|
||||
with subtest("dmarc reporting"):
|
||||
server.systemctl("start rspamd-dmarc-reporter.service")
|
||||
|
||||
with subtest("no warnings or errors"):
|
||||
server.fail("journalctl -u postfix | grep -i error >&2")
|
||||
server.fail("journalctl -u postfix | grep -i warning >&2")
|
||||
server.fail("journalctl -u dovecot | grep -v 'imap-login: Debug: SSL error: Connection closed' | grep -i error >&2")
|
||||
# harmless ? https://dovecot.org/pipermail/dovecot/2020-August/119575.html
|
||||
server.fail(
|
||||
"journalctl -u dovecot | \
|
||||
grep -v 'Expunged message reappeared, giving a new UID' | \
|
||||
grep -v 'Time moved forwards' | \
|
||||
grep -i warning >&2"
|
||||
)
|
||||
'';
|
||||
with subtest("no warnings or errors"):
|
||||
server.fail("journalctl -u postfix | grep -i error >&2")
|
||||
server.fail("journalctl -u postfix | grep -i warning >&2")
|
||||
server.fail("journalctl -u dovecot | grep -v 'imap-login: Debug: SSL error: Connection closed' | grep -i error >&2")
|
||||
# harmless ? https://dovecot.org/pipermail/dovecot/2020-August/119575.html
|
||||
server.fail(
|
||||
"journalctl -u dovecot | \
|
||||
grep -v 'Expunged message reappeared, giving a new UID' | \
|
||||
grep -v 'Time moved forwards' | \
|
||||
grep -i warning >&2"
|
||||
)
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -122,6 +122,7 @@ in
|
||||
nodes,
|
||||
...
|
||||
}:
|
||||
# python
|
||||
''
|
||||
machine.start()
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
|
||||
+29
-26
@@ -53,36 +53,38 @@ in
|
||||
};
|
||||
};
|
||||
};
|
||||
declarativeContents."dc=example" = ''
|
||||
dn: dc=example
|
||||
objectClass: domain
|
||||
dc: example
|
||||
declarativeContents."dc=example" =
|
||||
#ldif
|
||||
''
|
||||
dn: dc=example
|
||||
objectClass: domain
|
||||
dc: example
|
||||
|
||||
dn: cn=mail,dc=example
|
||||
objectClass: organizationalRole
|
||||
objectClass: simpleSecurityObject
|
||||
objectClass: top
|
||||
cn: mail
|
||||
userPassword: ${bindPassword}
|
||||
dn: cn=mail,dc=example
|
||||
objectClass: organizationalRole
|
||||
objectClass: simpleSecurityObject
|
||||
objectClass: top
|
||||
cn: mail
|
||||
userPassword: ${bindPassword}
|
||||
|
||||
dn: ou=users,dc=example
|
||||
objectClass: organizationalUnit
|
||||
ou: users
|
||||
dn: ou=users,dc=example
|
||||
objectClass: organizationalUnit
|
||||
ou: users
|
||||
|
||||
dn: cn=alice,ou=users,dc=example
|
||||
objectClass: inetOrgPerson
|
||||
cn: alice
|
||||
sn: Foo
|
||||
mail: alice@example.com
|
||||
userPassword: ${alicePassword}
|
||||
dn: cn=alice,ou=users,dc=example
|
||||
objectClass: inetOrgPerson
|
||||
cn: alice
|
||||
sn: Foo
|
||||
mail: alice@example.com
|
||||
userPassword: ${alicePassword}
|
||||
|
||||
dn: cn=bob,ou=users,dc=example
|
||||
objectClass: inetOrgPerson
|
||||
cn: bob
|
||||
sn: Bar
|
||||
mail: bob@example.com
|
||||
userPassword: ${bobPassword}
|
||||
'';
|
||||
dn: cn=bob,ou=users,dc=example
|
||||
objectClass: inetOrgPerson
|
||||
cn: bob
|
||||
sn: Bar
|
||||
mail: bob@example.com
|
||||
userPassword: ${bobPassword}
|
||||
'';
|
||||
};
|
||||
|
||||
mailserver = {
|
||||
@@ -121,6 +123,7 @@ in
|
||||
nodes,
|
||||
...
|
||||
}:
|
||||
# python
|
||||
''
|
||||
import sys
|
||||
import re
|
||||
|
||||
+23
-21
@@ -90,29 +90,31 @@ in
|
||||
];
|
||||
};
|
||||
};
|
||||
testScript = ''
|
||||
start_all()
|
||||
testScript =
|
||||
# python
|
||||
''
|
||||
start_all()
|
||||
|
||||
for domain in [domain1, domain2]:
|
||||
domain.wait_for_unit("multi-user.target")
|
||||
domain.wait_for_unit("dovecot.service")
|
||||
for domain in [domain1, domain2]:
|
||||
domain.wait_for_unit("multi-user.target")
|
||||
domain.wait_for_unit("dovecot.service")
|
||||
|
||||
# TODO put this blocking into the systemd units?
|
||||
domain1.wait_until_succeeds(
|
||||
"set +e; timeout 1 nc -U /run/rspamd/rspamd-milter.sock < /dev/null; [ $? -eq 124 ]"
|
||||
)
|
||||
domain2.wait_until_succeeds(
|
||||
"set +e; timeout 1 nc -U /run/rspamd/rspamd-milter.sock < /dev/null; [ $? -eq 124 ]"
|
||||
)
|
||||
# TODO put this blocking into the systemd units?
|
||||
domain1.wait_until_succeeds(
|
||||
"set +e; timeout 1 nc -U /run/rspamd/rspamd-milter.sock < /dev/null; [ $? -eq 124 ]"
|
||||
)
|
||||
domain2.wait_until_succeeds(
|
||||
"set +e; timeout 1 nc -U /run/rspamd/rspamd-milter.sock < /dev/null; [ $? -eq 124 ]"
|
||||
)
|
||||
|
||||
# user@domain1.com sends a mail to user@domain2.com via explicit TLS
|
||||
client.succeed(
|
||||
"mail-check send-and-read --smtp-port 587 --smtp-starttls --smtp-host domain1 --from-addr user@domain1.com --imap-host domain2 --to-addr user@domain2.com --src-password-file ${password} --dst-password-file ${password} --ignore-dkim-spf"
|
||||
)
|
||||
# user@domain1.com sends a mail to user@domain2.com via explicit TLS
|
||||
client.succeed(
|
||||
"mail-check send-and-read --smtp-port 587 --smtp-starttls --smtp-host domain1 --from-addr user@domain1.com --imap-host domain2 --to-addr user@domain2.com --src-password-file ${password} --dst-password-file ${password} --ignore-dkim-spf"
|
||||
)
|
||||
|
||||
# Send a mail to the address forwarded via implicit TLS and check it is in the recipient mailbox
|
||||
client.succeed(
|
||||
"mail-check send-and-read --smtp-port 465 --smtp-ssl --smtp-host domain1 --from-addr user@domain1.com --imap-host domain2 --to-addr non-local@domain1.com --imap-username user@domain2.com --src-password-file ${password} --dst-password-file ${password} --ignore-dkim-spf"
|
||||
)
|
||||
'';
|
||||
# Send a mail to the address forwarded via implicit TLS and check it is in the recipient mailbox
|
||||
client.succeed(
|
||||
"mail-check send-and-read --smtp-port 465 --smtp-ssl --smtp-host domain1 --from-addr user@domain1.com --imap-host domain2 --to-addr non-local@domain1.com --imap-username user@domain2.com --src-password-file ${password} --dst-password-file ${password} --ignore-dkim-spf"
|
||||
)
|
||||
'';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user