61 lines
3.4 KiB
Bash
61 lines
3.4 KiB
Bash
|
|
#!/bin/sh
|
||
|
|
# Configures Postfix to relay one domain to pneumatube over LMTP, per the
|
||
|
|
# plan discussed for the real deployment (main.cf relay_domains/
|
||
|
|
# transport_maps, master.cf's lmtp client service). This is a test/demo
|
||
|
|
# harness, not production hardening: no TLS, no abuse limits, open to any
|
||
|
|
# connecting host on the compose network.
|
||
|
|
set -e
|
||
|
|
|
||
|
|
: "${POSTFIX_RELAY_DOMAIN:?set POSTFIX_RELAY_DOMAIN to the email domain pneumatube accepts}"
|
||
|
|
: "${PNEUMATUBE_HOST:?set PNEUMATUBE_HOST to pneumatube's hostname on the compose network}"
|
||
|
|
PNEUMATUBE_PORT="${PNEUMATUBE_PORT:-2424}"
|
||
|
|
|
||
|
|
# "No configuration" at install time (Dockerfile) skips main.cf generation
|
||
|
|
# entirely, so start from Debian's template before postconf-ing it.
|
||
|
|
[ -f /etc/postfix/main.cf ] || cp /usr/share/postfix/main.cf.debian /etc/postfix/main.cf
|
||
|
|
|
||
|
|
# Postfix logs via syslog by default, which is silent in a minimal
|
||
|
|
# container with no syslog daemon; maillog_file (3.4+) writes directly.
|
||
|
|
postconf -e "maillog_file=/dev/stdout"
|
||
|
|
postconf -e "myhostname=${POSTFIX_MYHOSTNAME:-postfix.local}"
|
||
|
|
# Postfix's default "dns" host-lookup method queries the nameserver with
|
||
|
|
# the bare hostname, bypassing /etc/resolv.conf's search domain. Container
|
||
|
|
# DNS (e.g. podman's aardvark-dns) often only answers the FQDN form, so the
|
||
|
|
# compose service name alone resolves via getaddrinfo() ("native") but not
|
||
|
|
# via Postfix's own resolver. native also respects /etc/hosts.
|
||
|
|
postconf -e "smtp_host_lookup=native"
|
||
|
|
postconf -e "lmtp_host_lookup=native"
|
||
|
|
postconf -e "mydestination="
|
||
|
|
postconf -e "relay_domains=${POSTFIX_RELAY_DOMAIN}"
|
||
|
|
postconf -e "transport_maps=hash:/etc/postfix/transport"
|
||
|
|
# Split in two: relay_restrictions decides only whether this domain is ours
|
||
|
|
# to relay at all; recipient_restrictions then asks pneumatube's tcp_table
|
||
|
|
# lookup service about the specific user, live, before RCPT TO is accepted —
|
||
|
|
# this is what turns an unknown user into an inline reject instead of a
|
||
|
|
# queued-then-bounced message (see lookup_server.py for the other side).
|
||
|
|
postconf -e "smtpd_relay_restrictions=permit_mynetworks,reject_unauth_destination"
|
||
|
|
postconf -e "smtpd_recipient_restrictions=check_recipient_access tcp:${PNEUMATUBE_HOST}:${PNEUMATUBE_LOOKUP_PORT:-2526}"
|
||
|
|
# Test network only: every connecting host is trusted. Do not carry this
|
||
|
|
# setting into a real deployment (see the project's Postfix wiring notes).
|
||
|
|
postconf -e "mynetworks=0.0.0.0/0"
|
||
|
|
|
||
|
|
echo "${POSTFIX_RELAY_DOMAIN} lmtp:inet:${PNEUMATUBE_HOST}:${PNEUMATUBE_PORT}" > /etc/postfix/transport
|
||
|
|
postmap /etc/postfix/transport
|
||
|
|
|
||
|
|
grep -q '^lmtp[[:space:]]' /etc/postfix/master.cf \
|
||
|
|
|| echo 'lmtp unix - - n - - lmtp' >> /etc/postfix/master.cf
|
||
|
|
|
||
|
|
# The shipped master.cf chroots smtpd and the lmtp client by default, which
|
||
|
|
# hides /etc/resolv.conf and /etc/nsswitch.conf from them — resolving the
|
||
|
|
# pneumatube hostname then fails ("Temporary failure in name resolution")
|
||
|
|
# regardless of *_host_lookup, since getaddrinfo() itself can't see the
|
||
|
|
# chroot's host config. smtpd needs this too: it's the one connecting out to
|
||
|
|
# the tcp_table lookup service. Rewrite the chroot column (5th field)
|
||
|
|
# directly; postconf -P appends a "-o chroot=n" command-line override
|
||
|
|
# instead, which is not a valid override and is simply ignored.
|
||
|
|
awk '($1 == "lmtp" && $2 == "unix") || ($1 == "smtp" && $2 == "inet") { $5 = "n" } { print }' \
|
||
|
|
/etc/postfix/master.cf > /etc/postfix/master.cf.new
|
||
|
|
mv /etc/postfix/master.cf.new /etc/postfix/master.cf
|
||
|
|
|
||
|
|
exec postfix start-fg
|