3.0.4
SuperMTA v3.0.4 — Release Notes
Release Date: July 5, 2026
Package: smta_3.0.4_amd64.deb · smta-3.0.4-1.x86_64.rpm
🚀 What's New
1. Advanced Feedback Loop (FBL) & ARF Parsing
SuperMTA now ships a fully featured ARF (Abuse Reporting Format) complaint processing engine.
Structured f Record Emission
When a complaint arrives at a configured FBL mailbox, the engine parses the embedded ARF MIME body and emits a structured f (feedback-loop) accounting record with the following resolved fields:
| Field | Description |
|---|---|
rcpt |
Complained-about recipient address |
orig |
Original sender (envelope from) |
reportedDomainTo |
Recipient domain extracted from the report |
reportedDomainFrom |
Sender domain extracted from the report |
dlvSourceIp |
Sending IP that triggered the complaint |
feedbackType |
ARF feedback type (e.g. abuse, fraud) |
userAgent |
Reporting MUA / ISP agent string |
Multi-Recipient Resolution
A single ARF report may include multiple Original-Rcpt-To addresses. SuperMTA now parses each address independently, writing separate accounting log entries and recording an individual suppression-list bounce for each complained recipient.
Hotmail / JMRP Header Remapping
Hotmail and JMRP do not use standard ARF fields. SuperMTA now supports a map-header-to-field directive to remap custom ISP headers directly to standard accounting log fields:
<acct-file /var/log/smta/fbl.csv>
records f
record-fields f *,header_X-HmXmrOriginalRecipient
map-header-to-field fbl header_X-HmXmrOriginalRecipient rcpt
</acct-file>SpamCop / Non-Standard Report Regex Fallback
For ISPs like SpamCop that do not emit compliant ARF reports, a new body-pattern-file directive accepts a regex file to extract structured fields (rcpt, orig, dlvSourceIp, etc.) from plain-text report bodies:
<feedback-loop-processor>
deliver-unmatched-email no
deliver-matched-email yes
forward-unmatched-to auto-feedback@yourdomain.com
<address-list>
address /fbl@fbl.yourdomain.com/
domain complainant.com
</address-list>
<email-patterns>
body-pattern-file /etc/smta/report-pattern.txt
log-match-info true
</email-patterns>
</feedback-loop-processor>2. Asynchronous Remote Bounce Records (rb / rs)
SuperMTA now natively parses incoming DSN (Delivery Status Notification) bounce messages arriving at FBL mailboxes and emits two new structured accounting record types asynchronously:
| Record Type | Description | Key Fields |
|---|---|---|
rb |
Remote Bounce — permanent delivery failure reported by remote server | rcpt, orig, diag, remMta, dlvSourceIp |
rs |
Remote Status — transient/deferred status notification | rcpt, orig, action, resmta, diag |
Enable in accounting logs:
<acct-file /var/log/smta/acct.json>
records rb, rs
</acct-file>Add log-messages yes inside a <bounce> domain block to output detailed regex match/no-match debug traces for DSN parsing.
3. Enterprise Alias & Forwarding Engine
A new <aliases> top-level configuration block provides a production-grade local alias and forwarding table with these capabilities:
- Multi-target forwarding — comma-separated target list expands into independent delivery tasks, each evaluated individually for suppression, pattern blocks, and VMTA routing.
- Wildcard domain matching —
*@domain.comcatches and forwards all mail for an entire domain. - Local-part matching — bare local-part aliases (e.g.
jdoe) are matched against thehost-nameconfigured on the server. - Per-target suppression safety — if any expanded target is suppression-listed, only that address is silently dropped. Other targets in the same alias list are unaffected and continue delivering normally.
<aliases>
# Multi-target alias
alias newsletters@domain1.com support@yourdomain.com,info@yourdomain.com
# Wildcard domain catch-all
alias *@domain2.com info@yourdomain.com
# Local-part alias
alias jdoe someone@example.com
</aliases>4. Distributed Cluster (DCS) — How Email Flows
SuperMTA's Distributed Cluster Setup (DCS) provides high-availability email delivery with automatic failover. Here is how email flows in both modes:
Standalone Mode
SMTP Client
│
▼
SMTP Listener (port 25)
│ Accepts connection, validates source, AUTH
▼
Spool Writer
│ Writes message to /var/spool/smta/<shard>/
▼
Queue Runner
│ Picks up message, resolves MX via DNS
▼
Outbound Delivery Engine
│ Opens SMTP connection to destination MX
│ Applies DKIM signing, TLS, SMTP Brain delays
▼
Delivery / Bounce / Defer
│ Writes accounting record (b/d/t/rb/rs/f)
▼
Accounting Log / Webhook
In standalone mode the entire pipeline runs on a single node. Spool files live at /var/spool/smta/<shard_hex>/msg_<mid>.eml.
Cluster Mode (DCS Enabled)
In cluster mode, nodes form a consistent hash ring using the Ketama algorithm (32 virtual nodes per physical host). Every message ID is deterministically mapped to a primary owner node and one or more replica nodes.
SMTP Client
│
▼
Any Cluster Node (Ingress)
│ Computes message owner & replicas via hash ring
│ Writes body + metadata (JSON) to local spool
│ body: /var/spool/smta/body/<shard>/msg_<mid>.eml
│ meta: /var/spool/smta/meta/<shard>/msg_<mid>.json
│
├──── mTLS replication ────▶ Replica Node(s)
│ Writes body + meta locally
│ Sends CLUSTER_CMD_QUEUE_ACK
│
│ Waits for quorum: ⌈replica_count / 2⌉ + 1 ACKs
▼
250 OK → SMTP Client (only after quorum confirmed)
┌─────────────────────────────────────────────┐
│ Delivery Coordination │
│ │
│ Primary Owner Node: │
│ ① Locks file locally (.lock rename) │
│ ② Claims lease in metadata JSON │
│ (lease_expiry = now + 60s) │
│ ③ Delivers to destination MX │
│ ④ On success → queue_delete both │
│ body + meta from spool │
│ │
│ Replica Node (concurrent check): │
│ ① Sees local replica spool │
│ ② Queries primary owner for lease │
│ ③ Primary is alive → lease DENIED │
│ ④ Skips delivery (no duplicate sent) │
└─────────────────────────────────────────────┘
Failover Flow (Primary Node Failure)
If the primary node goes offline during or before delivery:
- The
lease_failover_watchdogon each replica node continuously scans/var/spool/smta/meta/. - When it finds a message whose
lease_expiryhas passed and whose primary owner node is markedFAILEDin the gossip ring, the replica promotes itself as the new primary. - It claims the lease locally and enqueues the message for delivery.
- No duplicate delivery occurs because the lease is held exclusively — other replicas attempting the same promotion are rejected.
Shared Spool Architecture
| Path | Content | Who Writes |
|---|---|---|
/var/spool/smta/body/<shard>/msg_<mid>.eml |
Raw message body | Ingest node + all replicas |
/var/spool/smta/meta/<shard>/msg_<mid>.json |
Delivery metadata, lease state, retry count | Ingest node + all replicas |
The spool is shared by design — both the ingest node and its replicas hold complete copies. The metadata JSON is the source of truth for lease ownership and delivery state.
Node Communication
- Nodes gossip every 5 seconds over mTLS TCP (default port
9100). - mTLS certificates are auto-generated on startup at
/etc/smta/certs/cluster.crtandcluster.key. - Node status is one of:
JOINING→ACTIVE→FAILED. - When membership changes, the consistent hash ring is automatically rebalanced (
cluster_rebalance_ring).
5. SMTP Brain — Cluster-Aware Behaviour
The SMTP Brain now documents its cluster-mode behaviour explicitly:
- Per-node reputation state — each cluster node maintains its own
brain.statefile. Reputation scores, rate-limit delays, and quarantine decisions are local to each node and are not automatically synchronised. - Primary-only Brain enforcement — Brain delays and quarantine decisions are applied only by the primary owner node when it actively delivers a message. Replica nodes do not apply Brain enforcement for messages they hold in passive backup.
- Manual state sync — to replicate Brain state across nodes, copy
/var/lib/smta/brain.stateand reload:POST /api/v1/system/reload.
⚠️ Note: If Node A quarantines a sending IP for a destination, Node B will not inherit that quarantine state. Manual replication is required to synchronise quarantine decisions across the cluster.
📦 Installation
Debian / Ubuntu
sudo dpkg -i smta_3.0.4_amd64.deb
sudo systemctl enable --now smtaRed Hat / Rocky Linux / CentOS
sudo rpm -i smta-3.0.4-1.x86_64.rpm
sudo systemctl enable --now smta🔧 Upgrade Notes
- The
<feedback-loop-processor>directivesdeliver-unmatchedanddeliver-matchedhave been renamed todeliver-unmatched-emailanddeliver-matched-emailfor clarity. The old names are still accepted but will emit a deprecation warning in the access log. - The
<aliases>block is new and requires no migration for existing installations. If not configured, behaviour is identical to previous versions. - Cluster DCS configurations are backward-compatible. Existing
<cluster>blocks require no changes.
🐛 Bug Fixes
- Fixed multi-line
Original-Rcpt-Toparsing in ARF reports where line folding caused the address to be truncated. - Fixed local-part alias matching against VMTA
host-namewhen the alias was defined without a domain part. - Fixed a race condition in the lease watchdog where two replica nodes could simultaneously detect a failed primary and both attempt lease promotion within the same 60-second window. The atomic
queue_claimnow serialises this correctly. - Fixed
rb/rsrecord emission when the DSN report body contained quoted-printable encoded diagnostic strings.
📖 Documentation
Full documentation is available in the built-in web portal at http://YOUR_SERVER:8080/docs.html.
SuperMTA is built and maintained by the SuperMTA Team. For support, open an issue on GitHub.