Skip to content

Releases: superelay/smta

3.0.5

Choose a tag to compare

@superelay superelay released this 13 Jul 16:49

🚀 SuperMTA v3.0.5 — Socket-Level Traffic Tracking, Scheduling Fixes & Cluster Guide

We are pleased to announce the release of SuperMTA v3.0.5. This release focuses on upgrading traffic calculation accuracy to raw socket-level tracking, fixing critical REST API issues, stabilizing inbound PTR validations, and delivering complete clustering configuration guidelines.


🌟 Key Highlights

⚡ Socket-Level Network Traffic Calculation

We shifted traffic data tracking from application-level estimations to direct socket-level network read/write counts:

  • Raw Socket Wrappers: Added wrappers intercepting send, recv, SSL_read, SSL_write, and dprintf globally to count exact bytes sent and received.
  • No Double Counting: Cleaned up duplicated legacy estimation counters across the mail engine logic (smtp_engine.c, inbound.c, delivery.c, dummysmtp.c).
  • Visual Telemetry: Restored precise, real-time volume chart updates on the Management Console.

📅 URL-Decoding Fix in Schedules API

  • Fixed a bug where URL-encoded schedule names (e.g. Daily%20Delivery%20Report) failed database queries on DELETE operations due to missing URL-decoding. The management backend now decodes request paths before matching SQLite schedule IDs.

🛡️ Reverse DNS (iprev) Loopback Bypass

  • Resolved an edge-case bug where local/loopback client connections triggered external PTR lookup timeouts. Added robust loopback checking inside is_local_ip() to bypass iprev processing for local relay sources.

📋 Configuration Directives Audit

The following configuration parameters are now fully documented with use cases and syntax examples in both docs/CONFIGURATION_DIRECTIVES_REFERENCE.md and web/docs.html:

Directive Scope Default Description & Use Case
inbound-mode Global thread Engine type: epoll (non-blocking event-driven) or thread (classic pool).
inbound-workers Global 0 (Auto) Thread pool size for the asynchronous epoll workers.
http-access Global None REST/Web Console IP access control list (roles: admin, user).
implicit-tls Listener no Forces immediate SSL/TLS handshake upon connection (Port 465 submission).
use-inbound-proxy Listener no Parses HAProxy PROXY Protocol v1/v2 headers to extract client IPs behind gateways.
check-iprev-inbound Inbound no Toggles client Reverse DNS PTR lookup checks.
smtp-max-auth-failure-rate Inbound None SMTP AUTH brute-force rate limiter threshold (e.g., 5/m).

🖧 Cluster Sizing & Topology Guide

To deploy SuperMTA in a Distributed Cluster Setup (DCS) with 4 or 5 nodes, follow these topology best practices:

1. Quorum & Replication Factor (cluster.replicas)

Always use odd replication numbers to facilitate clean majority quorums and eliminate split-brain scenarios:

  • Quorum Equation: $\text{Quorum} = \lfloor \frac{\text{replicas}}{2} \rfloor + 1$
  • 4-Node Cluster: Set cluster.replicas 3 (Quorum is 2 nodes, tolerates 1 node failure). Setting replicas to 4 increases write traffic and storage without increasing fault tolerance (both fail if 2 nodes are down).
  • 5-Node Cluster: Set cluster.replicas 3 (for lower write latencies) or cluster.replicas 5 (for higher survivability, tolerating 2 node failures).

2. Contact Seed Nodes (cluster.seed)

  • Seed lists must be identical across all node configurations.
  • 4-Node Cluster: Configure 2 static seeds (e.g. Node 1 and Node 2).
  • 5-Node Cluster: Configure 3 static seeds (e.g. Node 1, Node 2, and Node 3).

3. IP Bindings (cluster.listen)

  • cluster.listen is node-specific. Each node must bind to its own unique IP interface (e.g., 10.0.0.1:9100 on Node 1, 10.0.0.2:9100 on Node 2). Copy-pasting the same listen IP on other nodes will cause bind errors (EADDRINUSE) at startup. Use 0.0.0.0:9100 to bind to all local interfaces safely.

📦 Installation & Upgrades

Build from Source

# 1. Grab dependencies
sudo apt-get install -y build-essential libssl-dev libjansson-dev libcurl4-openssl-dev libsqlite3-dev libkrb5-dev

### Install Debian Package (.deb)

sudo dpkg -i smta_3.0.5_amd64.deb
sudo systemctl daemon-reload
sudo systemctl restart smta

🛠️ Verification

Run the built-in diagnostic tool to verify the syntax integrity of your active configuration:

smta-cli test config

3.0.4

Choose a tag to compare

@superelay superelay released this 05 Jul 11:43
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...
Read more

Version 3.0.2

Choose a tag to compare

@superelay superelay released this 04 Jul 15:42
863b74e

SMTA v3.0.2

