#!/bin/sh set -eu : "${MAIL_HOSTNAME:=mail.gentic.email}" : "${MAIL_DOMAIN:=gentic.email}" : "${INBOUND_DOMAINS:=${MAIL_DOMAIN}}" : "${RELAY_DOMAINS_FILE:=/data/relay_domains/domains.list}" : "${RELAY_DOMAINS_REFRESH:=60}" : "${BACKEND_INGEST_HOST:=backend}" : "${BACKEND_INGEST_PORT:=2525}" case "${MAIL_HOSTNAME}" in ""|*[!A-Za-z0-9._-]*) echo "MAIL_HOSTNAME contains invalid characters" >&2 exit 1 ;; esac case "${BACKEND_INGEST_HOST}" in ""|*[!A-Za-z0-9._-]*) echo "BACKEND_INGEST_HOST must be an IPv4 address or DNS hostname" >&2 exit 1 ;; esac case "${BACKEND_INGEST_PORT}" in ""|*[!0-9]*) echo "BACKEND_INGEST_PORT must be numeric" >&2 exit 1 ;; esac if [ "${BACKEND_INGEST_PORT}" -lt 1 ] || [ "${BACKEND_INGEST_PORT}" -gt 65535 ]; then echo "BACKEND_INGEST_PORT must be between 1 and 65535" >&2 exit 1 fi validate_domain() { domain="$1" printf '%s\n' "${domain}" | awk ' /^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/ { valid = 1 } END { exit !valid } ' } install_relay_maps() { relay_domains_tmp="$(mktemp)" transport_tmp="$(mktemp)" seen_tmp="$(mktemp)" add_domain() { raw_domain="$1" domain="$(printf '%s' "${raw_domain}" | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]')" if [ -z "${domain}" ]; then return 0 fi if ! validate_domain "${domain}"; then echo "Skipping invalid relay domain: ${raw_domain}" >&2 return 0 fi if grep -Fxq "${domain}" "${seen_tmp}" 2>/dev/null; then return 0 fi printf '%s\n' "${domain}" >> "${seen_tmp}" printf '%s OK\n' "${domain}" >> "${relay_domains_tmp}" printf '%s smtp:[%s]:%s\n' \ "${domain}" "${BACKEND_INGEST_HOST}" "${BACKEND_INGEST_PORT}" \ >> "${transport_tmp}" } old_ifs="${IFS}" IFS=',' for raw_domain in ${INBOUND_DOMAINS}; do add_domain "${raw_domain}" done IFS="${old_ifs}" if [ -f "${RELAY_DOMAINS_FILE}" ]; then while IFS= read -r line || [ -n "${line}" ]; do add_domain "${line}" done < "${RELAY_DOMAINS_FILE}" fi if [ ! -s "${relay_domains_tmp}" ]; then rm -f "${relay_domains_tmp}" "${transport_tmp}" "${seen_tmp}" echo "At least one inbound relay domain is required" >&2 return 1 fi install -m 0644 "${relay_domains_tmp}" /etc/postfix/relay_domains install -m 0644 "${transport_tmp}" /etc/postfix/transport postmap /etc/postfix/relay_domains postmap /etc/postfix/transport rm -f "${relay_domains_tmp}" "${transport_tmp}" "${seen_tmp}" } install_relay_maps postconf -e "myhostname = ${MAIL_HOSTNAME}" postconf -e "mydomain = ${MAIL_DOMAIN}" postconf -e "myorigin = \$mydomain" # STARTTLS cert for inbound providers (Gmail, Zoho, etc.) mkdir -p /etc/postfix/certs if [ ! -f /etc/postfix/certs/smtpd.crt ]; then openssl req -new -x509 -days 825 -nodes \ -subj "/CN=${MAIL_HOSTNAME}" \ -keyout /etc/postfix/certs/smtpd.key \ -out /etc/postfix/certs/smtpd.crt chmod 600 /etc/postfix/certs/smtpd.key chmod 644 /etc/postfix/certs/smtpd.crt fi # Postfix chroot cannot see Docker's resolver unless we copy these in. mkdir -p /var/spool/postfix/etc mkdir -p /var/spool/postfix/etc/postfix/certs cp /etc/postfix/certs/smtpd.crt /var/spool/postfix/etc/postfix/certs/smtpd.crt cp /etc/postfix/certs/smtpd.key /var/spool/postfix/etc/postfix/certs/smtpd.key chmod 644 /var/spool/postfix/etc/postfix/certs/smtpd.crt chmod 600 /var/spool/postfix/etc/postfix/certs/smtpd.key for file in resolv.conf hosts nsswitch.conf; do if [ -f "/etc/${file}" ]; then cp "/etc/${file}" "/var/spool/postfix/etc/${file}" fi done postfix check if [ "${RELAY_DOMAINS_REFRESH}" -gt 0 ] 2>/dev/null; then ( while true; do sleep "${RELAY_DOMAINS_REFRESH}" if install_relay_maps; then postfix reload >/dev/null 2>&1 || true fi done ) & fi exec postfix start-fg