Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion test/helper/common.bash
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ function __handle_container_name() {
printf '%s' "${CONTAINER_NAME}"
return 0
else
echo 'ERROR: (helper/common.sh) Container name was either provided explicitly without the required `dms-test_` prefix, or CONTAINER_NAME is not set for implicit usage' >&2
echo 'ERROR: (helper/common.sh) Container name was either provided explicitly without the required "dms-test_" prefix, or CONTAINER_NAME is not set for implicit usage' >&2
exit 1
fi
}
Expand Down Expand Up @@ -119,6 +119,27 @@ function _exec_in_container_bash() { _exec_in_container /bin/bash -c "${@}" ; }
# @param ... = Bash command to execute
function _run_in_container_bash() { _run_in_container /bin/bash -c "${@}" ; }

# Run a command in Bash and filter the output given a regex.
#
# @param ${1} = command to run in Bash
# @param ${2} = regex to filter [OPTIONAL]
#
# ## Attention
#
# The regex is given to `grep -E`, so make sure it is compatible.
#
# ## Note
#
# If no regex is provided, this function will default to one that strips
# empty lines and Bash comments from the output.
function _run_in_container_bash_and_filter_output() {
local COMMAND=${1:?Command must be provided}
local FILTER_REGEX=${2:-^[[:space:]]*$|^ *#}

_run_in_container_bash "${COMMAND} | grep -E -v '${FILTER_REGEX}'"
assert_success
}

# ? << Functions to execute commands inside a container
# ! -------------------------------------------------------------------
# ? >> Functions about executing commands with timeouts
Expand Down
2 changes: 1 addition & 1 deletion test/test-files/email-templates/smtp-only.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
HELO mail.localhost
HELO mail.example.test
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for this file since I think it's the only test that uses it, feel free to change the domains to use the .test TLD if it helps.

This is something I plan to do after all tests are migrated to the new format / helpers. I've noticed the DNS lookups (and attempts to send bounce mail in the logs) as well.

Copy link
Copy Markdown
Member Author

@georglauterbach georglauterbach Jan 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏼

EDIT: I will leave this open in case we stumble on it again in the future.

MAIL FROM: test@localhost
RCPT TO: [email protected]
DATA
Expand Down
48 changes: 19 additions & 29 deletions test/tests/serial/mail_quotas_disabled.bats
Original file line number Diff line number Diff line change
@@ -1,43 +1,33 @@
load "${REPOSITORY_ROOT}/test/test_helper/common"

# Test case
# ---------
# When ENABLE_QUOTAS is explicitly disabled (ENABLE_QUOTAS=0), dovecot quota must not be enabled.
load "${REPOSITORY_ROOT}/test/helper/common"
load "${REPOSITORY_ROOT}/test/helper/setup"

BATS_TEST_NAME_PREFIX='[Quotas Disabled] '
CONTAINER_NAME='dms-test_quotas-disabled'

function setup_file() {
local PRIVATE_CONFIG
PRIVATE_CONFIG=$(duplicate_config_for_container .)

docker run -d --name mail_no_quotas \
-v "${PRIVATE_CONFIG}":/tmp/docker-mailserver \
-v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \
-e ENABLE_QUOTAS=0 \
-h mail.my-domain.com -t "${NAME}"

wait_for_finished_setup_in_container mail_no_quotas
_init_with_defaults
local CUSTOM_SETUP_ARGUMENTS=(--env ENABLE_QUOTAS=0)
_common_container_setup 'CUSTOM_SETUP_ARGUMENTS'
}

function teardown_file() {
docker rm -f mail_no_quotas
}
function teardown_file() { _default_teardown ; }

@test "checking dovecot: (ENABLE_QUOTAS=0) quota plugin is disabled" {
run docker exec mail_no_quotas /bin/sh -c "grep '\$mail_plugins quota' /etc/dovecot/conf.d/10-mail.conf"
assert_failure
@test "(Dovecot) quota plugin is disabled" {
_run_in_container_bash_and_filter_output 'cat /etc/dovecot/conf.d/10-mail.conf'
refute_output --partial 'quota'

run docker exec mail_no_quotas /bin/sh -c "grep '\$mail_plugins imap_quota' /etc/dovecot/conf.d/20-imap.conf"
assert_failure
_run_in_container_bash_and_filter_output 'cat /etc/dovecot/conf.d/20-imap.conf'
refute_output --partial 'imap_quota'

run docker exec mail_no_quotas ls /etc/dovecot/conf.d/90-quota.conf
_run_in_container_bash "[[ -f /etc/dovecot/conf.d/90-quota.conf ]]"
assert_failure

run docker exec mail_no_quotas ls /etc/dovecot/conf.d/90-quota.conf.disab
_run_in_container_bash "[[ -f /etc/dovecot/conf.d/90-quota.conf.disab ]]"
assert_success
}

@test "checking postfix: (ENABLE_QUOTAS=0) dovecot quota absent in postconf" {
run docker exec mail_no_quotas /bin/bash -c "postconf | grep 'check_policy_service inet:localhost:65265'"
assert_failure
@test "(Postfix) Dovecot quota absent in postconf" {
_run_in_container postconf
assert_success
refute_output --partial "check_policy_service inet:localhost:65265'"
}

74 changes: 27 additions & 47 deletions test/tests/serial/mail_smtponly.bats
Original file line number Diff line number Diff line change
@@ -1,64 +1,44 @@
load "${REPOSITORY_ROOT}/test/test_helper/common"
load "${REPOSITORY_ROOT}/test/helper/common"
load "${REPOSITORY_ROOT}/test/helper/setup"

function setup_file() {
docker run --rm -d --name mail_smtponly \
-v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \
-e SMTP_ONLY=1 \
-e PERMIT_DOCKER=network \
-e OVERRIDE_HOSTNAME=mail.my-domain.com \
-t "${NAME}"
BATS_TEST_NAME_PREFIX='[SMTP-Only] '
CONTAINER_NAME='dms-test_env-smtp-only'

wait_for_finished_setup_in_container mail_smtponly
wait_for_smtp_port_in_container mail_smtponly
}
function setup_file() {
_init_with_defaults

function teardown_file() {
docker rm -f mail_smtponly
}
local CUSTOM_SETUP_ARGUMENTS=(
--env SMTP_ONLY=1
--env PERMIT_DOCKER=network
)

#
# configuration checks
#
_common_container_setup 'CUSTOM_SETUP_ARGUMENTS'

@test "checking configuration: hostname/domainname override" {
run docker exec mail_smtponly /bin/bash -c "cat /etc/mailname | grep my-domain.com"
assert_success
_wait_for_smtp_port_in_container
}

#
# imap
#

@test "checking configuration: dovecot quota absent in postconf (disabled using SMTP_ONLY)" {
run docker exec mail_smtponly /bin/bash -c "postconf | grep 'check_policy_service inet:localhost:65265'"
assert_failure
}
function teardown_file() { _default_teardown ; }

#
# smtp
#

@test "checking smtp_only: mail send should work" {
run docker exec mail_smtponly /bin/sh -c "postconf smtp_host_lookup=no"
@test "Dovecot quota absent in postconf" {
_run_in_container postconf
assert_success
refute_output --partial "check_policy_service inet:localhost:65265'"
}

_reload_postfix mail_smtponly
# TODO: needs complete rework when proper DNS container is running for tests
@test "sending mail should work" {
skip 'TODO: This test is absolutely broken and needs reworking!'

wait_for_smtp_port_in_container mail_smtponly
run docker exec mail_smtponly /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/smtp-only.txt"
assert_success
run docker exec mail_smtponly /bin/sh -c 'grep -cE "to=<user2\@external.tld>.*status\=sent" /var/log/mail/mail.log'
[[ ${status} -ge 0 ]]
}

#
# PERMIT_DOCKER=network
#

@test "checking PERMIT_DOCKER=network: opendmarc/opendkim config" {
run docker exec mail_smtponly /bin/sh -c "cat /etc/opendmarc/ignore.hosts | grep '172.16.0.0/12'"
# it looks as if someone tries to send mail to another domain outside of DMS
_run_in_container_bash "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/smtp-only.txt"
Comment on lines +35 to +36
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So test this isn't meant to deliver mail to the DMS container, but relay it externally?

I'm not too familiar with the feature, if accounts are tied to Dovecot for authentication, then it's also trying to submit mail without auth (which I think it is permitted to bypass by being sent internally like this).

Not much we can do about fixing that any time soon then 😅

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really know why this is the case, but the RCPT is for @external.tld .. I actually don't know if this makes sense either. Maybe it is useless and we can just deliver mail with Postfix to a local account and test the functionality this way too?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can DMS receive mail and store it without Dovecot when using SMTP_ONLY=1?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not, but I have not tried it TBH :D I'g go about this way: when all tests are refactored so we can run them in parallel, I'd then (after or before the DNS updates I don't know) tackle the left-over TODOs that we added when refactoring tests. I mean, this test was not properly working all the time, and we have enough to do when it comes to reworking the tests for now :)

assert_success
_wait_for_empty_mail_queue_in_container

run docker exec mail_smtponly /bin/sh -c "cat /etc/opendkim/TrustedHosts | grep '172.16.0.0/12'"
assert_success
# this seemingly succeeds, but looking at the logs, it doesn't
_run_in_container_bash 'grep -cE "to=<user2\@external.tld>.*status\=sent" /var/log/mail/mail.log'
# this is absolutely useless! `grep -c` count 0 but also returns 0; the mail was never properly sent!
[[ ${status} -ge 0 ]]
}
50 changes: 24 additions & 26 deletions test/tests/serial/mail_special_use_folders.bats
Original file line number Diff line number Diff line change
@@ -1,40 +1,38 @@
load "${REPOSITORY_ROOT}/test/test_helper/common"
load "${REPOSITORY_ROOT}/test/helper/common"
load "${REPOSITORY_ROOT}/test/helper/setup"

setup_file() {
local PRIVATE_CONFIG
PRIVATE_CONFIG=$(duplicate_config_for_container .)
BATS_TEST_NAME_PREFIX='[Special Use Folders] '
CONTAINER_NAME='dms-test_special-use-folders'

docker run -d --name mail_special_use_folders \
-v "${PRIVATE_CONFIG}":/tmp/docker-mailserver \
-v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \
-e ENABLE_CLAMAV=0 \
-e ENABLE_SPAMASSASSIN=0 \
-e PERMIT_DOCKER=host \
-h mail.my-domain.com -t "${NAME}"

wait_for_smtp_port_in_container mail_special_use_folders
function setup_file() {
_init_with_defaults
local CUSTOM_SETUP_ARGUMENTS=(--env PERMIT_DOCKER=host)
_common_container_setup 'CUSTOM_SETUP_ARGUMENTS'
_wait_for_smtp_port_in_container
}

teardown_file() {
docker rm -f mail_special_use_folders
}
function teardown_file() { _default_teardown ; }

@test "checking normal delivery" {
run docker exec mail_special_use_folders /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-user1.txt"
@test "normal delivery works" {
_run_in_container_bash "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-user1.txt"
assert_success

# shellcheck disable=SC2016
repeat_until_success_or_timeout 30 docker exec mail_special_use_folders /bin/sh -c '[ $(ls /var/mail/localhost.localdomain/user1/new | wc -l) -eq 1 ]'
_count_files_in_directory_in_container /var/mail/localhost.localdomain/user1/new 1
}

@test "checking special-use folders not yet created" {
run docker exec mail_special_use_folders /bin/bash -c "ls -A /var/mail/localhost.localdomain/user1 | grep -E '.Drafts|.Sent|.Trash' | wc -l"
@test "(IMAP) special-use folders should not exist yet" {
_run_in_container find /var/mail/localhost.localdomain/user1 -maxdepth 1 -type d
assert_success
assert_output 0
refute_output --partial '.Drafts'
refute_output --partial '.Sent'
refute_output --partial '.Trash'
}

@test "checking special-use folders available in IMAP" {
run docker exec mail_special_use_folders /bin/sh -c "nc -w 8 0.0.0.0 143 < /tmp/docker-mailserver-test/nc_templates/imap_special_use_folders.txt | grep -E 'Drafts|Junk|Trash|Sent' | wc -l"
@test "(IMAP) special-use folders should be created when necessary" {
_run_in_container_bash "nc -w 8 0.0.0.0 143 < /tmp/docker-mailserver-test/nc_templates/imap_special_use_folders.txt"
assert_success
assert_output 4
assert_output --partial 'Drafts'
assert_output --partial 'Junk'
assert_output --partial 'Trash'
assert_output --partial 'Sent'
}
30 changes: 12 additions & 18 deletions test/tests/serial/mail_time.bats
Original file line number Diff line number Diff line change
@@ -1,29 +1,23 @@
load "${REPOSITORY_ROOT}/test/test_helper/common"
load "${REPOSITORY_ROOT}/test/helper/common"
load "${REPOSITORY_ROOT}/test/helper/setup"

setup_file() {
local PRIVATE_CONFIG
PRIVATE_CONFIG=$(duplicate_config_for_container .)
BATS_TEST_NAME_PREFIX='[Timezone] '
CONTAINER_NAME='dms-test_timezone'

docker run -d --name mail_time \
-v "${PRIVATE_CONFIG}":/tmp/docker-mailserver \
-v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \
-e TZ='Asia/Jakarta' \
-e LOG_LEVEL=debug \
-h mail.my-domain.com -t "${NAME}"

wait_for_smtp_port_in_container mail_time
function setup_file() {
_init_with_defaults
local CUSTOM_SETUP_ARGUMENTS=(--env TZ='Asia/Jakarta')
_common_container_setup 'CUSTOM_SETUP_ARGUMENTS'
}

teardown_file() {
docker rm -f mail_time
}
function teardown_file() { _default_teardown ; }

@test "checking time: setting the time with TZ works correctly" {
run docker exec mail_time cat /etc/timezone
@test "setting the time with TZ works correctly" {
_run_in_container cat /etc/timezone
assert_success
assert_output 'Asia/Jakarta'

run docker exec mail_time date '+%Z'
_run_in_container date '+%Z'
assert_success
assert_output 'WIB'
}
9 changes: 9 additions & 0 deletions test/tests/serial/permit_docker.bats
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,12 @@ teardown_file() {
assert_output --partial "550 5.5.1 Protocol error"
[[ ${status} -ge 0 ]]
}

@test "checking PERMIT_DOCKER=network: opendmarc/opendkim config" {
skip 'TODO: this test was taken from mail_smtponly, where it did not actually belong to'
run docker exec mail_smtponly /bin/sh -c "cat /etc/opendmarc/ignore.hosts | grep '172.16.0.0/12'"
assert_success

run docker exec mail_smtponly /bin/sh -c "cat /etc/opendkim/TrustedHosts | grep '172.16.0.0/12'"
assert_success
}