Release Date: July 4, 2026


What's New

max-msg-per-connection — Outbound Connection Cycling

SMTA now enforces the max-msg-per-connection directive at runtime. When the number of messages delivered over a single outbound SMTP connection reaches the configured limit, the connection is cleanly closed and a fresh one is opened for the next message.

This is useful for improving deliverability with ISPs that prefer short-lived connections or have per-connection rate policies.

Example:

<domain gmail.com>
    max-msg-per-connection 25
</domain>

<domain *>
    max-msg-per-connection 15
</domain>

retry-upon-new-mail — Immediate Deferred Queue Retry

When retry-upon-new-mail yes is set for a domain, SMTA will now immediately reschedule any deferred messages for that domain as soon as a new message is successfully dispatched to it. Previously, deferred messages would wait for the normal queue sweep interval regardless.

This significantly reduces the time deferred messages wait in the queue when delivery conditions improve.

Example:

<domain hotmail.com>
    retry-upon-new-mail true
</domain>

<domain *>
    retry-upon-new-mail true
</domain>

Installation

Download the .deb package from the Releases page and install with:

sudo dpkg -i smta_3.0.2_amd64.deb
sudo systemctl restart smta

Upgrade Notes

  • No configuration changes are required. Both new options are backward-compatible — existing configs without them will behave identically to v3.0.1.
  • To enable connection cycling, add max-msg-per-connection <N> to the relevant <domain> blocks in your smta.conf.
  • To enable immediate deferred retries, add retry-upon-new-mail true to the relevant <domain> blocks.

Version 3.0.0

Choose a tag to compare

@superelay superelay released this 02 Jul 16:19
863b74e

Release Notes: SMTA v3.0.0

We are pleased to announce the release of SMTA v3.0.0, a high-performance, modular, multi-threaded SMTP server written in C. This release brings significant improvements in security, operational stability, standards compliance, and web management.

Tested Platform: This release has been fully tested and validated on Ubuntu 24.04 LTS.


Key Features & Improvements

1. SMTP Capability Control

CHUNKING Support (allow-chunking)

Advertises the EHLO CHUNKING extension and enables BDAT command gating.

SMTPUTF8 Support (allow-smtputf8)

Advertises the EHLO SMTPUTF8 protocol extension for UTF-8 address compliance.


2. Reverse PTR Validation (Inbound Security)

check-iprev-inbound

Enforces reverse DNS lookup verification on all inbound SMTP connections.

trace-iprev-check

Logs detailed DNS lookups and verification status for troubleshooting and auditing.

Granular rejection controls:

reject-iprev-check-temperror — Rejects connections on transient DNS failures (e.g. DNS timeouts).
reject-iprev-check-permerror — Rejects connections on permanent DNS failures (e.g. nonexistent domains).
reject-iprev-check-fail — Rejects connections when reverse verification fails.


3. Authentication Security

smtp-max-auth-failure-rate

Limits repeated authentication failures to help mitigate password-spraying and brute-force attacks.


4. Operations & Message Handling

Custom Job ID Prefix (jobid-prefix)

Prefixes generated Job IDs with a custom identifier (e.g. CUST-12345_1712203200) for easier tracking.

Date Header Injection (add-date-header)

Automatically injects an RFC 5322-compliant X-SMTA-Date header into messages missing a Date header, improving interoperability and deliverability.

SMTP Timeouts

smtp-command-timeout — Prevents slow-client resource exhaustion during SMTP command processing.
smtp-data-timeout — Applies timeout protection during DATA/BDAT message transmission.


5. Critical Fixes

Source IP Selection (is_local_ip)

Replaced socket-binding checks with safe, non-intrusive kernel interface discovery using getifaddrs().
Resolves the issue where SMTP servers bound to local IP addresses prevented the monitor thread from validating available VMTAs.
Eliminates the error:

No source IP available for VMTA

Management Logs & API

Enhanced the Management Logs API to parse multiple timestamp formats, including:

Space-separated timestamps
ISO timestamps without seconds
Other common formats

The web management interface now:

Displays the last 24 hours of logs by default.
Uses more robust timestamp parsing and formatting.


6. Packaging

Package Name: smta

Version: 3.0.0

Supported Platform

✅ Fully tested and validated on Ubuntu 24.04 LTS

Dependencies

libc6
libssl3 | libssl1.1
libjansson4
zlib1g
libcurl4 | libcurl3-gnutls
libsqlite3-0

Bundled Evaluation License

SMTA now includes a signed 90-day Trial License (etc/smta/smta.lic.trial) that:

Automatically activates on fresh installations.
Never overwrites an existing commercial license.
Supports up to 5 Virtual MTAs (VMTAs).
Has no message volume limitations.
Works on any supported host (not machine-bound).


Thank you for using SMTA. We appreciate your feedback and look forward to continuing to improve the platform.