diff --git a/target/mta/Dockerfile b/target/mta/Dockerfile index 8377ead0..0a4dddd0 100644 --- a/target/mta/Dockerfile +++ b/target/mta/Dockerfile @@ -1,9 +1,7 @@ -FROM ghcr.io/jeboehm/dockerize:0.9.3@sha256:d4e824aa120670658d7012421d2fdf1b2437be34a6acbb7a4ad92ed52edec8eb AS dockerize FROM alpine:3.23@sha256:25109184c71bdad752c8312a8623239686a9a2071e8825f20acb8f2198c3f659 LABEL maintainer="https://github.com/jeboehm/docker-mailserver" LABEL vendor="https://github.com/jeboehm/docker-mailserver" -LABEL de.ressourcenkonflikt.docker-mailserver.autoheal="true" ENV MAILNAME=mail.example.com \ MYNETWORKS=127.0.0.0/8 \ @@ -21,7 +19,9 @@ ENV MAILNAME=mail.example.com \ WAITSTART_TIMEOUT=1m \ RECIPIENT_DELIMITER=- -RUN apk --no-cache add \ +RUN --mount=type=cache,target=/var/cache/apk \ + apk add \ + envsubst \ postfix-mysql \ postfix && \ postconf virtual_mailbox_domains=mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf && \ @@ -64,7 +64,7 @@ RUN apk --no-cache add \ postconf smtpd_soft_error_limit=3 && \ postconf smtpd_hard_error_limit=5 && \ newaliases -COPY --from=dockerize /bin/dockerize /usr/local/bin/dockerize + COPY rootfs/ / EXPOSE 25 587 diff --git a/target/mta/rootfs/entrypoint.sh b/target/mta/rootfs/entrypoint.sh index e9ce327d..a27fdabd 100755 --- a/target/mta/rootfs/entrypoint.sh +++ b/target/mta/rootfs/entrypoint.sh @@ -15,9 +15,6 @@ if ! [ -r /etc/postfix/tls/tls.crt ] || ! [ -r /etc/postfix/tls/tls.key ]; then exit 1 fi -exec dockerize \ - -wait "tcp://${MYSQL_HOST}:${MYSQL_PORT}" \ - -wait "tcp://${MDA_LMTP_ADDRESS}" \ - -wait "tcp://${FILTER_MILTER_ADDRESS}" \ - -timeout "${WAITSTART_TIMEOUT}" \ - /usr/sbin/postfix start-fg +/usr/local/lib/wait-for-services.sh + +exec /usr/sbin/postfix start-fg diff --git a/target/mta/rootfs/etc/postfix/mysql-email-submission.cf.templ b/target/mta/rootfs/etc/postfix/mysql-email-submission.cf.templ index 3c67668c..832f6c39 100644 --- a/target/mta/rootfs/etc/postfix/mysql-email-submission.cf.templ +++ b/target/mta/rootfs/etc/postfix/mysql-email-submission.cf.templ @@ -1,6 +1,6 @@ -user = {{ .Env.MYSQL_USER }} -password = {{ .Env.MYSQL_PASSWORD }} -hosts = {{ .Env.MYSQL_HOST }}:{{ .Env.MYSQL_PORT }} -dbname = {{ .Env.MYSQL_DATABASE }} -tls_verify_cert = {{ .Env.MYSQL_TLS_VERIFY_CERT }} +user = ${MYSQL_USER} +password = ${MYSQL_PASSWORD} +hosts = ${MYSQL_HOST}:${MYSQL_PORT} +dbname = ${MYSQL_DATABASE} +tls_verify_cert = ${MYSQL_TLS_VERIFY_CERT} query = SELECT CONCAT(mail_users.name, '@', d1.name) AS email FROM mail_users JOIN mail_domains d1 ON mail_users.domain_id = d1.id HAVING email='%s' UNION SELECT destination AS email FROM mail_aliases JOIN mail_domains d2 ON mail_aliases.domain_id = d2.id WHERE CONCAT(mail_aliases.name, '@', d2.name)='%s' diff --git a/target/mta/rootfs/etc/postfix/mysql-email2email.cf.templ b/target/mta/rootfs/etc/postfix/mysql-email2email.cf.templ index e9db2522..4ad7f229 100644 --- a/target/mta/rootfs/etc/postfix/mysql-email2email.cf.templ +++ b/target/mta/rootfs/etc/postfix/mysql-email2email.cf.templ @@ -1,6 +1,6 @@ -user = {{ .Env.MYSQL_USER }} -password = {{ .Env.MYSQL_PASSWORD }} -hosts = {{ .Env.MYSQL_HOST }}:{{ .Env.MYSQL_PORT }} -dbname = {{ .Env.MYSQL_DATABASE }} -tls_verify_cert = {{ .Env.MYSQL_TLS_VERIFY_CERT }} +user = ${MYSQL_USER} +password = ${MYSQL_PASSWORD} +hosts = ${MYSQL_HOST}:${MYSQL_PORT} +dbname = ${MYSQL_DATABASE} +tls_verify_cert = ${MYSQL_TLS_VERIFY_CERT} query = SELECT CONCAT(mail_users.name, '@', mail_domains.name) AS email FROM mail_users JOIN mail_domains ON mail_users.domain_id = mail_domains.id HAVING email='%s' diff --git a/target/mta/rootfs/etc/postfix/mysql-recipient-access.cf.templ b/target/mta/rootfs/etc/postfix/mysql-recipient-access.cf.templ index 696c88ec..66856758 100644 --- a/target/mta/rootfs/etc/postfix/mysql-recipient-access.cf.templ +++ b/target/mta/rootfs/etc/postfix/mysql-recipient-access.cf.templ @@ -1,6 +1,6 @@ -user = {{ .Env.MYSQL_USER }} -password = {{ .Env.MYSQL_PASSWORD }} -hosts = {{ .Env.MYSQL_HOST }}:{{ .Env.MYSQL_PORT }} -dbname = {{ .Env.MYSQL_DATABASE }} -tls_verify_cert = {{ .Env.MYSQL_TLS_VERIFY_CERT }} +user = ${MYSQL_USER} +password = ${MYSQL_PASSWORD} +hosts = ${MYSQL_HOST}:${MYSQL_PORT} +dbname = ${MYSQL_DATABASE} +tls_verify_cert = ${MYSQL_TLS_VERIFY_CERT} query = SELECT IF(send_only = true, 'REJECT', 'OK') AS access FROM mail_users JOIN mail_domains ON mail_users.domain_id = mail_domains.id WHERE mail_users.name = '%u' AND mail_domains.name = '%d' diff --git a/target/mta/rootfs/etc/postfix/mysql-virtual-alias-maps.cf.templ b/target/mta/rootfs/etc/postfix/mysql-virtual-alias-maps.cf.templ index 9676cec6..7acd821a 100644 --- a/target/mta/rootfs/etc/postfix/mysql-virtual-alias-maps.cf.templ +++ b/target/mta/rootfs/etc/postfix/mysql-virtual-alias-maps.cf.templ @@ -1,6 +1,6 @@ -user = {{ .Env.MYSQL_USER }} -password = {{ .Env.MYSQL_PASSWORD }} -hosts = {{ .Env.MYSQL_HOST }}:{{ .Env.MYSQL_PORT }} -dbname = {{ .Env.MYSQL_DATABASE }} -tls_verify_cert = {{ .Env.MYSQL_TLS_VERIFY_CERT }} +user = ${MYSQL_USER} +password = ${MYSQL_PASSWORD} +hosts = ${MYSQL_HOST}:${MYSQL_PORT} +dbname = ${MYSQL_DATABASE} +tls_verify_cert = ${MYSQL_TLS_VERIFY_CERT} query = SELECT destination FROM mail_aliases JOIN mail_domains ON mail_aliases.domain_id = mail_domains.id WHERE CONCAT(mail_aliases.name, '@', mail_domains.name) = '%s' diff --git a/target/mta/rootfs/etc/postfix/mysql-virtual-mailbox-domains.cf.templ b/target/mta/rootfs/etc/postfix/mysql-virtual-mailbox-domains.cf.templ index 470b10b9..977fbc0a 100644 --- a/target/mta/rootfs/etc/postfix/mysql-virtual-mailbox-domains.cf.templ +++ b/target/mta/rootfs/etc/postfix/mysql-virtual-mailbox-domains.cf.templ @@ -1,6 +1,6 @@ -user = {{ .Env.MYSQL_USER }} -password = {{ .Env.MYSQL_PASSWORD }} -hosts = {{ .Env.MYSQL_HOST }}:{{ .Env.MYSQL_PORT }} -dbname = {{ .Env.MYSQL_DATABASE }} -tls_verify_cert = {{ .Env.MYSQL_TLS_VERIFY_CERT }} +user = ${MYSQL_USER} +password = ${MYSQL_PASSWORD} +hosts = ${MYSQL_HOST}:${MYSQL_PORT} +dbname = ${MYSQL_DATABASE} +tls_verify_cert = ${MYSQL_TLS_VERIFY_CERT} query = SELECT 1 FROM mail_domains WHERE name='%s' diff --git a/target/mta/rootfs/etc/postfix/mysql-virtual-mailbox-maps.cf.templ b/target/mta/rootfs/etc/postfix/mysql-virtual-mailbox-maps.cf.templ index 9e8be68b..607816f4 100644 --- a/target/mta/rootfs/etc/postfix/mysql-virtual-mailbox-maps.cf.templ +++ b/target/mta/rootfs/etc/postfix/mysql-virtual-mailbox-maps.cf.templ @@ -1,6 +1,6 @@ -user = {{ .Env.MYSQL_USER }} -password = {{ .Env.MYSQL_PASSWORD }} -hosts = {{ .Env.MYSQL_HOST }}:{{ .Env.MYSQL_PORT }} -dbname = {{ .Env.MYSQL_DATABASE }} -tls_verify_cert = {{ .Env.MYSQL_TLS_VERIFY_CERT }} +user = ${MYSQL_USER} +password = ${MYSQL_PASSWORD} +hosts = ${MYSQL_HOST}:${MYSQL_PORT} +dbname = ${MYSQL_DATABASE} +tls_verify_cert = ${MYSQL_TLS_VERIFY_CERT} query = SELECT 1 FROM mail_users JOIN mail_domains ON mail_users.domain_id = mail_domains.id WHERE mail_users.name = '%u' AND mail_domains.name = '%d' AND enabled = 1 diff --git a/target/mta/rootfs/usr/local/lib/init.sh b/target/mta/rootfs/usr/local/lib/init.sh index 905c144e..13771cb7 100755 --- a/target/mta/rootfs/usr/local/lib/init.sh +++ b/target/mta/rootfs/usr/local/lib/init.sh @@ -47,11 +47,9 @@ if [ "${MTA_UPSTREAM_PROXY}" = "true" ]; then postconf submission_upstream_proxy_protocol=haproxy fi -dockerize \ - -template /etc/postfix/mysql-email2email.cf.templ:/etc/postfix/mysql-email2email.cf \ - -template /etc/postfix/mysql-virtual-alias-maps.cf.templ:/etc/postfix/mysql-virtual-alias-maps.cf \ - -template /etc/postfix/mysql-virtual-mailbox-domains.cf.templ:/etc/postfix/mysql-virtual-mailbox-domains.cf \ - -template /etc/postfix/mysql-virtual-mailbox-maps.cf.templ:/etc/postfix/mysql-virtual-mailbox-maps.cf \ - -template /etc/postfix/mysql-recipient-access.cf.templ:/etc/postfix/mysql-recipient-access.cf \ - -template /etc/postfix/mysql-email-submission.cf.templ:/etc/postfix/mysql-email-submission.cf \ - /bin/true +envsubst /etc/postfix/mysql-email2email.cf +envsubst /etc/postfix/mysql-virtual-alias-maps.cf +envsubst /etc/postfix/mysql-virtual-mailbox-domains.cf +envsubst /etc/postfix/mysql-virtual-mailbox-maps.cf +envsubst /etc/postfix/mysql-recipient-access.cf +envsubst /etc/postfix/mysql-email-submission.cf diff --git a/target/mta/rootfs/usr/local/lib/wait-for-services.sh b/target/mta/rootfs/usr/local/lib/wait-for-services.sh new file mode 100755 index 00000000..1d4455ec --- /dev/null +++ b/target/mta/rootfs/usr/local/lib/wait-for-services.sh @@ -0,0 +1,63 @@ +#!/bin/sh +set -e + +# Wait for service to be available using nc +wait_for_service() { + ( + host="$1" + port="$2" + service_name="$3" + timeout="${WAITSTART_TIMEOUT:-60s}" + + # Convert timeout to seconds (handle formats like "1m", "60s", "60") + timeout_seconds=60 + if echo "$timeout" | grep -q "m$"; then + timeout_seconds=$(echo "$timeout" | sed 's/m$//' | awk '{print $1 * 60}') + elif echo "$timeout" | grep -q "s$"; then + timeout_seconds=$(echo "$timeout" | sed 's/s$//') + else + timeout_seconds="$timeout" + fi + + elapsed=0 + interval=1 + + echo "Waiting for $service_name at $host:$port..." + while [ "$elapsed" -lt "$timeout_seconds" ]; do + if nc -z "$host" "$port" 2>/dev/null; then + echo "$service_name is available" + exit 0 + fi + sleep "$interval" + elapsed=$((elapsed + interval)) + done + + echo "Error: Timeout waiting for $service_name at $host:$port" + exit 1 + ) +} + +# Wait for MySQL +if [ -z "$MYSQL_HOST" ] || [ -z "$MYSQL_PORT" ]; then + echo "Error: MYSQL_HOST or MYSQL_PORT not set" + exit 1 +fi +wait_for_service "$MYSQL_HOST" "$MYSQL_PORT" "MySQL" + +# Wait for MDA LMTP +if [ -z "$MDA_LMTP_ADDRESS" ]; then + echo "Error: MDA_LMTP_ADDRESS not set" + exit 1 +fi +MDA_LMTP_HOST=$(echo "$MDA_LMTP_ADDRESS" | cut -d: -f1) +MDA_LMTP_PORT=$(echo "$MDA_LMTP_ADDRESS" | cut -d: -f2) +wait_for_service "$MDA_LMTP_HOST" "$MDA_LMTP_PORT" "MDA LMTP" + +# Wait for Filter Milter +if [ -z "$FILTER_MILTER_ADDRESS" ]; then + echo "Error: FILTER_MILTER_ADDRESS not set" + exit 1 +fi +FILTER_MILTER_HOST=$(echo "$FILTER_MILTER_ADDRESS" | cut -d: -f1) +FILTER_MILTER_PORT=$(echo "$FILTER_MILTER_ADDRESS" | cut -d: -f2) +wait_for_service "$FILTER_MILTER_HOST" "$FILTER_MILTER_PORT" "Filter Milter"