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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@ All notable changes to this project will be documented in this file. The format
### Breaking

- The environment variable `ENABLE_LDAP=1` has been changed to `ACCOUNT_PROVISIONER=LDAP`.
- Postfix now defaults to supporting DSNs (_[Delivery Status Notifications](https://github.com/docker-mailserver/docker-mailserver/pull/3572#issuecomment-1751880574)_) only for authenticated users. This is a security measure to reduce spammer abuse of your DMS instance as a backscatter source.
- If you need to modify this change, please let us know by opening an issue / discussion.
- You can [opt-out (_enable DSNs_) via the `postfix-main.cf` override support](https://docker-mailserver.github.io/docker-mailserver/v12.1/config/advanced/override-defaults/postfix/) using the contents: `smtpd_discard_ehlo_keywords =`.
- Likewise for authenticated users, the submission(s) ports (465 + 587) are configured internally via `master.cf` to keep DSNs enabled (_since authentication protects from abuse_).

If necessary, DSNs for authenticated users can be disabled via the `postfix-master.cf` override with the following contents:

```
submission/inet/smtpd_discard_ehlo_keywords=silent-discard,dsn
submissions/inet/smtpd_discard_ehlo_keywords=silent-discard,dsn
```

### Added

Expand Down
1 change: 1 addition & 0 deletions target/postfix/main.cf
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_una
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, reject_unauth_pipelining, reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname, reject_unknown_recipient_domain
smtpd_client_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, reject_unauth_pipelining
smtpd_sender_restrictions = $dms_smtpd_sender_restrictions
smtpd_discard_ehlo_keywords = silent-discard, dsn
disable_vrfy_command = yes

# Custom defined parameters for DMS:
Expand Down
2 changes: 2 additions & 0 deletions target/postfix/master.cf
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ submission inet n - n - - smtpd
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o smtpd_sender_restrictions=$mua_sender_restrictions
-o smtpd_discard_ehlo_keywords=
-o milter_macro_daemon_name=ORIGINATING
-o cleanup_service_name=sender-cleanup

Expand All @@ -37,6 +38,7 @@ submissions inet n - n - - smtpd
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o smtpd_sender_restrictions=$mua_sender_restrictions
-o smtpd_discard_ehlo_keywords=
-o milter_macro_daemon_name=ORIGINATING
-o cleanup_service_name=sender-cleanup

Expand Down
1 change: 1 addition & 0 deletions test/config/dsn/postfix-main.cf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
smtpd_discard_ehlo_keywords =
2 changes: 2 additions & 0 deletions test/config/dsn/postfix-master.cf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
submission/inet/smtpd_discard_ehlo_keywords=silent-discard,dsn
submissions/inet/smtpd_discard_ehlo_keywords=silent-discard,dsn
14 changes: 14 additions & 0 deletions test/test-files/email-templates/dsn-authenticated.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
EHLO mail
AUTH LOGIN dXNlcjFAbG9jYWxob3N0LmxvY2FsZG9tYWlu
bXlwYXNzd29yZA==
MAIL FROM: [email protected]
RCPT TO: [email protected] NOTIFY=success,failure
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Am I right to understand the difference from regular authenticated / unauthenticated templates is effectively only the NOTIFY=success,failure addition?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, NOTIFY=... should be the only difference here.

DATA
From: Existing Local User <[email protected]>
To: Existing Local User <[email protected]>
Date: Sat, 22 May 2010 07:43:25 -0400
Subject: Test Message
This is a test mail.

.
QUIT
12 changes: 12 additions & 0 deletions test/test-files/email-templates/dsn-unauthenticated.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
HELO mail.external.tld
MAIL FROM: [email protected]
RCPT TO: [email protected] NOTIFY=success,failure
DATA
From: Docker Mail Server <[email protected]>
To: Existing Local User <[email protected]>
Date: Sat, 22 May 2010 07:43:25 -0400
Subject: Test Message
This is a test mail.

.
QUIT
95 changes: 95 additions & 0 deletions test/tests/parallel/set3/mta/dsn.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
load "${REPOSITORY_ROOT}/test/helper/setup"
load "${REPOSITORY_ROOT}/test/helper/common"

BATS_TEST_NAME_PREFIX='[DSN] '
CONTAINER1_NAME='dms-test_dsn_send_always'
CONTAINER2_NAME='dms-test_dsn_send_auth'
CONTAINER3_NAME='dms-test_dsn_send_none'
# A similar line is added to the log when a DSN (Delivery Status Notification) is sent:
#
# postfix/bounce[1023]: C943BA6B46: sender delivery status notification: DBF86A6B4CO
#
LOG_DSN='delivery status notification'

function setup_file() {
local CUSTOM_SETUP_ARGUMENTS=(
# Required only for delivery via nc (_send_email)
--env PERMIT_DOCKER=container
)

export CONTAINER_NAME=${CONTAINER1_NAME}
_init_with_defaults
# Unset `smtpd_discard_ehlo_keywords` to allow DSNs by default on any `smtpd` service:
cp "${TEST_TMP_CONFIG}/dsn/postfix-main.cf" "${TEST_TMP_CONFIG}/postfix-main.cf"
_common_container_setup 'CUSTOM_SETUP_ARGUMENTS'
_wait_for_service postfix
_wait_for_smtp_port_in_container
Comment thread
georglauterbach marked this conversation as resolved.

export CONTAINER_NAME=${CONTAINER2_NAME}
_init_with_defaults
_common_container_setup 'CUSTOM_SETUP_ARGUMENTS'
_wait_for_service postfix
_wait_for_smtp_port_in_container

export CONTAINER_NAME=${CONTAINER3_NAME}
_init_with_defaults
# Mirror default main.cf (disable DSN on ports 465 + 587 too):
cp "${TEST_TMP_CONFIG}/dsn/postfix-master.cf" "${TEST_TMP_CONFIG}/postfix-master.cf"
_common_container_setup 'CUSTOM_SETUP_ARGUMENTS'
_wait_for_service postfix
_wait_for_smtp_port_in_container
}

function teardown_file() {
docker rm -f "${CONTAINER1_NAME}" "${CONTAINER2_NAME}" "${CONTAINER3_NAME}"
}

@test "should always send a DSN when requested" {
export CONTAINER_NAME=${CONTAINER1_NAME}

Comment thread
allddd marked this conversation as resolved.
_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'
_wait_for_empty_mail_queue_in_container
Comment thread
allddd marked this conversation as resolved.

_run_in_container grep "${LOG_DSN}" /var/log/mail/mail.log
_should_output_number_of_lines 3
}

# Defaults test case
@test "should only send a DSN when requested from ports 465/587" {
Comment thread
polarathene marked this conversation as resolved.
export CONTAINER_NAME=${CONTAINER2_NAME}

_send_email 'email-templates/dsn-unauthenticated'
_wait_for_empty_mail_queue_in_container

# DSN requests can now only be made on ports 465 and 587,
# so grep should not find anything.
#
# Although external requests are discarded, anyone who has requested a DSN
# will still receive it, but it will come from the sending mail server, not this one.
_run_in_container grep "${LOG_DSN}" /var/log/mail/mail.log
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'
_wait_for_empty_mail_queue_in_container

_run_in_container grep "${LOG_DSN}" /var/log/mail/mail.log
_should_output_number_of_lines 2
}

@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'
_wait_for_empty_mail_queue_in_container

# DSN requests are rejected regardless of origin.
# This is usually a bad idea, as you won't get them either.
_run_in_container grep "${LOG_DSN}" /var/log/mail/mail.log
assert_failure
}