← PowerMTA Knowledge Hub
Extensibility • Programmable Transport Architecture

PowerMTA Lua Scripting Guide: Dynamic Header Rewriting, Custom Envelope Routing & SPF Filtering

Published by Fred Dawson • Senior Deliverability Systems Architect • 20 min read

While declarative configuration directives handle 90% of routine email transport requirements, modern enterprise senders frequently demand dynamic, real-time message manipulation that static configuration files cannot accommodate. Whether you need to inject cryptographic tracking tokens, dynamically assign outbound Virtual MTAs based on customer subscription tiers, rewrite envelope senders on-the-fly, or enforce zero-trust authentication policies before messages touch the disk spool, PowerMTA’s embedded Lua scripting engine delivers microsecond execution directly within the transport pipeline. By embedding an in-memory Lua JIT environment into the core C++ daemon, PowerMTA allows systems engineers to write high-throughput message interception hooks with zero inter-process overhead. This comprehensive engineering guide explores the PowerMTA Lua API, details the core execution hooks, and delivers five battle-tested production scripts.

< 0.05ms
In-Memory Lua Hook Latency
Pre-Spool
Zero Disk I/O Filter Execution
100% Dynamic
vMTA & Envelope Routing Logic
JIT Compiled
Ultra-High Concurrency Execution

1. The PowerMTA Lua Architecture: Embedded In-Memory JIT

Standard Unix mail transfer agents (such as Postfix or Exim) traditionally rely on external milter processes or shell pipes to manipulate messages. This architecture forces the operating system to fork processes or stream messages over loopback TCP sockets, creating severe serialization delays and CPU exhaustion under high load.

Embedded JIT Execution vs External Milters

PowerMTA’s Embedded Lua Engine: PowerMTA embeds the lightweight, high-performance Lua interpreter directly into its C++ worker threads. When an email arrives over an inbound SMTP listener, the message envelope and headers are passed as C++ pointers directly to the in-memory Lua runtime environment. Your Lua script inspects, alters, or reroutes the email in sub-millisecond time before the message is committed to the disk spool.

Non-Blocking Thread Safety: Each PowerMTA worker thread maintains an isolated Lua state. Scripts do not require cross-thread mutex locking for message manipulation, allowing PowerMTA to process hundreds of thousands of dynamic message alterations per second across multi-core processors.

2. The 4 Primary Lua Pipeline Hooks in PowerMTA

PowerMTA exposes four distinct lifecycle hooks during message processing:

1. Pre-Submission Hook (mta_pre_submission)

Fires immediately after the SMTP DATA command completes, before the message is accepted into the spool. Perfect for validating authentication, rewriting headers, injecting tracking pixels, or rejecting malicious payloads with custom 550 codes.

2. Recipient Filter Hook (mta_inbound_rcpt_to)

Fires during the RCPT TO conversation. Used for real-time recipient verification, internal suppression list lookups, and dropping invalid domains before payload transmission.

3. Outbound Pre-Delivery Hook (mta_pre_delivery)

Fires right before PowerMTA opens an outbound TCP socket to the destination MX. Allows dynamic override of the Virtual MTA, custom TLS cipher selection, or routing through backup gateways based on destination health.

4. Inbound Bounce Processor Hook

Fires when PowerMTA accepts an incoming DSN bounce or FBL complaint email. Ideal for parsing non-standard bounce formats and publishing structured JSON events to downstream webhooks.

3. Configuring PowerMTA to Load and Bind Lua Scripts

To activate Lua scripting in PowerMTA, configure the global script directives in your /etc/pmta/config file:

/etc/pmta/config • Lua Engine Binding PMTA Directives
# ==============================================================================
# POWERMTA EMBEDDED LUA SCRIPT ENGINE CONFIGURATION
# ==============================================================================
# Load the master Lua script file into the daemon runtime
script-file /etc/pmta/scripts/master_hooks.lua

# Optional: Set the maximum memory allocated per Lua state (in megabytes)
# Default is typically 32MB; increase for heavy in-memory routing tables
script-max-memory 64

# Enable dynamic reload of Lua scripts via 'pmta reload'
script-auto-reload yes

4. 5 Production-Ready Lua Script Recipes

Recipe 1: Dynamic Virtual MTA Routing Based on Customer Tier

Route high-priority transactional emails through dedicated premium IPs while routing bulk newsletters through secondary pools:

/etc/pmta/scripts/dynamic_routing.lua Lua Script
-- Hook executed before message is scheduled for delivery
function mta_pre_delivery(msg)
    local tier = msg:get_header("X-Customer-Tier")
    local category = msg:get_header("X-Mail-Category")

    if tier == "enterprise" or category == "transactional" then
        -- Route to clean, high-reputation dedicated IP pool
        msg:set_vmta("vmta-pool-vip")
        msg:set_header("X-PMTA-Routed-By", "VIP-Lua-Policy")
    elseif tier == "free" then
        -- Route to standard shared pool with conservative throttling
        msg:set_vmta("vmta-pool-bulk")
    end

    return pmta.action.ACCEPT
end

Recipe 2: Mandatory RFC 8058 One-Click Unsubscribe Injection

