This document contains an overview of how email moves through the system: SMTP ingress → Postfix → HTTPS handoff to API → SMTP egress.
- Mailserver: docker-mailserver (Postfix) accepts inbound SMTP and hands messages to the API.
- Email API: HTTPS service that receives raw messages and triggers outbound delivery.
- DB + Redis: dependencies required by the API.
- SMTP relay: where the API delivers outbound email (can be an external provider, or the mailserver itself).
Mailserver (Postfix):
25/tcpSMTP465/tcpESMTP (implicit TLS)587/tcpESMTP (STARTTLS)
API:
- The mailserver calls the API at
https://email-api/v1/email.
- Inbound SMTP arrives at Postfix on ports
25/465/587. - Postfix routes recipient domains to a local transport named
curl_email(via postfix maps inpostfix-virtual.cf). curl_emailis implemented as a pipe to/usr/local/bin/curl-email.sh(created viauser-patches.sh).- The pipe script POSTs the full RFC822 message bytes to the API:
- URL:
https://email-api/v1/email - Header:
Authorization: Bearer <PSK> - Body: raw message (
curl --data-binary @-)
- URL:
- The API parses the message and identifies the inbound alias address (the original recipient).
- It looks up which real mailbox recipient(s) are configured for that alias.
- It then forwards the message to those real recipient(s) via the configured SMTP relay (see “Outbound flow”).
- If the message is not deliverable (temporary errors), the API returns a non-2xx status so Postfix will defer/retry.
- The API endpoint
POST /v1/emailrequires a shared secret viaAuthorization: Bearer <token>. - The
PSKvalue must match on both sides:- mailserver:
PSKin mailserver/.env.sample - api:
PSKin api/.env.sample
- mailserver:
- If the API returns a non-2xx response, the mailserver pipe uses
curl --failand exits with code 75. - Exit code 75 signals a temporary failure to Postfix, so Postfix defers and retries later.
What this means operationally:
- API down / network issues / wrong PSK / API cannot submit outbound email ⇒ Postfix queue growth and repeated deferrals until fixed.
- Default Postfix retry intervals apply.
- The API connects as an SMTP client to the configured relay (
SMTP_CLIENT_HOST/SMTP_CLIENT_PORT).SMTP_CLIENT_PORT=587⇒ STARTTLS
Mailserver:
- Route the domain(s) to
curl_emailinpostfix-virtual.cfand runpostmap /etc/postfix/virtual. - Ensure
curl_emailalias exists (pipe to/usr/local/bin/curl-email.sh) and runnewaliases. - Set
PSK,DOMAIN,SMTP_USER,SMTP_PASS(used byuser-patches.sh).
API:
- Set
PSK(must match mailserver). - Set
SMTP_CLIENT_*for outbound delivery. - Ensure DB/Redis are reachable (as defined in api/compose.yml).