You've already forked docker-mailserver
							
							
				mirror of
				https://github.com/docker-mailserver/docker-mailserver.git
				synced 2025-10-31 00:17:45 +02:00 
			
		
		
		
	fix: accounts.sh - Support first valid local account (#4581)
				
					
				
			- Ensure catch-all alias entries (eg: `@example.test`) are also skipped. Adding a dummy account for catch-all will not match a `quota-status` query to Dovecot by Postfix for a recipient. - When there are multiple addresses provided, they will now be iterated through by the `,` delimiter, instead of as a single value that fails. This way the first valid aliased address to a local Dovecot mailbox account will now be used for the dummy alias account. - The common logic for extracting the quota user attribute is now split out to a common function call.
This commit is contained in:
		| @@ -6,6 +6,11 @@ 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. | ||||
|  | ||||
| ### Fixed | ||||
|  | ||||
| - **Internal:** | ||||
|   - `ENABLE_QUOTAS=1` - When an alias has multiple addresses, the first local mailbox address found will be used for the Dovecot dummy account workaround ([#4581](https://github.com/docker-mailserver/docker-mailserver/pull/4581)) | ||||
|  | ||||
| ### Removed | ||||
|  | ||||
| - **SpamAssassin:** | ||||
| @@ -36,7 +41,7 @@ All notable changes to this project will be documented in this file. The format | ||||
|   - [ENV can be declared with a `__FILE` suffix](https://docker-mailserver.github.io/docker-mailserver/v15.1/config/environment/) to read a value from a file during initial DMS setup scripts ([#4359](https://github.com/docker-mailserver/docker-mailserver/pull/4359)) | ||||
|   - Improved docs for the ENV `OVERRIDE_HOSTNAME` ([#4492](https://github.com/docker-mailserver/docker-mailserver/pull/4492)) | ||||
| - **Internal:** | ||||
|   - [`DMS_CONFIG_POLL`](https://docker-mailserver.github.io/docker-mailserver/v15.0/config/environment/#dms_config_poll) supports adjusting the polling rate (seconds) for the change detection service `check-for-changes.sh` ([#4450](https://github.com/docker-mailserver/docker-mailserver/pull/4450)) | ||||
|   - [`DMS_CONFIG_POLL`](https://docker-mailserver.github.io/docker-mailserver/v15.1/config/environment/#dms_config_poll) supports adjusting the polling rate (seconds) for the change detection service `check-for-changes.sh` ([#4450](https://github.com/docker-mailserver/docker-mailserver/pull/4450)) | ||||
|  | ||||
| ### Fixes | ||||
|  | ||||
|   | ||||
| @@ -36,16 +36,7 @@ function _create_accounts() { | ||||
|       USER=$(echo "${LOGIN}" | cut -d @ -f1) | ||||
|       DOMAIN=$(echo "${LOGIN}" | cut -d @ -f2) | ||||
|  | ||||
|       # test if user has a defined quota | ||||
|       if [[ -f /tmp/docker-mailserver/dovecot-quotas.cf ]]; then | ||||
|         declare -a USER_QUOTA | ||||
|         IFS=':' read -r -a USER_QUOTA < <(grep "${USER}@${DOMAIN}:" -i /tmp/docker-mailserver/dovecot-quotas.cf) | ||||
|  | ||||
|         if [[ ${#USER_QUOTA[@]} -eq 2 ]]; then | ||||
|           USER_ATTRIBUTES="${USER_ATTRIBUTES:+${USER_ATTRIBUTES} }userdb_quota_rule=*:bytes=${USER_QUOTA[1]}" | ||||
|         fi | ||||
|       fi | ||||
|  | ||||
|       USER_ATTRIBUTES="$(_add_attribute_dovecot_quota "${LOGIN}" "${USER_ATTRIBUTES}")" | ||||
|       if [[ -z ${USER_ATTRIBUTES} ]]; then | ||||
|         _log 'debug' "Creating user '${USER}' for domain '${DOMAIN}'" | ||||
|       else | ||||
| @@ -82,41 +73,53 @@ function _create_accounts() { | ||||
|   fi | ||||
| } | ||||
|  | ||||
| # Required when using Dovecot Quotas to avoid blacklisting risk from backscatter | ||||
| # Note: This is a workaround only suitable for basic aliases that map to single real addresses, | ||||
| # not multiple addresses (real accounts or additional aliases), those will not work with Postfix | ||||
| # `quota-status` policy service and remain at risk of backscatter. | ||||
| # Required when using Dovecot Quotas to avoid blacklisting risk from backscatter. | ||||
| # Note: This is a workaround only suitable for basic aliases that map to a single real address, | ||||
| # not multiple addresses (real accounts or additional aliases), those will not work with | ||||
| # the Postfix `quota-status` policy service and remain at risk of backscatter. | ||||
| # | ||||
| # see https://github.com/docker-mailserver/docker-mailserver/pull/2248#issuecomment-953313852 | ||||
| # for more details on this method | ||||
| # for more details on this method, see: | ||||
| # https://github.com/docker-mailserver/docker-mailserver/pull/2248#issuecomment-953313852 | ||||
| function _create_dovecot_alias_dummy_accounts() { | ||||
|   local DATABASE_VIRTUAL='/tmp/docker-mailserver/postfix-virtual.cf' | ||||
|   # NOTE: `DATABASE_ACCOUNTS` should be in scope (provided from the expected caller: `_create_accounts()`) | ||||
|  | ||||
|   # Add aliases associated to DMS mailbox accounts as dummy entries into Dovecot's userdb, | ||||
|   # These will share the same storage as a real account for the `quota-status` check to query. | ||||
|   if [[ -f ${DATABASE_VIRTUAL} ]] && [[ ${ENABLE_QUOTAS} -eq 1 ]]; then | ||||
|     # adding aliases to Dovecot's userdb | ||||
|     # ${REAL_FQUN} is a user's fully-qualified username | ||||
|     local ALIAS REAL_FQUN DOVECOT_USERDB_LINE | ||||
|     while read -r ALIAS REAL_FQUN; do | ||||
|       # alias is assumed to not be a proper e-mail | ||||
|       # these aliases do not need to be added to Dovecot's userdb | ||||
|       [[ ! ${ALIAS} == *@* ]] && continue | ||||
|     local ALIAS ALIASED DOVECOT_USERDB_LINE | ||||
|     while read -r ALIAS ALIASED; do | ||||
|       # Skip any alias lacking `@` (aka local-part only) or is a catch-all domain (starts with `@`): | ||||
|       [[ ! ${ALIAS} =~ .+@.+ ]] && continue | ||||
|  | ||||
|       # clear possibly already filled arrays | ||||
|       # do not remove the following line of code | ||||
|       unset REAL_ACC USER_QUOTA | ||||
|       declare -a REAL_ACC USER_QUOTA | ||||
|       # ${REAL_FQUN} is a user's fully-qualified username | ||||
|       unset REAL_FQUN | ||||
|       local REAL_FQUN REAL_USERNAME REAL_DOMAINNAME | ||||
|  | ||||
|       local REAL_USERNAME REAL_DOMAINNAME | ||||
|       REAL_USERNAME=$(cut -d '@' -f 1 <<< "${REAL_FQUN}") | ||||
|       REAL_DOMAINNAME=$(cut -d '@' -f 2 <<< "${REAL_FQUN}") | ||||
|       # Support checking multiple aliased addresses (split by `,` delimiter): | ||||
|       # - The first local account matched will be associated to the alias | ||||
|       # - Does not support resolving FQUN if it were also an alias | ||||
|       for FQUN in ${ALIASED//,/ } | ||||
|       do | ||||
|         if grep -q "${FQUN}" "${DATABASE_ACCOUNTS}"; then | ||||
|           REAL_FQUN="${FQUN}" | ||||
|           REAL_USERNAME=$(cut -d '@' -f 1 <<< "${REAL_FQUN}") | ||||
|           REAL_DOMAINNAME=$(cut -d '@' -f 2 <<< "${REAL_FQUN}") | ||||
|           break | ||||
|         fi | ||||
|       done | ||||
|  | ||||
|       if ! grep -q "${REAL_FQUN}" "${DATABASE_ACCOUNTS}"; then | ||||
|       if [[ -z ${REAL_FQUN} ]] || ! grep -q "${REAL_FQUN}" "${DATABASE_ACCOUNTS}"; then | ||||
|         _log 'debug' "Alias '${ALIAS}' is non-local (or mapped to a non-existing account) and will not be added to Dovecot's userdb" | ||||
|         continue | ||||
|       fi | ||||
|  | ||||
|       _log 'debug' "Adding alias '${ALIAS}' for user '${REAL_FQUN}' to Dovecot's userdb" | ||||
|  | ||||
|       # Clear possibly already filled arrays (do not remove the following line of code) | ||||
|       unset REAL_ACC USER_QUOTA | ||||
|       declare -a REAL_ACC USER_QUOTA | ||||
|  | ||||
|       # ${REAL_ACC[0]} => real account name (e-mail address) == ${REAL_FQUN} | ||||
|       # ${REAL_ACC[1]} => password hash | ||||
|       # ${REAL_ACC[2]} => optional user attributes | ||||
| @@ -126,13 +129,8 @@ function _create_dovecot_alias_dummy_accounts() { | ||||
|         _dms_panic__misconfigured 'postfix-accounts.cf' 'alias configuration' | ||||
|       fi | ||||
|  | ||||
|       # test if user has a defined quota | ||||
|       if [[ -f /tmp/docker-mailserver/dovecot-quotas.cf ]]; then | ||||
|         IFS=':' read -r -a USER_QUOTA < <(grep "${REAL_FQUN}:" -i /tmp/docker-mailserver/dovecot-quotas.cf) | ||||
|         if [[ ${#USER_QUOTA[@]} -eq 2 ]]; then | ||||
|           REAL_ACC[2]="${REAL_ACC[2]:+${REAL_ACC[2]} }userdb_quota_rule=*:bytes=${USER_QUOTA[1]}" | ||||
|         fi | ||||
|       fi | ||||
|       # Update user attributes with custom quota if found for the `REAL_FQUN`: | ||||
|       REAL_ACC[2]="$(_add_attribute_dovecot_quota "${REAL_FQUN}" "${REAL_ACC[2]}")" | ||||
|  | ||||
|       DOVECOT_USERDB_LINE="${ALIAS}:${REAL_ACC[1]}:${DMS_VMAIL_UID}:${DMS_VMAIL_GID}::/var/mail/${REAL_DOMAINNAME}/${REAL_USERNAME}/home::${REAL_ACC[2]:-}" | ||||
|       # Match a full line with `-xF` to avoid regex patterns introducing false positives matching `ALIAS`: | ||||
| @@ -178,3 +176,19 @@ function _create_masters() { | ||||
|     done < <(_get_valid_lines_from_file "${DATABASE_DOVECOT_MASTERS}") | ||||
|   fi | ||||
| } | ||||
|  | ||||
| function _add_attribute_dovecot_quota() { | ||||
|   local MAIL_ACCOUNT="${1}" | ||||
|   local USER_ATTRIBUTES="${2}" | ||||
|  | ||||
|   if [[ -f /tmp/docker-mailserver/dovecot-quotas.cf ]]; then | ||||
|     declare -a USER_QUOTA | ||||
|     IFS=':' read -r -a USER_QUOTA < <(grep -i "${MAIL_ACCOUNT}:" /tmp/docker-mailserver/dovecot-quotas.cf) | ||||
|  | ||||
|     if [[ ${#USER_QUOTA[@]} -eq 2 ]]; then | ||||
|       USER_ATTRIBUTES="${USER_ATTRIBUTES:+${USER_ATTRIBUTES} }userdb_quota_rule=*:bytes=${USER_QUOTA[1]}" | ||||
|     fi | ||||
|   fi | ||||
|  | ||||
|   echo "${USER_ATTRIBUTES}" | ||||
| } | ||||
|   | ||||
| @@ -27,19 +27,18 @@ function teardown_file() { _default_teardown ; } | ||||
|   assert_line --index 3 'added@localhost.localdomain' | ||||
|   assert_line --index 4 'pass@localhost.localdomain' | ||||
|   assert_line --index 5 'alias1@localhost.localdomain' | ||||
|   # TODO: Probably not intentional?: | ||||
|   assert_line --index 6 '@localdomain2.com' | ||||
|   # Dovecot "dummy accounts" for quota support, see `test/config/postfix-virtual.cf` for more context | ||||
|   assert_line --index 7 'prefixtest@localhost.localdomain' | ||||
|   assert_line --index 8 'test@localhost.localdomain' | ||||
|   assert_line --index 9 'first-name@localhost.localdomain' | ||||
|   assert_line --index 10 'first.name@localhost.localdomain' | ||||
|   _should_output_number_of_lines 11 | ||||
|   assert_line --index 6 'prefixtest@localhost.localdomain' | ||||
|   assert_line --index 7 'test@localhost.localdomain' | ||||
|   assert_line --index 8 'first-name@localhost.localdomain' | ||||
|   assert_line --index 9 'first.name@localhost.localdomain' | ||||
|   _should_output_number_of_lines 10 | ||||
|  | ||||
|   refute_line --partial '@localdomain2.com' | ||||
|  | ||||
|   # Relevant log output from scripts/helpers/accounts.sh:_create_dovecot_alias_dummy_accounts(): | ||||
|   # [  DEBUG  ]  Adding alias 'alias1@localhost.localdomain' for user 'user1@localhost.localdomain' to Dovecot's userdb | ||||
|   # [  DEBUG  ]  Alias 'alias2@localhost.localdomain' is non-local (or mapped to a non-existing account) and will not be added to Dovecot's userdb | ||||
|   # [  DEBUG  ]  Adding alias '@localdomain2.com' for user 'user1@localhost.localdomain' to Dovecot's userdb | ||||
| } | ||||
|  | ||||
| # Dovecot "dummy accounts" for quota support, see `test/config/postfix-virtual.cf` for more context | ||||
|   | ||||
		Reference in New Issue
	
	Block a user