1
0
mirror of https://github.com/tomav/docker-mailserver.git synced 2024-07-01 05:31:36 +02:00
docker-mailserver/target/scripts/helpers/postfix.sh
Brennan Kinney 5b54d1d32e
refactor: relay.sh (#3845)
* chore: `relay.sh` helper - Reference user config paths via variables

* chore: Better document postfix helper `_vhost_collect_postfix_domains()`

The functionality is effectively the same for the two configs for the most part when it comes to parsing out a domain from the target value.

Virtual aliases is more flexible in value, which may not have a domain-part present (manual user edit).

* chore: `check-for-change.sh` - Support VHOST change visibility

- Moves the "handle changes" logic into it's own scoped function, out of the main change detection loop logic.
- This will be benefit a future commit change that will rely on `VHOST_UPDATED=1`.

* chore: `relay.sh` - Minor revisions to minimize diff noise

- Better phrasing of the current logic comments.
- Regex patterns assigned to variables (easier to grok intention)
- Bulk of the logic for generating `/etc/postfix/relayhost_map` wrapped into a separate function with Postfix config setting handled separately.

* refactor: `relay.sh` opt-out logic

- Split the two distinct features that configure `/etc/postfix/relayhost_map` into separate functions (_`MATCH_VALID` var no longer needed for legacy support_).
- Instead of extracting domains from `postfix-accounts.cf` + `postfix-virtual.cf`, this has already been handled at `/etc/postfix/vhost`, sourcing from there is far less complicated.
- Rename loop var `DOMAIN_PART`to `SENDER_DOMAIN` for better context of what it represents when appended to the config file.
- Revised maintenance notes + guidance towards a future refactor of this relayhost feature support.

* docs: `relay.sh` - Additional comment revisions

* feat: `DEFAULT_RELAY_HOST` can now also use relay credentials ENV

- Remove comment regarding `smtp_sasl_password_maps = static:${RELAY_USER}:${RELAY_PASSWORD}`, it could be used but `main.cf` presently has `644` permissions vs the `sasl_passwd` file permissions of `600`, less secure at preventing leaking of secrets (ignoring the ENV exposure itself).
- Move the `main.cf` settings specific to relayhost credentials support / security into to the relevant function scope instead. This also allows for the configuration to be applied by a change detection event without container restart requirement.
- Outer functions for setup and change detection to call have a clearer config dependency guard, as does the `_legacy_support()`.
- These changes now support `DEFAULT_RELAY_HOST` to leverage the relay credentials ENV as well.
- `DATABASE_RELAYHOSTS` is available in scope to the functions called here that reference it.

* docs: Revised ENV docs on relay host config

Better quality guidance on configuring relay hosts.

* chore: Add entry to `CHANGELOG.md`

* fix: `relay.sh` - `grep` regex compatibility with `+` requires `-E`

* chore: `postfix.sh` - `FIRST_FIELD` => More descriptive field name
2024-01-31 10:24:43 +13:00

142 lines
5.9 KiB
Bash

#!/bin/bash
# Support for Postfix features
# Docs - virtual_mailbox_domains (Used in /etc/postfix/main.cf):
# http://www.postfix.org/ADDRESS_CLASS_README.html#virtual_mailbox_class
# http://www.postfix.org/VIRTUAL_README.html
# > If you omit this setting then Postfix will reject mail (relay access denied) or will not be able to deliver it.
# > NEVER list a virtual MAILBOX domain name as a `mydestination` domain!
# > NEVER list a virtual MAILBOX domain name as a virtual ALIAS domain!
#
# > Execute the command "postmap /etc/postfix/virtual" after changing the virtual file,
# > execute "postmap /etc/postfix/vmailbox" after changing the vmailbox file,
# > and execute the command "postfix reload" after changing the main.cf file.
#
# - virtual_alias_domains is not used by docker-mailserver at present, although LDAP docs reference it.
# - `postmap` only seems relevant when the lookup type is one of these `file_type` values: http://www.postfix.org/postmap.1.html
# Should not be a concern for most types used by `docker-mailserver`: texthash, ldap, pcre, tcp, unionmap, unix.
# The only other type in use by `docker-mailserver` is the hash type for /etc/aliases, which `postalias` handles.
function _create_postfix_vhost() {
# `main.cf` configures `virtual_mailbox_domains = /etc/postfix/vhost`
# NOTE: Amavis also consumes this file.
local DATABASE_VHOST='/etc/postfix/vhost'
local TMP_VHOST='/tmp/vhost.postfix.tmp'
_vhost_collect_postfix_domains
_create_vhost
}
# Filter unique values into a proper DATABASE_VHOST config:
function _create_vhost() {
: >"${DATABASE_VHOST}"
if [[ -f ${TMP_VHOST} ]]; then
sort < "${TMP_VHOST}" | uniq >>"${DATABASE_VHOST}"
rm "${TMP_VHOST}"
fi
}
# Collects domains from configs (DATABASE_) into TMP_VHOST
function _vhost_collect_postfix_domains() {
local DATABASE_ACCOUNTS='/tmp/docker-mailserver/postfix-accounts.cf'
local DATABASE_VIRTUAL='/tmp/docker-mailserver/postfix-virtual.cf'
local DOMAIN UNAME
# Extract domains from mail accounts:
if [[ -f ${DATABASE_ACCOUNTS} ]]; then
while IFS=$'|' read -r MAIL_ACCOUNT _; do
# It is expected valid lines have the format local-part@domain-part:
DOMAIN=$(cut -d '@' -f 2 <<< "${MAIL_ACCOUNT}")
echo "${DOMAIN}" >>"${TMP_VHOST}"
done < <(_get_valid_lines_from_file "${DATABASE_ACCOUNTS}")
fi
# TODO: Consider if virtual aliases should be configured to the same vhost file:
# https://github.com/docker-mailserver/docker-mailserver/issues/2813#issuecomment-1272394563
# Extract domains from virtual alias config:
# Aliases may have the forms: 'local-part@domain-part', only 'local-part', or '@domain-part' (wildcard catch-all)
if [[ -f ${DATABASE_VIRTUAL} ]]; then
while read -r ALIAS_FIELD _; do
UNAME=$(cut -d '@' -f 1 <<< "${ALIAS_FIELD}")
DOMAIN=$(cut -d '@' -f 2 <<< "${ALIAS_FIELD}")
# Only add valid domain-parts found:
# The '@' is optional for an alias key (eg: "user1 other@domain.tld"),
# but cut with -f2 would output the same value as it would -f1 when '@' is missing.
[[ ${UNAME} != "${DOMAIN}" ]] && echo "${DOMAIN}" >>"${TMP_VHOST}"
done < <(_get_valid_lines_from_file "${DATABASE_VIRTUAL}")
fi
_vhost_ldap_support
}
# Add DOMAINNAME (not an ENV, set by `helpers/dns.sh`) to vhost.
# NOTE: `setup-stack.sh:_setup_ldap` has related logic:
# - `main.cf:mydestination` setting removes `$mydestination` as an LDAP bugfix.
# - `main.cf:virtual_mailbox_domains` uses `/etc/postfix/vhost`, but may
# conditionally include a 2nd table (ldap:/etc/postfix/ldap-domains.cf).
function _vhost_ldap_support() {
[[ ${ACCOUNT_PROVISIONER} == 'LDAP' ]] && echo "${DOMAINNAME}" >>"${TMP_VHOST}"
}
# Docs - Postfix lookup table files:
# http://www.postfix.org/DATABASE_README.html
#
# Types used in scripts or config: ldap, texthash, hash, pcre, tcp, unionmap, unix
# ldap type changes are network based, no `postfix reload` required.
# texthash type is read into memory when Postfix process starts, requires `postfix reload` to apply changes.
# texthash type does not require running `postmap` after changes are made, other types might.
#
# Examples of different types actively used:
# setup-stack.sh:_setup_spoof_protection uses texthash + hash + pcre, and conditionally unionmap
# main.cf:
# - alias_maps and alias_database both use hash:/etc/aliases
# - virtual_mailbox_maps and virtual_alias_maps use texthash
# - `alias.sh` may append pcre:/etc/postfix/regexp to virtual_alias_maps in `main.cf`
#
# /etc/aliases is handled by `alias.sh` and uses `postalias` to update the Postfix alias database. No need for `postmap`.
# http://www.postfix.org/postalias.1.html
# Add a key with a value to Postfix's main configuration file
# or update an existing key. An already existing key can be updated
# by either appending to the existing value (default) or by prepending.
#
# @param ${1} = key name in Postfix's main configuration file
# @param ${2} = new value (appended or prepended)
# @param ${3} = action "append" (default) or "prepend" [OPTIONAL]
function _add_to_or_update_postfix_main() {
local KEY=${1:?Key name is required}
local NEW_VALUE=${2:?New value is required}
local ACTION=${3:-append}
local CURRENT_VALUE
# Get current value from /etc/postfix/main.cf
_adjust_mtime_for_postfix_maincf
CURRENT_VALUE=$(postconf -h "${KEY}" 2>/dev/null)
# If key does not exist or value is empty, add it - otherwise update with ACTION:
if [[ -z ${CURRENT_VALUE} ]]; then
postconf "${KEY} = ${NEW_VALUE}"
else
# If $NEW_VALUE is already present --> nothing to do, skip.
if [[ " ${CURRENT_VALUE} " == *" ${NEW_VALUE} "* ]]; then
return 0
fi
case "${ACTION}" in
('append')
postconf "${KEY} = ${CURRENT_VALUE} ${NEW_VALUE}"
;;
('prepend')
postconf "${KEY} = ${NEW_VALUE} ${CURRENT_VALUE}"
;;
(*)
_log 'error' "Action '${3}' in _add_to_or_update_postfix_main is unknown"
return 1
;;
esac
fi
}