Introduction
Posthorn is the unified outbound mail layer for self-hosted projects. One gateway between every app you self-host and the transactional mail provider you’ve already picked. It accepts mail through three ingress shapes — HTTP form, HTTP API (JSON, bearer-authenticated), and SMTP — and delivers via five transports: Postmark, Resend, Mailgun, AWS SES, and a generic outbound-SMTP relay.
The problem
Section titled “The problem”Nobody wants to run a mail server in 2026. Self-hosted operators use Postmark, Resend, Mailgun, or AWS SES because they’re cheap, they handle deliverability properly, and somebody else can worry about sender authentication, bounce processing, and reputation management.
But every app you self-host has to integrate with that service independently:
- The contact form on your static site.
- Ghost’s admin emails and password resets.
- Gitea’s magic-link logins.
- Mastodon’s notification fan-out.
- The worker that fires a license-delivery email when someone pays.
- The cron job that sends weekly reports.
Each one needs its own copy of the API key, its own integration code, its own quirks around retry and bounce handling. The same outbound concern, duplicated across five or ten services in your stack.
And on cloud hosts that block outbound SMTP — DigitalOcean, AWS Lightsail, Linode, Vultr — the apps that only speak SMTP don’t work at all without a workaround. A 2026-04 support exchange with DigitalOcean confirmed they will not unblock the range, and explicitly recommended using an HTTP API service like Postmark, Resend, Mailgun, or AWS SES instead.
The status quo workarounds are bad:
- Pay for SaaS form services (Formspree, Netlify Forms) — only solves the form half.
- Rewrite app configs to use API SDKs — rarely supported by the app.
- Run Postfix as a relay with custom HTTP glue — heavy, fragile, security surface.
- Move to a host that doesn’t block SMTP — disruptive, sometimes not viable.
There is no actively maintained, self-hosted, HTTP-API-first email gateway in 2026 that unifies forms, APIs, and SMTP-emitting apps onto one transactional provider. Posthorn is that gateway.
The shape
Section titled “The shape”Posthorn is a single Go binary distributed primarily as a Docker container. It speaks form-encoded HTTP, JSON HTTP, and SMTP on the ingress side, and HTTP API calls or outbound SMTP on the egress side. A single TOML file configures one or more endpoints, each with its own recipients, templates, spam protection, and rate limit, plus an optional SMTP listener block.
Posthorn doesn’t terminate TLS — run it behind whatever reverse proxy you already use (Caddy, nginx, Traefik, Cloudflare). The reverse proxy page covers the common ones with worked configs.
What ships in v1.0
Section titled “What ships in v1.0”| Capability | Detail |
|---|---|
| HTTP form ingress | application/x-www-form-urlencoded, multipart/form-data; honeypot, Origin/Referer check, rate limit, optional CSRF tokens |
| HTTP API mode | Bearer-authenticated JSON; idempotency keys; per-request to_override; per-key rate limiting |
| SMTP ingress | TCP listener with AUTH PLAIN / client-cert; STARTTLS required by default; sender allowlist + recipient allowlist or cap; size cap |
| Transports | Postmark, Resend, Mailgun (US + EU), AWS SES, outbound-SMTP relay — five total, all bespoke (no SDK deps) |
| Operations | /healthz, /metrics (Prometheus exposition), dry-run mode, IP-stripping option, named trusted_proxies presets (Cloudflare) |
| Validation | Required fields, email syntax check |
| Templating | Go text/template for subject and body, with custom-field passthrough |
| Response handling | JSON, redirect via content negotiation, redirect_success / redirect_error (form mode) |
| Failure handling | 1 retry on transient/5xx (1s), 1 retry on 429 (5s), no retry on 4xx config errors, 10s hard timeout |
| Logging | Structured JSON with UUIDv4 submission ID; SMTP session IDs |
| Deployment | Standalone Docker container or Go binary, behind any reverse proxy |
What’s out of scope for v1.0
Section titled “What’s out of scope for v1.0”These come later, intentionally. See the Roadmap for the full trajectory.
- File attachments, webhook transport, HTML body, suppression list, durable retry queue, automatic unsubscribe injection — v2
- Admin UI, proof-of-work spam challenge, PGP encryption — v3
- Inbound mail parsing (MX target, IMAP polling) — deliberately deferred to v3+
See the project brief for the full roadmap.
Where to next
Section titled “Where to next”- New to Posthorn? → Installation and Quick start
- Want the mental model? → Core concepts
- Already have it running? → Configuration reference