mirror of
https://github.com/docker-mailserver/docker-mailserver.git
synced 2024-01-19 02:48:50 +00:00
ab55343d8e
* outsourcing env variable setup This commit contains major parts of the work of refactoring the setup and usage of environment variables. It outsources the setup into its own script and provides dedicated functions to be executed at a later point in time. A **new** env variable was added: `USER_PROVISIONG` which provides a better way of defining which method / protocol to use when it comes to setting up users. This way, the `ENABLE_LDAP` variable is deprecated, but all of this is backwards compatible due to a "compatibility layer", a function provided by the new variables script. This is not a breaking change. It mostly refators internal scripts. The only change facing the user-side is the deprecation of `ENABLE_LDAP`. We can prolong the period of deprecation for this variable as long as we want, because the new function that ensures backwards compatibility provides a clean interface for the future. Co-authored-by: Brennan Kinney <5098581+polarathene@users.noreply.github.com> Co-authored-by: Casper <casperklein@users.noreply.github.com>
215 lines
7.9 KiB
Bash
215 lines
7.9 KiB
Bash
#! /bin/bash
|
|
|
|
# Support for Postfix accounts managed via Dovecot
|
|
|
|
# It looks like the DOMAIN in below logic is being stored in /etc/postfix/vhost,
|
|
# even if it's a value used for Postfix `main.cf:mydestination`, which apparently isn't good?
|
|
# Only an issue when $myhostname is an exact match (eg: bare domain FQDN).
|
|
|
|
DOVECOT_USERDB_FILE=/etc/dovecot/userdb
|
|
DOVECOT_MASTERDB_FILE=/etc/dovecot/masterdb
|
|
|
|
function _create_accounts
|
|
{
|
|
: >/etc/postfix/vmailbox
|
|
: >"${DOVECOT_USERDB_FILE}"
|
|
|
|
[[ ${ACCOUNT_PROVISIONER} == 'FILE' ]] || return 0
|
|
|
|
local DATABASE_ACCOUNTS='/tmp/docker-mailserver/postfix-accounts.cf'
|
|
_create_masters
|
|
|
|
if [[ -f ${DATABASE_ACCOUNTS} ]]
|
|
then
|
|
_log 'trace' "Checking file line endings"
|
|
sed -i 's|\r||g' "${DATABASE_ACCOUNTS}"
|
|
|
|
_log 'trace' "Regenerating postfix user list"
|
|
echo "# WARNING: this file is auto-generated. Modify ${DATABASE_ACCOUNTS} to edit the user list." > /etc/postfix/vmailbox
|
|
|
|
# checking that ${DATABASE_ACCOUNTS} ends with a newline
|
|
# shellcheck disable=SC1003
|
|
sed -i -e '$a\' "${DATABASE_ACCOUNTS}"
|
|
|
|
chown dovecot:dovecot "${DOVECOT_USERDB_FILE}"
|
|
chmod 640 "${DOVECOT_USERDB_FILE}"
|
|
|
|
sed -i -e '/\!include auth-ldap\.conf\.ext/s/^/#/' /etc/dovecot/conf.d/10-auth.conf
|
|
sed -i -e '/\!include auth-passwdfile\.inc/s/^#//' /etc/dovecot/conf.d/10-auth.conf
|
|
|
|
# creating users ; 'pass' is encrypted
|
|
# comments and empty lines are ignored
|
|
local LOGIN PASS USER_ATTRIBUTES
|
|
while IFS=$'|' read -r LOGIN PASS USER_ATTRIBUTES
|
|
do
|
|
# Setting variables for better readability
|
|
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
|
|
|
|
if [[ -z ${USER_ATTRIBUTES} ]]
|
|
then
|
|
_log 'debug' "Creating user '${USER}' for domain '${DOMAIN}'"
|
|
else
|
|
_log 'debug' "Creating user '${USER}' for domain '${DOMAIN}' with attributes '${USER_ATTRIBUTES}'"
|
|
fi
|
|
|
|
local POSTFIX_VMAILBOX_LINE DOVECOT_USERDB_LINE
|
|
|
|
POSTFIX_VMAILBOX_LINE="${LOGIN} ${DOMAIN}/${USER}/"
|
|
if grep -qF "${POSTFIX_VMAILBOX_LINE}" /etc/postfix/vmailbox
|
|
then
|
|
_log 'warn' "User '${USER}@${DOMAIN}' will not be added to '/etc/postfix/vmailbox' twice"
|
|
else
|
|
echo "${POSTFIX_VMAILBOX_LINE}" >>/etc/postfix/vmailbox
|
|
fi
|
|
|
|
# Dovecot's userdb has the following format
|
|
# user:password:uid:gid:(gecos):home:(shell):extra_fields
|
|
DOVECOT_USERDB_LINE="${LOGIN}:${PASS}:5000:5000::/var/mail/${DOMAIN}/${USER}::${USER_ATTRIBUTES}"
|
|
if grep -qF "${DOVECOT_USERDB_LINE}" "${DOVECOT_USERDB_FILE}"
|
|
then
|
|
_log 'warn' "Login '${LOGIN}' will not be added to '${DOVECOT_USERDB_FILE}' twice"
|
|
else
|
|
echo "${DOVECOT_USERDB_LINE}" >>"${DOVECOT_USERDB_FILE}"
|
|
fi
|
|
|
|
mkdir -p "/var/mail/${DOMAIN}/${USER}"
|
|
|
|
# copy user provided sieve file, if present
|
|
if [[ -e "/tmp/docker-mailserver/${LOGIN}.dovecot.sieve" ]]
|
|
then
|
|
cp "/tmp/docker-mailserver/${LOGIN}.dovecot.sieve" "/var/mail/${DOMAIN}/${USER}/.dovecot.sieve"
|
|
fi
|
|
done < <(_get_valid_lines_from_file "${DATABASE_ACCOUNTS}")
|
|
|
|
_create_dovecot_alias_dummy_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.
|
|
#
|
|
# see https://github.com/docker-mailserver/docker-mailserver/pull/2248#issuecomment-953313852
|
|
# for more details on this method
|
|
function _create_dovecot_alias_dummy_accounts
|
|
{
|
|
local DATABASE_VIRTUAL='/tmp/docker-mailserver/postfix-virtual.cf'
|
|
|
|
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
|
|
|
|
# clear possibly already filled arrays
|
|
# do not remove the following line of code
|
|
unset REAL_ACC USER_QUOTA
|
|
declare -a REAL_ACC USER_QUOTA
|
|
|
|
local REAL_USERNAME REAL_DOMAINNAME
|
|
REAL_USERNAME=$(cut -d '@' -f 1 <<< "${REAL_FQUN}")
|
|
REAL_DOMAINNAME=$(cut -d '@' -f 2 <<< "${REAL_FQUN}")
|
|
|
|
if ! 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"
|
|
|
|
# ${REAL_ACC[0]} => real account name (e-mail address) == ${REAL_FQUN}
|
|
# ${REAL_ACC[1]} => password hash
|
|
# ${REAL_ACC[2]} => optional user attributes
|
|
IFS='|' read -r -a REAL_ACC < <(grep "${REAL_FQUN}" "${DATABASE_ACCOUNTS}")
|
|
|
|
if [[ -z ${REAL_ACC[1]} ]]
|
|
then
|
|
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
|
|
|
|
DOVECOT_USERDB_LINE="${ALIAS}:${REAL_ACC[1]}:5000:5000::/var/mail/${REAL_DOMAINNAME}/${REAL_USERNAME}::${REAL_ACC[2]:-}"
|
|
if grep -qi "^${ALIAS}:" "${DOVECOT_USERDB_FILE}"
|
|
then
|
|
_log 'warn' "Alias '${ALIAS}' will not be added to '${DOVECOT_USERDB_FILE}' twice"
|
|
else
|
|
echo "${DOVECOT_USERDB_LINE}" >>"${DOVECOT_USERDB_FILE}"
|
|
fi
|
|
done < <(_get_valid_lines_from_file "${DATABASE_VIRTUAL}")
|
|
fi
|
|
}
|
|
|
|
# Support Dovecot master user: https://doc.dovecot.org/configuration_manual/authentication/master_users/
|
|
# Supporting LDAP users requires `auth_bind = yes` in `dovecot-ldap.conf.ext`, see docker-mailserver/docker-mailserver/pull/2535 for details
|
|
function _create_masters
|
|
{
|
|
: >"${DOVECOT_MASTERDB_FILE}"
|
|
|
|
local DATABASE_DOVECOT_MASTERS='/tmp/docker-mailserver/dovecot-masters.cf'
|
|
if [[ -f ${DATABASE_DOVECOT_MASTERS} ]]
|
|
then
|
|
_log 'trace' "Checking file line endings"
|
|
sed -i 's|\r||g' "${DATABASE_DOVECOT_MASTERS}"
|
|
|
|
_log 'trace' "Regenerating dovecot masters list"
|
|
|
|
# checking that ${DATABASE_DOVECOT_MASTERS} ends with a newline
|
|
# shellcheck disable=SC1003
|
|
sed -i -e '$a\' "${DATABASE_DOVECOT_MASTERS}"
|
|
|
|
chown dovecot:dovecot "${DOVECOT_MASTERDB_FILE}"
|
|
chmod 640 "${DOVECOT_MASTERDB_FILE}"
|
|
|
|
sed -i -e '/\!include auth-master\.inc/s/^#//' /etc/dovecot/conf.d/10-auth.conf
|
|
|
|
# creating users ; 'pass' is encrypted
|
|
# comments and empty lines are ignored
|
|
local LOGIN PASS
|
|
while IFS=$'|' read -r LOGIN PASS
|
|
do
|
|
_log 'debug' "Creating master user '${LOGIN}'"
|
|
|
|
local DOVECOT_MASTERDB_LINE
|
|
|
|
# Dovecot's masterdb has the following format
|
|
# user:password
|
|
DOVECOT_MASTERDB_LINE="${LOGIN}:${PASS}"
|
|
if grep -qF "${DOVECOT_MASTERDB_LINE}" "${DOVECOT_MASTERDB_FILE}"
|
|
then
|
|
_log 'warn' "Login '${LOGIN}' will not be added to '${DOVECOT_MASTERDB_FILE}' twice"
|
|
else
|
|
echo "${DOVECOT_MASTERDB_LINE}" >>"${DOVECOT_MASTERDB_FILE}"
|
|
fi
|
|
done < <(_get_valid_lines_from_file "${DATABASE_DOVECOT_MASTERS}")
|
|
fi
|
|
}
|