Ensure every marketing message has verified List-Unsubscribe-Post and List-Unsubscribe headers:

/etc/pmta/scripts/rfc8058_inject.lua Lua Script
function mta_pre_submission(msg)
    local list_unsub = msg:get_header("List-Unsubscribe")
    local recipient = msg:get_recipient()

    if list_unsub and not msg:get_header("List-Unsubscribe-Post") then
        -- Inject required RFC 8058 one-click header for Gmail/Yahoo compliance
        msg:add_header("List-Unsubscribe-Post", "List-Unsubscribe=One-Click")
    end

    -- Add audit timestamp
    msg:add_header("X-PMTA-Processed-At", os.date("!%Y-%m-%dT%H:%M:%SZ"))
    return pmta.action.ACCEPT
end

Recipe 3: Quarantine Suspicious Inbound Submissions

Reject submissions attempting to send with forged high-profile sender addresses:

/etc/pmta/scripts/anti_spoof.lua Lua Script
function mta_pre_submission(msg)
    local from_header = msg:get_header("From") or ""
    local client_ip = msg:get_envelope_param("client_ip") or ""

    -- If sender claims to be executive domain but connects from untrusted network
    if string.find(from_header:lower(), "@corporate%-bank%.com") then
        if not string.find(client_ip, "^10%.25%.") and not string.find(client_ip, "^192%.168%.10%.") then
            -- Reject permanently with RFC 550 Diagnostic Code
            return pmta.action.REJECT, "550 5.7.1 Unauthorized sender origin for corporate domain"

5. Performance Engineering: Avoiding Blocking Pitfalls

Because PowerMTA processes millions of emails per hour, poorly engineered Lua scripts can degrade throughput. Adhere strictly to these architectural rules:

Antipattern: Synchronous Database Queries

Never connect directly to MySQL or PostgreSQL inside a Lua hook. If a database query takes 15 milliseconds, your worker thread is blocked, slashing node throughput from 400 messages/sec down to 60 messages/sec.

Best Practice: In-Memory Lookups & Local IPC

Store routing tables, customer tiers, and suppression hashes in local Lua tables refreshed periodically, or query a local Unix-socket Redis cache with a 2-millisecond timeout threshold.

6. Hook Lifecycle & Security Comparison Matrix

Lifecycle Hook Trigger Point Available Objects Can Reject Message? Primary Operational Use Case
mta_inbound_rcpt_to SMTP RCPT TO Recipient address, source IP Yes (SMTP 550/554) Immediate bad-domain & suppression rejection
mta_pre_submission End of DATA (Pre-Spool) Full headers, body preview, metadata Yes (SMTP 550) Header rewriting, tracking, DMARC validation
mta_pre_delivery Prior to Outbound TCP Connect Recipient, vMTA, retry counter No (Hold/Defer only) Dynamic vMTA routing & IP failover
mta_bounce_processor DSN / ARF Receipt Raw bounce body, DSN diagnostic No Automated suppression list API webhooks

7. Production Case Study: Routing 30M Multi-Tenant Sends

Production Architecture • B2B Marketing Automation Platform

Automating Dynamic Tenant IP Allocation Across 64 Virtual MTAs

A multi-tenant email platform delivering 30 million monthly messages was struggling with manual IP management. When free-tier users uploaded low-quality lists, they occasionally poisoned shared pools, threatening high-paying enterprise tenants.

The Lua Solution: AutoSMTP deployed an optimized 45-line Lua script embedded into PowerMTA’s mta_pre_delivery hook. The script queries an in-memory shared memory hash of customer account tiers and historical reputation scores, automatically routing traffic to VIP, Warmup, or Quarantined Virtual MTA subnets.

The Results: Zero manual intervention required for tenant routing. Enterprise customer deliverability stabilized at 99.7% inbox placement, and the entire Lua routing evaluation overhead measured under 0.04 milliseconds per message.

Enterprise Clustered Infrastructure

The AutoSMTP Deliverability Defense Advantage

Inbound and outbound filtering pipelines require robust underlying transport hardware. AutoSMTP provisions sovereign, dedicated bare-metal MTA infrastructure engineered for high-throughput filtering, synchronous 550 bounce suppression, and permanent reputation control.

Turnkey Dedicated Bare-Metal Clusters

Provisions fully licensed PowerMTA and KumoMTA clusters on enterprise bare-metal with dedicated IPv4 subnets and predictable flat pricing.

Automated Gas-Pedal IP Warming

Monitors Google Postmaster spam ratios (<0.1%) and real-time ISP deferrals with algorithmic volume scaling across your entire IP pool.

Native FBL & Socket Interceptors

RFC 5321 in-band 550 bounce suppression, automated Yahoo/Outlook Complaint Feedback Loops (CFL), and instant bad-IP eviction.

Fully Managed DNS & Multi-IP Auth

Pre-configured forward and reverse DNS (PTR) per IP, SPF CIDR alignment, 2048-bit DKIM rotation, and strict DMARC enforcement.

Upgrade Your Email Infrastructure with Dedicated Bare Metal

Eliminate filter lag, queue serialization bottlenecks, and noisy neighbor contamination. Deploy a turnkey AutoSMTP cluster today.

Deploy Turnkey MTA Cluster →