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