From 72517d3f824859cb15a3ccc653ad8cc4bb1a4c32 Mon Sep 17 00:00:00 2001 From: Brennan Kinney <5098581+polarathene@users.noreply.github.com> Date: Tue, 26 Dec 2023 09:53:32 +1300 Subject: [PATCH 1/5] docs: Debugging - Delivery failure from service downtime (#3718) * docs: Debugging - Delivery failure from service downtime Services may be temporarily down, such as when restarted when certificates are updated due to the `check-for-changes.sh` service. This is another known source of intermittent delivery failures. --- CHANGELOG.md | 3 ++- docs/content/config/debugging.md | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fc60c05..7a260508 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,8 @@ All notable changes to this project will be documented in this file. The format ### Updates - **Documentation:** - - Raise awareness in the troubleshooting page for a common misconfiguration when deviating from our advice by using a bare domain ([#3680](https://github.com/docker-mailserver/docker-mailserver/pull/3680)) + - Debugging - Raise awareness in the troubleshooting page for a common misconfiguration when deviating from our advice by using a bare domain ([#3680](https://github.com/docker-mailserver/docker-mailserver/pull/3680)) + - Debugging - Raise awareness of temporary downtime during certificate renewal that can cause a failure to deliver local mail ([#3718](https://github.com/docker-mailserver/docker-mailserver/pull/3718)) - **Internal:** - Postfix configures `virtual_mailbox_maps` and `virtual_transport` during startup instead of using defaults (configured for Dovecot) via our `main.cf` ([#3681](https://github.com/docker-mailserver/docker-mailserver/pull/3681)) diff --git a/docs/content/config/debugging.md b/docs/content/config/debugging.md index 9c3bebb5..d58430e1 100644 --- a/docs/content/config/debugging.md +++ b/docs/content/config/debugging.md @@ -55,6 +55,8 @@ Common logs related to this are: If your logs look like this, you likely have [assigned the same FQDN to the DMS `hostname` and your mail accounts][gh-issues::dms-fqdn-misconfigured] which is not supported by default. You can either adjust your DMS `hostname` or follow [this FAQ advice][docs::faq-bare-domain] +It is also possible that [DMS services are temporarily unavailable][gh-issues::dms-services-unavailable] when configuration changes are detected, producing the 2nd error. Certificate updates may be a less obvious trigger. + ## Steps for Debugging DMS 1. **Increase log verbosity**: Very helpful for troubleshooting problems during container startup. Set the environment variable [`LOG_LEVEL`][docs-environment-log-level] to `debug` or `trace`. @@ -126,6 +128,7 @@ This could be from outdated software, or running a system that isn't able to pro [gh-issues]: https://github.com/docker-mailserver/docker-mailserver/issues [gh-issues::dms-fqdn-misconfigured]: https://github.com/docker-mailserver/docker-mailserver/issues/3679#issuecomment-1837609043 +[gh-issues::dms-services-unavailable]: https://github.com/docker-mailserver/docker-mailserver/issues/3679#issuecomment-1848083358 [gh-macos-support]: https://github.com/docker-mailserver/docker-mailserver/issues/3648#issuecomment-1822774080 [gh-discuss-roundcube-fail2ban]: https://github.com/orgs/docker-mailserver/discussions/3273#discussioncomment-5654603 From 8392e3c1a8db660e6fd458b1bf426ab4736104c4 Mon Sep 17 00:00:00 2001 From: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com> Date: Fri, 29 Dec 2023 13:58:54 +0100 Subject: [PATCH 2/5] release: v13.1.0 (#3720) Co-authored-by: Casper Co-authored-by: Brennan Kinney <5098581+polarathene@users.noreply.github.com> --- CHANGELOG.md | 4 ++++ VERSION | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a260508..32aaf78d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ All notable changes to this project will be documented in this file. The format > **Note**: Changes and additions listed here are contained in the `:edge` image tag. These changes may not be as stable as released changes. +## [v13.1.0](https://github.com/docker-mailserver/docker-mailserver/releases/tag/v13.1.0) + ### Added - **Dovecot:** @@ -22,6 +24,8 @@ All notable changes to this project will be documented in this file. The format - Debugging - Raise awareness of temporary downtime during certificate renewal that can cause a failure to deliver local mail ([#3718](https://github.com/docker-mailserver/docker-mailserver/pull/3718)) - **Internal:** - Postfix configures `virtual_mailbox_maps` and `virtual_transport` during startup instead of using defaults (configured for Dovecot) via our `main.cf` ([#3681](https://github.com/docker-mailserver/docker-mailserver/pull/3681)) +- **Rspamd:** + - Upgraded to version `3.7.5`. This was previously inconsistent between our AMD64 (`3.5`) and ARM64 (`3.4`) images ([#3686](https://github.com/docker-mailserver/docker-mailserver/pull/3686)) ### Fixed diff --git a/VERSION b/VERSION index 5cb7d856..e6ba3513 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -13.0.1 +13.1.0 From 0889b0ff063a37b482113a684d934e4bd728a33c Mon Sep 17 00:00:00 2001 From: Brennan Kinney <5098581+polarathene@users.noreply.github.com> Date: Sat, 30 Dec 2023 09:59:09 +1300 Subject: [PATCH 3/5] fix: `supervisor-app.conf` - Correct the log location for `postgrey` (#3724) * fix: `supervisor-app.conf` - Correct `postgrey` log location Looks like this should have been like every other service and reference a log file(s) based on program name in the supervisor log directory. * tests: Adjust log location for `postgrey_enabled.bats` --- CHANGELOG.md | 1 + target/supervisor/conf.d/supervisor-app.conf | 4 ++-- test/tests/parallel/set1/spam_virus/postgrey_enabled.bats | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32aaf78d..f37fded4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ All notable changes to this project will be documented in this file. The format - `VERSION` is no longer included in the image ([#3711](https://github.com/docker-mailserver/docker-mailserver/pull/3711)) - Update-check: fix 'read' exit status ([#3688](https://github.com/docker-mailserver/docker-mailserver/pull/3688)) - `ENABLE_QUOTAS=0` no longer tries to remove non-existent config ([#3715](https://github.com/docker-mailserver/docker-mailserver/pull/3715)) + - The `postgrey` service now writes logs to the supervisor directory like all other services. Previously this was `/var/log/mail/mail.log` ([#3724](https://github.com/docker-mailserver/docker-mailserver/pull/3724)) - **Rspamd:** - Switch to official arm64 packages to avoid segfaults ([#3686](https://github.com/docker-mailserver/docker-mailserver/pull/3686)) - **CI / Automation:** diff --git a/target/supervisor/conf.d/supervisor-app.conf b/target/supervisor/conf.d/supervisor-app.conf index 2dd8b917..431357d8 100644 --- a/target/supervisor/conf.d/supervisor-app.conf +++ b/target/supervisor/conf.d/supervisor-app.conf @@ -83,8 +83,8 @@ startsecs=0 stopwaitsecs=55 autostart=false autorestart=true -stdout_logfile=/var/log/mail/mail.log -stderr_logfile=/var/log/mail/mail.log +stdout_logfile=/var/log/supervisor/%(program_name)s.log +stderr_logfile=/var/log/supervisor/%(program_name)s.log command=/usr/sbin/postgrey --inet=127.0.0.1:10023 --syslog-facility=mail --delay="%(ENV_POSTGREY_DELAY)s" --max-age="%(ENV_POSTGREY_MAX_AGE)s" --auto-whitelist-clients="%(ENV_POSTGREY_AUTO_WHITELIST_CLIENTS)s" --greylist-text="%(ENV_POSTGREY_TEXT)s" [program:amavis] diff --git a/test/tests/parallel/set1/spam_virus/postgrey_enabled.bats b/test/tests/parallel/set1/spam_virus/postgrey_enabled.bats index d877a1ce..e32210ca 100644 --- a/test/tests/parallel/set1/spam_virus/postgrey_enabled.bats +++ b/test/tests/parallel/set1/spam_virus/postgrey_enabled.bats @@ -123,7 +123,7 @@ function _should_have_log_entry() { # Allow some extra time for logs to update to avoids a false-positive failure: _run_until_success_or_timeout 10 _exec_in_container grep \ "${ACTION}, ${REASON}," \ - /var/log/mail/mail.log + /var/log/supervisor/postgrey.log # Log entry matched should be for the expected triplet: assert_output --partial "${TRIPLET}" From 9e81517fe36d95597d3c8890f998bd7f9ea29aa7 Mon Sep 17 00:00:00 2001 From: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com> Date: Wed, 3 Jan 2024 01:17:54 +0100 Subject: [PATCH 4/5] tests: Use `swaks` instead of `nc` for sending mail (#3732) See associated `CHANGELOG.md` entry for details. --------- Co-authored-by: Brennan Kinney <5098581+polarathene@users.noreply.github.com> --- .gitattributes | 6 +- CHANGELOG.md | 7 ++ target/scripts/build/packages.sh | 2 +- .../auth/added-imap-auth.txt | 0 .../auth/added-pop3-auth.txt | 0 test/{test-files => files}/auth/imap-auth.txt | 0 .../auth/imap-ldap-auth.txt | 0 test/{test-files => files}/auth/pop3-auth.txt | 0 .../emails/amavis/spam.txt} | 9 +- .../emails/amavis/virus.txt} | 9 +- .../auth/added-smtp-auth-spoofed-alias.txt | 9 -- .../emails}/auth/added-smtp-auth-spoofed.txt | 9 -- .../auth/ldap-smtp-auth-spoofed-alias.txt | 10 --- ...h-spoofed-sender-with-filter-exception.txt | 10 --- .../emails}/auth/ldap-smtp-auth-spoofed.txt | 10 --- .../emails/existing/added.txt} | 7 -- .../emails/existing/alias-external.txt} | 7 -- .../emails/existing/alias-local.txt} | 7 -- .../existing/alias-recipient-delimiter.txt} | 7 -- .../emails/existing/catchall-local.txt} | 7 -- .../existing/regexp-alias-external.txt} | 7 -- .../emails/existing/regexp-alias-local.txt} | 7 -- .../existing/user-and-cc-local-alias.txt} | 7 -- .../emails/existing/user1.txt} | 7 -- .../emails/nc_raw/dsn/authenticated.txt} | 0 .../emails/nc_raw/dsn/unauthenticated.txt} | 0 .../emails/nc_raw}/postscreen.txt | 0 .../emails/nc_raw}/smtp-only.txt | 0 .../emails}/non-existing-user.txt | 7 -- .../emails}/postgrey.txt | 7 -- test/files/emails/postscreen.txt | 5 ++ .../emails/privacy.txt} | 9 -- .../emails}/quota-exceeded.txt | 7 -- .../emails/rspamd/pass.txt} | 9 +- .../emails/rspamd/spam-header.txt} | 7 -- .../emails/rspamd/spam.txt} | 7 -- .../emails/rspamd/virus.txt} | 7 -- .../emails/sendmail}/root-email.txt | 0 .../emails/sieve/pipe.txt} | 7 -- .../emails/sieve/spam-folder.txt} | 7 -- .../emails}/test-email.txt | 0 .../nc}/imap_special_use_folders.txt | 0 .../nc}/postgrey_whitelist.txt | 0 .../nc}/postgrey_whitelist_recipients.txt | 0 .../nc}/rspamd_imap_move_to_inbox.txt | 0 .../nc}/rspamd_imap_move_to_junk.txt | 0 .../ssl/custom-dhe-params.pem | 0 .../ssl/example.test/README.md | 0 .../ssl/example.test/cert.ecdsa.pem | 0 .../ssl/example.test/cert.rsa.pem | 0 .../ssl/example.test/key.ecdsa.pem | 0 .../ssl/example.test/key.rsa.pem | 0 .../ssl/example.test/testssl.txt | 0 .../ssl/example.test/traefik.md | 0 .../with_ca/ecdsa/ca-cert.ecdsa.pem | 0 .../with_ca/ecdsa/ca-key.ecdsa.pem | 0 .../example.test/with_ca/ecdsa/cert.ecdsa.pem | 0 .../example.test/with_ca/ecdsa/cert.rsa.pem | 0 .../with_ca/ecdsa/ecdsa.acme.json | 0 .../example.test/with_ca/ecdsa/key.ecdsa.pem | 0 .../example.test/with_ca/ecdsa/key.rsa.pem | 0 .../example.test/with_ca/ecdsa/rsa.acme.json | 0 .../with_ca/ecdsa/wildcard/cert.ecdsa.pem | 0 .../with_ca/ecdsa/wildcard/ecdsa.acme.json | 0 .../with_ca/ecdsa/wildcard/key.ecdsa.pem | 0 .../example.test/with_ca/rsa/ca-cert.rsa.pem | 0 .../example.test/with_ca/rsa/ca-key.rsa.pem | 0 .../example.test/with_ca/rsa/cert.ecdsa.pem | 0 .../ssl/example.test/with_ca/rsa/cert.rsa.pem | 0 .../example.test/with_ca/rsa/ecdsa.acme.json | 0 .../example.test/with_ca/rsa/key.ecdsa.pem | 0 .../ssl/example.test/with_ca/rsa/key.rsa.pem | 0 .../example.test/with_ca/rsa/rsa.acme.json | 0 .../with_ca/rsa/wildcard/cert.rsa.pem | 0 .../with_ca/rsa/wildcard/key.rsa.pem | 0 .../with_ca/rsa/wildcard/rsa.acme.json | 0 test/helper/common.bash | 14 +++ test/helper/sending.bash | 65 +++++++++----- test/helper/setup.bash | 2 +- .../auth/added-smtp-auth-login-wrong.txt | 4 - .../test-files/auth/added-smtp-auth-login.txt | 4 - .../auth/added-smtp-auth-plain-wrong.txt | 3 - .../test-files/auth/added-smtp-auth-plain.txt | 3 - test/test-files/auth/sasl-ldap-smtp-auth.txt | 5 -- .../test-files/auth/smtp-auth-login-wrong.txt | 4 - test/test-files/auth/smtp-auth-login.txt | 4 - .../test-files/auth/smtp-auth-plain-wrong.txt | 3 - test/test-files/auth/smtp-auth-plain.txt | 3 - .../email-templates/existing-user2.txt | 12 --- .../email-templates/existing-user3.txt | 12 --- test/test-files/email-templates/smtp-ehlo.txt | 2 - .../parallel/set1/dovecot/dovecot_quotas.bats | 9 +- .../parallel/set1/dovecot/dovecot_sieve.bats | 6 +- .../set1/dovecot/mailbox_format_dbox.bats | 6 +- .../set1/dovecot/special_use_folders.bats | 5 +- .../parallel/set1/spam_virus/clamav.bats | 13 +-- .../disabled_clamav_spamassassin.bats | 4 +- .../parallel/set1/spam_virus/fail2ban.bats | 13 ++- .../set1/spam_virus/postgrey_enabled.bats | 37 +++----- .../parallel/set1/spam_virus/postscreen.bats | 55 +++++------- .../parallel/set1/spam_virus/rspamd_full.bats | 12 +-- .../set1/spam_virus/spam_junk_folder.bats | 2 +- test/tests/parallel/set1/tls/dhparams.bats | 2 +- test/tests/parallel/set1/tls/letsencrypt.bats | 4 +- test/tests/parallel/set1/tls/manual.bats | 6 +- test/tests/parallel/set2/tls_cipherlists.bats | 2 +- .../container_configuration/hostname.bats | 2 +- test/tests/parallel/set3/mta/dsn.bats | 20 +++-- test/tests/parallel/set3/mta/lmtp_ip.bats | 2 +- test/tests/parallel/set3/mta/privacy.bats | 6 +- .../parallel/set3/mta/smtp_delivery.bats | 88 +++++++++++-------- test/tests/parallel/set3/mta/smtponly.bats | 11 ++- test/tests/serial/mail_pop3.bats | 6 +- test/tests/serial/mail_with_imap.bats | 28 ++++-- test/tests/serial/mail_with_ldap.bats | 57 +++++++++--- test/tests/serial/permit_docker.bats | 10 +-- test/tests/serial/test_helper.bats | 8 +- test/tests/serial/tests.bats | 31 ++++++- test/tests/serial/vmail-id.bats | 2 +- 119 files changed, 355 insertions(+), 455 deletions(-) rename test/{test-files => files}/auth/added-imap-auth.txt (100%) rename test/{test-files => files}/auth/added-pop3-auth.txt (100%) rename test/{test-files => files}/auth/imap-auth.txt (100%) rename test/{test-files => files}/auth/imap-ldap-auth.txt (100%) rename test/{test-files => files}/auth/pop3-auth.txt (100%) rename test/{test-files/email-templates/amavis-spam.txt => files/emails/amavis/spam.txt} (63%) rename test/{test-files/email-templates/amavis-virus.txt => files/emails/amavis/virus.txt} (83%) rename test/{test-files => files/emails}/auth/added-smtp-auth-spoofed-alias.txt (52%) rename test/{test-files => files/emails}/auth/added-smtp-auth-spoofed.txt (53%) rename test/{test-files => files/emails}/auth/ldap-smtp-auth-spoofed-alias.txt (57%) rename test/{test-files => files/emails}/auth/ldap-smtp-auth-spoofed-sender-with-filter-exception.txt (58%) rename test/{test-files => files/emails}/auth/ldap-smtp-auth-spoofed.txt (53%) rename test/{test-files/email-templates/existing-added.txt => files/emails/existing/added.txt} (67%) rename test/{test-files/email-templates/existing-alias-external.txt => files/emails/existing/alias-external.txt} (68%) rename test/{test-files/email-templates/existing-alias-local.txt => files/emails/existing/alias-local.txt} (68%) rename test/{test-files/email-templates/existing-alias-recipient-delimiter.txt => files/emails/existing/alias-recipient-delimiter.txt} (70%) rename test/{test-files/email-templates/existing-catchall-local.txt => files/emails/existing/catchall-local.txt} (68%) rename test/{test-files/email-templates/existing-regexp-alias-external.txt => files/emails/existing/regexp-alias-external.txt} (68%) rename test/{test-files/email-templates/existing-regexp-alias-local.txt => files/emails/existing/regexp-alias-local.txt} (68%) rename test/{test-files/email-templates/existing-user-and-cc-local-alias.txt => files/emails/existing/user-and-cc-local-alias.txt} (73%) rename test/{test-files/email-templates/existing-user1.txt => files/emails/existing/user1.txt} (67%) rename test/{test-files/email-templates/dsn-authenticated.txt => files/emails/nc_raw/dsn/authenticated.txt} (100%) rename test/{test-files/email-templates/dsn-unauthenticated.txt => files/emails/nc_raw/dsn/unauthenticated.txt} (100%) rename test/{test-files/email-templates => files/emails/nc_raw}/postscreen.txt (100%) rename test/{test-files/email-templates => files/emails/nc_raw}/smtp-only.txt (100%) rename test/{test-files/email-templates => files/emails}/non-existing-user.txt (67%) rename test/{test-files/email-templates => files/emails}/postgrey.txt (66%) create mode 100644 test/files/emails/postscreen.txt rename test/{test-files/email-templates/send-privacy-email.txt => files/emails/privacy.txt} (61%) rename test/{test-files/email-templates => files/emails}/quota-exceeded.txt (98%) rename test/{test-files/email-templates/rspamd-pass.txt => files/emails/rspamd/pass.txt} (57%) rename test/{test-files/email-templates/rspamd-spam-header.txt => files/emails/rspamd/spam-header.txt} (70%) rename test/{test-files/email-templates/rspamd-spam.txt => files/emails/rspamd/spam.txt} (70%) rename test/{test-files/email-templates/rspamd-virus.txt => files/emails/rspamd/virus.txt} (70%) rename test/{test-files/email-templates => files/emails/sendmail}/root-email.txt (100%) rename test/{test-files/email-templates/sieve-pipe.txt => files/emails/sieve/pipe.txt} (67%) rename test/{test-files/email-templates/sieve-spam-folder.txt => files/emails/sieve/spam-folder.txt} (64%) rename test/{test-files/email-templates => files/emails}/test-email.txt (100%) rename test/{test-files/nc_templates => files/nc}/imap_special_use_folders.txt (100%) rename test/{test-files/nc_templates => files/nc}/postgrey_whitelist.txt (100%) rename test/{test-files/nc_templates => files/nc}/postgrey_whitelist_recipients.txt (100%) rename test/{test-files/nc_templates => files/nc}/rspamd_imap_move_to_inbox.txt (100%) rename test/{test-files/nc_templates => files/nc}/rspamd_imap_move_to_junk.txt (100%) rename test/{test-files => files}/ssl/custom-dhe-params.pem (100%) rename test/{test-files => files}/ssl/example.test/README.md (100%) rename test/{test-files => files}/ssl/example.test/cert.ecdsa.pem (100%) rename test/{test-files => files}/ssl/example.test/cert.rsa.pem (100%) rename test/{test-files => files}/ssl/example.test/key.ecdsa.pem (100%) rename test/{test-files => files}/ssl/example.test/key.rsa.pem (100%) rename test/{test-files => files}/ssl/example.test/testssl.txt (100%) rename test/{test-files => files}/ssl/example.test/traefik.md (100%) rename test/{test-files => files}/ssl/example.test/with_ca/ecdsa/ca-cert.ecdsa.pem (100%) rename test/{test-files => files}/ssl/example.test/with_ca/ecdsa/ca-key.ecdsa.pem (100%) rename test/{test-files => files}/ssl/example.test/with_ca/ecdsa/cert.ecdsa.pem (100%) rename test/{test-files => files}/ssl/example.test/with_ca/ecdsa/cert.rsa.pem (100%) rename test/{test-files => files}/ssl/example.test/with_ca/ecdsa/ecdsa.acme.json (100%) rename test/{test-files => files}/ssl/example.test/with_ca/ecdsa/key.ecdsa.pem (100%) rename test/{test-files => files}/ssl/example.test/with_ca/ecdsa/key.rsa.pem (100%) rename test/{test-files => files}/ssl/example.test/with_ca/ecdsa/rsa.acme.json (100%) rename test/{test-files => files}/ssl/example.test/with_ca/ecdsa/wildcard/cert.ecdsa.pem (100%) rename test/{test-files => files}/ssl/example.test/with_ca/ecdsa/wildcard/ecdsa.acme.json (100%) rename test/{test-files => files}/ssl/example.test/with_ca/ecdsa/wildcard/key.ecdsa.pem (100%) rename test/{test-files => files}/ssl/example.test/with_ca/rsa/ca-cert.rsa.pem (100%) rename test/{test-files => files}/ssl/example.test/with_ca/rsa/ca-key.rsa.pem (100%) rename test/{test-files => files}/ssl/example.test/with_ca/rsa/cert.ecdsa.pem (100%) rename test/{test-files => files}/ssl/example.test/with_ca/rsa/cert.rsa.pem (100%) rename test/{test-files => files}/ssl/example.test/with_ca/rsa/ecdsa.acme.json (100%) rename test/{test-files => files}/ssl/example.test/with_ca/rsa/key.ecdsa.pem (100%) rename test/{test-files => files}/ssl/example.test/with_ca/rsa/key.rsa.pem (100%) rename test/{test-files => files}/ssl/example.test/with_ca/rsa/rsa.acme.json (100%) rename test/{test-files => files}/ssl/example.test/with_ca/rsa/wildcard/cert.rsa.pem (100%) rename test/{test-files => files}/ssl/example.test/with_ca/rsa/wildcard/key.rsa.pem (100%) rename test/{test-files => files}/ssl/example.test/with_ca/rsa/wildcard/rsa.acme.json (100%) delete mode 100644 test/test-files/auth/added-smtp-auth-login-wrong.txt delete mode 100644 test/test-files/auth/added-smtp-auth-login.txt delete mode 100644 test/test-files/auth/added-smtp-auth-plain-wrong.txt delete mode 100644 test/test-files/auth/added-smtp-auth-plain.txt delete mode 100644 test/test-files/auth/sasl-ldap-smtp-auth.txt delete mode 100644 test/test-files/auth/smtp-auth-login-wrong.txt delete mode 100644 test/test-files/auth/smtp-auth-login.txt delete mode 100644 test/test-files/auth/smtp-auth-plain-wrong.txt delete mode 100644 test/test-files/auth/smtp-auth-plain.txt delete mode 100644 test/test-files/email-templates/existing-user2.txt delete mode 100644 test/test-files/email-templates/existing-user3.txt delete mode 100644 test/test-files/email-templates/smtp-ehlo.txt diff --git a/.gitattributes b/.gitattributes index d3dba13d..869c153e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -10,7 +10,7 @@ *.yml text ### Documentation (Project, Tests, Docs site) *.md text -### TLS certs (test/test-files/) + DHE params (target/shared/) +### TLS certs (test/files/) + DHE params (target/shared/) *.pem text *.pem.sha512sum text @@ -90,9 +90,9 @@ TrustedHosts text whitelist_recipients text ## MISC -### test/config/ + test/test-files/ +### test/config/ + test/files/ *.txt text -### test/linting/ (.ecrc.json) + test/test-files/ (*.acme.json): +### test/linting/ (.ecrc.json) + test/files/ (*.acme.json): *.json text ################################################# diff --git a/CHANGELOG.md b/CHANGELOG.md index f37fded4..eeeb843d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,13 @@ All notable changes to this project will be documented in this file. The format > **Note**: Changes and additions listed here are contained in the `:edge` image tag. These changes may not be as stable as released changes. +### Updates + +- The test suite now uses `swaks` instead of `nc`, which has multiple benefits ([#3732](https://github.com/docker-mailserver/docker-mailserver/pull/3732)): + - `swaks` handles pipelining correctly, hence we can now use `reject_unauth_pipelining` in Postfix's configuration. + - `swaks` provides better CLI options that make many files superflous. + - `swaks` can also replace `openssl s_client` and handles authentication on submission ports better. + ## [v13.1.0](https://github.com/docker-mailserver/docker-mailserver/releases/tag/v13.1.0) ### Added diff --git a/target/scripts/build/packages.sh b/target/scripts/build/packages.sh index ec468d41..566d5441 100644 --- a/target/scripts/build/packages.sh +++ b/target/scripts/build/packages.sh @@ -80,7 +80,7 @@ function _install_packages() { # `bind9-dnsutils` provides the `dig` command # `iputils-ping` provides the `ping` command DEBUG_PACKAGES=( - bind9-dnsutils iputils-ping less nano + bind9-dnsutils iputils-ping less nano swaks ) apt-get "${QUIET}" --no-install-recommends install \ diff --git a/test/test-files/auth/added-imap-auth.txt b/test/files/auth/added-imap-auth.txt similarity index 100% rename from test/test-files/auth/added-imap-auth.txt rename to test/files/auth/added-imap-auth.txt diff --git a/test/test-files/auth/added-pop3-auth.txt b/test/files/auth/added-pop3-auth.txt similarity index 100% rename from test/test-files/auth/added-pop3-auth.txt rename to test/files/auth/added-pop3-auth.txt diff --git a/test/test-files/auth/imap-auth.txt b/test/files/auth/imap-auth.txt similarity index 100% rename from test/test-files/auth/imap-auth.txt rename to test/files/auth/imap-auth.txt diff --git a/test/test-files/auth/imap-ldap-auth.txt b/test/files/auth/imap-ldap-auth.txt similarity index 100% rename from test/test-files/auth/imap-ldap-auth.txt rename to test/files/auth/imap-ldap-auth.txt diff --git a/test/test-files/auth/pop3-auth.txt b/test/files/auth/pop3-auth.txt similarity index 100% rename from test/test-files/auth/pop3-auth.txt rename to test/files/auth/pop3-auth.txt diff --git a/test/test-files/email-templates/amavis-spam.txt b/test/files/emails/amavis/spam.txt similarity index 63% rename from test/test-files/email-templates/amavis-spam.txt rename to test/files/emails/amavis/spam.txt index 66be1df3..e8d26138 100644 --- a/test/test-files/email-templates/amavis-spam.txt +++ b/test/files/emails/amavis/spam.txt @@ -1,13 +1,6 @@ -HELO mail.external.tld -MAIL FROM: spam@external.tld -RCPT TO: user1@localhost.localdomain -DATA From: Docker Mail Server To: Existing Local User Date: Sat, 22 May 2010 07:43:25 -0400 -Subject: Test Message amavis-spam.txt +Subject: Test Message amavis/spam.txt This is a test mail. XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X - -. -QUIT diff --git a/test/test-files/email-templates/amavis-virus.txt b/test/files/emails/amavis/virus.txt similarity index 83% rename from test/test-files/email-templates/amavis-virus.txt rename to test/files/emails/amavis/virus.txt index 1343a07c..2c47dcad 100644 --- a/test/test-files/email-templates/amavis-virus.txt +++ b/test/files/emails/amavis/virus.txt @@ -1,11 +1,7 @@ -HELO mail.external.tld -MAIL FROM: virus@external.tld -RCPT TO: user1@localhost.localdomain -DATA From: Docker Mail Server To: Existing Local User Date: Sat, 22 May 2010 07:43:25 -0400 -Subject: Test Message amavis-virus.txt +Subject: Test Message amavis/virus.txt Content-type: multipart/mixed; boundary="emailboundary" MIME-version: 1.0 @@ -27,6 +23,3 @@ ACAA/4EAAAAAZWljYXIuY29tUEsFBgAAAAABAAEANwAAAGsAAAAAAA== --emailboundary-- - -. -QUIT diff --git a/test/test-files/auth/added-smtp-auth-spoofed-alias.txt b/test/files/emails/auth/added-smtp-auth-spoofed-alias.txt similarity index 52% rename from test/test-files/auth/added-smtp-auth-spoofed-alias.txt rename to test/files/emails/auth/added-smtp-auth-spoofed-alias.txt index 48145183..eeb68ac8 100644 --- a/test/test-files/auth/added-smtp-auth-spoofed-alias.txt +++ b/test/files/emails/auth/added-smtp-auth-spoofed-alias.txt @@ -1,14 +1,5 @@ -EHLO mail -AUTH LOGIN dXNlcjFAbG9jYWxob3N0LmxvY2FsZG9tYWlu -bXlwYXNzd29yZA== -MAIL FROM: alias1@localhost.localdomain -RCPT TO: user1@localhost.localdomain -DATA From: user1_alias To: Existing Local User Date: Sat, 22 May 2010 07:43:25 -0400 Subject: Test Message This is a test mail. - -. -QUIT diff --git a/test/test-files/auth/added-smtp-auth-spoofed.txt b/test/files/emails/auth/added-smtp-auth-spoofed.txt similarity index 53% rename from test/test-files/auth/added-smtp-auth-spoofed.txt rename to test/files/emails/auth/added-smtp-auth-spoofed.txt index 279b6c0e..fd96d401 100644 --- a/test/test-files/auth/added-smtp-auth-spoofed.txt +++ b/test/files/emails/auth/added-smtp-auth-spoofed.txt @@ -1,14 +1,5 @@ -EHLO mail -AUTH LOGIN YWRkZWRAbG9jYWxob3N0LmxvY2FsZG9tYWlu -bXlwYXNzd29yZA== -MAIL FROM: user2@localhost.localdomain -RCPT TO: user1@localhost.localdomain -DATA From: Not_My_Business To: Existing Local User Date: Sat, 22 May 2010 07:43:25 -0400 Subject: Test Message This is a test mail. - -. -QUIT diff --git a/test/test-files/auth/ldap-smtp-auth-spoofed-alias.txt b/test/files/emails/auth/ldap-smtp-auth-spoofed-alias.txt similarity index 57% rename from test/test-files/auth/ldap-smtp-auth-spoofed-alias.txt rename to test/files/emails/auth/ldap-smtp-auth-spoofed-alias.txt index 007b0f99..7453675c 100644 --- a/test/test-files/auth/ldap-smtp-auth-spoofed-alias.txt +++ b/test/files/emails/auth/ldap-smtp-auth-spoofed-alias.txt @@ -1,15 +1,5 @@ -EHLO mail -AUTH LOGIN -c29tZS51c2VyQGxvY2FsaG9zdC5sb2NhbGRvbWFpbg== -c2VjcmV0 -MAIL FROM: postmaster@localhost.localdomain -RCPT TO: some.user@localhost.localdomain -DATA From: alias_address To: Existing Local User Date: Sat, 22 May 2010 07:43:25 -0400 Subject: Test Message This is a test mail from ldap-smtp-auth-spoofed-alias.txt - -. -QUIT diff --git a/test/test-files/auth/ldap-smtp-auth-spoofed-sender-with-filter-exception.txt b/test/files/emails/auth/ldap-smtp-auth-spoofed-sender-with-filter-exception.txt similarity index 58% rename from test/test-files/auth/ldap-smtp-auth-spoofed-sender-with-filter-exception.txt rename to test/files/emails/auth/ldap-smtp-auth-spoofed-sender-with-filter-exception.txt index bc0447af..3b500bf6 100644 --- a/test/test-files/auth/ldap-smtp-auth-spoofed-sender-with-filter-exception.txt +++ b/test/files/emails/auth/ldap-smtp-auth-spoofed-sender-with-filter-exception.txt @@ -1,15 +1,5 @@ -EHLO mail -AUTH LOGIN -c29tZS51c2VyLmVtYWlsQGxvY2FsaG9zdC5sb2NhbGRvbWFpbgo= -c2VjcmV0 -MAIL FROM: randomspoofedaddress@localhost.localdomain -RCPT TO: some.user@localhost.localdomain -DATA From: spoofed_address To: Existing Local User Date: Sat, 22 May 2010 07:43:25 -0400 Subject: Test Message This is a test mail from ldap-smtp-auth-spoofed-sender-with-filter-exception.txt - -. -QUIT diff --git a/test/test-files/auth/ldap-smtp-auth-spoofed.txt b/test/files/emails/auth/ldap-smtp-auth-spoofed.txt similarity index 53% rename from test/test-files/auth/ldap-smtp-auth-spoofed.txt rename to test/files/emails/auth/ldap-smtp-auth-spoofed.txt index cc0b164d..83193e17 100644 --- a/test/test-files/auth/ldap-smtp-auth-spoofed.txt +++ b/test/files/emails/auth/ldap-smtp-auth-spoofed.txt @@ -1,15 +1,5 @@ -EHLO mail -AUTH LOGIN -c29tZS51c2VyQGxvY2FsaG9zdC5sb2NhbGRvbWFpbg== -c2VjcmV0 -MAIL FROM: ldap@localhost.localdomain -RCPT TO: user1@localhost.localdomain -DATA From: forged_address To: Existing Local User Date: Sat, 22 May 2010 07:43:25 -0400 Subject: Test Message This is a test mail. - -. -QUIT diff --git a/test/test-files/email-templates/existing-added.txt b/test/files/emails/existing/added.txt similarity index 67% rename from test/test-files/email-templates/existing-added.txt rename to test/files/emails/existing/added.txt index 320fa4d2..827b681f 100644 --- a/test/test-files/email-templates/existing-added.txt +++ b/test/files/emails/existing/added.txt @@ -1,12 +1,5 @@ -HELO mail.external.tld -MAIL FROM: user@external.tld -RCPT TO: added@localhost.localdomain -DATA From: Docker Mail Server To: Existing Local User Date: Sat, 22 May 2010 07:43:25 -0400 Subject: Test Message existing-added.txt This is a test mail. - -. -QUIT diff --git a/test/test-files/email-templates/existing-alias-external.txt b/test/files/emails/existing/alias-external.txt similarity index 68% rename from test/test-files/email-templates/existing-alias-external.txt rename to test/files/emails/existing/alias-external.txt index 61b1df3c..03f1af6c 100644 --- a/test/test-files/email-templates/existing-alias-external.txt +++ b/test/files/emails/existing/alias-external.txt @@ -1,12 +1,5 @@ -HELO mail.external.tld -MAIL FROM: user@external.tld -RCPT TO: alias1@localhost.localdomain -DATA From: Docker Mail Server To: Existing Local User Date: Sat, 22 May 2010 07:43:25 -0400 Subject: Test Message existing-alias-external.txt This is a test mail. - -. -QUIT diff --git a/test/test-files/email-templates/existing-alias-local.txt b/test/files/emails/existing/alias-local.txt similarity index 68% rename from test/test-files/email-templates/existing-alias-local.txt rename to test/files/emails/existing/alias-local.txt index c1bbc890..9b481a98 100644 --- a/test/test-files/email-templates/existing-alias-local.txt +++ b/test/files/emails/existing/alias-local.txt @@ -1,12 +1,5 @@ -HELO mail.external.tld -MAIL FROM: user@external.tld -RCPT TO: alias2@localhost.localdomain -DATA From: Docker Mail Server To: Existing Local Alias Date: Sat, 22 May 2010 07:43:25 -0400 Subject: Test Message existing-alias-local.txt This is a test mail. - -. -QUIT diff --git a/test/test-files/email-templates/existing-alias-recipient-delimiter.txt b/test/files/emails/existing/alias-recipient-delimiter.txt similarity index 70% rename from test/test-files/email-templates/existing-alias-recipient-delimiter.txt rename to test/files/emails/existing/alias-recipient-delimiter.txt index 47b01397..07cb8d40 100644 --- a/test/test-files/email-templates/existing-alias-recipient-delimiter.txt +++ b/test/files/emails/existing/alias-recipient-delimiter.txt @@ -1,12 +1,5 @@ -HELO mail.external.tld -MAIL FROM: user@external.tld -RCPT TO: alias1~test@localhost.localdomain -DATA From: Docker Mail Server To: Existing Local Alias With Delimiter Date: Sat, 22 May 2010 07:43:25 -0400 Subject: Test Message existing-alias-recipient-delimiter.txt This is a test mail. - -. -QUIT diff --git a/test/test-files/email-templates/existing-catchall-local.txt b/test/files/emails/existing/catchall-local.txt similarity index 68% rename from test/test-files/email-templates/existing-catchall-local.txt rename to test/files/emails/existing/catchall-local.txt index c80db170..ab3e1988 100644 --- a/test/test-files/email-templates/existing-catchall-local.txt +++ b/test/files/emails/existing/catchall-local.txt @@ -1,12 +1,5 @@ -HELO mail.external.tld -MAIL FROM: user@external.tld -RCPT TO: wildcard@localdomain2.com -DATA From: Docker Mail Server To: Existing Local User Date: Sat, 22 May 2010 07:43:25 -0400 Subject: Test Message existing-catchall-local.txt This is a test mail. - -. -QUIT diff --git a/test/test-files/email-templates/existing-regexp-alias-external.txt b/test/files/emails/existing/regexp-alias-external.txt similarity index 68% rename from test/test-files/email-templates/existing-regexp-alias-external.txt rename to test/files/emails/existing/regexp-alias-external.txt index 0e214db4..b50ac90f 100644 --- a/test/test-files/email-templates/existing-regexp-alias-external.txt +++ b/test/files/emails/existing/regexp-alias-external.txt @@ -1,12 +1,5 @@ -HELO mail.external.tld -MAIL FROM: user@external.tld -RCPT TO: bounce-always@localhost.localdomain -DATA From: Docker Mail Server To: Existing Local User Date: Sat, 22 May 2010 07:43:25 -0400 Subject: Test Message existing-regexp-alias-external.txt This is a test mail. - -. -QUIT diff --git a/test/test-files/email-templates/existing-regexp-alias-local.txt b/test/files/emails/existing/regexp-alias-local.txt similarity index 68% rename from test/test-files/email-templates/existing-regexp-alias-local.txt rename to test/files/emails/existing/regexp-alias-local.txt index 6af46e92..e45b7c6c 100644 --- a/test/test-files/email-templates/existing-regexp-alias-local.txt +++ b/test/files/emails/existing/regexp-alias-local.txt @@ -1,12 +1,5 @@ -HELO mail.external.tld -MAIL FROM: user@external.tld -RCPT TO: test123@localhost.localdomain -DATA From: Docker Mail Server To: Existing Local User Date: Sat, 22 May 2010 07:43:25 -0400 Subject: Test Message existing-regexp-alias-local.txt This is a test mail. - -. -QUIT diff --git a/test/test-files/email-templates/existing-user-and-cc-local-alias.txt b/test/files/emails/existing/user-and-cc-local-alias.txt similarity index 73% rename from test/test-files/email-templates/existing-user-and-cc-local-alias.txt rename to test/files/emails/existing/user-and-cc-local-alias.txt index 5fcb333b..37814f91 100644 --- a/test/test-files/email-templates/existing-user-and-cc-local-alias.txt +++ b/test/files/emails/existing/user-and-cc-local-alias.txt @@ -1,13 +1,6 @@ -HELO mail.external.tld -MAIL FROM: user@external.tld -RCPT TO: user1@localhost.localdomain -DATA From: Docker Mail Server To: Existing Local User Cc: Existing Local Alias Date: Sat, 22 May 2010 07:43:25 -0400 Subject: Test Message existing-user-and-cc-local-alias.txt This is a test mail. - -. -QUIT diff --git a/test/test-files/email-templates/existing-user1.txt b/test/files/emails/existing/user1.txt similarity index 67% rename from test/test-files/email-templates/existing-user1.txt rename to test/files/emails/existing/user1.txt index 5ab0333f..23d49dc9 100644 --- a/test/test-files/email-templates/existing-user1.txt +++ b/test/files/emails/existing/user1.txt @@ -1,12 +1,5 @@ -HELO mail.external.tld -MAIL FROM: user@external.tld -RCPT TO: user1@localhost.localdomain -DATA From: Docker Mail Server To: Existing Local User Date: Sat, 22 May 2010 07:43:25 -0400 Subject: Test Message existing-user1.txt This is a test mail. - -. -QUIT diff --git a/test/test-files/email-templates/dsn-authenticated.txt b/test/files/emails/nc_raw/dsn/authenticated.txt similarity index 100% rename from test/test-files/email-templates/dsn-authenticated.txt rename to test/files/emails/nc_raw/dsn/authenticated.txt diff --git a/test/test-files/email-templates/dsn-unauthenticated.txt b/test/files/emails/nc_raw/dsn/unauthenticated.txt similarity index 100% rename from test/test-files/email-templates/dsn-unauthenticated.txt rename to test/files/emails/nc_raw/dsn/unauthenticated.txt diff --git a/test/test-files/email-templates/postscreen.txt b/test/files/emails/nc_raw/postscreen.txt similarity index 100% rename from test/test-files/email-templates/postscreen.txt rename to test/files/emails/nc_raw/postscreen.txt diff --git a/test/test-files/email-templates/smtp-only.txt b/test/files/emails/nc_raw/smtp-only.txt similarity index 100% rename from test/test-files/email-templates/smtp-only.txt rename to test/files/emails/nc_raw/smtp-only.txt diff --git a/test/test-files/email-templates/non-existing-user.txt b/test/files/emails/non-existing-user.txt similarity index 67% rename from test/test-files/email-templates/non-existing-user.txt rename to test/files/emails/non-existing-user.txt index 406f6755..3d92470e 100644 --- a/test/test-files/email-templates/non-existing-user.txt +++ b/test/files/emails/non-existing-user.txt @@ -1,12 +1,5 @@ -HELO mail.external.tld -MAIL FROM: user@external.tld -RCPT TO: nouser@localhost.localdomain -DATA From: Docker Mail Server To: Existing Local User Date: Sat, 22 May 2010 07:43:25 -0400 Subject: Test Message non-existing-user.txt This is a test mail. - -. -QUIT diff --git a/test/test-files/email-templates/postgrey.txt b/test/files/emails/postgrey.txt similarity index 66% rename from test/test-files/email-templates/postgrey.txt rename to test/files/emails/postgrey.txt index 33a3b153..cdfe8f93 100644 --- a/test/test-files/email-templates/postgrey.txt +++ b/test/files/emails/postgrey.txt @@ -1,12 +1,5 @@ -HELO mail.external.tld -MAIL FROM: user@external.tld -RCPT TO: user1@localhost.localdomain -DATA From: Docker Mail Server To: Existing Local User Date: Sat, 22 May 2010 07:43:25 -0400 Subject: Postgrey Test Message This is a test mail. - -. -QUIT diff --git a/test/files/emails/postscreen.txt b/test/files/emails/postscreen.txt new file mode 100644 index 00000000..732ac897 --- /dev/null +++ b/test/files/emails/postscreen.txt @@ -0,0 +1,5 @@ +From: Docker Mail Server +To: Existing Local User +Date: Sat, 22 May 2010 07:43:25 -0400 +Subject: Test Message postscreen.txt +This is a test mail for postscreen. diff --git a/test/test-files/email-templates/send-privacy-email.txt b/test/files/emails/privacy.txt similarity index 61% rename from test/test-files/email-templates/send-privacy-email.txt rename to test/files/emails/privacy.txt index 0c51ec5b..1d3a1b96 100644 --- a/test/test-files/email-templates/send-privacy-email.txt +++ b/test/files/emails/privacy.txt @@ -1,15 +1,6 @@ -EHLO mail -AUTH LOGIN dXNlcjFAbG9jYWxob3N0LmxvY2FsZG9tYWlu -bXlwYXNzd29yZA== -mail from: -rcpt to: -data From: Some User To: Some User User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:52.0) Gecko/20100101 Thunderbird/52.2.1 Subject: Test ESMTP Auth LOGIN and remove privacy This is a test mail. - -. -QUIT diff --git a/test/test-files/email-templates/quota-exceeded.txt b/test/files/emails/quota-exceeded.txt similarity index 98% rename from test/test-files/email-templates/quota-exceeded.txt rename to test/files/emails/quota-exceeded.txt index 71d221a1..c5281637 100644 --- a/test/test-files/email-templates/quota-exceeded.txt +++ b/test/files/emails/quota-exceeded.txt @@ -1,7 +1,3 @@ -HELO mail.external.tld -MAIL FROM: user@external.tld -RCPT TO: quotauser@otherdomain.tld -DATA From: Docker Mail Server To: Existing Local User Date: Sat, 22 May 2010 07:43:25 -0400 @@ -20,6 +16,3 @@ Et voluptatum nobis ut odio voluptatem et quibusdam fugit ut libero sapiente vel Sit sint obcaecati et reiciendis tenetur aut dolorum culpa. Ab veritatis maxime qui necessitatibus facilis eum voluptate asperiores non totam omnis. Nam modi officia in reiciendis odit sit rerum laudantium est rerum voluptatem ut fugit cupiditate! Sit atque sint aut delectus omnis ut asperiores enim quo reprehenderit quae! In quasi nemo ut error totam ut quia harum ut commodi tenetur? Non quod dolorum eum explicabo labore vel asperiores quas est perferendis nulla eum nemo tenetur. Ut libero blanditiis ex voluptatibus repudiandae ab reiciendis nemo id debitis impedit hic quia incidunt sed quam excepturi ut magnam odit. Qui dolor deleniti aut sunt voluptas aut blanditiis distinctio nam omnis deleniti hic omnis rerum eum magni voluptatem. Nam labore facere eum molestiae dolorum ea consectetur praesentium ut cupiditate iste ad magnam aut neque maiores! Et excepturi ducimus ut nemo voluptas eum voluptas nihil hic perferendis quos vel quasi nesciunt est praesentium dolore hic quia quis. Et maxime ducimus ea cupiditate voluptatem ad quia dolores! Sed quos quaerat vel aperiam minus non sapiente quia ut ratione dolore eum officiis rerum. Non dolor vitae qui facilis dignissimos aut voluptate odit et ullam consequuntur. Et laudantium perspiciatis sit nisi temporibus a temporibus itaque ut iure dolor a voluptatum mollitia eos officia nobis et quibusdam voluptas. Amet eligendi eos nulla corporis et blanditiis nihil vel eveniet veritatis et sunt perferendis id molestiae eius! Quo harum quod aut nemo autem ut adipisci sint sed quia sunt. Aut voluptas error ut quae perferendis eos adipisci internos. Nam rerum fugiat aut minima nostrum quo repellendus quas exercitationem tenetur. Et molestiae architecto id quibusdam reprehenderit et magnam aliquam! Quo tempora veritatis At dolorem sint ex nulla blanditiis At voluptas laudantium est molestiae exercitationem et sequi voluptates aut ipsa atque. Et animi ipsum aut atque recusandae ea nemo ullam non quisquam quos sit libero sint vel libero delectus. Eos labore quidem a velit obcaecati nam explicabo consequatur eos maxime blanditiis? Et ipsam molestiae non quia explicabo ex galisum repudiandae et tempora veniam. Sed optio repellendus ut consequatur temporibus et harum quas hic ipsa officia? Aut dolores ipsum sit nulla dignissimos id quia perferendis aut dolores dolor et quibusdam porro aut Quis consequatur. - -. -QUIT diff --git a/test/test-files/email-templates/rspamd-pass.txt b/test/files/emails/rspamd/pass.txt similarity index 57% rename from test/test-files/email-templates/rspamd-pass.txt rename to test/files/emails/rspamd/pass.txt index 0f244740..ce9286b1 100644 --- a/test/test-files/email-templates/rspamd-pass.txt +++ b/test/files/emails/rspamd/pass.txt @@ -1,12 +1,5 @@ -HELO mail.external.tld -MAIL FROM: pass@example.test -RCPT TO: user1@localhost.localdomain -DATA From: Docker Mail Server To: Existing Local User Date: Sat, 22 May 2010 07:43:25 -0400 -Subject: Test Message rspamd-pass.txt +Subject: Test Message rspamd/pass.txt This mail should pass and Rspamd should not mark it. - -. -QUIT diff --git a/test/test-files/email-templates/rspamd-spam-header.txt b/test/files/emails/rspamd/spam-header.txt similarity index 70% rename from test/test-files/email-templates/rspamd-spam-header.txt rename to test/files/emails/rspamd/spam-header.txt index 7be1a56d..8722e42f 100644 --- a/test/test-files/email-templates/rspamd-spam-header.txt +++ b/test/files/emails/rspamd/spam-header.txt @@ -1,12 +1,5 @@ -HELO mail.example.test -MAIL FROM: spam-header@example.test -RCPT TO: user1@localhost.localdomain -DATA From: Docker Mail Server To: Existing Local User Date: Sat, 21 Jan 2023 11:11:11 +0000 Subject: Test Message rspamd-spam-header.txt YJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X - -. -QUIT diff --git a/test/test-files/email-templates/rspamd-spam.txt b/test/files/emails/rspamd/spam.txt similarity index 70% rename from test/test-files/email-templates/rspamd-spam.txt rename to test/files/emails/rspamd/spam.txt index 88bd719c..c561e779 100644 --- a/test/test-files/email-templates/rspamd-spam.txt +++ b/test/files/emails/rspamd/spam.txt @@ -1,12 +1,5 @@ -HELO mail.example.test -MAIL FROM: spam@example.test -RCPT TO: user1@localhost.localdomain -DATA From: Docker Mail Server To: Existing Local User Date: Sat, 21 Jan 2023 11:11:11 +0000 Subject: Test Message rspamd-spam.txt XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X - -. -QUIT diff --git a/test/test-files/email-templates/rspamd-virus.txt b/test/files/emails/rspamd/virus.txt similarity index 70% rename from test/test-files/email-templates/rspamd-virus.txt rename to test/files/emails/rspamd/virus.txt index c745f261..cb18927d 100644 --- a/test/test-files/email-templates/rspamd-virus.txt +++ b/test/files/emails/rspamd/virus.txt @@ -1,12 +1,5 @@ -HELO mail.example.test -MAIL FROM: virus@example.test -RCPT TO: user1@localhost.localdomain -DATA From: Docker Mail Server To: Existing Local User Date: Sat, 21 Jan 2023 11:11:11 +0000 Subject: Test Message rspamd-virus.txt X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H* - -. -QUIT diff --git a/test/test-files/email-templates/root-email.txt b/test/files/emails/sendmail/root-email.txt similarity index 100% rename from test/test-files/email-templates/root-email.txt rename to test/files/emails/sendmail/root-email.txt diff --git a/test/test-files/email-templates/sieve-pipe.txt b/test/files/emails/sieve/pipe.txt similarity index 67% rename from test/test-files/email-templates/sieve-pipe.txt rename to test/files/emails/sieve/pipe.txt index f13dba87..4e8cfb39 100644 --- a/test/test-files/email-templates/sieve-pipe.txt +++ b/test/files/emails/sieve/pipe.txt @@ -1,12 +1,5 @@ -HELO mail.external.tld -MAIL FROM: user@external.tld -RCPT TO: user2@otherdomain.tld -DATA From: Sieve-pipe-test To: Existing Local User Date: Sat, 22 May 2010 07:43:25 -0400 Subject: Sieve pipe test message This is a test mail to sieve pipe. - -. -QUIT diff --git a/test/test-files/email-templates/sieve-spam-folder.txt b/test/files/emails/sieve/spam-folder.txt similarity index 64% rename from test/test-files/email-templates/sieve-spam-folder.txt rename to test/files/emails/sieve/spam-folder.txt index 8e802817..7ffd09a7 100644 --- a/test/test-files/email-templates/sieve-spam-folder.txt +++ b/test/files/emails/sieve/spam-folder.txt @@ -1,12 +1,5 @@ -HELO mail.external.tld -MAIL FROM: user@external.tld -RCPT TO: user1@localhost.localdomain -DATA From: Spambot To: Existing Local User Date: Sat, 22 May 2010 07:43:25 -0400 Subject: Test Message sieve-spam-folder.txt This is a test mail. - -. -QUIT diff --git a/test/test-files/email-templates/test-email.txt b/test/files/emails/test-email.txt similarity index 100% rename from test/test-files/email-templates/test-email.txt rename to test/files/emails/test-email.txt diff --git a/test/test-files/nc_templates/imap_special_use_folders.txt b/test/files/nc/imap_special_use_folders.txt similarity index 100% rename from test/test-files/nc_templates/imap_special_use_folders.txt rename to test/files/nc/imap_special_use_folders.txt diff --git a/test/test-files/nc_templates/postgrey_whitelist.txt b/test/files/nc/postgrey_whitelist.txt similarity index 100% rename from test/test-files/nc_templates/postgrey_whitelist.txt rename to test/files/nc/postgrey_whitelist.txt diff --git a/test/test-files/nc_templates/postgrey_whitelist_recipients.txt b/test/files/nc/postgrey_whitelist_recipients.txt similarity index 100% rename from test/test-files/nc_templates/postgrey_whitelist_recipients.txt rename to test/files/nc/postgrey_whitelist_recipients.txt diff --git a/test/test-files/nc_templates/rspamd_imap_move_to_inbox.txt b/test/files/nc/rspamd_imap_move_to_inbox.txt similarity index 100% rename from test/test-files/nc_templates/rspamd_imap_move_to_inbox.txt rename to test/files/nc/rspamd_imap_move_to_inbox.txt diff --git a/test/test-files/nc_templates/rspamd_imap_move_to_junk.txt b/test/files/nc/rspamd_imap_move_to_junk.txt similarity index 100% rename from test/test-files/nc_templates/rspamd_imap_move_to_junk.txt rename to test/files/nc/rspamd_imap_move_to_junk.txt diff --git a/test/test-files/ssl/custom-dhe-params.pem b/test/files/ssl/custom-dhe-params.pem similarity index 100% rename from test/test-files/ssl/custom-dhe-params.pem rename to test/files/ssl/custom-dhe-params.pem diff --git a/test/test-files/ssl/example.test/README.md b/test/files/ssl/example.test/README.md similarity index 100% rename from test/test-files/ssl/example.test/README.md rename to test/files/ssl/example.test/README.md diff --git a/test/test-files/ssl/example.test/cert.ecdsa.pem b/test/files/ssl/example.test/cert.ecdsa.pem similarity index 100% rename from test/test-files/ssl/example.test/cert.ecdsa.pem rename to test/files/ssl/example.test/cert.ecdsa.pem diff --git a/test/test-files/ssl/example.test/cert.rsa.pem b/test/files/ssl/example.test/cert.rsa.pem similarity index 100% rename from test/test-files/ssl/example.test/cert.rsa.pem rename to test/files/ssl/example.test/cert.rsa.pem diff --git a/test/test-files/ssl/example.test/key.ecdsa.pem b/test/files/ssl/example.test/key.ecdsa.pem similarity index 100% rename from test/test-files/ssl/example.test/key.ecdsa.pem rename to test/files/ssl/example.test/key.ecdsa.pem diff --git a/test/test-files/ssl/example.test/key.rsa.pem b/test/files/ssl/example.test/key.rsa.pem similarity index 100% rename from test/test-files/ssl/example.test/key.rsa.pem rename to test/files/ssl/example.test/key.rsa.pem diff --git a/test/test-files/ssl/example.test/testssl.txt b/test/files/ssl/example.test/testssl.txt similarity index 100% rename from test/test-files/ssl/example.test/testssl.txt rename to test/files/ssl/example.test/testssl.txt diff --git a/test/test-files/ssl/example.test/traefik.md b/test/files/ssl/example.test/traefik.md similarity index 100% rename from test/test-files/ssl/example.test/traefik.md rename to test/files/ssl/example.test/traefik.md diff --git a/test/test-files/ssl/example.test/with_ca/ecdsa/ca-cert.ecdsa.pem b/test/files/ssl/example.test/with_ca/ecdsa/ca-cert.ecdsa.pem similarity index 100% rename from test/test-files/ssl/example.test/with_ca/ecdsa/ca-cert.ecdsa.pem rename to test/files/ssl/example.test/with_ca/ecdsa/ca-cert.ecdsa.pem diff --git a/test/test-files/ssl/example.test/with_ca/ecdsa/ca-key.ecdsa.pem b/test/files/ssl/example.test/with_ca/ecdsa/ca-key.ecdsa.pem similarity index 100% rename from test/test-files/ssl/example.test/with_ca/ecdsa/ca-key.ecdsa.pem rename to test/files/ssl/example.test/with_ca/ecdsa/ca-key.ecdsa.pem diff --git a/test/test-files/ssl/example.test/with_ca/ecdsa/cert.ecdsa.pem b/test/files/ssl/example.test/with_ca/ecdsa/cert.ecdsa.pem similarity index 100% rename from test/test-files/ssl/example.test/with_ca/ecdsa/cert.ecdsa.pem rename to test/files/ssl/example.test/with_ca/ecdsa/cert.ecdsa.pem diff --git a/test/test-files/ssl/example.test/with_ca/ecdsa/cert.rsa.pem b/test/files/ssl/example.test/with_ca/ecdsa/cert.rsa.pem similarity index 100% rename from test/test-files/ssl/example.test/with_ca/ecdsa/cert.rsa.pem rename to test/files/ssl/example.test/with_ca/ecdsa/cert.rsa.pem diff --git a/test/test-files/ssl/example.test/with_ca/ecdsa/ecdsa.acme.json b/test/files/ssl/example.test/with_ca/ecdsa/ecdsa.acme.json similarity index 100% rename from test/test-files/ssl/example.test/with_ca/ecdsa/ecdsa.acme.json rename to test/files/ssl/example.test/with_ca/ecdsa/ecdsa.acme.json diff --git a/test/test-files/ssl/example.test/with_ca/ecdsa/key.ecdsa.pem b/test/files/ssl/example.test/with_ca/ecdsa/key.ecdsa.pem similarity index 100% rename from test/test-files/ssl/example.test/with_ca/ecdsa/key.ecdsa.pem rename to test/files/ssl/example.test/with_ca/ecdsa/key.ecdsa.pem diff --git a/test/test-files/ssl/example.test/with_ca/ecdsa/key.rsa.pem b/test/files/ssl/example.test/with_ca/ecdsa/key.rsa.pem similarity index 100% rename from test/test-files/ssl/example.test/with_ca/ecdsa/key.rsa.pem rename to test/files/ssl/example.test/with_ca/ecdsa/key.rsa.pem diff --git a/test/test-files/ssl/example.test/with_ca/ecdsa/rsa.acme.json b/test/files/ssl/example.test/with_ca/ecdsa/rsa.acme.json similarity index 100% rename from test/test-files/ssl/example.test/with_ca/ecdsa/rsa.acme.json rename to test/files/ssl/example.test/with_ca/ecdsa/rsa.acme.json diff --git a/test/test-files/ssl/example.test/with_ca/ecdsa/wildcard/cert.ecdsa.pem b/test/files/ssl/example.test/with_ca/ecdsa/wildcard/cert.ecdsa.pem similarity index 100% rename from test/test-files/ssl/example.test/with_ca/ecdsa/wildcard/cert.ecdsa.pem rename to test/files/ssl/example.test/with_ca/ecdsa/wildcard/cert.ecdsa.pem diff --git a/test/test-files/ssl/example.test/with_ca/ecdsa/wildcard/ecdsa.acme.json b/test/files/ssl/example.test/with_ca/ecdsa/wildcard/ecdsa.acme.json similarity index 100% rename from test/test-files/ssl/example.test/with_ca/ecdsa/wildcard/ecdsa.acme.json rename to test/files/ssl/example.test/with_ca/ecdsa/wildcard/ecdsa.acme.json diff --git a/test/test-files/ssl/example.test/with_ca/ecdsa/wildcard/key.ecdsa.pem b/test/files/ssl/example.test/with_ca/ecdsa/wildcard/key.ecdsa.pem similarity index 100% rename from test/test-files/ssl/example.test/with_ca/ecdsa/wildcard/key.ecdsa.pem rename to test/files/ssl/example.test/with_ca/ecdsa/wildcard/key.ecdsa.pem diff --git a/test/test-files/ssl/example.test/with_ca/rsa/ca-cert.rsa.pem b/test/files/ssl/example.test/with_ca/rsa/ca-cert.rsa.pem similarity index 100% rename from test/test-files/ssl/example.test/with_ca/rsa/ca-cert.rsa.pem rename to test/files/ssl/example.test/with_ca/rsa/ca-cert.rsa.pem diff --git a/test/test-files/ssl/example.test/with_ca/rsa/ca-key.rsa.pem b/test/files/ssl/example.test/with_ca/rsa/ca-key.rsa.pem similarity index 100% rename from test/test-files/ssl/example.test/with_ca/rsa/ca-key.rsa.pem rename to test/files/ssl/example.test/with_ca/rsa/ca-key.rsa.pem diff --git a/test/test-files/ssl/example.test/with_ca/rsa/cert.ecdsa.pem b/test/files/ssl/example.test/with_ca/rsa/cert.ecdsa.pem similarity index 100% rename from test/test-files/ssl/example.test/with_ca/rsa/cert.ecdsa.pem rename to test/files/ssl/example.test/with_ca/rsa/cert.ecdsa.pem diff --git a/test/test-files/ssl/example.test/with_ca/rsa/cert.rsa.pem b/test/files/ssl/example.test/with_ca/rsa/cert.rsa.pem similarity index 100% rename from test/test-files/ssl/example.test/with_ca/rsa/cert.rsa.pem rename to test/files/ssl/example.test/with_ca/rsa/cert.rsa.pem diff --git a/test/test-files/ssl/example.test/with_ca/rsa/ecdsa.acme.json b/test/files/ssl/example.test/with_ca/rsa/ecdsa.acme.json similarity index 100% rename from test/test-files/ssl/example.test/with_ca/rsa/ecdsa.acme.json rename to test/files/ssl/example.test/with_ca/rsa/ecdsa.acme.json diff --git a/test/test-files/ssl/example.test/with_ca/rsa/key.ecdsa.pem b/test/files/ssl/example.test/with_ca/rsa/key.ecdsa.pem similarity index 100% rename from test/test-files/ssl/example.test/with_ca/rsa/key.ecdsa.pem rename to test/files/ssl/example.test/with_ca/rsa/key.ecdsa.pem diff --git a/test/test-files/ssl/example.test/with_ca/rsa/key.rsa.pem b/test/files/ssl/example.test/with_ca/rsa/key.rsa.pem similarity index 100% rename from test/test-files/ssl/example.test/with_ca/rsa/key.rsa.pem rename to test/files/ssl/example.test/with_ca/rsa/key.rsa.pem diff --git a/test/test-files/ssl/example.test/with_ca/rsa/rsa.acme.json b/test/files/ssl/example.test/with_ca/rsa/rsa.acme.json similarity index 100% rename from test/test-files/ssl/example.test/with_ca/rsa/rsa.acme.json rename to test/files/ssl/example.test/with_ca/rsa/rsa.acme.json diff --git a/test/test-files/ssl/example.test/with_ca/rsa/wildcard/cert.rsa.pem b/test/files/ssl/example.test/with_ca/rsa/wildcard/cert.rsa.pem similarity index 100% rename from test/test-files/ssl/example.test/with_ca/rsa/wildcard/cert.rsa.pem rename to test/files/ssl/example.test/with_ca/rsa/wildcard/cert.rsa.pem diff --git a/test/test-files/ssl/example.test/with_ca/rsa/wildcard/key.rsa.pem b/test/files/ssl/example.test/with_ca/rsa/wildcard/key.rsa.pem similarity index 100% rename from test/test-files/ssl/example.test/with_ca/rsa/wildcard/key.rsa.pem rename to test/files/ssl/example.test/with_ca/rsa/wildcard/key.rsa.pem diff --git a/test/test-files/ssl/example.test/with_ca/rsa/wildcard/rsa.acme.json b/test/files/ssl/example.test/with_ca/rsa/wildcard/rsa.acme.json similarity index 100% rename from test/test-files/ssl/example.test/with_ca/rsa/wildcard/rsa.acme.json rename to test/files/ssl/example.test/with_ca/rsa/wildcard/rsa.acme.json diff --git a/test/helper/common.bash b/test/helper/common.bash index 8fb7854e..ab21ef60 100644 --- a/test/helper/common.bash +++ b/test/helper/common.bash @@ -469,5 +469,19 @@ function _print_mail_log_for_id() { _run_in_container grep -F "${MAIL_ID}" /var/log/mail.log } +# A simple wrapper for netcat (`nc`). This is useful when sending +# "raw" e-mails or doing IMAP-related work. +# +# @param ${1} = the file that is given to `nc` +# @param ${1} = custom parameters for `nc` [OPTIONAL] (default: 0.0.0.0 25) +function _nc_wrapper() { + local FILE=${1:?Must provide name of template file} + local NC_PARAMETERS=${2:-0.0.0.0 25} + + [[ -v CONTAINER_NAME ]] || return 1 + + _run_in_container_bash "nc ${NC_PARAMETERS} < /tmp/docker-mailserver-test/${FILE}.txt" +} + # ? << Miscellaneous helper functions # ! ------------------------------------------------------------------- diff --git a/test/helper/sending.bash b/test/helper/sending.bash index 631617a1..48012178 100644 --- a/test/helper/sending.bash +++ b/test/helper/sending.bash @@ -8,11 +8,12 @@ # ! ATTENTION: This file requires helper functions from `common.sh`! # Sends a mail from localhost (127.0.0.1) to a container. To send -# a custom email, create a file at `test/test-files/`, +# a custom email, create a file at `test/files/`, # and provide `` as an argument to this function. # -# @param ${1} = template file (path) name -# @param ${2} = parameters for `nc` [OPTIONAL] (default: `0.0.0.0 25`) +# Parameters include all options that one can supply to `swaks` +# itself. The `--data` parameter expects a relative path from `emails/` +# where the contents will be implicitly provided to `swaks` via STDIN. # # ## Attention # @@ -23,17 +24,42 @@ # send the email but it will not make sure the mail queue is empty after the mail # has been sent. function _send_email() { - local TEMPLATE_FILE=${1:?Must provide name of template file} - local NC_PARAMETERS=${2:-0.0.0.0 25} + [[ -v CONTAINER_NAME ]] || return 1 - assert_not_equal "${NC_PARAMETERS}" '' - assert_not_equal "${CONTAINER_NAME:-}" '' + # Parameter defaults common to our testing needs: + local EHLO='mail.external.tld' + local FROM='user@external.tld' + local TO='user1@localhost.localdomain' + local SERVER='0.0.0.0' + local PORT=25 + # Extra options for `swaks` that aren't covered by the default options above: + local ADDITIONAL_SWAKS_OPTIONS=() + # Specifically for handling `--data` option below: + local FINAL_SWAKS_OPTIONS=() - _run_in_container_bash "nc ${NC_PARAMETERS} < /tmp/docker-mailserver-test/${TEMPLATE_FILE}.txt" - assert_success + while [[ ${#} -gt 0 ]]; do + case "${1}" in + ( '--ehlo' ) EHLO=${2:?--ehlo given but no argument} ; shift 2 ;; + ( '--from' ) FROM=${2:?--from given but no argument} ; shift 2 ;; + ( '--to' ) TO=${2:?--to given but no argument} ; shift 2 ;; + ( '--server' ) SERVER=${2:?--server given but no argument} ; shift 2 ;; + ( '--port' ) PORT=${2:?--port given but no argument} ; shift 2 ;; + ( '--data' ) + local TEMPLATE_FILE="/tmp/docker-mailserver-test/emails/${2:?--data given but no argument provided}.txt" + FINAL_SWAKS_OPTIONS+=('--data') + FINAL_SWAKS_OPTIONS+=('-') + FINAL_SWAKS_OPTIONS+=('<') + FINAL_SWAKS_OPTIONS+=("${TEMPLATE_FILE}") + shift 2 + ;; + ( * ) ADDITIONAL_SWAKS_OPTIONS+=("${1}") ; shift 1 ;; + esac + done + + _run_in_container_bash "swaks --server ${SERVER} --port ${PORT} --ehlo ${EHLO} --from ${FROM} --to ${TO} ${ADDITIONAL_SWAKS_OPTIONS[*]} ${FINAL_SWAKS_OPTIONS[*]}" } -# Like `_send_mail` with two major differences: +# Like `_send_email` with two major differences: # # 1. this function waits for the mail to be processed; there is no asynchronicity # because filtering the logs in a synchronous way is easier and safer! @@ -42,8 +68,7 @@ function _send_email() { # No. 2 is especially useful in case you send more than one email in a single # test file and need to assert certain log entries for each mail individually. # -# @param ${1} = template file (path) name -# @param ${2} = parameters for `nc` [OPTIONAL] (default: `0.0.0.0 25`) +# This function takes the same arguments as `_send_mail`. # # ## Attention # @@ -57,17 +82,13 @@ function _send_email() { # chosen. Sending more than one mail at any given point in time with this function # is UNDEFINED BEHAVIOR! function _send_email_and_get_id() { - local TEMPLATE_FILE=${1:?Must provide name of template file} - local NC_PARAMETERS=${2:-0.0.0.0 25} + [[ -v CONTAINER_NAME ]] || return 1 + + _wait_for_empty_mail_queue_in_container + _send_email "${@}" + _wait_for_empty_mail_queue_in_container + local MAIL_ID - - assert_not_equal "${NC_PARAMETERS}" '' - assert_not_equal "${CONTAINER_NAME:-}" '' - - _wait_for_empty_mail_queue_in_container - _send_email "${TEMPLATE_FILE}" - _wait_for_empty_mail_queue_in_container - # The unique ID Postfix (and other services) use may be different in length # on different systems (e.g. amd64 (11) vs aarch64 (10)). Hence, we use a # range to safely capture it. diff --git a/test/helper/setup.bash b/test/helper/setup.bash index 65e2999f..0dd57bd6 100644 --- a/test/helper/setup.bash +++ b/test/helper/setup.bash @@ -98,7 +98,7 @@ function _init_with_defaults() { # Common complimentary test files, read-only safe to share across containers: export TEST_FILES_CONTAINER_PATH='/tmp/docker-mailserver-test' - export TEST_FILES_VOLUME="${REPOSITORY_ROOT}/test/test-files:${TEST_FILES_CONTAINER_PATH}:ro" + export TEST_FILES_VOLUME="${REPOSITORY_ROOT}/test/files:${TEST_FILES_CONTAINER_PATH}:ro" # The config volume cannot be read-only as some data needs to be written at container startup # diff --git a/test/test-files/auth/added-smtp-auth-login-wrong.txt b/test/test-files/auth/added-smtp-auth-login-wrong.txt deleted file mode 100644 index a75856f1..00000000 --- a/test/test-files/auth/added-smtp-auth-login-wrong.txt +++ /dev/null @@ -1,4 +0,0 @@ -EHLO mail -AUTH LOGIN YWRkZWRAbG9jYWxob3N0LmxvY2FsZG9tYWlu -Bn3JKisq4HQ2RO== -QUIT diff --git a/test/test-files/auth/added-smtp-auth-login.txt b/test/test-files/auth/added-smtp-auth-login.txt deleted file mode 100644 index 5276b7f4..00000000 --- a/test/test-files/auth/added-smtp-auth-login.txt +++ /dev/null @@ -1,4 +0,0 @@ -EHLO mail -AUTH LOGIN YWRkZWRAbG9jYWxob3N0LmxvY2FsZG9tYWlu -bXlwYXNzd29yZA== -QUIT diff --git a/test/test-files/auth/added-smtp-auth-plain-wrong.txt b/test/test-files/auth/added-smtp-auth-plain-wrong.txt deleted file mode 100644 index 6ce5a383..00000000 --- a/test/test-files/auth/added-smtp-auth-plain-wrong.txt +++ /dev/null @@ -1,3 +0,0 @@ -EHLO mail -AUTH PLAIN YWRkZWRAbG9jYWxob3N0LmxvY2FsZG9tYWluAGFkZGVkQGxvY2FsaG9zdC5sb2NhbGRvbWFpbgBCQURQQVNTV09SRA== -QUIT diff --git a/test/test-files/auth/added-smtp-auth-plain.txt b/test/test-files/auth/added-smtp-auth-plain.txt deleted file mode 100644 index ed48d77d..00000000 --- a/test/test-files/auth/added-smtp-auth-plain.txt +++ /dev/null @@ -1,3 +0,0 @@ -EHLO mail -AUTH PLAIN YWRkZWRAbG9jYWxob3N0LmxvY2FsZG9tYWluAGFkZGVkQGxvY2FsaG9zdC5sb2NhbGRvbWFpbgBteXBhc3N3b3Jk -QUIT diff --git a/test/test-files/auth/sasl-ldap-smtp-auth.txt b/test/test-files/auth/sasl-ldap-smtp-auth.txt deleted file mode 100644 index df4d7db4..00000000 --- a/test/test-files/auth/sasl-ldap-smtp-auth.txt +++ /dev/null @@ -1,5 +0,0 @@ -EHLO mail -AUTH LOGIN -c29tZS51c2VyQGxvY2FsaG9zdC5sb2NhbGRvbWFpbg== -c2VjcmV0 -QUIT diff --git a/test/test-files/auth/smtp-auth-login-wrong.txt b/test/test-files/auth/smtp-auth-login-wrong.txt deleted file mode 100644 index 39b4f01c..00000000 --- a/test/test-files/auth/smtp-auth-login-wrong.txt +++ /dev/null @@ -1,4 +0,0 @@ -EHLO mail -AUTH LOGIN dXNlcjFAbG9jYWxob3N0LmxvY2FsZG9tYWlu -Bn3JKisq4HQ2RO== -QUIT diff --git a/test/test-files/auth/smtp-auth-login.txt b/test/test-files/auth/smtp-auth-login.txt deleted file mode 100644 index 50ff99f3..00000000 --- a/test/test-files/auth/smtp-auth-login.txt +++ /dev/null @@ -1,4 +0,0 @@ -EHLO mail -AUTH LOGIN dXNlcjFAbG9jYWxob3N0LmxvY2FsZG9tYWlu -bXlwYXNzd29yZA== -QUIT diff --git a/test/test-files/auth/smtp-auth-plain-wrong.txt b/test/test-files/auth/smtp-auth-plain-wrong.txt deleted file mode 100644 index d8d8ad2a..00000000 --- a/test/test-files/auth/smtp-auth-plain-wrong.txt +++ /dev/null @@ -1,3 +0,0 @@ -EHLO mail -AUTH PLAIN WRONGPASSWORD -QUIT diff --git a/test/test-files/auth/smtp-auth-plain.txt b/test/test-files/auth/smtp-auth-plain.txt deleted file mode 100644 index 2e60fdc3..00000000 --- a/test/test-files/auth/smtp-auth-plain.txt +++ /dev/null @@ -1,3 +0,0 @@ -EHLO mail -AUTH PLAIN dXNlcjFAbG9jYWxob3N0LmxvY2FsZG9tYWluAHVzZXIxQGxvY2FsaG9zdC5sb2NhbGRvbWFpbgBteXBhc3N3b3Jk -QUIT diff --git a/test/test-files/email-templates/existing-user2.txt b/test/test-files/email-templates/existing-user2.txt deleted file mode 100644 index 63554f27..00000000 --- a/test/test-files/email-templates/existing-user2.txt +++ /dev/null @@ -1,12 +0,0 @@ -HELO mail.external.tld -MAIL FROM: user@external.tld -RCPT TO: user2@otherdomain.tld -DATA -From: Docker Mail Server -To: Existing Local User -Date: Sat, 22 May 2010 07:43:25 -0400 -Subject: Test Message existing-user2.txt -This is a test mail. - -. -QUIT diff --git a/test/test-files/email-templates/existing-user3.txt b/test/test-files/email-templates/existing-user3.txt deleted file mode 100644 index facd5328..00000000 --- a/test/test-files/email-templates/existing-user3.txt +++ /dev/null @@ -1,12 +0,0 @@ -HELO mail.external.tld -MAIL FROM: user@external.tld -RCPT TO: user3@localhost.localdomain -DATA -From: Docker Mail Server -To: Existing Local User -Date: Sat, 22 May 2010 07:43:33 -0400 -Subject: Test Message existing-user1.txt -This is a test mail. - -. -QUIT diff --git a/test/test-files/email-templates/smtp-ehlo.txt b/test/test-files/email-templates/smtp-ehlo.txt deleted file mode 100644 index 05524efd..00000000 --- a/test/test-files/email-templates/smtp-ehlo.txt +++ /dev/null @@ -1,2 +0,0 @@ -EHLO mail.localhost -QUIT diff --git a/test/tests/parallel/set1/dovecot/dovecot_quotas.bats b/test/tests/parallel/set1/dovecot/dovecot_quotas.bats index 2c176235..81cf9bc1 100644 --- a/test/tests/parallel/set1/dovecot/dovecot_quotas.bats +++ b/test/tests/parallel/set1/dovecot/dovecot_quotas.bats @@ -225,9 +225,12 @@ function teardown_file() { _default_teardown ; } sleep 10 # send some big emails - _send_email 'email-templates/quota-exceeded' '0.0.0.0 25' - _send_email 'email-templates/quota-exceeded' '0.0.0.0 25' - _send_email 'email-templates/quota-exceeded' '0.0.0.0 25' + _send_email --to 'quotauser@otherdomain.tld' --data 'quota-exceeded' + assert_success + _send_email --to 'quotauser@otherdomain.tld' --data 'quota-exceeded' + assert_success + _send_email --to 'quotauser@otherdomain.tld' --data 'quota-exceeded' + assert_success # check for quota warn message existence run _repeat_until_success_or_timeout 20 _exec_in_container grep -R 'Subject: quota warning' /var/mail/otherdomain.tld/quotauser/new/ assert_success diff --git a/test/tests/parallel/set1/dovecot/dovecot_sieve.bats b/test/tests/parallel/set1/dovecot/dovecot_sieve.bats index c2e9e6c7..e3e076a5 100644 --- a/test/tests/parallel/set1/dovecot/dovecot_sieve.bats +++ b/test/tests/parallel/set1/dovecot/dovecot_sieve.bats @@ -26,9 +26,11 @@ function setup_file() { _wait_for_smtp_port_in_container # Single mail sent from 'spam@spam.com' that is handled by User (relocate) and Global (copy) sieves for user1: - _send_email 'email-templates/sieve-spam-folder' + _send_email --data 'sieve/spam-folder' + assert_success # Mail for user2 triggers the sieve-pipe: - _send_email 'email-templates/sieve-pipe' + _send_email --to 'user2@otherdomain.tld' --data 'sieve/pipe' + assert_success _wait_for_empty_mail_queue_in_container } diff --git a/test/tests/parallel/set1/dovecot/mailbox_format_dbox.bats b/test/tests/parallel/set1/dovecot/mailbox_format_dbox.bats index 8ce03d9a..033a5bde 100644 --- a/test/tests/parallel/set1/dovecot/mailbox_format_dbox.bats +++ b/test/tests/parallel/set1/dovecot/mailbox_format_dbox.bats @@ -26,7 +26,8 @@ function teardown() { _default_teardown ; } _common_container_setup 'CUSTOM_SETUP_ARGUMENTS' _wait_for_smtp_port_in_container - _send_email 'email-templates/existing-user1' + _send_email --data 'existing/user1' + assert_success _wait_for_empty_mail_queue_in_container # Mail received should be stored as `u.1` (one file per message) @@ -47,7 +48,8 @@ function teardown() { _default_teardown ; } _common_container_setup 'CUSTOM_SETUP_ARGUMENTS' _wait_for_smtp_port_in_container - _send_email 'email-templates/existing-user1' + _send_email --data 'existing/user1' + assert_success _wait_for_empty_mail_queue_in_container # Mail received should be stored in `m.1` (1 or more messages) diff --git a/test/tests/parallel/set1/dovecot/special_use_folders.bats b/test/tests/parallel/set1/dovecot/special_use_folders.bats index e70899a0..fe1f554e 100644 --- a/test/tests/parallel/set1/dovecot/special_use_folders.bats +++ b/test/tests/parallel/set1/dovecot/special_use_folders.bats @@ -14,7 +14,8 @@ function setup_file() { function teardown_file() { _default_teardown ; } @test 'normal delivery works' { - _send_email 'email-templates/existing-user1' + _send_email --data 'existing/user1' + assert_success _count_files_in_directory_in_container /var/mail/localhost.localdomain/user1/new 1 } @@ -26,7 +27,7 @@ function teardown_file() { _default_teardown ; } } @test "(IMAP) special-use folders should be created when necessary" { - _send_email 'nc_templates/imap_special_use_folders' '-w 8 0.0.0.0 143' + _nc_wrapper 'nc/imap_special_use_folders' '-w 8 0.0.0.0 143' assert_output --partial 'Drafts' assert_output --partial 'Junk' assert_output --partial 'Trash' diff --git a/test/tests/parallel/set1/spam_virus/clamav.bats b/test/tests/parallel/set1/spam_virus/clamav.bats index 31608ef8..9232f90f 100644 --- a/test/tests/parallel/set1/spam_virus/clamav.bats +++ b/test/tests/parallel/set1/spam_virus/clamav.bats @@ -25,34 +25,35 @@ function setup_file() { _wait_for_service postfix _wait_for_smtp_port_in_container - _send_email 'email-templates/amavis-virus' + _send_email --from 'virus@external.tld' --data 'amavis/virus' + assert_success _wait_for_empty_mail_queue_in_container } function teardown_file() { _default_teardown ; } -@test "log files exist at /var/log/mail directory" { +@test 'log files exist at /var/log/mail directory' { _run_in_container_bash "ls -1 /var/log/mail/ | grep -E 'clamav|freshclam|mail.log' | wc -l" assert_success assert_output 3 } -@test "should be identified by Amavis" { +@test 'should be identified by Amavis' { _run_in_container grep -i 'Found secondary av scanner ClamAV-clamscan' /var/log/mail/mail.log assert_success } -@test "freshclam cron is enabled" { +@test 'freshclam cron is enabled' { _run_in_container_bash "grep '/usr/bin/freshclam' -r /etc/cron.d" assert_success } -@test "env CLAMAV_MESSAGE_SIZE_LIMIT is set correctly" { +@test 'env CLAMAV_MESSAGE_SIZE_LIMIT is set correctly' { _run_in_container grep -q '^MaxFileSize 30M$' /etc/clamav/clamd.conf assert_success } -@test "rejects virus" { +@test 'rejects virus' { _run_in_container_bash "grep 'Blocked INFECTED' /var/log/mail/mail.log | grep ' -> '" assert_success } diff --git a/test/tests/parallel/set1/spam_virus/disabled_clamav_spamassassin.bats b/test/tests/parallel/set1/spam_virus/disabled_clamav_spamassassin.bats index 8402422c..f2474cc0 100644 --- a/test/tests/parallel/set1/spam_virus/disabled_clamav_spamassassin.bats +++ b/test/tests/parallel/set1/spam_virus/disabled_clamav_spamassassin.bats @@ -12,12 +12,14 @@ function setup_file() { --env ENABLE_CLAMAV=0 --env ENABLE_SPAMASSASSIN=0 --env AMAVIS_LOGLEVEL=2 + --env PERMIT_DOCKER=container ) _common_container_setup 'CUSTOM_SETUP_ARGUMENTS' _wait_for_smtp_port_in_container - _send_email 'email-templates/existing-user1' + _send_email --data 'existing/user1' + assert_success _wait_for_empty_mail_queue_in_container } diff --git a/test/tests/parallel/set1/spam_virus/fail2ban.bats b/test/tests/parallel/set1/spam_virus/fail2ban.bats index 9ae30758..8a03ba04 100644 --- a/test/tests/parallel/set1/spam_virus/fail2ban.bats +++ b/test/tests/parallel/set1/spam_virus/fail2ban.bats @@ -73,8 +73,17 @@ function teardown_file() { @test "ban ip on multiple failed login" { CONTAINER1_IP=$(_get_container_ip "${CONTAINER1_NAME}") # Trigger a ban by failing to login twice: - CONTAINER_NAME=${CONTAINER2_NAME} _send_email 'auth/smtp-auth-login-wrong' "${CONTAINER1_IP} 465" - CONTAINER_NAME=${CONTAINER2_NAME} _send_email 'auth/smtp-auth-login-wrong' "${CONTAINER1_IP} 465" + for _ in {1..2}; do + CONTAINER_NAME=${CONTAINER2_NAME} _send_email \ + --server "${CONTAINER1_IP}" \ + --port 465 \ + --auth PLAIN \ + --auth-user user1@localhost.localdomain \ + --auth-password wrongpassword + assert_failure + assert_output --partial 'authentication failed' + assert_output --partial 'No authentication type succeeded' + done # Checking that CONTAINER2_IP is banned in "${CONTAINER1_NAME}" CONTAINER2_IP=$(_get_container_ip "${CONTAINER2_NAME}") diff --git a/test/tests/parallel/set1/spam_virus/postgrey_enabled.bats b/test/tests/parallel/set1/spam_virus/postgrey_enabled.bats index e32210ca..316e3350 100644 --- a/test/tests/parallel/set1/spam_virus/postgrey_enabled.bats +++ b/test/tests/parallel/set1/spam_virus/postgrey_enabled.bats @@ -51,17 +51,15 @@ function teardown_file() { _default_teardown ; } _reload_postfix # Send test mail (it should fail to deliver): - _send_test_mail '/tmp/docker-mailserver-test/email-templates/postgrey.txt' '25' + _send_email --from 'user@external.tld' --port 25 --data 'postgrey' + assert_failure + assert_output --partial 'Recipient address rejected: Delayed by Postgrey' # Confirm mail was greylisted: _should_have_log_entry \ 'action=greylist' \ 'reason=new' \ 'client_address=127.0.0.1/32, sender=user@external.tld, recipient=user1@localhost.localdomain' - - _repeat_until_success_or_timeout 10 _run_in_container grep \ - 'Recipient address rejected: Delayed by Postgrey' \ - /var/log/mail/mail.log } # NOTE: This test case depends on the previous one @@ -69,7 +67,8 @@ function teardown_file() { _default_teardown ; } # Wait until `$POSTGREY_DELAY` seconds pass before trying again: sleep 3 # Retry delivering test mail (it should be trusted this time): - _send_test_mail '/tmp/docker-mailserver-test/email-templates/postgrey.txt' '25' + _send_email --from 'user@external.tld' --port 25 --data 'postgrey' + assert_success # Confirm postgrey permitted delivery (triplet is now trusted): _should_have_log_entry \ @@ -78,8 +77,9 @@ function teardown_file() { _default_teardown ; } 'client_address=127.0.0.1/32, sender=user@external.tld, recipient=user1@localhost.localdomain' } - -# NOTE: These two whitelist tests use `test-files/nc_templates/` instead of `test-files/email-templates`. +# NOTE: These two whitelist tests use `files/nc/` instead of `files/emails`. +# `nc` option `-w 0` terminates the connection after sending the template, it does not wait for a response. +# This is required for port 10023, otherwise the connection never drops. # - This allows to bypass the SMTP protocol on port 25, and send data directly to Postgrey instead. # - Appears to be a workaround due to `client_name=localhost` when sent from Postfix. # - Could send over port 25 if whitelisting `localhost`, @@ -87,7 +87,7 @@ function teardown_file() { _default_teardown ; } # - It'd also cause the earlier greylist test to fail. # - TODO: Actually confirm whitelist feature works correctly as these test cases are using a workaround: @test "should whitelist sender 'user@whitelist.tld'" { - _send_test_mail '/tmp/docker-mailserver-test/nc_templates/postgrey_whitelist.txt' '10023' + _nc_wrapper 'nc/postgrey_whitelist' '-w 0 0.0.0.0 10023' _should_have_log_entry \ 'action=pass' \ @@ -96,7 +96,7 @@ function teardown_file() { _default_teardown ; } } @test "should whitelist recipient 'user2@otherdomain.tld'" { - _send_test_mail '/tmp/docker-mailserver-test/nc_templates/postgrey_whitelist_recipients.txt' '10023' + _nc_wrapper 'nc/postgrey_whitelist_recipients' '-w 0 0.0.0.0 10023' _should_have_log_entry \ 'action=pass' \ @@ -104,21 +104,10 @@ function teardown_file() { _default_teardown ; } 'client_address=127.0.0.1/32, sender=test@nonwhitelist.tld, recipient=user2@otherdomain.tld' } -function _send_test_mail() { - local MAIL_TEMPLATE=$1 - local PORT=${2:-25} - - # `-w 0` terminates the connection after sending the template, it does not wait for a response. - # This is required for port 10023, otherwise the connection never drops. - # It could increase the number of seconds to wait for port 25 to allow for asserting a response, - # but that would enforce the delay in tests for port 10023. - _run_in_container_bash "nc -w 0 0.0.0.0 ${PORT} < ${MAIL_TEMPLATE}" -} - function _should_have_log_entry() { - local ACTION=$1 - local REASON=$2 - local TRIPLET=$3 + local ACTION=${1} + local REASON=${2} + local TRIPLET=${3} # Allow some extra time for logs to update to avoids a false-positive failure: _run_until_success_or_timeout 10 _exec_in_container grep \ diff --git a/test/tests/parallel/set1/spam_virus/postscreen.bats b/test/tests/parallel/set1/spam_virus/postscreen.bats index a1ddeb29..377b2479 100644 --- a/test/tests/parallel/set1/spam_virus/postscreen.bats +++ b/test/tests/parallel/set1/spam_virus/postscreen.bats @@ -37,46 +37,35 @@ function teardown_file() { docker rm -f "${CONTAINER1_NAME}" "${CONTAINER2_NAME}" } +# `POSTSCREEN_ACTION=enforce` (DMS default) should reject delivery with a 550 SMTP reply +# A legitimate mail client should speak SMTP by waiting it's turn, which postscreen defaults enforce (only on port 25) +# https://www.postfix.org/postconf.5.html#postscreen_greet_wait +# +# Use `nc` to send all SMTP commands at once instead (emulate a misbehaving client that should be rejected) +# NOTE: Postscreen only runs on port 25, avoid implicit ports in test methods @test 'should fail send when talking out of turn' { - CONTAINER_NAME=${CONTAINER2_NAME} _send_email 'email-templates/postscreen' "${CONTAINER1_IP} 25" + CONTAINER_NAME=${CONTAINER2_NAME} _nc_wrapper 'emails/nc_raw/postscreen' "${CONTAINER1_IP} 25" + # Expected postscreen log entry: assert_output --partial 'Protocol error' - # Expected postscreen log entry: - _run_in_container cat /var/log/mail/mail.log + _run_in_container cat /var/log/mail.log assert_output --partial 'COMMAND PIPELINING' + assert_output --partial 'DATA without valid RCPT' } @test "should successfully pass postscreen and get postfix greeting message (respecting postscreen_greet_wait time)" { - # NOTE: Sometimes fails on first attempt (trying too soon?), - # Instead of a `run` + asserting partial, Using repeat + internal grep match: - _repeat_until_success_or_timeout 10 _should_wait_turn_speaking_smtp \ - "${CONTAINER2_NAME}" \ - "${CONTAINER1_IP}" \ - '/tmp/docker-mailserver-test/email-templates/postscreen.txt' \ - '220 mail.example.test ESMTP' + # Configure `send_email()` to send from the mail client container (CONTAINER2_NAME) via ENV override, + # mail is sent to the DMS server container (CONTAINER1_NAME) via `--server` parameter: + CONTAINER_NAME=${CONTAINER2_NAME} _send_email --server "${CONTAINER1_IP}" --port 25 --data 'postscreen' + # NOTE: Cannot assert_success due to sender address not being resolvable. + # TODO: Uncomment when proper resolution of domain names is possible: + # assert_success - # Expected postscreen log entry: - _run_in_container cat /var/log/mail/mail.log + # TODO: Prefer this approach when `_send_email_and_get_id()` can support separate client and server containers: + # local MAIL_ID=$(_send_email_and_get_id --port 25 --data 'postscreen') + # _print_mail_log_for_id "${MAIL_ID}" + # assert_output --partial "stored mail into mailbox 'INBOX'" + + _run_in_container cat /var/log/mail.log assert_output --partial 'PASS NEW' } - -# When postscreen is active, it prevents the usual method of piping a file through nc: -# (Won't work: CONTAINER_NAME=${CLIENT_CONTAINER_NAME} _send_email "${SMTP_TEMPLATE}" "${TARGET_CONTAINER_IP} 25") -# The below workaround respects `postscreen_greet_wait` time (default 6 sec), talking to the mail-server in turn: -# https://www.postfix.org/postconf.5.html#postscreen_greet_wait -function _should_wait_turn_speaking_smtp() { - local CLIENT_CONTAINER_NAME=$1 - local TARGET_CONTAINER_IP=$2 - local SMTP_TEMPLATE=$3 - local EXPECTED=$4 - - # shellcheck disable=SC2016 - local UGLY_WORKAROUND='exec 3<>/dev/tcp/'"${TARGET_CONTAINER_IP}"'/25 && \ - while IFS= read -r cmd; do \ - head -1 <&3; \ - [[ ${cmd} == "EHLO"* ]] && sleep 6; \ - echo ${cmd} >&3; \ - done < '"${SMTP_TEMPLATE}" - - docker exec "${CLIENT_CONTAINER_NAME}" bash -c "${UGLY_WORKAROUND}" | grep "${EXPECTED}" -} diff --git a/test/tests/parallel/set1/spam_virus/rspamd_full.bats b/test/tests/parallel/set1/spam_virus/rspamd_full.bats index ba8a23f5..2e610d72 100644 --- a/test/tests/parallel/set1/spam_virus/rspamd_full.bats +++ b/test/tests/parallel/set1/spam_virus/rspamd_full.bats @@ -45,10 +45,10 @@ function setup_file() { # We will send 3 emails: the first one should pass just fine; the second one should # be rejected due to spam; the third one should be rejected due to a virus. - export MAIL_ID1=$(_send_email_and_get_id 'email-templates/rspamd-pass') - export MAIL_ID2=$(_send_email_and_get_id 'email-templates/rspamd-spam') - export MAIL_ID3=$(_send_email_and_get_id 'email-templates/rspamd-virus') - export MAIL_ID4=$(_send_email_and_get_id 'email-templates/rspamd-spam-header') + export MAIL_ID1=$(_send_email_and_get_id --from 'rspamd-pass@example.test' --data 'rspamd/pass') + export MAIL_ID2=$(_send_email_and_get_id --from 'rspamd-spam@example.test' --data 'rspamd/spam') + export MAIL_ID3=$(_send_email_and_get_id --from 'rspamd-virus@example.test' --data 'rspamd/virus') + export MAIL_ID4=$(_send_email_and_get_id --from 'rspamd-spam-header@example.test' --data 'rspamd/spam-header') for ID in MAIL_ID{1,2,3,4}; do [[ -n ${!ID} ]] || { echo "${ID} is empty - aborting!" ; return 1 ; } @@ -256,7 +256,7 @@ function teardown_file() { _default_teardown ; } # Move an email to the "Junk" folder from "INBOX"; the first email we # sent should pass fine, hence we can now move it. - _send_email 'nc_templates/rspamd_imap_move_to_junk' '0.0.0.0 143' + _nc_wrapper 'nc/rspamd_imap_move_to_junk' '0.0.0.0 143' sleep 1 # wait for the transaction to finish _run_in_container cat /var/log/mail/mail.log @@ -270,7 +270,7 @@ function teardown_file() { _default_teardown ; } # Move an email to the "INBOX" folder from "Junk"; there should be two mails # in the "Junk" folder, since the second email we sent during setup should # have landed in the Junk folder already. - _send_email 'nc_templates/rspamd_imap_move_to_inbox' '0.0.0.0 143' + _nc_wrapper 'nc/rspamd_imap_move_to_inbox' '0.0.0.0 143' sleep 1 # wait for the transaction to finish _run_in_container cat /var/log/mail/mail.log diff --git a/test/tests/parallel/set1/spam_virus/spam_junk_folder.bats b/test/tests/parallel/set1/spam_virus/spam_junk_folder.bats index 94a9b9c4..fea23b0b 100644 --- a/test/tests/parallel/set1/spam_virus/spam_junk_folder.bats +++ b/test/tests/parallel/set1/spam_virus/spam_junk_folder.bats @@ -95,7 +95,7 @@ function teardown() { _default_teardown ; } function _should_send_spam_message() { _wait_for_smtp_port_in_container _wait_for_tcp_port_in_container 10024 # port 10024 is for Amavis - _send_email 'email-templates/amavis-spam' + _send_email --from 'spam@external.tld' --data 'amavis/spam' } function _should_be_received_by_amavis() { diff --git a/test/tests/parallel/set1/tls/dhparams.bats b/test/tests/parallel/set1/tls/dhparams.bats index 3157034c..8b3047d1 100644 --- a/test/tests/parallel/set1/tls/dhparams.bats +++ b/test/tests/parallel/set1/tls/dhparams.bats @@ -38,7 +38,7 @@ function teardown() { _default_teardown ; } # - A warning is raised about usage of potentially insecure parameters. @test "Custom" { export CONTAINER_NAME=${CONTAINER2_NAME} - local DH_PARAMS_CUSTOM='test/test-files/ssl/custom-dhe-params.pem' + local DH_PARAMS_CUSTOM='test/files/ssl/custom-dhe-params.pem' local DH_CHECKSUM_CUSTOM=$(sha512sum "${DH_PARAMS_CUSTOM}" | awk '{print $1}') _init_with_defaults diff --git a/test/tests/parallel/set1/tls/letsencrypt.bats b/test/tests/parallel/set1/tls/letsencrypt.bats index 91a05997..bcdb1758 100644 --- a/test/tests/parallel/set1/tls/letsencrypt.bats +++ b/test/tests/parallel/set1/tls/letsencrypt.bats @@ -88,7 +88,7 @@ function _initial_setup() { # All of these certs support both FQDNs (`mail.example.test` and `example.test`), # Except for the wildcard cert (`*.example.test`), that was created with `example.test` intentionally excluded from SAN. # We want to maintain the same FQDN (`mail.example.test`) between the _acme_ecdsa and _acme_rsa tests. - local LOCAL_BASE_PATH="${PWD}/test/test-files/ssl/example.test/with_ca/rsa" + local LOCAL_BASE_PATH="${PWD}/test/files/ssl/example.test/with_ca/rsa" function _prepare() { # Default `acme.json` for _acme_ecdsa test: @@ -240,7 +240,7 @@ function _copy_to_letsencrypt_storage() { FQDN_DIR=$(echo "${DEST}" | cut -d '/' -f1) mkdir -p "${TEST_TMP_CONFIG}/letsencrypt/${FQDN_DIR}" - if ! cp "${PWD}/test/test-files/ssl/${SRC}" "${TEST_TMP_CONFIG}/letsencrypt/${DEST}"; then + if ! cp "${PWD}/test/files/ssl/${SRC}" "${TEST_TMP_CONFIG}/letsencrypt/${DEST}"; then echo "Could not copy cert file '${SRC}'' to '${DEST}'" >&2 exit 1 fi diff --git a/test/tests/parallel/set1/tls/manual.bats b/test/tests/parallel/set1/tls/manual.bats index 2a55f14f..c082d6ed 100644 --- a/test/tests/parallel/set1/tls/manual.bats +++ b/test/tests/parallel/set1/tls/manual.bats @@ -20,7 +20,7 @@ function setup_file() { export TEST_DOMAIN='example.test' local CUSTOM_SETUP_ARGUMENTS=( - --volume "${PWD}/test/test-files/ssl/${TEST_DOMAIN}/with_ca/ecdsa/:/config/ssl/:ro" + --volume "${PWD}/test/files/ssl/${TEST_DOMAIN}/with_ca/ecdsa/:/config/ssl/:ro" --env LOG_LEVEL='trace' --env SSL_TYPE='manual' --env TLS_LEVEL='modern' @@ -108,10 +108,10 @@ function teardown_file() { _default_teardown ; } @test "manual cert changes are picked up by check-for-changes" { printf '%s' 'someThingsChangedHere' \ - >>"$(pwd)/test/test-files/ssl/${TEST_DOMAIN}/with_ca/ecdsa/key.ecdsa.pem" + >>"$(pwd)/test/files/ssl/${TEST_DOMAIN}/with_ca/ecdsa/key.ecdsa.pem" run timeout 15 docker exec "${CONTAINER_NAME}" bash -c "tail -F /var/log/supervisor/changedetector.log | sed '/Manual certificates have changed/ q'" assert_success - sed -i '/someThingsChangedHere/d' "$(pwd)/test/test-files/ssl/${TEST_DOMAIN}/with_ca/ecdsa/key.ecdsa.pem" + sed -i '/someThingsChangedHere/d' "$(pwd)/test/files/ssl/${TEST_DOMAIN}/with_ca/ecdsa/key.ecdsa.pem" } diff --git a/test/tests/parallel/set2/tls_cipherlists.bats b/test/tests/parallel/set2/tls_cipherlists.bats index 2b9511b9..3429f516 100644 --- a/test/tests/parallel/set2/tls_cipherlists.bats +++ b/test/tests/parallel/set2/tls_cipherlists.bats @@ -17,7 +17,7 @@ function setup_file() { # Contains various certs for testing TLS support (read-only): export TLS_CONFIG_VOLUME - TLS_CONFIG_VOLUME="${PWD}/test/test-files/ssl/${TEST_DOMAIN}/:/config/ssl/:ro" + TLS_CONFIG_VOLUME="${PWD}/test/files/ssl/${TEST_DOMAIN}/:/config/ssl/:ro" # Used for connecting testssl and DMS containers via network name `TEST_DOMAIN`: # NOTE: If the network already exists, the test will fail to start diff --git a/test/tests/parallel/set3/container_configuration/hostname.bats b/test/tests/parallel/set3/container_configuration/hostname.bats index fcb84b28..f5774eef 100644 --- a/test/tests/parallel/set3/container_configuration/hostname.bats +++ b/test/tests/parallel/set3/container_configuration/hostname.bats @@ -207,7 +207,7 @@ function _should_have_correct_mail_headers() { # (eg: OVERRIDE_HOSTNAME or `--hostname mail --domainname example.test`) local EXPECTED_HOSTNAME=${3:-${EXPECTED_FQDN}} - _send_email 'email-templates/existing-user1' + _send_email --from 'user@external.tld' --data 'existing/user1' _wait_for_empty_mail_queue_in_container _count_files_in_directory_in_container '/var/mail/localhost.localdomain/user1/new/' '1' diff --git a/test/tests/parallel/set3/mta/dsn.bats b/test/tests/parallel/set3/mta/dsn.bats index dcbb79b6..a5228cfc 100644 --- a/test/tests/parallel/set3/mta/dsn.bats +++ b/test/tests/parallel/set3/mta/dsn.bats @@ -47,9 +47,11 @@ function teardown_file() { @test "should always send a DSN when requested" { export CONTAINER_NAME=${CONTAINER1_NAME} - _send_email 'email-templates/dsn-unauthenticated' - _send_email 'email-templates/dsn-authenticated' '0.0.0.0 465' - _send_email 'email-templates/dsn-authenticated' '0.0.0.0 587' + # TODO replace with _send_email as soon as it supports DSN + # TODO ref: https://github.com/jetmore/swaks/issues/41 + _nc_wrapper 'emails/nc_raw/dsn/unauthenticated' + _nc_wrapper 'emails/nc_raw/dsn/authenticated' '0.0.0.0 465' + _nc_wrapper 'emails/nc_raw/dsn/authenticated' '0.0.0.0 587' _wait_for_empty_mail_queue_in_container _run_in_container grep "${LOG_DSN}" /var/log/mail/mail.log @@ -60,7 +62,7 @@ function teardown_file() { @test "should only send a DSN when requested from ports 465/587" { export CONTAINER_NAME=${CONTAINER2_NAME} - _send_email 'email-templates/dsn-unauthenticated' + _nc_wrapper 'emails/nc_raw/dsn/unauthenticated' _wait_for_empty_mail_queue_in_container # DSN requests can now only be made on ports 465 and 587, @@ -72,8 +74,8 @@ function teardown_file() { assert_failure # These ports are excluded via master.cf. - _send_email 'email-templates/dsn-authenticated' '0.0.0.0 465' - _send_email 'email-templates/dsn-authenticated' '0.0.0.0 587' + _nc_wrapper 'emails/nc_raw/dsn/authenticated' '0.0.0.0 465' + _nc_wrapper 'emails/nc_raw/dsn/authenticated' '0.0.0.0 587' _wait_for_empty_mail_queue_in_container _run_in_container grep "${LOG_DSN}" /var/log/mail/mail.log @@ -83,9 +85,9 @@ function teardown_file() { @test "should never send a DSN" { export CONTAINER_NAME=${CONTAINER3_NAME} - _send_email 'email-templates/dsn-unauthenticated' - _send_email 'email-templates/dsn-authenticated' '0.0.0.0 465' - _send_email 'email-templates/dsn-authenticated' '0.0.0.0 587' + _nc_wrapper 'emails/nc_raw/dsn/unauthenticated' + _nc_wrapper 'emails/nc_raw/dsn/authenticated' '0.0.0.0 465' + _nc_wrapper 'emails/nc_raw/dsn/authenticated' '0.0.0.0 587' _wait_for_empty_mail_queue_in_container # DSN requests are rejected regardless of origin. diff --git a/test/tests/parallel/set3/mta/lmtp_ip.bats b/test/tests/parallel/set3/mta/lmtp_ip.bats index 8d35c062..d8be42d9 100644 --- a/test/tests/parallel/set3/mta/lmtp_ip.bats +++ b/test/tests/parallel/set3/mta/lmtp_ip.bats @@ -38,7 +38,7 @@ function teardown_file() { _default_teardown ; } @test "delivers mail to existing account" { _wait_for_smtp_port_in_container - _send_email 'email-templates/existing-user1' # send a test email + _send_email --data 'existing/user1' # send a test email # Verify delivery was successful, log line should look similar to: # postfix/lmtp[1274]: 0EA424ABE7D9: to=, 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 ixPpB+Zvv2P7BAAAUi6ngw Saved) diff --git a/test/tests/parallel/set3/mta/privacy.bats b/test/tests/parallel/set3/mta/privacy.bats index f8160827..4d4d82ba 100644 --- a/test/tests/parallel/set3/mta/privacy.bats +++ b/test/tests/parallel/set3/mta/privacy.bats @@ -25,7 +25,11 @@ function teardown_file() { _default_teardown ; } # this test covers https://github.com/docker-mailserver/docker-mailserver/issues/681 @test "(Postfix) remove privacy details of the sender" { - _run_in_container_bash "openssl s_client -quiet -starttls smtp -connect 0.0.0.0:587 < /tmp/docker-mailserver-test/email-templates/send-privacy-email.txt" + _send_email \ + --port 587 -tls --auth LOGIN \ + --auth-user user1@localhost.localdomain \ + --auth-password mypassword \ + --data 'privacy' assert_success _run_until_success_or_timeout 120 _exec_in_container_bash '[[ -d /var/mail/localhost.localdomain/user1/new ]]' diff --git a/test/tests/parallel/set3/mta/smtp_delivery.bats b/test/tests/parallel/set3/mta/smtp_delivery.bats index af98b2f4..169f374a 100644 --- a/test/tests/parallel/set3/mta/smtp_delivery.bats +++ b/test/tests/parallel/set3/mta/smtp_delivery.bats @@ -63,34 +63,55 @@ function setup_file() { # 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 'email-templates/amavis-virus' + # _send_email --from 'virus@external.tld' --data 'amavis/virus' # Required for 'delivers mail to existing alias': - _send_email 'email-templates/existing-alias-external' + _send_email --to alias1@localhost.localdomain --data 'existing/alias-external' # Required for 'delivers mail to existing alias with recipient delimiter': - _send_email 'email-templates/existing-alias-recipient-delimiter' + _send_email --to alias1~test@localhost.localdomain --data 'existing/alias-recipient-delimiter' # Required for 'delivers mail to existing catchall': - _send_email 'email-templates/existing-catchall-local' + _send_email --to wildcard@localdomain2.com --data 'existing/catchall-local' # Required for 'delivers mail to regexp alias': - _send_email 'email-templates/existing-regexp-alias-local' + _send_email --to test123@localhost.localdomain --data 'existing/regexp-alias-local' # Required for 'rejects mail to unknown user': - _send_email 'email-templates/non-existing-user' + _send_email --to nouser@localhost.localdomain --data 'non-existing-user' # Required for 'redirects mail to external aliases': - _send_email 'email-templates/existing-regexp-alias-external' - _send_email 'email-templates/existing-alias-local' + _send_email --to bounce-always@localhost.localdomain --data 'existing/regexp-alias-external' + _send_email --to alias2@localhost.localdomain --data 'existing/alias-local' # Required for 'rejects spam': - _send_email 'email-templates/amavis-spam' + _send_email --from 'spam@external.tld' --data 'amavis/spam' # Required for 'delivers mail to existing account': - _send_email 'email-templates/existing-user1' - _send_email 'email-templates/existing-user2' - _send_email 'email-templates/existing-user3' - _send_email 'email-templates/existing-added' - _send_email 'email-templates/existing-user-and-cc-local-alias' - _send_email 'email-templates/sieve-spam-folder' - _send_email 'email-templates/sieve-pipe' - _run_in_container_bash 'sendmail root < /tmp/docker-mailserver-test/email-templates/root-email.txt' + _send_email --data 'existing/user1' + assert_success + _send_email --to user2@otherdomain.tld + assert_success + _send_email --to user3@localhost.localdomain + assert_success + _send_email --to added@localhost.localdomain --data 'existing/added' + assert_success + _send_email --to user1@localhost.localdomain --data 'existing/user-and-cc-local-alias' + assert_success + _send_email --data 'sieve/spam-folder' + assert_success + _send_email --to user2@otherdomain.tld --data 'sieve/pipe' + assert_success + _run_in_container_bash 'sendmail root < /tmp/docker-mailserver-test/emails/sendmail/root-email.txt' + assert_success +} + +function _unsuccessful() { + _send_email --port 465 --auth "${1}" --auth-user "${2}" --auth-password wrongpassword + 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_success + assert_output --partial 'Authentication successful' } @test "should succeed at emptying mail queue" { @@ -103,44 +124,35 @@ function setup_file() { } @test "should successfully authenticate with good password (plain)" { - _send_email 'auth/smtp-auth-plain' '-w 5 0.0.0.0 465' - assert_output --partial 'Authentication successful' + _successful PLAIN user1@localhost.localdomain } @test "should fail to authenticate with wrong password (plain)" { - _send_email 'auth/smtp-auth-plain-wrong' '-w 20 0.0.0.0 465' - assert_output --partial 'authentication failed' + _unsuccessful PLAIN user1@localhost.localdomain } @test "should successfully authenticate with good password (login)" { - _send_email 'auth/smtp-auth-login' '-w 5 0.0.0.0 465' - assert_output --partial 'Authentication successful' + _successful LOGIN user1@localhost.localdomain } @test "should fail to authenticate with wrong password (login)" { - _send_email 'auth/smtp-auth-login-wrong' '-w 20 0.0.0.0 465' - assert_output --partial 'authentication failed' + _unsuccessful LOGIN user1@localhost.localdomain } @test "[user: 'added'] should successfully authenticate with good password (plain)" { - _send_email 'auth/added-smtp-auth-plain' '-w 5 0.0.0.0 465' - assert_output --partial 'Authentication successful' + _successful PLAIN added@localhost.localdomain } @test "[user: 'added'] should fail to authenticate with wrong password (plain)" { - _send_email 'auth/added-smtp-auth-plain-wrong' '-w 20 0.0.0.0 465' - assert_output --partial 'authentication failed' + _unsuccessful PLAIN added@localhost.localdomain } @test "[user: 'added'] should successfully authenticate with good password (login)" { - _send_email 'auth/added-smtp-auth-login' '-w 5 0.0.0.0 465' - assert_success - assert_output --partial 'Authentication successful' + _successful LOGIN added@localhost.localdomain } @test "[user: 'added'] should fail to authenticate with wrong password (login)" { - _send_email 'auth/added-smtp-auth-login-wrong' '-w 20 0.0.0.0 465' - assert_output --partial 'authentication failed' + _unsuccessful LOGIN added@localhost.localdomain } # TODO: Add a test covering case SPAMASSASSIN_SPAM_TO_INBOX=1 (default) @@ -258,7 +270,13 @@ function setup_file() { # 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" { - _send_email 'email-templates/smtp-ehlo' + # 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 refute_output --partial 'SMTPUTF8' } diff --git a/test/tests/parallel/set3/mta/smtponly.bats b/test/tests/parallel/set3/mta/smtponly.bats index 66123de6..7b1f8699 100644 --- a/test/tests/parallel/set3/mta/smtponly.bats +++ b/test/tests/parallel/set3/mta/smtponly.bats @@ -32,7 +32,16 @@ function teardown_file() { _default_teardown ; } assert_success # it looks as if someone tries to send mail to another domain outside of DMS - _send_email 'email-templates/smtp-only' + _send_email \ + --ehlo mail.origin.test \ + --protocol SSMTPA \ + --server mail.origin.test \ + --from user@origin.test \ + --to user@destination.test \ + --auth PLAIN \ + --auth-user user@origin.test \ + --auth-password secret + assert_success _wait_for_empty_mail_queue_in_container # this seemingly succeeds, but looking at the logs, it doesn't diff --git a/test/tests/serial/mail_pop3.bats b/test/tests/serial/mail_pop3.bats index cb07484a..008921e4 100644 --- a/test/tests/serial/mail_pop3.bats +++ b/test/tests/serial/mail_pop3.bats @@ -24,11 +24,13 @@ function teardown_file() { _default_teardown ; } } @test 'authentication works' { - _send_email 'auth/pop3-auth' '-w 1 0.0.0.0 110' + _nc_wrapper 'auth/pop3-auth' '-w 1 0.0.0.0 110' + assert_success } @test 'added user authentication works' { - _send_email 'auth/added-pop3-auth' '-w 1 0.0.0.0 110' + _nc_wrapper 'auth/added-pop3-auth' '-w 1 0.0.0.0 110' + assert_success } @test '/var/log/mail/mail.log is error-free' { diff --git a/test/tests/serial/mail_with_imap.bats b/test/tests/serial/mail_with_imap.bats index d729c142..eeccf888 100644 --- a/test/tests/serial/mail_with_imap.bats +++ b/test/tests/serial/mail_with_imap.bats @@ -21,7 +21,8 @@ function setup_file() { function teardown_file() { _default_teardown ; } @test '(Dovecot) LDAP RIMAP connection and authentication works' { - _send_email 'auth/imap-auth' '-w 1 0.0.0.0 143' + _nc_wrapper 'auth/imap-auth' '-w 1 0.0.0.0 143' + assert_success } @test '(SASLauthd) SASL RIMAP authentication works' { @@ -30,13 +31,30 @@ function teardown_file() { _default_teardown ; } } @test '(SASLauthd) RIMAP SMTP authentication works' { - _send_email 'auth/smtp-auth-login' '-w 5 0.0.0.0 25' - assert_output --partial 'Error: authentication not enabled' + _send_email \ + --auth LOGIN \ + --auth-user user1@localhost.localdomain \ + --auth-password mypassword \ + --quit-after AUTH + assert_failure + assert_output --partial 'Host did not advertise authentication' - _send_email 'auth/smtp-auth-login' '-w 5 0.0.0.0 465' + _send_email \ + --port 465 \ + --auth LOGIN \ + --auth-user user1@localhost.localdomain \ + --auth-password mypassword \ + --quit-after AUTH + assert_success assert_output --partial 'Authentication successful' - _send_email 'auth/smtp-auth-login' '-w 5 0.0.0.0 587' + _send_email \ + --port 587 \ + --auth LOGIN \ + --auth-user user1@localhost.localdomain \ + --auth-password mypassword \ + --quit-after AUTH + assert_success assert_output --partial 'Authentication successful' } diff --git a/test/tests/serial/mail_with_ldap.bats b/test/tests/serial/mail_with_ldap.bats index b7b3884b..f2011d22 100644 --- a/test/tests/serial/mail_with_ldap.bats +++ b/test/tests/serial/mail_with_ldap.bats @@ -122,7 +122,6 @@ function setup_file() { # Extra ENV needed to support specific test-cases: local ENV_SUPPORT=( - --env PERMIT_DOCKER=container # Required for attempting SMTP auth on port 25 via nc # Required for openssl commands to be successul: # NOTE: snakeoil cert is created (for `docker-mailserver.invalid`) via Debian post-install script for Postfix package. # TODO: Use proper TLS cert @@ -249,7 +248,7 @@ function teardown() { # dovecot @test "dovecot: ldap imap connection and authentication works" { - _run_in_container_bash 'nc -w 1 0.0.0.0 143 < /tmp/docker-mailserver-test/auth/imap-ldap-auth.txt' + _nc_wrapper 'auth/imap-ldap-auth' '-w 1 0.0.0.0 143' assert_success } @@ -327,12 +326,25 @@ function teardown() { @test "spoofing (with LDAP): rejects sender forging" { _wait_for_smtp_port_in_container_to_respond dms-test_ldap - _run_in_container_bash 'openssl s_client -quiet -connect 0.0.0.0:465 < /tmp/docker-mailserver-test/auth/ldap-smtp-auth-spoofed.txt' + _send_email \ + --port 465 -tlsc --auth LOGIN \ + --auth-user some.user@localhost.localdomain \ + --auth-password secret \ + --ehlo mail \ + --from ldap@localhost.localdomain \ + --data 'auth/ldap-smtp-auth-spoofed' assert_output --partial 'Sender address rejected: not owned by user' } @test "spoofing (with LDAP): accepts sending as alias" { - _run_in_container_bash 'openssl s_client -quiet -connect 0.0.0.0:465 < /tmp/docker-mailserver-test/auth/ldap-smtp-auth-spoofed-alias.txt' + _send_email \ + --port 465 -tlsc --auth LOGIN \ + --auth-user some.user@localhost.localdomain \ + --auth-password secret \ + --ehlo mail \ + --from postmaster@localhost.localdomain \ + --to some.user@localhost.localdomain \ + --data 'auth/ldap-smtp-auth-spoofed-alias' assert_output --partial 'End data with' } @@ -341,19 +353,42 @@ function teardown() { # Template used has invalid AUTH: https://github.com/docker-mailserver/docker-mailserver/pull/3006#discussion_r1073321432 skip 'TODO: This test seems to have been broken from the start (?)' - _run_in_container_bash 'openssl s_client -quiet -connect 0.0.0.0:465 < /tmp/docker-mailserver-test/auth/ldap-smtp-auth-spoofed-sender-with-filter-exception.txt' + _send_email \ + --port 465 -tlsc --auth LOGIN \ + --auth-user some.user.email@localhost.localdomain \ + --auth-password secret \ + --ehlo mail \ + --from randomspoofedaddress@localhost.localdomain \ + --to some.user@localhost.localdomain \ + --data 'auth/ldap-smtp-auth-spoofed-sender-with-filter-exception' assert_output --partial 'Sender address rejected: not owned by user' } @test "saslauthd: ldap smtp authentication" { - # Requires ENV `PERMIT_DOCKER=container` - _send_email 'auth/sasl-ldap-smtp-auth' '-w 5 0.0.0.0 25' - assert_output --partial 'Error: authentication not enabled' + _send_email \ + --auth LOGIN \ + --auth-user some.user@localhost.localdomain \ + --auth-password wrongpassword \ + --quit-after AUTH + assert_failure + assert_output --partial 'Host did not advertise authentication' - _run_in_container_bash 'openssl s_client -quiet -connect 0.0.0.0:465 < /tmp/docker-mailserver-test/auth/sasl-ldap-smtp-auth.txt' + _send_email \ + --port 465 -tlsc \ + --auth LOGIN \ + --auth-user some.user@localhost.localdomain \ + --auth-password secret \ + --quit-after AUTH + assert_success assert_output --partial 'Authentication successful' - _run_in_container_bash 'openssl s_client -quiet -starttls smtp -connect 0.0.0.0:587 < /tmp/docker-mailserver-test/auth/sasl-ldap-smtp-auth.txt' + _send_email \ + --port 587 -tls \ + --auth LOGIN \ + --auth-user some.user@localhost.localdomain \ + --auth-password secret \ + --quit-after AUTH + assert_success assert_output --partial 'Authentication successful' } @@ -391,7 +426,7 @@ function _should_successfully_deliver_mail_to() { local SENDER_ADDRESS='user@external.tld' local RECIPIENT_ADDRESS=${1:?Recipient address is required} local MAIL_STORAGE_RECIPIENT=${2:?Recipient storage location is required} - local MAIL_TEMPLATE='/tmp/docker-mailserver-test/email-templates/test-email.txt' + local MAIL_TEMPLATE='/tmp/docker-mailserver-test/emails/test-email.txt' _run_in_container_bash "sendmail -f ${SENDER_ADDRESS} ${RECIPIENT_ADDRESS} < ${MAIL_TEMPLATE}" _wait_for_empty_mail_queue_in_container diff --git a/test/tests/serial/permit_docker.bats b/test/tests/serial/permit_docker.bats index 85f00484..2ebf5e3e 100644 --- a/test/tests/serial/permit_docker.bats +++ b/test/tests/serial/permit_docker.bats @@ -13,7 +13,7 @@ setup_file() { PRIVATE_CONFIG=$(duplicate_config_for_container . mail_smtponly_second_network) docker create --name mail_smtponly_second_network \ -v "${PRIVATE_CONFIG}":/tmp/docker-mailserver \ - -v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \ + -v "$(pwd)/test/files":/tmp/docker-mailserver-test:ro \ -e SMTP_ONLY=1 \ -e PERMIT_DOCKER=connected-networks \ -e OVERRIDE_HOSTNAME=mail.my-domain.com \ @@ -26,7 +26,7 @@ setup_file() { PRIVATE_CONFIG=$(duplicate_config_for_container . mail_smtponly_second_network_sender) docker run -d --name mail_smtponly_second_network_sender \ -v "${PRIVATE_CONFIG}":/tmp/docker-mailserver \ - -v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \ + -v "$(pwd)/test/files":/tmp/docker-mailserver-test:ro \ -e SMTP_ONLY=1 \ -e PERMIT_DOCKER=connected-networks \ -e OVERRIDE_HOSTNAME=mail.my-domain.com \ @@ -39,7 +39,7 @@ setup_file() { # create another container that enforces authentication even on local connections docker run -d --name mail_smtponly_force_authentication \ -v "${PRIVATE_CONFIG}":/tmp/docker-mailserver \ - -v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \ + -v "$(pwd)/test/files":/tmp/docker-mailserver-test:ro \ -e SMTP_ONLY=1 \ -e PERMIT_DOCKER=none \ -e OVERRIDE_HOSTNAME=mail.my-domain.com \ @@ -68,7 +68,7 @@ teardown_file() { _reload_postfix mail_smtponly_second_network # we should be able to send from the other container on the second network! - run docker exec mail_smtponly_second_network_sender /bin/sh -c "nc mail_smtponly_second_network 25 < /tmp/docker-mailserver-test/email-templates/smtp-only.txt" + run docker exec mail_smtponly_second_network_sender /bin/sh -c "nc mail_smtponly_second_network 25 < /tmp/docker-mailserver-test/emails/nc_raw/smtp-only.txt" assert_output --partial "250 2.0.0 Ok: queued as " repeat_in_container_until_success_or_timeout 60 mail_smtponly_second_network /bin/sh -c 'grep -cE "to=.*status\=sent" /var/log/mail/mail.log' } @@ -80,7 +80,7 @@ teardown_file() { _reload_postfix mail_smtponly_force_authentication # the mailserver should require authentication and a protocol error should occur when using TLS - run docker exec mail_smtponly_force_authentication /bin/sh -c "nc localhost 25 < /tmp/docker-mailserver-test/email-templates/smtp-only.txt" + run docker exec mail_smtponly_force_authentication /bin/sh -c "nc localhost 25 < /tmp/docker-mailserver-test/emails/nc_raw/smtp-only.txt" assert_output --partial "550 5.5.1 Protocol error" [[ ${status} -ge 0 ]] } diff --git a/test/tests/serial/test_helper.bats b/test/tests/serial/test_helper.bats index ecca3d85..a3ffa6cf 100644 --- a/test/tests/serial/test_helper.bats +++ b/test/tests/serial/test_helper.bats @@ -171,7 +171,7 @@ BATS_TEST_NAME_PREFIX='test helper functions:' # enable ClamAV to make message delivery slower, so we can detect it CONTAINER_NAME=$(docker run -d --rm \ -v "${PRIVATE_CONFIG}":/tmp/docker-mailserver \ - -v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \ + -v "$(pwd)/test/files":/tmp/docker-mailserver-test:ro \ -e ENABLE_CLAMAV=1 \ -h mail.my-domain.com \ -t "${NAME}") @@ -186,7 +186,7 @@ BATS_TEST_NAME_PREFIX='test helper functions:' [[ ${SECONDS} -lt 5 ]] # fill the queue with a message - docker exec "${CONTAINER_NAME}" /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/amavis-virus.txt" + docker exec "${CONTAINER_NAME}" /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/emails/amavis-virus.txt" # that should still be stuck in the queue ! TEST_TIMEOUT_IN_SECONDS=0 wait_for_empty_mail_queue_in_container "${CONTAINER_NAME}" @@ -203,7 +203,7 @@ BATS_TEST_NAME_PREFIX='test helper functions:' # enable ClamAV to make message delivery slower, so we can detect it CONTAINER_NAME=$(docker run -d --rm \ -v "${PRIVATE_CONFIG}":/tmp/docker-mailserver \ - -v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \ + -v "$(pwd)/test/files":/tmp/docker-mailserver-test:ro \ -e ENABLE_CLAMAV=1 \ -h mail.my-domain.com \ -t "${NAME}") @@ -213,7 +213,7 @@ BATS_TEST_NAME_PREFIX='test helper functions:' wait_for_smtp_port_in_container "${CONTAINER_NAME}" || docker logs "${CONTAINER_NAME}" # fill the queue with a message - docker exec "${CONTAINER_NAME}" /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/amavis-virus.txt" + docker exec "${CONTAINER_NAME}" /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/emails/amavis-virus.txt" # give it some time to clear the queue SECONDS=0 diff --git a/test/tests/serial/tests.bats b/test/tests/serial/tests.bats index 094454f0..26deb541 100644 --- a/test/tests/serial/tests.bats +++ b/test/tests/serial/tests.bats @@ -80,11 +80,13 @@ function teardown_file() { _default_teardown ; } } @test "imap: authentication works" { - _send_email 'auth/imap-auth' '-w 1 0.0.0.0 143' + _nc_wrapper 'auth/imap-auth' '-w 1 0.0.0.0 143' + assert_success } @test "imap: added user authentication works" { - _send_email 'auth/added-imap-auth' '-w 1 0.0.0.0 143' + _nc_wrapper 'auth/added-imap-auth' '-w 1 0.0.0.0 143' + assert_success } # @@ -288,13 +290,34 @@ EOF @test "spoofing: rejects sender forging" { # rejection of spoofed sender _wait_for_smtp_port_in_container_to_respond - _run_in_container_bash "openssl s_client -quiet -connect 0.0.0.0:465 < /tmp/docker-mailserver-test/auth/added-smtp-auth-spoofed.txt" + + # An authenticated user cannot use an envelope sender (MAIL FROM) + # address they do not own according to `main.cf:smtpd_sender_login_maps` lookup + _send_email \ + --port 465 -tlsc --auth LOGIN \ + --auth-user added@localhost.localdomain \ + --auth-password mypassword \ + --ehlo mail \ + --from user2@localhost.localdomain \ + --data 'auth/added-smtp-auth-spoofed' assert_output --partial 'Sender address rejected: not owned by user' } @test "spoofing: accepts sending as alias" { - _run_in_container_bash "openssl s_client -quiet -connect 0.0.0.0:465 < /tmp/docker-mailserver-test/auth/added-smtp-auth-spoofed-alias.txt | grep 'End data with'" + # An authenticated account should be able to send mail from an alias, + # Verifies `main.cf:smtpd_sender_login_maps` includes /etc/postfix/virtual + # The envelope sender address (MAIL FROM) is the lookup key + # to each table. Address is authorized when a result that maps to + # the DMS account is returned. + _send_email \ + --port 465 -tlsc --auth LOGIN \ + --auth-user user1@localhost.localdomain \ + --auth-password mypassword \ + --ehlo mail \ + --from alias1@localhost.localdomain \ + --data 'auth/added-smtp-auth-spoofed-alias' assert_success + assert_output --partial 'End data with' } # diff --git a/test/tests/serial/vmail-id.bats b/test/tests/serial/vmail-id.bats index b44670b2..0f54ea96 100644 --- a/test/tests/serial/vmail-id.bats +++ b/test/tests/serial/vmail-id.bats @@ -20,7 +20,7 @@ function setup_file() { function teardown_file() { _default_teardown ; } @test 'should successfully deliver mail' { - _send_email 'email-templates/existing-user1' + _send_email --data 'existing/user1' _wait_for_empty_mail_queue_in_container # Should be successfully sent (received) by Postfix: From 25c7024cc4c7a6ee81be70144f6ecaf4fddf44ca Mon Sep 17 00:00:00 2001 From: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com> Date: Wed, 3 Jan 2024 02:02:59 +0100 Subject: [PATCH 5/5] security(Postfix): Protect against "SMTP Smuggling" attack (#3727) View `CHANGELOG.md` entry and PR for details. --------- Co-authored-by: Brennan Kinney <5098581+polarathene@users.noreply.github.com> --- CHANGELOG.md | 15 ++++++++++++++- target/postfix/main.cf | 6 ++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eeeb843d..b6e6d906 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,23 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased](https://github.com/docker-mailserver/docker-mailserver/compare/v13.0.0...HEAD) +## [Unreleased](https://github.com/docker-mailserver/docker-mailserver/compare/v13.1.0...HEAD) > **Note**: Changes and additions listed here are contained in the `:edge` image tag. These changes may not be as stable as released changes. +### Security + +DMS is now secured against the [recently published spoofing attack "SMTP Smuggling"](https://www.postfix.org/smtp-smuggling.html) that affected Postfix ([#3727](https://github.com/docker-mailserver/docker-mailserver/pull/3727)): +- Postfix upgraded from `3.5.18` to `3.5.23` which provides the [long-term fix with `smtpd_forbid_bare_newline = yes`](https://www.postfix.org/smtp-smuggling.html#long) +- If you are unable to upgrade to this release of DMS, you may follow [these instructions](https://github.com/docker-mailserver/docker-mailserver/issues/3719#issuecomment-1870865118) for applying the [short-term workaround](https://www.postfix.org/smtp-smuggling.html#short). +- This change should not cause compatibility concerns for legitimate mail clients, however if you use software like `netcat` to send mail to DMS (_like our test-suite previously did_) it may now be rejected (_especially with the the short-term workaround `smtpd_data_restrictions = reject_unauth_pipelining`_). +- **NOTE:** This Postfix update also includes the new parameter [`smtpd_forbid_bare_newline_exclusions`](https://www.postfix.org/postconf.5.html#smtpd_forbid_bare_newline_exclusions) which defaults to `$mynetworks` for excluding trusted mail clients excluded from the restriction. + - With our default `PERMIT_DOCKER=none` this is not a concern. + - Presently the Docker daemon config has `user-proxy: true` enabled by default. + - On a host that can be reached by IPv6, this will route to a DMS IPv4 only container implicitly through the Docker network bridge gateway which rewrites the source address. + - If your `PERMIT_DOCKER` setting allows that gateway IP, then it is part of `$mynetworks` and this attack would not be prevented from such connections. + - If this affects your deployment, refer to [our IPv6 docs](https://docker-mailserver.github.io/docker-mailserver/v13.2/config/advanced/ipv6/) for advice on handling IPv6 correctly in Docker. Alternatively [use our `postfix-main.cf`](https://docker-mailserver.github.io/docker-mailserver/v13.2/config/advanced/override-defaults/postfix/) to set `smtpd_forbid_bare_newline_exclusions=` as empty. + ### Updates - The test suite now uses `swaks` instead of `nc`, which has multiple benefits ([#3732](https://github.com/docker-mailserver/docker-mailserver/pull/3732)): diff --git a/target/postfix/main.cf b/target/postfix/main.cf index 8c329c94..a9230347 100644 --- a/target/postfix/main.cf +++ b/target/postfix/main.cf @@ -57,6 +57,12 @@ smtpd_sender_restrictions = $dms_smtpd_sender_restrictions smtpd_discard_ehlo_keywords = silent-discard, dsn disable_vrfy_command = yes +# Security - Prevent SMTP Smuggling attack +# https://www.postfix.org/smtp-smuggling.html#long +smtpd_forbid_bare_newline = yes +# It is possible to exclude clients on trusted networks from this restriction (the upstream default is `$mynetwork`): +# smtpd_forbid_bare_newline_exclusions = $mynetworks + # Custom defined parameters for DMS: dms_smtpd_sender_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unknown_sender_domain # Submission ports 587 and 465 support for SPOOF_PROTECTION=1