Skip to content

3.0.4

Choose a tag to compare

@superelay superelay released this 05 Jul 11:43
· 3 commits to smta since this release
863b74e

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.com catches and forwards all mail for an entire domain.
  • Local-part matching — bare local-part aliases (e.g. jdoe) are matched against the host-name configured 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:

  1. The lease_failover_watchdog on each replica node continuously scans /var/spool/smta/meta/.
  2. When it finds a message whose lease_expiry has passed and whose primary owner node is marked FAILED in the gossip ring, the replica promotes itself as the new primary.
  3. It claims the lease locally and enqueues the message for delivery.
  4. 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.crt and cluster.key.
  • Node status is one of: JOININGACTIVEFAILED.
  • 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.state file. 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.state and 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 smta

Red 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> directives deliver-unmatched and deliver-matched have been renamed to deliver-unmatched-email and deliver-matched-email for 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-To parsing in ARF reports where line folding caused the address to be truncated.
  • Fixed local-part alias matching against VMTA host-name when 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_claim now serialises this correctly.
  • Fixed rb/rs record 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.