mirror of
https://github.com/docker-mailserver/docker-mailserver.git
synced 2024-01-19 02:48:50 +00:00
c851f5b6aa
* chore(refactor): DRY up the `_setup_ssl` method - `/etc/postfix/ssl` was a bit misleading in usage here. As a maintainer (of my own contribution!) I was confused why only `/etc/postfix/ssl` was referenced and not `/etc/dovecot/ssl`. - The postfix specific path is unnecessary, dovecot was referencing it via it's config, the same can be done from postfix to a generic DMS specific config location instead. - This location is defined and created early as `/etc/dms/tls` (with var `DMS_TLS_PATH`). All usage of `/etc/postfix/ssl` has been replaced, making it easier to grok. Several `mkdir` commands related to this have been dropped as a result. - Likewise, a related `TMP_DMS_TLS_PATH` var provides a reference to the config volume path `/tmp/docker-mailserver` which is used for conditions on presently hard-coded paths. - Other values that benefit from being DRY have been lifted up into vars. Definitely easier to follow now and makes some further opportunities clearer to tackle in a future refactor. - `chmod` has been updated where appropriate. Public key/cert is acceptable to have as readable by non-root users (644). The custom type with single fullchain file was not root accessible only, but should as it contains a private key. - That said, the security benefit can be a bit moot due to source files that were copied remain present, the user would be responsible to ensure similar permissions on their source files. - I've not touched LetsEncrypt section as I don't have time to investigate into that yet (not familiar with that portion). --- * chore: Remove mkcert logic and dovecot cert - No longer serving a purpose. - Our own TLS startup script handles a variety of cert scenarios, while the dropped code was always generating a self-signed cert and persisting an unused cert regardless with `ONE_DIR=1`. - To avoid similar issues that DH params had with doveadm validating filepath values in the SSL config, the default dummy values match postfix pointing to "snakeoil" cert. That serves the same purpose as mkcert was covering in the image. - Bonus, no more hassle with differing mkcert target paths for users replacing our supplied Dovecot with the latest community edition. --- * Error handling for SSL_TYPE - Added a panic utility to exit early when SSL_TYPE conditions are misconfigured. - Some info text had order of key/cert occurrence swapped to be consistent with key then cert. - Some existing comments moved and rephrased. - Additional comments added. - `-f` test for cert files instead of `-e` (true also for directories/devices/symlinks). - _notify messages lifted out of conditionals so that they always output when the case is hit. - ~~Empty SSL_TYPE collapsed into catch all panic, while it's contents is now mapped to a new 'disabled' value.~~ --- * Use sedfile + improve sed expressions + update case style - Uses sedfile when appropriate (file change intentional, not optional match/check). - sed expressions modified to be DRY and reduce escaping via `-r` flag (acceptable if actual text content contains no `?`,`+`,`()` or `{}` characters, [otherwise they must be escaped](https://www.gnu.org/software/sed/manual/html_node/Extended-regexps.html)). - sed captures anything matched between the parenthesis`()` and inserts it via `\1` as part of the replacement. - case statements adopt the `(` prefix, adopting recent shell style for consistency. --- * Refactor SSL_TYPE=disabled - Postfix is also disabled now. - Included heavy inline documentation reference for maintainers. - Dropped an obsolete postfix config option 'use_tls' on the relayhost function, it was replaced by 'security_level'. --- * I'm a friggin' sed wizard now - The `modern` TLS_LEVEL is the default values for the configs they modify. As such, `sedfile` outputs an "Error" which isn't an actual concern, back to regular `sed`. - I realized that multiple edits for the same file can all be done at once via `-e` (assuming other sed options are the same for each operation), and that `g` suffix is global scope for single line match, not whole file (default as sed iterates through individual lines). - Some postfix replacements have `smtp` and `smtpd` lines, collapsed into a single `smtpd?` instead now that I know sed better. --- * tests(fix): Tests that require SSL/TLS to pass - SSL_TYPE=snakeoil added as temporary workaround. - nmap tests are being dropped. These were added about 4-5 years ago, I have since made these redundant with the `testssl.sh` tests. - Additionally the `--link` option is deprecated and IIRC these grades were a bit misleading when I initially used nmap in my own TLS cipher suite update PRs in the past. - The removed SSL test is already handled in mail_ssl_manual.bats ldap test: - Replace `--link` alias option with `--network` and alias assignment. - Parameterized some values and added the `SSL_TYPE` to resolve the starttls test failure. privacy test: - Also needed `SSL_TYPE` to pass the starttls test. `tests.bats` had another starttls test for imap: - Workaround for now is to give the main test container `SSL_TYPE=snakeoil`. --- * Remove the expired lets-encrypt cert This expired in March 2021. It was originally required when first added back in 2016 as LetsEncrypt was fairly new and not as broadly accepted into OS trust stores. No longer the case today. --- * chore: Housekeeping Not required for this PR branch, little bit of tidying up while working on these two test files. - privacy test copied over content when extracted from `tests.bats` that isn't relevant. - ldap test was not as easy to identify the source of DOVECOT_TLS. Added comment to make the prefix connection to `configomat.sh` and `.ext` files more easier to find. - Additionally converted the two localhost FQDN to vars. --- * Default SSL_TYPE becomes `''` (aka equivalent to desired `disabled` case) - This is to prevent other tests from failing by hitting the panic catchall case. - More ideal would be adjusting tests to default to `disabled`, rather than treating `disabled` as an empty / unset SSL_TYPE value. --- * Add inline documentation for `dms_panic` - This could later be better formatted and placed into contributor docs. Panic with kill (shutdown) not exit (errex): - `kill 1` from `_shutdown` will send SIGTERM signal to PID 1 (init process). - `exit 1` within the `start-mailserver.sh` init scripts context, will just exit the initialization script leaving the container running when it shouldn't. The two previous `_shutdown` methods can benefit from using `dms_panic` wrapper instead to standardize on panic messages.
1249 lines
44 KiB
Bash
1249 lines
44 KiB
Bash
load 'test_helper/bats-support/load'
|
|
load 'test_helper/bats-assert/load'
|
|
load 'test_helper/common'
|
|
|
|
export IMAGE_NAME
|
|
IMAGE_NAME="${NAME}"
|
|
|
|
setup() {
|
|
run_setup_file_if_necessary
|
|
}
|
|
|
|
setup_file() {
|
|
local PRIVATE_CONFIG
|
|
PRIVATE_CONFIG="$(duplicate_config_for_container . mail)"
|
|
mv "${PRIVATE_CONFIG}/user-patches/user-patches.sh" "${PRIVATE_CONFIG}/user-patches.sh"
|
|
docker run --rm -d --name mail \
|
|
-v "${PRIVATE_CONFIG}":/tmp/docker-mailserver \
|
|
-v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \
|
|
-v "$(pwd)/test/onedir":/var/mail-state \
|
|
-e ENABLE_CLAMAV=1 \
|
|
-e SPOOF_PROTECTION=1 \
|
|
-e ENABLE_SPAMASSASSIN=1 \
|
|
-e REPORT_RECIPIENT=user1@localhost.localdomain \
|
|
-e REPORT_SENDER=report1@mail.my-domain.com \
|
|
-e SA_TAG=-5.0 \
|
|
-e SA_TAG2=2.0 \
|
|
-e SA_KILL=3.0 \
|
|
-e AMAVIS_LOGLEVEL=2 \
|
|
-e SA_SPAM_SUBJECT="SPAM: " \
|
|
-e VIRUSMAILS_DELETE_DELAY=7 \
|
|
-e ENABLE_SRS=1 \
|
|
-e SASL_PASSWD="external-domain.com username:password" \
|
|
-e ENABLE_MANAGESIEVE=1 \
|
|
-e PERMIT_DOCKER=host \
|
|
-e DMS_DEBUG=0 \
|
|
-e SSL_TYPE='snakeoil' \
|
|
-h mail.my-domain.com \
|
|
--cap-add=SYS_PTRACE \
|
|
--tty \
|
|
"${NAME}"
|
|
|
|
wait_for_finished_setup_in_container mail
|
|
|
|
# generate accounts after container has been started
|
|
docker run --rm -e MAIL_USER=added@localhost.localdomain -e MAIL_PASS=mypassword -t "${NAME}" /bin/sh -c 'echo "${MAIL_USER}|$(doveadm pw -s SHA512-CRYPT -u ${MAIL_USER} -p ${MAIL_PASS})"' >> "${PRIVATE_CONFIG}/postfix-accounts.cf"
|
|
docker exec mail addmailuser pass@localhost.localdomain 'may be \a `p^a.*ssword'
|
|
|
|
# setup sieve
|
|
docker cp "${PRIVATE_CONFIG}/sieve/dovecot.sieve" mail:/var/mail/localhost.localdomain/user1/.dovecot.sieve
|
|
|
|
# this relies on the checksum file beeing updated after all changes have been applied
|
|
wait_for_changes_to_be_detected_in_container mail
|
|
|
|
wait_for_smtp_port_in_container mail
|
|
|
|
# wait for clamav to be fully setup or we will get errors on the log
|
|
repeat_in_container_until_success_or_timeout 60 mail test -e /var/run/clamav/clamd.ctl
|
|
|
|
# sending test mails
|
|
docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/amavis-spam.txt"
|
|
docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/amavis-virus.txt"
|
|
docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-alias-external.txt"
|
|
docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-alias-local.txt"
|
|
docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-alias-recipient-delimiter.txt"
|
|
docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-user1.txt"
|
|
docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-user2.txt"
|
|
docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-user3.txt"
|
|
docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-added.txt"
|
|
docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-user-and-cc-local-alias.txt"
|
|
docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-regexp-alias-external.txt"
|
|
docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-regexp-alias-local.txt"
|
|
docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-catchall-local.txt"
|
|
docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/sieve-spam-folder.txt"
|
|
docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/sieve-pipe.txt"
|
|
docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/non-existing-user.txt"
|
|
docker exec mail /bin/sh -c "sendmail root < /tmp/docker-mailserver-test/email-templates/root-email.txt"
|
|
|
|
wait_for_empty_mail_queue_in_container mail
|
|
}
|
|
|
|
teardown() {
|
|
run_teardown_file_if_necessary
|
|
}
|
|
|
|
teardown_file() {
|
|
docker rm -f mail
|
|
}
|
|
|
|
# this test must come first to reliably identify when to run setup_file
|
|
@test "first" {
|
|
skip 'Starting testing of letsencrypt SSL'
|
|
}
|
|
|
|
#
|
|
# configuration checks
|
|
#
|
|
|
|
@test "checking configuration: user-patches.sh executed" {
|
|
run docker logs mail
|
|
assert_output --partial "Default user-patches.sh successfully executed"
|
|
}
|
|
|
|
@test "checking configuration: hostname/domainname" {
|
|
run docker run "${IMAGE_NAME:?}"
|
|
assert_success
|
|
}
|
|
|
|
#
|
|
# processes
|
|
#
|
|
|
|
@test "checking process: postfix" {
|
|
run docker exec mail /bin/bash -c "ps aux --forest | grep -v grep | grep '/usr/lib/postfix/sbin/master'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking process: clamd" {
|
|
run docker exec mail /bin/bash -c "ps aux --forest | grep -v grep | grep '/usr/sbin/clamd'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking process: new" {
|
|
run docker exec mail /bin/bash -c "ps aux --forest | grep -v grep | grep '/usr/sbin/amavisd-new'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking process: opendkim" {
|
|
run docker exec mail /bin/bash -c "ps aux --forest | grep -v grep | grep '/usr/sbin/opendkim'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking process: opendmarc" {
|
|
run docker exec mail /bin/bash -c "ps aux --forest | grep -v grep | grep '/usr/sbin/opendmarc'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking process: fail2ban (disabled in default configuration)" {
|
|
run docker exec mail /bin/bash -c "ps aux --forest | grep -v grep | grep '/usr/bin/python3 /usr/bin/fail2ban-server'"
|
|
assert_failure
|
|
}
|
|
|
|
@test "checking process: fetchmail (disabled in default configuration)" {
|
|
run docker exec mail /bin/bash -c "ps aux --forest | grep -v grep | grep '/usr/bin/fetchmail'"
|
|
assert_failure
|
|
}
|
|
|
|
#
|
|
# imap
|
|
#
|
|
|
|
@test "checking process: dovecot imaplogin (enabled in default configuration)" {
|
|
run docker exec mail /bin/bash -c "ps aux --forest | grep -v grep | grep '/usr/sbin/dovecot'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking imap: server is ready with STARTTLS" {
|
|
run docker exec mail /bin/bash -c "nc -w 2 0.0.0.0 143 | grep '* OK' | grep 'STARTTLS' | grep 'ready'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking imap: authentication works" {
|
|
run docker exec mail /bin/sh -c "nc -w 1 0.0.0.0 143 < /tmp/docker-mailserver-test/auth/imap-auth.txt"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking imap: added user authentication works" {
|
|
run docker exec mail /bin/sh -c "nc -w 1 0.0.0.0 143 < /tmp/docker-mailserver-test/auth/added-imap-auth.txt"
|
|
assert_success
|
|
}
|
|
|
|
#
|
|
# sasl
|
|
#
|
|
|
|
@test "checking sasl: doveadm auth test works with good password" {
|
|
run docker exec mail /bin/sh -c "doveadm auth test -x service=smtp user2@otherdomain.tld mypassword | grep 'auth succeeded'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking sasl: doveadm auth test fails with bad password" {
|
|
run docker exec mail /bin/sh -c "doveadm auth test -x service=smtp user2@otherdomain.tld BADPASSWORD | grep 'auth failed'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking sasl: sasl_passwd exists" {
|
|
run docker exec mail [ -f /etc/postfix/sasl_passwd ]
|
|
assert_success
|
|
}
|
|
|
|
#
|
|
# logs
|
|
#
|
|
|
|
@test "checking logs: mail related logs should be located in a subdirectory" {
|
|
run docker exec mail /bin/sh -c "ls -1 /var/log/mail/ | grep -E 'clamav|freshclam|mail.log'|wc -l"
|
|
assert_success
|
|
assert_output 3
|
|
}
|
|
|
|
#
|
|
# smtp
|
|
#
|
|
|
|
@test "checking smtp: authentication works with good password (plain)" {
|
|
run docker exec mail /bin/sh -c "nc -w 5 0.0.0.0 25 < /tmp/docker-mailserver-test/auth/smtp-auth-plain.txt | grep 'Authentication successful'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking smtp: authentication fails with wrong password (plain)" {
|
|
run docker exec mail /bin/sh -c "nc -w 20 0.0.0.0 25 < /tmp/docker-mailserver-test/auth/smtp-auth-plain-wrong.txt"
|
|
assert_output --partial 'authentication failed'
|
|
assert_success
|
|
}
|
|
|
|
@test "checking smtp: authentication works with good password (login)" {
|
|
run docker exec mail /bin/sh -c "nc -w 5 0.0.0.0 25 < /tmp/docker-mailserver-test/auth/smtp-auth-login.txt | grep 'Authentication successful'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking smtp: authentication fails with wrong password (login)" {
|
|
run docker exec mail /bin/sh -c "nc -w 20 0.0.0.0 25 < /tmp/docker-mailserver-test/auth/smtp-auth-login-wrong.txt"
|
|
assert_output --partial 'authentication failed'
|
|
assert_success
|
|
}
|
|
|
|
@test "checking smtp: added user authentication works with good password (plain)" {
|
|
run docker exec mail /bin/sh -c "nc -w 5 0.0.0.0 25 < /tmp/docker-mailserver-test/auth/added-smtp-auth-plain.txt | grep 'Authentication successful'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking smtp: added user authentication fails with wrong password (plain)" {
|
|
run docker exec mail /bin/sh -c "nc -w 20 0.0.0.0 25 < /tmp/docker-mailserver-test/auth/added-smtp-auth-plain-wrong.txt | grep 'authentication failed'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking smtp: added user authentication works with good password (login)" {
|
|
run docker exec mail /bin/sh -c "nc -w 5 0.0.0.0 25 < /tmp/docker-mailserver-test/auth/added-smtp-auth-login.txt | grep 'Authentication successful'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking smtp: added user authentication fails with wrong password (login)" {
|
|
run docker exec mail /bin/sh -c "nc -w 20 0.0.0.0 25 < /tmp/docker-mailserver-test/auth/added-smtp-auth-login-wrong.txt | grep 'authentication failed'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking smtp: delivers mail to existing account" {
|
|
run docker exec mail /bin/sh -c "grep 'postfix/lmtp' /var/log/mail/mail.log | grep 'status=sent' | grep ' Saved)' | sed 's/.* to=</</g' | sed 's/, relay.*//g' | sort | uniq -c | tr -s \" \""
|
|
assert_success
|
|
assert_output <<'EOF'
|
|
1 <added@localhost.localdomain>
|
|
6 <user1@localhost.localdomain>
|
|
1 <user1@localhost.localdomain>, orig_to=<postmaster@my-domain.com>
|
|
1 <user1@localhost.localdomain>, orig_to=<root>
|
|
1 <user1~test@localhost.localdomain>
|
|
2 <user2@otherdomain.tld>
|
|
1 <user3@localhost.localdomain>
|
|
EOF
|
|
}
|
|
|
|
@test "checking smtp: delivers mail to existing alias" {
|
|
run docker exec mail /bin/sh -c "grep 'to=<user1@localhost.localdomain>, orig_to=<alias1@localhost.localdomain>' /var/log/mail/mail.log | grep 'status=sent' | wc -l"
|
|
assert_success
|
|
assert_output 1
|
|
}
|
|
|
|
@test "checking smtp: delivers mail to existing alias with recipient delimiter" {
|
|
run docker exec mail /bin/sh -c "grep 'to=<user1~test@localhost.localdomain>, orig_to=<alias1~test@localhost.localdomain>' /var/log/mail/mail.log | grep 'status=sent' | wc -l"
|
|
assert_success
|
|
assert_output 1
|
|
|
|
run docker exec mail /bin/sh -c "grep 'to=<user1~test@localhost.localdomain>' /var/log/mail/mail.log | grep 'status=bounced'"
|
|
assert_failure
|
|
}
|
|
|
|
@test "checking smtp: delivers mail to existing catchall" {
|
|
run docker exec mail /bin/sh -c "grep 'to=<user1@localhost.localdomain>, orig_to=<wildcard@localdomain2.com>' /var/log/mail/mail.log | grep 'status=sent' | wc -l"
|
|
assert_success
|
|
assert_output 1
|
|
}
|
|
|
|
@test "checking smtp: delivers mail to regexp alias" {
|
|
run docker exec mail /bin/sh -c "grep 'to=<user1@localhost.localdomain>, orig_to=<test123@localhost.localdomain>' /var/log/mail/mail.log | grep 'status=sent' | wc -l"
|
|
assert_success
|
|
assert_output 1
|
|
}
|
|
|
|
@test "checking smtp: user1 should have received 9 mails" {
|
|
run docker exec mail /bin/sh -c "grep Subject /var/mail/localhost.localdomain/user1/new/* | sed 's/.*Subject: //g' | sed 's/\.txt.*//g' | sed 's/VIRUS.*/VIRUS/g' | sort"
|
|
assert_success
|
|
# 9 messages, the virus mail has three subject lines
|
|
cat <<'EOF' | assert_output
|
|
Root Test Message
|
|
Test Message amavis-virus
|
|
Test Message amavis-virus
|
|
Test Message existing-alias-external
|
|
Test Message existing-alias-recipient-delimiter
|
|
Test Message existing-catchall-local
|
|
Test Message existing-regexp-alias-local
|
|
Test Message existing-user-and-cc-local-alias
|
|
Test Message existing-user1
|
|
Test Message sieve-spam-folder
|
|
VIRUS
|
|
EOF
|
|
}
|
|
|
|
@test "checking smtp: rejects mail to unknown user" {
|
|
run docker exec mail /bin/sh -c "grep '<nouser@localhost.localdomain>: Recipient address rejected: User unknown in virtual mailbox table' /var/log/mail/mail.log | wc -l"
|
|
assert_success
|
|
assert_output 1
|
|
}
|
|
|
|
@test "checking smtp: redirects mail to external aliases" {
|
|
run docker exec mail /bin/sh -c "grep -- '-> <external1@otherdomain.tld>' /var/log/mail/mail.log* | grep RelayedInbound | wc -l"
|
|
assert_success
|
|
assert_output 2
|
|
}
|
|
|
|
@test "checking smtp: rejects spam" {
|
|
run docker exec mail /bin/sh -c "grep 'Blocked SPAM' /var/log/mail/mail.log | grep external.tld=spam@my-domain.com | wc -l"
|
|
assert_success
|
|
assert_output 1
|
|
}
|
|
|
|
@test "checking smtp: rejects virus" {
|
|
run docker exec mail /bin/sh -c "grep 'Blocked INFECTED' /var/log/mail/mail.log | grep external.tld=virus@my-domain.com | wc -l"
|
|
assert_success
|
|
assert_output 1
|
|
}
|
|
|
|
@test "checking smtp: not advertising smtputf8" {
|
|
# Dovecot does not support SMTPUTF8, so while we can send we cannot receive
|
|
# Better disable SMTPUTF8 support entirely if we can't handle it correctly
|
|
run docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/smtp-ehlo.txt | grep SMTPUTF8 | wc -l"
|
|
assert_success
|
|
assert_output 0
|
|
}
|
|
|
|
#
|
|
# accounts
|
|
#
|
|
|
|
@test "checking accounts: user accounts" {
|
|
run docker exec mail doveadm user '*'
|
|
assert_success
|
|
assert_line --index 0 "user1@localhost.localdomain"
|
|
assert_line --index 1 "user2@otherdomain.tld"
|
|
assert_line --index 2 "user3@localhost.localdomain"
|
|
assert_line --index 3 "added@localhost.localdomain"
|
|
}
|
|
|
|
@test "checking accounts: user mail folder for user1" {
|
|
run docker exec mail /bin/bash -c "ls -d /var/mail/localhost.localdomain/user1"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking accounts: user mail folder for user2" {
|
|
run docker exec mail /bin/bash -c "ls -d /var/mail/otherdomain.tld/user2"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking accounts: user mail folder for user3" {
|
|
run docker exec mail /bin/bash -c "ls -d /var/mail/localhost.localdomain/user3/mail"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking accounts: user mail folder for added user" {
|
|
run docker exec mail /bin/bash -c "ls -d /var/mail/localhost.localdomain/added"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking accounts: comments are not parsed" {
|
|
run docker exec mail /bin/bash -c "ls /var/mail | grep 'comment'"
|
|
assert_failure
|
|
}
|
|
|
|
#
|
|
# postfix
|
|
#
|
|
|
|
@test "checking postfix: vhost file is correct" {
|
|
run docker exec mail cat /etc/postfix/vhost
|
|
assert_success
|
|
assert_line --index 0 "localdomain2.com"
|
|
assert_line --index 1 "localhost.localdomain"
|
|
assert_line --index 2 "otherdomain.tld"
|
|
}
|
|
|
|
@test "checking postfix: main.cf overrides" {
|
|
run docker exec mail grep -q 'max_idle = 600s' /tmp/docker-mailserver/postfix-main.cf
|
|
assert_success
|
|
run docker exec mail grep -q 'readme_directory = /tmp' /tmp/docker-mailserver/postfix-main.cf
|
|
assert_success
|
|
}
|
|
|
|
@test "checking postfix: master.cf overrides" {
|
|
run docker exec mail grep -q 'submission/inet/smtpd_sasl_security_options=noanonymous' /tmp/docker-mailserver/postfix-master.cf
|
|
assert_success
|
|
}
|
|
|
|
#
|
|
# dovecot
|
|
#
|
|
|
|
@test "checking dovecot: config additions" {
|
|
run docker exec mail grep -q 'mail_max_userip_connections = 69' /tmp/docker-mailserver/dovecot.cf
|
|
assert_success
|
|
run docker exec mail /bin/sh -c "doveconf | grep 'mail_max_userip_connections = 69'"
|
|
assert_success
|
|
assert_output 'mail_max_userip_connections = 69'
|
|
}
|
|
|
|
#
|
|
# spamassassin
|
|
#
|
|
|
|
@test "checking spamassassin: should be listed in amavis when enabled" {
|
|
run docker exec mail /bin/sh -c "grep -i 'ANTI-SPAM-SA code' /var/log/mail/mail.log | grep 'NOT loaded'"
|
|
assert_failure
|
|
}
|
|
|
|
@test "checking spamassassin: all registered domains should see spam headers" {
|
|
run docker exec mail /bin/sh -c "grep -ir 'X-Spam-' /var/mail/localhost.localdomain/user1/new"
|
|
assert_success
|
|
run docker exec mail /bin/sh -c "grep -ir 'X-Spam-' /var/mail/otherdomain.tld/user2/new"
|
|
assert_success
|
|
}
|
|
|
|
|
|
#
|
|
# clamav
|
|
#
|
|
|
|
@test "checking clamav: should be listed in amavis when enabled" {
|
|
run docker exec mail grep -i 'Found secondary av scanner ClamAV-clamscan' /var/log/mail/mail.log
|
|
assert_success
|
|
}
|
|
|
|
#
|
|
# postsrsd
|
|
#
|
|
|
|
@test "checking SRS: main.cf entries" {
|
|
run docker exec mail grep "sender_canonical_maps = tcp:localhost:10001" /etc/postfix/main.cf
|
|
assert_success
|
|
run docker exec mail grep "sender_canonical_classes = envelope_sender" /etc/postfix/main.cf
|
|
assert_success
|
|
run docker exec mail grep "recipient_canonical_maps = tcp:localhost:10002" /etc/postfix/main.cf
|
|
assert_success
|
|
run docker exec mail grep "recipient_canonical_classes = envelope_recipient,header_recipient" /etc/postfix/main.cf
|
|
assert_success
|
|
}
|
|
|
|
@test "checking SRS: postsrsd running" {
|
|
run docker exec mail /bin/sh -c "ps aux | grep ^postsrsd"
|
|
assert_success
|
|
}
|
|
|
|
|
|
@test "checking SRS: fallback to hostname is handled correctly" {
|
|
run docker exec mail grep "SRS_DOMAIN=my-domain.com" /etc/default/postsrsd
|
|
assert_success
|
|
}
|
|
|
|
#
|
|
# system
|
|
#
|
|
|
|
@test "checking system: freshclam cron is enabled" {
|
|
run docker exec mail bash -c "grep '/usr/bin/freshclam' -r /etc/cron.d"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking amavis: virusmail wiper cron exists" {
|
|
run docker exec mail bash -c "crontab -l | grep '/usr/local/bin/virus-wiper'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking amavis: VIRUSMAILS_DELETE_DELAY override works as expected" {
|
|
# shellcheck disable=SC2016
|
|
run docker run --rm -e VIRUSMAILS_DELETE_DELAY=2 "${IMAGE_NAME:?}" /bin/bash -c 'echo "${VIRUSMAILS_DELETE_DELAY}"'
|
|
assert_output 2
|
|
}
|
|
|
|
@test "checking amavis: old virusmail is wipped by cron" {
|
|
docker exec mail bash -c 'touch -d "`date --date=2000-01-01`" /var/lib/amavis/virusmails/should-be-deleted'
|
|
run docker exec mail bash -c '/usr/local/bin/virus-wiper'
|
|
assert_success
|
|
run docker exec mail bash -c 'ls -la /var/lib/amavis/virusmails/ | grep should-be-deleted'
|
|
assert_failure
|
|
}
|
|
|
|
@test "checking amavis: recent virusmail is not wipped by cron" {
|
|
docker exec mail bash -c 'touch -d "`date`" /var/lib/amavis/virusmails/should-not-be-deleted'
|
|
run docker exec mail bash -c '/usr/local/bin/virus-wiper'
|
|
assert_success
|
|
run docker exec mail bash -c 'ls -la /var/lib/amavis/virusmails/ | grep should-not-be-deleted'
|
|
assert_success
|
|
}
|
|
|
|
@test "checking system: /var/log/mail/mail.log is error free" {
|
|
run docker exec mail grep 'non-null host address bits in' /var/log/mail/mail.log
|
|
assert_failure
|
|
run docker exec mail grep 'mail system configuration error' /var/log/mail/mail.log
|
|
assert_failure
|
|
run docker exec mail grep ': error:' /var/log/mail/mail.log
|
|
assert_failure
|
|
run docker exec mail grep -i 'is not writable' /var/log/mail/mail.log
|
|
assert_failure
|
|
run docker exec mail grep -i 'permission denied' /var/log/mail/mail.log
|
|
assert_failure
|
|
run docker exec mail grep -i '(!)connect' /var/log/mail/mail.log
|
|
assert_failure
|
|
run docker exec mail grep -i 'backwards-compatible default setting chroot=y' /var/log/mail/mail.log
|
|
assert_failure
|
|
run docker exec mail grep -i 'connect to 127.0.0.1:10023: Connection refused' /var/log/mail/mail.log
|
|
assert_failure
|
|
}
|
|
|
|
@test "checking system: /var/log/auth.log is error free" {
|
|
run docker exec mail grep 'Unable to open env file: /etc/default/locale' /var/log/auth.log
|
|
assert_failure
|
|
}
|
|
|
|
@test "checking system: sets the server fqdn" {
|
|
run docker exec mail hostname
|
|
assert_success
|
|
assert_output "mail.my-domain.com"
|
|
}
|
|
|
|
@test "checking system: sets the server domain name in /etc/mailname" {
|
|
run docker exec mail cat /etc/mailname
|
|
assert_success
|
|
assert_output "my-domain.com"
|
|
}
|
|
|
|
@test "checking system: postfix should not log to syslog" {
|
|
run docker exec mail grep 'postfix' /var/log/syslog
|
|
assert_failure
|
|
}
|
|
|
|
@test "checking system: amavis decoders installed and available" {
|
|
run docker exec mail /bin/sh -c "grep -E '.*(Internal decoder|Found decoder) for\s+\..*' /var/log/mail/mail.log*|grep -Eo '(mail|Z|gz|bz2|xz|lzma|lrz|lzo|lz4|rpm|cpio|tar|deb|rar|arj|arc|zoo|doc|cab|tnef|zip|kmz|7z|jar|swf|lha|iso|exe)' | sort | uniq"
|
|
assert_success
|
|
# Support for doc and zoo removed in buster
|
|
cat <<'EOF' | assert_output
|
|
7z
|
|
Z
|
|
arc
|
|
arj
|
|
bz2
|
|
cab
|
|
cpio
|
|
deb
|
|
exe
|
|
gz
|
|
iso
|
|
jar
|
|
kmz
|
|
lha
|
|
lrz
|
|
lz4
|
|
lzma
|
|
lzo
|
|
mail
|
|
rar
|
|
rpm
|
|
swf
|
|
tar
|
|
tnef
|
|
xz
|
|
zip
|
|
EOF
|
|
}
|
|
|
|
|
|
#
|
|
# sieve
|
|
#
|
|
|
|
@test "checking sieve: user1 should have received 1 email in folder INBOX.spam" {
|
|
run docker exec mail /bin/sh -c "ls -A /var/mail/localhost.localdomain/user1/.INBOX.spam/new | wc -l"
|
|
assert_success
|
|
assert_output 1
|
|
}
|
|
|
|
@test "checking manage sieve: server is ready when ENABLE_MANAGESIEVE has been set" {
|
|
run docker exec mail /bin/bash -c "nc -z 0.0.0.0 4190"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking sieve: user2 should have piped 1 email to /tmp/" {
|
|
run docker exec mail /bin/sh -c "ls -A /tmp/pipe-test.out | wc -l"
|
|
assert_success
|
|
assert_output 1
|
|
}
|
|
|
|
@test "checking sieve global: user1 should have gotten a copy of his spam mail" {
|
|
run docker exec mail /bin/sh -c "grep 'Spambot <spam@spam.com>' -R /var/mail/localhost.localdomain/user1/new/"
|
|
assert_success
|
|
}
|
|
|
|
#
|
|
# accounts
|
|
#
|
|
@test "checking accounts: user_without_domain creation should be rejected since user@domain format is required" {
|
|
run docker exec mail /bin/sh -c "addmailuser user_without_domain mypassword"
|
|
assert_failure
|
|
assert_output --partial "Username must include the domain"
|
|
}
|
|
|
|
@test "checking accounts: user3 should have been added to /tmp/docker-mailserver/postfix-accounts.cf" {
|
|
docker exec mail /bin/sh -c "addmailuser user3@domain.tld mypassword"
|
|
|
|
run docker exec mail /bin/sh -c "grep '^user3@domain\.tld|' -i /tmp/docker-mailserver/postfix-accounts.cf"
|
|
assert_success
|
|
[ -n "${output}" ]
|
|
}
|
|
|
|
@test "checking accounts: auser3 should have been added to /tmp/docker-mailserver/postfix-accounts.cf" {
|
|
docker exec mail /bin/sh -c "addmailuser auser3@domain.tld mypassword"
|
|
|
|
run docker exec mail /bin/sh -c "grep '^auser3@domain\.tld|' -i /tmp/docker-mailserver/postfix-accounts.cf"
|
|
assert_success
|
|
[ -n "${output}" ]
|
|
}
|
|
|
|
@test "checking accounts: a.ser3 should have been added to /tmp/docker-mailserver/postfix-accounts.cf" {
|
|
docker exec mail /bin/sh -c "addmailuser a.ser3@domain.tld mypassword"
|
|
|
|
run docker exec mail /bin/sh -c "grep '^a\.ser3@domain\.tld|' -i /tmp/docker-mailserver/postfix-accounts.cf"
|
|
assert_success
|
|
[ -n "${output}" ]
|
|
}
|
|
|
|
@test "checking accounts: user3 should have been removed from /tmp/docker-mailserver/postfix-accounts.cf but not auser3" {
|
|
docker exec mail /bin/sh -c "delmailuser -y user3@domain.tld"
|
|
|
|
run docker exec mail /bin/sh -c "grep '^user3@domain\.tld' -i /tmp/docker-mailserver/postfix-accounts.cf"
|
|
assert_failure
|
|
[ -z "${output}" ]
|
|
|
|
run docker exec mail /bin/sh -c "grep '^auser3@domain\.tld' -i /tmp/docker-mailserver/postfix-accounts.cf"
|
|
assert_success
|
|
[ -n "${output}" ]
|
|
}
|
|
|
|
@test "checking user updating password for user in /tmp/docker-mailserver/postfix-accounts.cf" {
|
|
docker exec mail /bin/sh -c "addmailuser user4@domain.tld mypassword"
|
|
|
|
initialpass=$(docker exec mail /bin/sh -c "grep '^user4@domain\.tld' -i /tmp/docker-mailserver/postfix-accounts.cf")
|
|
sleep 2
|
|
docker exec mail /bin/sh -c "updatemailuser user4@domain.tld mynewpassword"
|
|
sleep 2
|
|
changepass=$(docker exec mail /bin/sh -c "grep '^user4@domain\.tld' -i /tmp/docker-mailserver/postfix-accounts.cf")
|
|
|
|
[ "${initialpass}" != "${changepass}" ]
|
|
|
|
docker exec mail /bin/sh -c "delmailuser -y auser3@domain.tld"
|
|
|
|
assert_success
|
|
}
|
|
|
|
@test "checking accounts: listmailuser" {
|
|
run docker exec mail /bin/sh -c "listmailuser | head -n 1"
|
|
assert_success
|
|
assert_output '* user1@localhost.localdomain ( 12K / ~ ) [0%]'
|
|
}
|
|
|
|
@test "checking accounts: no error is generated when deleting a user if /tmp/docker-mailserver/postfix-accounts.cf is missing" {
|
|
run docker run --rm \
|
|
-v "$(duplicate_config_for_container without-accounts/ without-accounts-deleting-user)":/tmp/docker-mailserver/ \
|
|
"${IMAGE_NAME:?}" /bin/sh -c 'delmailuser -y user3@domain.tld'
|
|
assert_success
|
|
[ -z "${output}" ]
|
|
}
|
|
|
|
@test "checking accounts: user3 should have been added to /tmp/docker-mailserver/postfix-accounts.cf even when that file does not exist" {
|
|
local PRIVATE_CONFIG
|
|
PRIVATE_CONFIG=$(duplicate_config_for_container without-accounts/ without-accounts_file_does_not_exist)
|
|
run docker run --rm \
|
|
-v "${PRIVATE_CONFIG}/without-accounts/":/tmp/docker-mailserver/ \
|
|
"${IMAGE_NAME:?}" /bin/sh -c 'addmailuser user3@domain.tld mypassword'
|
|
assert_success
|
|
run docker run --rm \
|
|
-v "${PRIVATE_CONFIG}/without-accounts/":/tmp/docker-mailserver/ \
|
|
"${IMAGE_NAME:?}" /bin/sh -c 'grep user3@domain.tld -i /tmp/docker-mailserver/postfix-accounts.cf'
|
|
assert_success
|
|
[ -n "${output}" ]
|
|
}
|
|
|
|
|
|
@test "checking quota: setquota user must be existing" {
|
|
run docker exec mail /bin/sh -c "addmailuser quota_user@domain.tld mypassword"
|
|
assert_success
|
|
|
|
run docker exec mail /bin/sh -c "setquota quota_user 50M"
|
|
assert_failure
|
|
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld 50M"
|
|
assert_success
|
|
|
|
run docker exec mail /bin/sh -c "setquota username@fulldomain 50M"
|
|
assert_failure
|
|
|
|
run docker exec mail /bin/sh -c "delmailuser -y quota_user@domain.tld"
|
|
assert_success
|
|
}
|
|
@test "checking quota: setquota <quota> must be well formatted" {
|
|
run docker exec mail /bin/sh -c "addmailuser quota_user@domain.tld mypassword"
|
|
assert_success
|
|
|
|
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld 26GIGOTS"
|
|
assert_failure
|
|
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld 123"
|
|
assert_failure
|
|
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld M"
|
|
assert_failure
|
|
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld -60M"
|
|
assert_failure
|
|
|
|
|
|
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld 10B"
|
|
assert_success
|
|
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld 10k"
|
|
assert_success
|
|
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld 10M"
|
|
assert_success
|
|
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld 10G"
|
|
assert_success
|
|
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld 10T"
|
|
assert_success
|
|
|
|
|
|
run docker exec mail /bin/sh -c "delmailuser -y quota_user@domain.tld"
|
|
assert_success
|
|
}
|
|
|
|
|
|
@test "checking quota: delquota user must be existing" {
|
|
run docker exec mail /bin/sh -c "addmailuser quota_user@domain.tld mypassword"
|
|
assert_success
|
|
|
|
run docker exec mail /bin/sh -c "delquota uota_user@domain.tld"
|
|
assert_failure
|
|
run docker exec mail /bin/sh -c "delquota quota_user"
|
|
assert_failure
|
|
run docker exec mail /bin/sh -c "delquota dontknowyou@domain.tld"
|
|
assert_failure
|
|
|
|
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld 10T"
|
|
assert_success
|
|
run docker exec mail /bin/sh -c "delquota quota_user@domain.tld"
|
|
assert_success
|
|
run docker exec mail /bin/sh -c "grep -i 'quota_user@domain.tld' /tmp/docker-mailserver/dovecot-quotas.cf"
|
|
assert_failure
|
|
|
|
run docker exec mail /bin/sh -c "delmailuser -y quota_user@domain.tld"
|
|
assert_success
|
|
}
|
|
@test "checking quota: delquota allow when no quota for existing user" {
|
|
run docker exec mail /bin/sh -c "addmailuser quota_user@domain.tld mypassword"
|
|
assert_success
|
|
|
|
run docker exec mail /bin/sh -c "grep -i 'quota_user@domain.tld' /tmp/docker-mailserver/dovecot-quotas.cf"
|
|
assert_failure
|
|
|
|
run docker exec mail /bin/sh -c "delquota quota_user@domain.tld"
|
|
assert_success
|
|
run docker exec mail /bin/sh -c "delquota quota_user@domain.tld"
|
|
assert_success
|
|
|
|
run docker exec mail /bin/sh -c "delmailuser -y quota_user@domain.tld"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking quota: dovecot quota present in postconf" {
|
|
run docker exec mail /bin/bash -c "postconf | grep 'check_policy_service inet:localhost:65265'"
|
|
assert_success
|
|
}
|
|
|
|
|
|
@test "checking quota: dovecot mailbox max size must be equal to postfix mailbox max size" {
|
|
postfix_mailbox_size=$(docker exec mail sh -c "postconf | grep -Po '(?<=mailbox_size_limit = )[0-9]+'")
|
|
run echo "${postfix_mailbox_size}"
|
|
refute_output ""
|
|
|
|
# dovecot relies on virtual_mailbox_size by default
|
|
postfix_virtual_mailbox_size=$(docker exec mail sh -c "postconf | grep -Po '(?<=virtual_mailbox_limit = )[0-9]+'")
|
|
assert_equal "${postfix_virtual_mailbox_size}" "${postfix_mailbox_size}"
|
|
|
|
postfix_mailbox_size_mb=$(( postfix_mailbox_size / 1000000))
|
|
|
|
dovecot_mailbox_size_mb=$(docker exec mail sh -c "doveconf | grep -oP '(?<=quota_rule \= \*\:storage=)[0-9]+'")
|
|
run echo "${dovecot_mailbox_size_mb}"
|
|
refute_output ""
|
|
|
|
assert_equal "${postfix_mailbox_size_mb}" "${dovecot_mailbox_size_mb}"
|
|
}
|
|
|
|
|
|
@test "checking quota: dovecot message max size must be equal to postfix messsage max size" {
|
|
postfix_message_size=$(docker exec mail sh -c "postconf | grep -Po '(?<=message_size_limit = )[0-9]+'")
|
|
run echo "${postfix_message_size}"
|
|
refute_output ""
|
|
|
|
postfix_message_size_mb=$(( postfix_message_size / 1000000))
|
|
|
|
dovecot_message_size_mb=$(docker exec mail sh -c "doveconf | grep -oP '(?<=quota_max_mail_size = )[0-9]+'")
|
|
run echo "${dovecot_message_size_mb}"
|
|
refute_output ""
|
|
|
|
assert_equal "${postfix_message_size_mb}" "${dovecot_message_size_mb}"
|
|
}
|
|
|
|
@test "checking quota: quota directive is removed when mailbox is removed" {
|
|
run docker exec mail /bin/sh -c "addmailuser quserremoved@domain.tld mypassword"
|
|
assert_success
|
|
|
|
run docker exec mail /bin/sh -c "setquota quserremoved@domain.tld 12M"
|
|
assert_success
|
|
|
|
run docker exec mail /bin/sh -c 'cat /tmp/docker-mailserver/dovecot-quotas.cf | grep -E "^quserremoved@domain.tld\:12M\$" | wc -l | grep 1'
|
|
assert_success
|
|
|
|
run docker exec mail /bin/sh -c "delmailuser -y quserremoved@domain.tld"
|
|
assert_success
|
|
|
|
run docker exec mail /bin/sh -c 'cat /tmp/docker-mailserver/dovecot-quotas.cf | grep -E "^quserremoved@domain.tld\:12M\$"'
|
|
assert_failure
|
|
}
|
|
|
|
@test "checking quota: dovecot applies user quota" {
|
|
wait_for_changes_to_be_detected_in_container mail
|
|
|
|
run docker exec mail /bin/sh -c "doveadm quota get -u 'user1@localhost.localdomain' | grep 'User quota STORAGE'"
|
|
assert_output --partial "- 0"
|
|
|
|
run docker exec mail /bin/sh -c "setquota user1@localhost.localdomain 50M"
|
|
assert_success
|
|
|
|
wait_for_changes_to_be_detected_in_container mail
|
|
|
|
# wait until quota has been updated
|
|
run repeat_until_success_or_timeout 20 sh -c "docker exec mail sh -c 'doveadm quota get -u user1@localhost.localdomain | grep -oP \"(User quota STORAGE\s+[0-9]+\s+)51200(.*)\"'"
|
|
assert_success
|
|
|
|
run docker exec mail /bin/sh -c "delquota user1@localhost.localdomain"
|
|
assert_success
|
|
|
|
wait_for_changes_to_be_detected_in_container mail
|
|
|
|
# wait until quota has been updated
|
|
run repeat_until_success_or_timeout 20 sh -c "docker exec mail sh -c 'doveadm quota get -u user1@localhost.localdomain | grep -oP \"(User quota STORAGE\s+[0-9]+\s+)-(.*)\"'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking quota: warn message received when quota exceeded" {
|
|
wait_for_changes_to_be_detected_in_container mail
|
|
|
|
# create user
|
|
run docker exec mail /bin/sh -c "addmailuser quotauser@otherdomain.tld mypassword && setquota quotauser@otherdomain.tld 10k"
|
|
assert_success
|
|
|
|
wait_for_changes_to_be_detected_in_container mail
|
|
|
|
# wait until quota has been updated
|
|
run repeat_until_success_or_timeout 20 sh -c "docker exec mail sh -c 'doveadm quota get -u quotauser@otherdomain.tld | grep -oP \"(User quota STORAGE\s+[0-9]+\s+)10(.*)\"'"
|
|
assert_success
|
|
|
|
# dovecot and postfix has been restarted
|
|
wait_for_service mail postfix
|
|
wait_for_service mail dovecot
|
|
sleep 10
|
|
|
|
# send some big emails
|
|
run docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/quota-exceeded.txt"
|
|
assert_success
|
|
run docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/quota-exceeded.txt"
|
|
assert_success
|
|
run docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/quota-exceeded.txt"
|
|
assert_success
|
|
# check for quota warn message existence
|
|
run repeat_until_success_or_timeout 20 sh -c "docker exec mail sh -c 'grep \"Subject: quota warning\" /var/mail/otherdomain.tld/quotauser/new/ -R'"
|
|
assert_success
|
|
|
|
run repeat_until_success_or_timeout 20 sh -c "docker logs mail | grep 'Quota exceeded (mailbox for user is full)'"
|
|
assert_success
|
|
|
|
# ensure only the first big message and the warn message are present (other messages are rejected: mailbox is full)
|
|
run docker exec mail sh -c 'ls /var/mail/otherdomain.tld/quotauser/new/ | wc -l'
|
|
assert_success
|
|
assert_output "2"
|
|
|
|
run docker exec mail /bin/sh -c "delmailuser -y quotauser@otherdomain.tld"
|
|
assert_success
|
|
}
|
|
|
|
#
|
|
# PERMIT_DOCKER mynetworks
|
|
#
|
|
|
|
@test "checking PERMIT_DOCKER: can get container ip" {
|
|
run docker exec mail /bin/sh -c "ip addr show eth0 | grep 'inet ' | sed 's/[^0-9\.\/]*//g' | cut -d '/' -f 1 | egrep '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking PERMIT_DOCKER: my network value" {
|
|
run docker exec mail /bin/sh -c "postconf | grep '^mynetworks =' | egrep '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.0\.0/16'"
|
|
assert_success
|
|
}
|
|
|
|
#
|
|
# amavis
|
|
#
|
|
|
|
@test "checking amavis: config overrides" {
|
|
run docker exec mail /bin/sh -c "grep 'Test Verification' /etc/amavis/conf.d/50-user | wc -l"
|
|
assert_success
|
|
assert_output 1
|
|
}
|
|
|
|
# TODO investigate why this test fails
|
|
@test "checking user login: predefined user can login" {
|
|
skip 'disabled as it fails randomly: https://github.com/docker-mailserver/docker-mailserver/pull/2177'
|
|
run docker exec mail /bin/bash -c "doveadm auth test -x service=smtp pass@localhost.localdomain 'may be \\a \`p^a.*ssword' | grep 'passdb'"
|
|
assert_output "passdb: pass@localhost.localdomain auth succeeded"
|
|
}
|
|
|
|
# -----------------------------------------------
|
|
# --- setup.sh ----------------------------------
|
|
# -----------------------------------------------
|
|
|
|
@test "setup.sh :: exit with error when no arguments provided" {
|
|
run ./setup.sh
|
|
assert_failure
|
|
assert_line --index 0 --partial "The command '' is invalid."
|
|
}
|
|
|
|
@test "setup.sh :: exit with error when wrong arguments provided" {
|
|
run ./setup.sh lol troll
|
|
assert_failure
|
|
assert_line --index 0 --partial "The command 'lol troll' is invalid."
|
|
}
|
|
|
|
@test "checking setup.sh: setup.sh email add and login" {
|
|
wait_for_service mail changedetector
|
|
assert_success
|
|
|
|
run ./setup.sh -c mail email add setup_email_add@example.com test_password
|
|
assert_success
|
|
|
|
value=$(grep setup_email_add@example.com "$(private_config_path mail)/postfix-accounts.cf" | awk -F '|' '{print $1}')
|
|
[ "${value}" = "setup_email_add@example.com" ]
|
|
assert_success
|
|
|
|
wait_for_changes_to_be_detected_in_container mail
|
|
|
|
wait_for_service mail postfix
|
|
wait_for_service mail dovecot
|
|
sleep 5
|
|
|
|
run docker exec mail /bin/bash -c "doveadm auth test -x service=smtp setup_email_add@example.com 'test_password' | grep 'passdb'"
|
|
assert_output "passdb: setup_email_add@example.com auth succeeded"
|
|
}
|
|
|
|
@test "checking setup.sh: setup.sh email list" {
|
|
run ./setup.sh -c mail email list
|
|
assert_success
|
|
}
|
|
|
|
@test "checking setup.sh: setup.sh email update" {
|
|
run ./setup.sh -c mail email add lorem@impsum.org test_test
|
|
assert_success
|
|
|
|
initialpass=$(grep lorem@impsum.org "$(private_config_path mail)/postfix-accounts.cf" | awk -F '|' '{print $2}')
|
|
[ "${initialpass}" != "" ]
|
|
assert_success
|
|
|
|
run ./setup.sh -c mail email update lorem@impsum.org my password
|
|
assert_success
|
|
|
|
updatepass=$(grep lorem@impsum.org "$(private_config_path mail)/postfix-accounts.cf" | awk -F '|' '{print $2}')
|
|
[ "${updatepass}" != "" ]
|
|
[ "${initialpass}" != "${updatepass}" ]
|
|
|
|
docker exec mail doveadm pw -t "${updatepass}" -p 'my password' | grep 'verified'
|
|
assert_success
|
|
}
|
|
|
|
@test "checking setup.sh: setup.sh email del" {
|
|
run ./setup.sh -c mail email del -y lorem@impsum.org
|
|
assert_success
|
|
|
|
# TODO
|
|
# delmailuser does not work as expected.
|
|
# Its implementation is not functional, you cannot delete a user data
|
|
# directory in the running container by running a new docker container
|
|
# and not mounting the mail folders (persistance is broken).
|
|
# The add script is only adding the user to account file.
|
|
|
|
# run docker exec mail ls /var/mail/impsum.org/lorem
|
|
# assert_failure
|
|
run grep lorem@impsum.org "$(private_config_path mail)/postfix-accounts.cf"
|
|
assert_failure
|
|
}
|
|
|
|
@test "checking setup.sh: setup.sh email restrict" {
|
|
run ./setup.sh -c mail email restrict
|
|
assert_failure
|
|
run ./setup.sh -c mail email restrict add
|
|
assert_failure
|
|
./setup.sh -c mail email restrict add send lorem@impsum.org
|
|
run ./setup.sh -c mail email restrict list send
|
|
assert_output --regexp "^lorem@impsum.org.*REJECT"
|
|
|
|
run ./setup.sh -c mail email restrict del send lorem@impsum.org
|
|
assert_success
|
|
run ./setup.sh -c mail email restrict list send
|
|
assert_output --partial "Everyone is allowed"
|
|
|
|
./setup.sh -c mail email restrict add receive rec_lorem@impsum.org
|
|
run ./setup.sh -c mail email restrict list receive
|
|
assert_output --regexp "^rec_lorem@impsum.org.*REJECT"
|
|
run ./setup.sh -c mail email restrict del receive rec_lorem@impsum.org
|
|
assert_success
|
|
}
|
|
|
|
# alias
|
|
@test "checking setup.sh: setup.sh alias list" {
|
|
run ./setup.sh alias list
|
|
assert_success
|
|
assert_output --partial "alias1@localhost.localdomain user1@localhost.localdomain"
|
|
assert_output --partial "@localdomain2.com user1@localhost.localdomain"
|
|
}
|
|
|
|
@test "checking setup.sh: setup.sh alias add" {
|
|
./setup.sh alias add alias@example.com target1@forward.com
|
|
./setup.sh alias add alias@example.com target2@forward.com
|
|
./setup.sh alias add alias2@example.org target3@forward.com
|
|
sleep 5
|
|
run grep "alias@example.com target1@forward.com,target2@forward.com" "$(private_config_path mail)/postfix-virtual.cf"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking setup.sh: setup.sh alias del" {
|
|
./setup.sh alias del alias@example.com target1@forward.com
|
|
run grep "target1@forward.com" "$(private_config_path mail)/postfix-virtual.cf"
|
|
assert_failure
|
|
|
|
run grep "target2@forward.com" "$(private_config_path mail)/postfix-virtual.cf"
|
|
assert_output "alias@example.com target2@forward.com"
|
|
|
|
./setup.sh alias del alias@example.org target2@forward.com
|
|
run grep "alias@example.org" "$(private_config_path mail)/postfix-virtual.cf"
|
|
assert_failure
|
|
|
|
run grep "alias2@example.org" "$(private_config_path mail)/postfix-virtual.cf"
|
|
assert_success
|
|
|
|
./setup.sh alias del alias2@example.org target3@forward.com
|
|
run grep "alias2@example.org" "$(private_config_path mail)/postfix-virtual.cf"
|
|
assert_failure
|
|
}
|
|
|
|
# quota
|
|
@test "checking setup.sh: setup.sh setquota" {
|
|
run ./setup.sh email add quota_user@example.com test_password
|
|
run ./setup.sh email add quota_user2@example.com test_password
|
|
|
|
run ./setup.sh quota set quota_user@example.com 12M
|
|
assert_success
|
|
run ./setup.sh quota set 51M quota_user@example.com
|
|
assert_failure
|
|
run ./setup.sh quota set unknown@domain.com 150M
|
|
assert_failure
|
|
|
|
run ./setup.sh quota set quota_user2 51M
|
|
assert_failure
|
|
|
|
run /bin/sh -c 'cat ./test/duplicate_configs/mail/dovecot-quotas.cf | grep -E "^quota_user@example.com\:12M\$" | wc -l | grep 1'
|
|
assert_success
|
|
|
|
run ./setup.sh quota set quota_user@example.com 26M
|
|
assert_success
|
|
run /bin/sh -c 'cat ./test/duplicate_configs/mail/dovecot-quotas.cf | grep -E "^quota_user@example.com\:26M\$" | wc -l | grep 1'
|
|
assert_success
|
|
|
|
run grep "quota_user2@example.com" ./test/duplicate_configs/mail/dovecot-quotas.cf
|
|
assert_failure
|
|
}
|
|
|
|
@test "checking setup.sh: setup.sh delquota" {
|
|
run ./setup.sh email add quota_user@example.com test_password
|
|
run ./setup.sh email add quota_user2@example.com test_password
|
|
|
|
run ./setup.sh quota set quota_user@example.com 12M
|
|
assert_success
|
|
run /bin/sh -c 'cat ./test/duplicate_configs/mail/dovecot-quotas.cf | grep -E "^quota_user@example.com\:12M\$" | wc -l | grep 1'
|
|
assert_success
|
|
|
|
run ./setup.sh quota del unknown@domain.com
|
|
assert_failure
|
|
run /bin/sh -c 'cat ./test/duplicate_configs/mail/dovecot-quotas.cf | grep -E "^quota_user@example.com\:12M\$" | wc -l | grep 1'
|
|
assert_success
|
|
|
|
run ./setup.sh quota del quota_user@example.com
|
|
assert_success
|
|
run grep "quota_user@example.com" ./test/duplicate_configs/mail/dovecot-quotas.cf
|
|
assert_failure
|
|
}
|
|
|
|
@test "setup.sh :: setup.sh config dkim help correctly displayed" {
|
|
run ./setup.sh -c mail config dkim help
|
|
assert_success
|
|
assert_line --index 3 --partial " open-dkim - configure DomainKeys Identified Mail (DKIM)"
|
|
}
|
|
|
|
# debug
|
|
|
|
@test "checking setup.sh: setup.sh debug fetchmail" {
|
|
run ./setup.sh -c mail debug fetchmail
|
|
assert_failure
|
|
assert_output --partial "fetchmail: normal termination, status 11"
|
|
}
|
|
|
|
@test "checking setup.sh: setup.sh debug login ls" {
|
|
run ./setup.sh -c mail debug login ls
|
|
assert_success
|
|
}
|
|
|
|
@test "checking setup.sh: setup.sh relay add-domain" {
|
|
./setup.sh relay add-domain example1.org smtp.relay1.com 2525
|
|
./setup.sh relay add-domain example2.org smtp.relay2.com
|
|
./setup.sh relay add-domain example3.org smtp.relay3.com 2525
|
|
./setup.sh relay add-domain example3.org smtp.relay.com 587
|
|
|
|
# check adding
|
|
run /bin/sh -c "cat $(private_config_path mail)/postfix-relaymap.cf | grep -e \"^@example1.org\s\+\[smtp.relay1.com\]:2525\" | wc -l | grep 1"
|
|
assert_success
|
|
# test default port
|
|
run /bin/sh -c "cat $(private_config_path mail)/postfix-relaymap.cf | grep -e \"^@example2.org\s\+\[smtp.relay2.com\]:25\" | wc -l | grep 1"
|
|
assert_success
|
|
# test modifying
|
|
run /bin/sh -c "cat $(private_config_path mail)/postfix-relaymap.cf | grep -e \"^@example3.org\s\+\[smtp.relay.com\]:587\" | wc -l | grep 1"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking setup.sh: setup.sh relay add-auth" {
|
|
./setup.sh relay add-auth example.org smtp_user smtp_pass
|
|
./setup.sh relay add-auth example2.org smtp_user2 smtp_pass2
|
|
./setup.sh relay add-auth example2.org smtp_user2 smtp_pass_new
|
|
|
|
# test adding
|
|
run /bin/sh -c "cat $(private_config_path mail)/postfix-sasl-password.cf | grep -e \"^@example.org\s\+smtp_user:smtp_pass\" | wc -l | grep 1"
|
|
assert_success
|
|
# test updating
|
|
run /bin/sh -c "cat $(private_config_path mail)/postfix-sasl-password.cf | grep -e \"^@example2.org\s\+smtp_user2:smtp_pass_new\" | wc -l | grep 1"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking setup.sh: setup.sh relay exclude-domain" {
|
|
./setup.sh relay exclude-domain example.org
|
|
|
|
run /bin/sh -c "cat $(private_config_path mail)/postfix-relaymap.cf | grep -e \"^@example.org\s*$\" | wc -l | grep 1"
|
|
assert_success
|
|
}
|
|
|
|
#
|
|
# LDAP
|
|
#
|
|
|
|
# postfix
|
|
|
|
@test "checking dovecot: postmaster address" {
|
|
run docker exec mail /bin/sh -c "grep 'postmaster_address = postmaster@my-domain.com' /etc/dovecot/conf.d/15-lda.conf"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking spoofing: rejects sender forging" {
|
|
# checking rejection of spoofed sender
|
|
wait_for_smtp_port_in_container_to_respond mail
|
|
run docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/auth/added-smtp-auth-spoofed.txt"
|
|
assert_output --partial 'Sender address rejected: not owned by user'
|
|
}
|
|
|
|
@test "checking spoofing: accepts sending as alias" {
|
|
run docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/auth/added-smtp-auth-spoofed-alias.txt | grep 'End data with'"
|
|
assert_success
|
|
}
|
|
|
|
#
|
|
# Pflogsumm delivery check
|
|
#
|
|
|
|
@test "checking pflogsum delivery" {
|
|
# checking logrotation working and report being sent
|
|
docker exec mail logrotate --force /etc/logrotate.d/maillog
|
|
sleep 10
|
|
run docker exec mail grep "Subject: Postfix Summary for " /var/mail/localhost.localdomain/user1/new/ -R
|
|
assert_success
|
|
# check sender is the one specified in REPORT_SENDER
|
|
run docker exec mail grep "From: report1@mail.my-domain.com" /var/mail/localhost.localdomain/user1/new/ -R
|
|
assert_success
|
|
# check sender is not the default one.
|
|
run docker exec mail grep "From: mailserver-report@mail.my-domain.com" /var/mail/localhost.localdomain/user1/new/ -R
|
|
assert_failure
|
|
}
|
|
|
|
#
|
|
# supervisor
|
|
#
|
|
|
|
@test "checking restart of process: postfix" {
|
|
run docker exec mail /bin/bash -c "pkill master && sleep 10 && ps aux --forest | grep -v grep | grep '/usr/lib/postfix/sbin/master'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking restart of process: clamd" {
|
|
run docker exec mail /bin/bash -c "pkill clamd && sleep 10 && ps aux --forest | grep -v grep | grep '/usr/sbin/clamd'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking restart of process: amavisd-new" {
|
|
run docker exec mail /bin/bash -c "pkill amavi && sleep 12 && ps aux --forest | grep -v grep | grep '/usr/sbin/amavisd-new (master)'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking restart of process: opendkim" {
|
|
run docker exec mail /bin/bash -c "pkill opendkim && sleep 10 && ps aux --forest | grep -v grep | grep '/usr/sbin/opendkim'"
|
|
assert_success
|
|
}
|
|
|
|
@test "checking restart of process: opendmarc" {
|
|
run docker exec mail /bin/bash -c "pkill opendmarc && sleep 10 && ps aux --forest | grep -v grep | grep '/usr/sbin/opendmarc'"
|
|
assert_success
|
|
}
|
|
|
|
#
|
|
# root mail delivery
|
|
#
|
|
|
|
@test "checking that mail for root was delivered" {
|
|
run docker exec mail grep "Subject: Root Test Message" /var/mail/localhost.localdomain/user1/new/ -R
|
|
assert_success
|
|
}
|
|
|
|
@test "last" {
|
|
skip 'this test is only there to reliably mark the end for the teardown_file (test.bats finished)'
|
|
}
|