KumoMTA overview
Use KumoMTA as the sending engine, with SMTP authentication, queues, rate limits and delivery webhooks.
KumoMTA is a high-volume mail transfer agent. The outbound/ folder holds its policy: Lua and TOML files that tell it how to accept, queue and deliver your mail.
Read the known issues first
DKIM signing and USE_RELAY=true work and were tested with KumoMTA 2026.09.29. Traffic shaping is not loaded yet. See Known issues.
What it does
- A client or your Node app connects on port 587 and logs in.
- KumoMTA checks the sender and recipient, and puts the message in a queue for each destination domain.
- It delivers from one of your outbound IP addresses, at a rate set for each provider, and retries temporary failures.
- Every delivery, bounce and delay is posted to your webhook as JSON.
Use it from the Node server
The Node server can send its queued mail through KumoMTA, so Node keeps ports 25 and 587 and KumoMTA stays on the private network:
OUTBOUND_DRIVER=relaysubmits over SMTP. KumoMTA needs the Node server inrelay_hosts, or a login.OUTBOUND_DRIVER=kumo-httpposts to KumoMTA's HTTP API. KumoMTA needs the Node server intrusted_hostson its HTTP listener.
KumoMTA's delivery events can be posted back to the Node server's bounce HTTP server. See Outbound drivers for what each driver sends.
Files
Everything KumoMTA reads is in outbound/policy/. The folder is mounted read-only at /opt/kumomta/etc/policy, so your .env file never enters the container.
| File | What it does |
|---|---|
init.lua | Entry point. Starts the 587 listener, defines the spool and logs, and handles AUTH, sender and recipient checks. |
dkim.lua | DKIM signing. Keys come from a file, an HTTP service or Redis. |
egress.lua | Builds the egress pool main-pool from KUMOMTA_SOURCE_IPS. |
queue.lua | Per-domain message rate and the retry schedule. |
webhook.lua | Posts log events to WEBHOOK_URL. |
listener_domains.toml | Which domains accept relayed mail and bounce reports. |
domains.lua | Sender domains that are allowed when USE_RELAY=true. |
shaping.toml | Per-provider connection and rate rules. Not loaded yet. |
users.lua | SMTP usernames and passwords. Not committed. Start from users.example.lua. |
Run it
From the repository root:
Spool and logs live in the kumo-spool and kumo-logs volumes, so queued mail survives a rebuild.
KumoMTA's HTTP API listens on 127.0.0.1:8000 inside the container only. To look at the queues, use kcli from inside it: