個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證postmarkd is a small daemon that runs next to your apps (as a systemd service or a container sidecar) and delivers mail through Postmark
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗Sending mail should be one line. postmarkd is a small daemon that runs next
to your apps (as a systemd service or a container sidecar) and delivers mail
through Postmark. Apps hand it mail however they
like: HTTP, SMTP, the sendmail command or a CLI. postmarkd holds the
credentials, fills in defaults, sends in parallel and retries safely.
echo "The nightly backup finished." | postmarkd send -to [email protected] -subject "Backup OK"
| From | How |
|---|---|
| Shell scripts | postmarkd send -to … -subject … (body from stdin or -text/-html, -attach files) |
Anything that uses sendmail: cron, mail/mailx, PHP mail(), git, logwatch, smartd | Symlink postmarkd as /usr/sbin/sendmail. No other change needed. |
| Apps that speak SMTP: Rails, Django, Laravel, WordPress, Grafana, Gitea… | Set POSTMARKD_SMTP_LISTEN=127.0.0.1:2525 (on by default in the container) and point them at it. No username, password or TLS needed. |
| Apps with a Postmark SDK | Change the SDK's base URL to postmarkd |
| Any HTTP client | curl --unix-socket /run/postmarkd/postmarkd.sock http://localhost/email -d '{…}' |
All of them end up in the same place: validated, defaulted, rate-limited and sent to Postmark over pooled HTTPS connections.
Postmark already has a good API, SMTP and SDKs, and for a single app that already uses a Postmark SDK, calling Postmark directly is fine. postmarkd helps when mail comes from many places, or from places that can't easily talk to Postmark.
| Postmark directly | With postmarkd | |
|---|---|---|
| Server token | Copied into every app, container and CI secret. Rotating it means touching all of them. | Lives in one place (a systemd credential or one Secret). Apps get nothing, or their own client token that you can revoke alone. |
System mail (cron, mail, PHP mail(), git, monitoring tools) | Needs a local MTA such as Postfix set up as an authenticated TLS relay. | Symlink as sendmail. Done. |
| Legacy or SMTP-only apps | Must be configured for Postmark's SMTP host, TLS and credentials. | localhost:2525, no credentials, no TLS. |
| Shell scripts | Hand-written curl with the token and JSON escaping. | echo body | postmarkd send -to … -subject … |
| Defaults and rules (From address, message stream, validation) | Repeated in each app. | Set once for every app on the host. |
| Tests and CI | Postmark's test token or blackhole address. Still needs network and an account, and you can't easily read back what was sent. | POSTMARKD_BLACKHOLE=true: no account, no network, and tests can read what was "sent". |
| Request latency | Every send waits on a round trip to Postmark. | Over a local socket, or ?async=true returns immediately while postmarkd sends in the background. |
| Load on Postmark | Each app opens its own connections and does its own retries. | Shared keep-alive connections, one concurrency limit, retries only when safe (no duplicate mail). |
| Visibility | Postmark's activity page. | The same, plus Prometheus metrics for every app on the host. |
| DNS setup | Postmark's dashboard. | postmarkd check-domain checks DKIM, Return-Path and DMARC from the command line or CI. |
It's one more component to run, but a small one: a single static binary with no dependencies and no state on disk.
sendmail or the CLI.POSTMARKD_MAX_CONCURRENCY requests to Postmark at once over pooled
keep-alive connections, and an optional bounded async queue with back-pressure.MessageStream, the
X-PM-Message-Stream header, -stream, or ?stream= per request), so
transactional and broadcast mail flow side by side, even in one batch.POSTMARKD_BLACKHOLE=true accepts everything,
answers exactly like Postmark, sends nothing, and lets your tests read back
what was "sent" at /blackhole/messages.postmarkd check-domain example.com tells
you which DNS records are missing so your mail doesn't land in spam.Type=notify, watchdog, graceful drain, hardened unit./metrics, /healthz, /readyz.Install the package for your distribution (amd64 or arm64):
# Debian / Ubuntu
VERSION=0.1.1 ARCH=$(dpkg --print-architecture)
REL=https://github.com/rossedman/postmarkd/releases/download/v$VERSION
curl -fsSLO $REL/postmarkd_${VERSION}_linux_$ARCH.deb
sudo apt install ./postmarkd_${VERSION}_linux_$ARCH.deb
# Fedora / RHEL / Rocky / Amazon Linux
VERSION=0.1.1 ARCH=$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/')
REL=https://github.com/rossedman/postmarkd/releases/download/v$VERSION
sudo dnf install $REL/postmarkd_${VERSION}_linux_$ARCH.rpm
This installs the binary, systemd units, a postmarkd user and
/etc/postmarkd/postmarkd.conf. Then add your token, set a sender and start it:
sudo install -m 0600 /dev/stdin /etc/postmarkd/server-token <<< 'your-postmark-server-token'
sudoedit /etc/postmarkd/postmarkd.conf # set [email protected]
sudo systemctl enable --now postmarkd
sudo usermod -aG postmarkd "$USER" # let your user use the socket (log in again)
echo "Hello from $(hostname)" | postmarkd send -to [email protected] -subject "It works"
Make every program on the host send through Postmark:
sudo ln -s /usr/bin/postmarkd /usr/sbin/sendmail
echo "Subject: test" | sendmail [email protected]
Binaries, packages and checksums for every version are on the
releases page. To build
from source instead: git clone https://github.com/rossedman/postmarkd && cd postmarkd && sudo make install.
More options in Getting started.
docker run -d --name postmarkd -p 127.0.0.1:8025:8025 -p 127.0.0.1:2525:2525 \
-e POSTMARKD_SERVER_TOKEN=your-postmark-server-token \
-e [email protected] \
ghcr.io/rossedman/postmarkd:0.1
curl localhost:8025/email -d '{"To":"[email protected]","Subject":"Hi","TextBody":"Hello"}'
As a sidecar, see Containers and the examples: Docker Compose, Kubernetes native sidecar, GitHub Actions service.
docker run -d -p 8025:8025 -p 2525:2525 -e POSTMARKD_BLACKHOLE=true ghcr.io/rossedman/postmarkd:0.1
# … run your test suite against localhost:8025 or SMTP localhost:2525 …
curl -s localhost:8025/blackhole/messages | jq '.Messages[].Message.Subject'
postmarkd is rarely the bottleneck: a send to Postmark takes 100 ms or more, while postmarkd's own work takes microseconds. Benchmarks run on every CI build, and pull requests fail if they add allocations or make a benchmark more than 25% slower.
Measured on a 4 vCPU Intel Xeon @ 2.80GHz with Go 1.24, upstream replaced by an instant fake (medians of 6 runs):
| Benchmark | Result | Before optimizing |
|---|---|---|
| End to end over the unix socket (client + daemon on the same 4 CPUs) | 33,700 messages/s, 30 µs each | 21,600/s |
| Full relay: client → postmarkd → pooled HTTP → fake Postmark | 15,400 messages/s | 13,100/s |
| Batch of 500 through the HTTP handler | ~115,000 messages/s, 4.3 ms per batch | 7.0 ms |
| Validate and apply defaults to one message | 4.4 µs, 6 allocations | 17.8 µs, 66 |
| Same for a 500-message batch | 4.0 ms, 172 KB | 9.7 ms, 2 MB |
| SMTP message → Postmark (MIME parse + send) | 22 µs | 36 µs |
| MIME conversion, 100 KB PDF attachment | 0.7 ms, 190 MB/s | 1.25 ms |
| Recording metrics for a request (lock-free) | 215 ns, 0 allocations | 293 ns |
| Prometheus scrape | 13 µs, 5 allocations | 67 µs, 386 |
In practice, throughput is set by POSTMARKD_MAX_CONCURRENCY ÷ Postmark's
latency (128 ÷ 0.25 s ≈ 500 requests/s, or up to 256,000 messages/s with
500-message batches) and by your Postmark account's limits. Details, what each
benchmark measures and how to run them: docs/benchmarks.md.
Postmark signs your mail with DKIM once you add DNS records for your domain; a custom Return-Path makes SPF line up with your domain; and a DMARC record tells receivers what to do with mail that fails both. Gmail and Yahoo require these for bulk senders. Check them in one command:
postmarkd check-domain yourdomain.com -account-token "$POSTMARK_ACCOUNT_TOKEN"
It prints each record's status and the exact record to add when one is missing. Read Email authentication for what these mean.
The full documentation is at rossedman.io/postmarkd,
built from the docs/ folder:
Contributions are welcome. See CONTRIBUTING.md and the Code of Conduct. To report a security issue, see SECURITY.md.
MIT. postmarkd is not affiliated with or endorsed by Postmark or ActiveCampaign.