mirror of
https://github.com/docker-mailserver/docker-mailserver
synced 2024-12-18 23:14:11 +01:00
ed1e1ebbd3
* move log/filter functions into own file * add ShellCheck global directives * use new function for tracking logs The new function, called `_send_email_with_mid`, aligns with suggestions from @polarethene and is heavily simplified compared to its predecessor `_send_email_and_get_id`. New helpers will be introduced to filter logs according to the MID constructed in this function. * new filters for searching logs with MID * use new filters (and sending) functions * add new helper for asserting non-existence of log message * use new filters in tests * Apply suggestions from code review - `_mid` / `MID` => `_msgid` / `MSG_ID` - Revised documentation / tooltip comments * Apply suggestions from code review * fix tests * use more distinct names for MSG_ID headers * update `_filter_service_log` to not use `-i -E` Moreover, I added a function to print the whole mail log. Appropriate comments were added to this function to indicate that one should only use this function when necessary. * adjust helpers to new helper filter * follow-up of previous commit * add CHANGELOG entry * Apply suggestions from code review * chore: Update OAuth2 to use new log helper * Apply suggestions from code review Co-authored-by: Brennan Kinney <5098581+polarathene@users.noreply.github.com> * added explicit `_regexp` filters for logs * Apply suggestions from code review --------- Co-authored-by: Brennan Kinney <5098581+polarathene@users.noreply.github.com>
279 lines
12 KiB
Bash
279 lines
12 KiB
Bash
load "${REPOSITORY_ROOT}/test/helper/common"
|
|
load "${REPOSITORY_ROOT}/test/helper/change-detection"
|
|
load "${REPOSITORY_ROOT}/test/helper/setup"
|
|
|
|
BATS_TEST_NAME_PREFIX='[SMTP] (delivery) '
|
|
CONTAINER_NAME='dms-test_smtp-delivery'
|
|
|
|
function teardown_file() { _default_teardown ; }
|
|
|
|
function setup_file() {
|
|
_init_with_defaults
|
|
|
|
local CONTAINER_ARGS_ENV_CUSTOM=(
|
|
# Required not only for authentication, but delivery in these tests (via nc):
|
|
# TODO: Properly test with DNS records configured and separate container for
|
|
# handling delivery (without nc). This would remove the need for this ENV:
|
|
--env PERMIT_DOCKER=container
|
|
# NOTE: Authentication is rejected due to default POSTSCREEN_ACTION=enforce and PERMIT_DOCKER=none
|
|
# Non-issue when PERMIT_DOCKER is not the default `none` for these nc 0.0.0.0 tests:
|
|
# --env POSTSCREEN_ACTION=ignore
|
|
|
|
# Required for test 'rejects spam':
|
|
--env ENABLE_SPAMASSASSIN=1
|
|
--env SPAMASSASSIN_SPAM_TO_INBOX=0
|
|
# Either SA_TAG or ENABLE_SRS=1 will pass the spamassassin X-SPAM headers test case:
|
|
--env SA_TAG=-5.0
|
|
|
|
# Only relevant for tests expecting to match `external.tld=`?:
|
|
# NOTE: Disabling support in tests as it doesn't seem relevant to the test, but misleading..
|
|
# `spam@external.tld` and `user@external.tld` are delivered with with the domain-part changed to `example.test`
|
|
# https://github.com/roehling/postsrsd
|
|
# --env ENABLE_SRS=1
|
|
# Required for ENABLE_SRS=1:
|
|
# --ulimit "nofile=$(ulimit -Sn):$(ulimit -Hn)"
|
|
|
|
# Required for tests: 'redirects mail to external aliases' + 'rejects spam':
|
|
--env ENABLE_AMAVIS=1
|
|
|
|
# TODO: Relocate relevant tests to the separated clamav test file:
|
|
# Originally relevant, but tests expecting ClamAV weren't properly implemented and didn't raise a failure.
|
|
# --env ENABLE_CLAMAV=1
|
|
)
|
|
|
|
# Required for 'delivers mail to existing alias with recipient delimiter':
|
|
mv "${TEST_TMP_CONFIG}/smtp-delivery/postfix-main.cf" "${TEST_TMP_CONFIG}/postfix-main.cf"
|
|
mv "${TEST_TMP_CONFIG}/smtp-delivery/dovecot.cf" "${TEST_TMP_CONFIG}/dovecot.cf"
|
|
|
|
_common_container_setup 'CONTAINER_ARGS_ENV_CUSTOM'
|
|
|
|
_run_in_container setup email add 'added@localhost.localdomain' 'mypassword'
|
|
assert_success
|
|
_wait_until_change_detection_event_completes
|
|
|
|
# Even if the Amavis port is reachable at this point, it may still refuse connections?
|
|
_wait_for_tcp_port_in_container 10024
|
|
_wait_for_smtp_port_in_container_to_respond
|
|
|
|
# see https://github.com/docker-mailserver/docker-mailserver/pull/3105#issuecomment-1441055103
|
|
# Amavis may still not be ready to receive mail, sleep a little to avoid connection failures:
|
|
sleep 5
|
|
|
|
### Send mail to queue for delivery ###
|
|
|
|
# TODO: Move to clamav tests (For use when ClamAV is enabled):
|
|
# _repeat_in_container_until_success_or_timeout 60 "${CONTAINER_NAME}" test -e /var/run/clamav/clamd.ctl
|
|
# _send_email --from 'virus@external.tld' --data 'amavis/virus.txt'
|
|
|
|
# Required for 'delivers mail to existing alias':
|
|
_send_email --to alias1@localhost.localdomain --header "Subject: Test Message existing-alias-external"
|
|
# Required for 'delivers mail to existing alias with recipient delimiter':
|
|
_send_email --to alias1~test@localhost.localdomain --header 'Subject: Test Message existing-alias-recipient-delimiter'
|
|
# Required for 'delivers mail to existing catchall':
|
|
_send_email --to wildcard@localdomain2.com --header 'Subject: Test Message existing-catchall-local'
|
|
# Required for 'delivers mail to regexp alias':
|
|
_send_email --to test123@localhost.localdomain --header 'Subject: Test Message existing-regexp-alias-local'
|
|
|
|
# Required for 'rejects mail to unknown user':
|
|
_send_email --expect-rejection --to nouser@localhost.localdomain
|
|
assert_failure
|
|
# Required for 'redirects mail to external aliases':
|
|
_send_email --to bounce-always@localhost.localdomain
|
|
_send_email --to alias2@localhost.localdomain
|
|
# Required for 'rejects spam':
|
|
_send_spam
|
|
|
|
# Required for 'delivers mail to existing account':
|
|
_send_email --header 'Subject: Test Message existing-user1'
|
|
_send_email --to user2@otherdomain.tld
|
|
_send_email --to user3@localhost.localdomain
|
|
_send_email --to added@localhost.localdomain --header 'Subject: Test Message existing-added'
|
|
_send_email \
|
|
--to user1@localhost.localdomain \
|
|
--header 'Subject: Test Message existing-user-and-cc-local-alias' \
|
|
--cc 'alias2@localhost.localdomain'
|
|
_send_email --data 'sieve/spam-folder.txt'
|
|
_send_email --to user2@otherdomain.tld --data 'sieve/pipe.txt'
|
|
_run_in_container_bash 'sendmail root < /tmp/docker-mailserver-test/emails/sendmail/root-email.txt'
|
|
assert_success
|
|
}
|
|
|
|
function _unsuccessful() {
|
|
_send_email --expect-rejection --port 465 --auth "${1}" --auth-user "${2}" --auth-password wrongpassword --quit-after AUTH
|
|
assert_failure
|
|
assert_output --partial 'authentication failed'
|
|
assert_output --partial 'No authentication type succeeded'
|
|
}
|
|
|
|
function _successful() {
|
|
_send_email --port 465 --auth "${1}" --auth-user "${2}" --auth-password mypassword --quit-after AUTH
|
|
assert_output --partial 'Authentication successful'
|
|
}
|
|
|
|
@test "should succeed at emptying mail queue" {
|
|
# Try catch errors preventing emptying the queue ahead of waiting:
|
|
_run_in_container mailq
|
|
# Amavis (Port 10024) may not have been ready when first mail was sent:
|
|
refute_output --partial 'Connection refused'
|
|
refute_output --partial '(unknown mail transport error)'
|
|
_wait_for_empty_mail_queue_in_container
|
|
}
|
|
|
|
@test "should successfully authenticate with good password (plain)" {
|
|
_successful PLAIN user1@localhost.localdomain
|
|
}
|
|
|
|
@test "should fail to authenticate with wrong password (plain)" {
|
|
_unsuccessful PLAIN user1@localhost.localdomain
|
|
}
|
|
|
|
@test "should successfully authenticate with good password (login)" {
|
|
_successful LOGIN user1@localhost.localdomain
|
|
}
|
|
|
|
@test "should fail to authenticate with wrong password (login)" {
|
|
_unsuccessful LOGIN user1@localhost.localdomain
|
|
}
|
|
|
|
@test "[user: 'added'] should successfully authenticate with good password (plain)" {
|
|
_successful PLAIN added@localhost.localdomain
|
|
}
|
|
|
|
@test "[user: 'added'] should fail to authenticate with wrong password (plain)" {
|
|
_unsuccessful PLAIN added@localhost.localdomain
|
|
}
|
|
|
|
@test "[user: 'added'] should successfully authenticate with good password (login)" {
|
|
_successful LOGIN added@localhost.localdomain
|
|
}
|
|
|
|
@test "[user: 'added'] should fail to authenticate with wrong password (login)" {
|
|
_unsuccessful LOGIN added@localhost.localdomain
|
|
}
|
|
|
|
# TODO: Add a test covering case SPAMASSASSIN_SPAM_TO_INBOX=1 (default)
|
|
@test "delivers mail to existing account" {
|
|
# NOTE: Matched log lines should look similar to:
|
|
# postfix/lmtp[1274]: 0EA424ABE7D9: to=<user1@localhost.localdomain>, relay=127.0.0.1[127.0.0.1]:24, delay=0.13, delays=0.07/0.01/0.01/0.05, dsn=2.0.0, status=sent (250 2.0.0 <user1@localhost.localdomain> ixPpB+Zvv2P7BAAAUi6ngw Saved)
|
|
local LOG_DELIVERED='postfix/lmtp.* status=sent .* Saved)'
|
|
local FORMAT_LINES="sed 's/.* to=</</g' | sed 's/, relay.*//g' | sort | uniq -c | tr -s ' '"
|
|
_run_in_container_bash "grep '${LOG_DELIVERED}' /var/log/mail/mail.log | ${FORMAT_LINES}"
|
|
assert_success
|
|
|
|
assert_output --partial '1 <added@localhost.localdomain>'
|
|
assert_output --partial '6 <user1@localhost.localdomain>'
|
|
assert_output --partial '1 <user1@localhost.localdomain>, orig_to=<root>'
|
|
assert_output --partial '1 <user1~test@localhost.localdomain>'
|
|
assert_output --partial '2 <user2@otherdomain.tld>'
|
|
assert_output --partial '1 <user3@localhost.localdomain>'
|
|
_should_output_number_of_lines 6
|
|
|
|
# NOTE: Requires ClamAV enabled and to send `amavis-virus` template:
|
|
# assert_output --partial '1 <user1@localhost.localdomain>, orig_to=<postmaster@example.test>'
|
|
# _should_output_number_of_lines 7
|
|
}
|
|
|
|
@test "delivers mail to existing alias" {
|
|
_service_log_should_contain_string 'mail' 'to=<user1@localhost.localdomain>, orig_to=<alias1@localhost.localdomain>'
|
|
assert_output --partial 'status=sent'
|
|
_should_output_number_of_lines 1
|
|
}
|
|
|
|
@test "delivers mail to existing alias with recipient delimiter" {
|
|
_service_log_should_contain_string 'mail' 'to=<user1~test@localhost.localdomain>, orig_to=<alias1~test@localhost.localdomain>'
|
|
assert_output --partial 'status=sent'
|
|
_should_output_number_of_lines 1
|
|
|
|
_service_log_should_contain_string 'mail' 'to=<user1~test@localhost.localdomain>'
|
|
refute_output --partial 'status=bounced'
|
|
}
|
|
|
|
@test "delivers mail to existing catchall" {
|
|
_service_log_should_contain_string 'mail' 'to=<user1@localhost.localdomain>, orig_to=<wildcard@localdomain2.com>'
|
|
assert_output --partial 'status=sent'
|
|
_should_output_number_of_lines 1
|
|
}
|
|
|
|
@test "delivers mail to regexp alias" {
|
|
_service_log_should_contain_string 'mail' 'to=<user1@localhost.localdomain>, orig_to=<test123@localhost.localdomain>'
|
|
assert_output --partial 'status=sent'
|
|
_should_output_number_of_lines 1
|
|
}
|
|
|
|
@test "user1 should have received 8 mails" {
|
|
_run_in_container_bash "grep Subject /var/mail/localhost.localdomain/user1/new/* | sed 's/.*Subject: //g' | sed 's/\.txt.*//g' | sed 's/VIRUS.*/VIRUS/g' | sort"
|
|
assert_success
|
|
|
|
assert_output --partial 'Root Test Message'
|
|
assert_output --partial 'Test Message existing-alias-external'
|
|
assert_output --partial 'Test Message existing-alias-recipient-delimiter'
|
|
assert_output --partial 'Test Message existing-catchall-local'
|
|
assert_output --partial 'Test Message existing-regexp-alias-local'
|
|
assert_output --partial 'Test Message existing-user-and-cc-local-alias'
|
|
assert_output --partial 'Test Message existing-user1'
|
|
assert_output --partial 'Test Message sieve-spam-folder'
|
|
_should_output_number_of_lines 8
|
|
|
|
# The virus mail has three subject lines
|
|
# NOTE: Requires ClamAV enabled and to send amavis-virus:
|
|
# assert_output --partial 'Test Message amavis-virus' # Should verify two lines expected with this content
|
|
# assert_output --partial 'VIRUS'
|
|
# _should_output_number_of_lines 11
|
|
}
|
|
|
|
@test "rejects mail to unknown user" {
|
|
_service_log_should_contain_string 'mail' '<nouser@localhost.localdomain>: Recipient address rejected: User unknown in virtual mailbox table'
|
|
_should_output_number_of_lines 1
|
|
}
|
|
|
|
@test "redirects mail to external aliases" {
|
|
_service_log_should_contain_string 'mail' 'Passed CLEAN {RelayedInbound}'
|
|
run bash -c "grep '<user@external.tld> -> <external1@otherdomain.tld>' <<< '${output}'"
|
|
_should_output_number_of_lines 2
|
|
# assert_output --partial 'external.tld=user@example.test> -> <external1@otherdomain.tld>'
|
|
}
|
|
|
|
# TODO: Add a test covering case SPAMASSASSIN_SPAM_TO_INBOX=1 (default)
|
|
@test "rejects spam" {
|
|
_service_log_should_contain_string 'mail' 'Blocked SPAM {NoBounceInbound,Quarantined}'
|
|
assert_output --partial '<spam@external.tld> -> <user1@localhost.localdomain>'
|
|
_should_output_number_of_lines 1
|
|
|
|
# Amavis log line with SPAMASSASSIN_SPAM_TO_INBOX=0 + grep 'Passed SPAM {RelayedTaggedInbound,Quarantined}' /var/log/mail/mail.log:
|
|
# Amavis log line with SPAMASSASSIN_SPAM_TO_INBOX=1 + grep 'Blocked SPAM {NoBounceInbound,Quarantined}' /var/log/mail/mail.log:
|
|
# <spam@external.tld> -> <user1@localhost.localdomain>
|
|
# Amavis log line with ENABLE_SRS=1 changes the domain-part to match in a log:
|
|
# <SRS0=g+ca=5C=external.tld=spam@example.test> -> <user1@localhost.localdomain>
|
|
# assert_output --partial 'external.tld=spam@example.test> -> <user1@localhost.localdomain>'
|
|
}
|
|
|
|
@test "SA - All registered domains should receive mail with spam headers (X-Spam)" {
|
|
_run_in_container grep -ir 'X-Spam-' /var/mail/localhost.localdomain/user1/new
|
|
assert_success
|
|
|
|
_run_in_container grep -ir 'X-Spam-' /var/mail/otherdomain.tld/user2/new
|
|
assert_success
|
|
}
|
|
|
|
# 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
|
|
@test "not advertising smtputf8" {
|
|
# Query supported extensions; SMTPUTF8 should not be available.
|
|
# - This query requires a EHLO greeting to the destination server.
|
|
_send_email \
|
|
--ehlo mail.external.tld \
|
|
--protocol ESMTP \
|
|
--server mail.example.test \
|
|
--quit-after FIRST-EHLO
|
|
|
|
# Ensure the output is actually related to what we want to refute against:
|
|
assert_output --partial 'EHLO mail.external.tld'
|
|
assert_output --partial '221 2.0.0 Bye'
|
|
refute_output --partial 'SMTPUTF8'
|
|
}
|
|
|
|
@test "mail for root was delivered" {
|
|
_run_in_container grep -R 'Subject: Root Test Message' /var/mail/localhost.localdomain/user1/new/
|
|
assert_success
|
|
}
|