Contents
Why integration matters
PowerMTA and MailWizz solve fundamentally different problems and the integration between them is where most operational confusion lives. MailWizz is the application layer: it manages subscriber lists, builds campaign content, schedules sends, handles unsubscribes, tracks opens and clicks, generates reports for customers. PowerMTA is the delivery layer: it takes messages and gets them to receiving MTAs with proper throttling, IP reputation management, bounce classification, and the precise control that high-volume sending requires. Neither tool tries to do the other's job; the integration is where they meet.
This guide exists because operators repeatedly stand up MailWizz + PowerMTA without thinking through the integration choices and discover later that they have built something that works but not in the way they intended. The pickup directory pattern survives in old documentation and tutorials, but most 2026 deployments use SMTP relay and the difference matters operationally. VirtualMTA selection logic is rarely documented from MailWizz's perspective. Multi-IP rotation can happen at the MailWizz delivery server level or at the PowerMTA VMTA level with different operational implications. The X-Job header is hugely useful for accounting correlation and operators frequently do not set it.
The structure: the two integration patterns and which to choose, the SMTP relay configuration with exact MailWizz field values, the pickup directory configuration for the rare cases where it applies, how MailWizz selects PowerMTA VirtualMTAs, multi-IP rotation patterns and their trade-offs, the X-Job header pattern, separating marketing from transactional traffic, bounce server and FBL server configuration when those flow back through SMTP, common failure modes operators encounter.
SMTP relay vs pickup directory
The two integration patterns serve different operational profiles.
| Attribute | SMTP relay | Pickup directory |
|---|---|---|
| Handoff mechanism | MailWizz SMTPs to PowerMTA listener | MailWizz writes files to dir, PowerMTA consumes |
| Network requirement | Same host or routable network | Shared filesystem |
| Authentication | Standard SMTP AUTH | Filesystem permissions |
| Throughput overhead | SMTP protocol per message | Filesystem write per message |
| Multiple MailWizz instances | Yes, share PowerMTA | Difficult, filesystem sharing complex |
| Separate hosts | Yes, network is the boundary | No, must share filesystem |
| Modern usage | Standard pattern in 2026 | Legacy, narrow use cases |
For new deployments in 2026: SMTP relay almost always. Pickup directory is appropriate only in narrow scenarios where the SMTP handoff overhead is measurably affecting throughput at extreme volumes and the architectural constraint of shared filesystem is acceptable. Operators considering pickup should benchmark SMTP relay first; the overhead is usually negligible compared to actual delivery time.
SMTP relay configuration
The standard configuration: MailWizz delivery server points to PowerMTA's SMTP listener (typically port 25 on localhost when co-located, or the appropriate hostname:port when separate hosts).
Configure PowerMTA's SMTP listener in /etc/pmta/config to accept connections from MailWizz:
<smtp-listener 127.0.0.1:25>
process-x-virtual-mta yes
process-x-job yes
</smtp-listener>
<source 127.0.0.1>
always-allow-relaying yes
process-x-virtual-mta yes
process-x-job yes
</source>
The process-x-virtual-mta yes tells PowerMTA to honor X-Virtual-MTA headers from incoming messages and use them for VMTA routing. The process-x-job yes preserves X-Job headers in accounting records for downstream correlation.
For separate-host deployments where MailWizz and PowerMTA are on different servers, configure the listener on a routable interface and add authentication:
<smtp-listener 0.0.0.0:587>
process-x-virtual-mta yes
process-x-job yes
auth-only yes
</smtp-listener>
<auth-group mailwizz-auth>
smtp-user mailwizz-user
password STRONG_SECRET_HERE
</auth-group>
Now configure the MailWizz side. In MailWizz backend, navigate to Servers then Delivery Servers then Add then SMTP. Field values:
| Field | Value | Notes |
|---|---|---|
| Name | PowerMTA Main | Identifier shown in MailWizz UI |
| Hostname | localhost (or PowerMTA IP) | Where MailWizz connects |
| Port | 25 (or 587 for auth) | Match PowerMTA listener |
| Username | (blank or mailwizz-user) | Only if AUTH configured |
| Password | (blank or matching) | Only if AUTH configured |
| Encryption | None (or TLS) | None acceptable on localhost |
| From email | noreply@yourdomain.com | Default from address |
| From name | Your Brand | Default from name |
| Reply-To email | support@yourdomain.com | Where replies go |
| Return-Path | bounce@yourdomain.com | Where bounces go |
| Hourly quota | 0 (unlimited) | PowerMTA controls actual rate |
| Monthly quota | 0 (unlimited) | PowerMTA controls actual rate |
| Pause after send | 0 | No artificial pacing needed |
| Additional headers | X-Virtual-MTA: marketing-pool | VMTA name in PowerMTA config |
The Additional Headers field is where you inject X-Virtual-MTA to route messages to a specific PowerMTA VMTA. Format is one header per line, name colon space value.
Test the integration by clicking the "Validate server" button in MailWizz; the validation sends a small test message through the configured SMTP relay. Successful validation confirms MailWizz can connect to PowerMTA and PowerMTA accepts the handoff.
Pickup directory configuration
The pickup directory pattern is older and rarely used in new 2026 deployments. Documented here for completeness because some legacy installations still use it.
Configure PowerMTA pickup in /etc/pmta/config:
<pickup-dir /var/spool/mailwizz/pickup>
interval 5s
user www-data
group www-data
</pickup-dir>
Create the directory with appropriate ownership:
mkdir -p /var/spool/mailwizz/pickup
chown www-data:www-data /var/spool/mailwizz/pickup
chmod 0775 /var/spool/mailwizz/pickup
In MailWizz, configure the delivery server as PickupDirectory type pointing to /var/spool/mailwizz/pickup. PowerMTA polls the directory every 5 seconds and consumes any new files MailWizz writes there.
The pickup pattern requires MailWizz and PowerMTA to run on the same host (or share a network filesystem like NFS, which adds complexity and failure modes). For most operators this constraint is enough reason to use SMTP relay instead.
PowerMTA VirtualMTA selection
VirtualMTA selection determines which PowerMTA VMTA handles each message. MailWizz has a few mechanisms operators choose between.
Mechanism 1: X-Virtual-MTA header injection. MailWizz delivery server injects X-Virtual-MTA header with value matching a VMTA name in PowerMTA config. PowerMTA reads the header and routes to the named VMTA. Setup: in MailWizz delivery server Additional Headers field add X-Virtual-MTA: vmta-name-here.
Mechanism 2: Let PowerMTA route via domain { } directives. Do not inject X-Virtual-MTA. PowerMTA's domain { } directives or VMTA pool routing decide based on destination domain or other attributes. Setup: in PowerMTA config, set default VMTA for each destination domain using queue-to or pool assignment.
Mechanism 3: Multiple MailWizz delivery servers with different X-Virtual-MTA values. Create one MailWizz delivery server per VMTA, each injecting a different X-Virtual-MTA. Assign delivery servers to MailWizz lists or customers for per-customer or per-list isolation. Setup: in MailWizz, create N delivery servers; each one's Additional Headers points to a different PowerMTA VMTA; under each List or Customer settings, assign the appropriate delivery server.
The third mechanism is standard for multi-tenant ESPs running MailWizz over PowerMTA because it achieves customer isolation without requiring custom PowerMTA logic. Each customer's messages route through a dedicated VMTA with potentially dedicated IPs, dedicated throttling, dedicated reputation.
Multi-IP rotation patterns
Multi-IP rotation can happen at either the MailWizz delivery server level or the PowerMTA VMTA level, with different operational implications.
Rotation at MailWizz level. Create multiple MailWizz delivery servers each pointing to a different IP (typically through different VMTAs in PowerMTA). MailWizz round-robins between delivery servers per campaign or per send. This pattern works but has limitations: MailWizz rotation logic is coarser than PowerMTA's; per-destination throttling does not coordinate across MailWizz delivery servers; MailWizz reports become harder to aggregate across delivery servers.
Rotation at PowerMTA level (recommended). Configure a single MailWizz delivery server pointing to PowerMTA. In PowerMTA config, define a VMTA pool containing multiple VMTAs each bound to different source IPs. PowerMTA handles rotation internally with proper per-IP throttling and unified accounting.
# PowerMTA config
<virtual-mta vmta-ip1>
smtp-source-host 203.0.113.42 mta1.example.com
</virtual-mta>
<virtual-mta vmta-ip2>
smtp-source-host 203.0.113.43 mta2.example.com
</virtual-mta>
<virtual-mta vmta-ip3>
smtp-source-host 203.0.113.44 mta3.example.com
</virtual-mta>
<virtual-mta-pool marketing-pool>
virtual-mta vmta-ip1
virtual-mta vmta-ip2
virtual-mta vmta-ip3
</virtual-mta-pool>
MailWizz delivery server injects X-Virtual-MTA: marketing-pool. PowerMTA routes through the pool, rotating among the three IPs with weighted round-robin (or simple round-robin if weights not specified). Per-IP throttling can be set via the source-ip-max-msg-rate directive added in PowerMTA 4.5 to limit each IP individually within the pool.
The PowerMTA-level pattern is substantially better for production because rotation logic is internal to PowerMTA where reputation tracking and throttling already live, and reports remain unified.
X-Job header for accounting correlation
The X-Job header is one of the most undervalued features in the MailWizz + PowerMTA integration. Setting X-Job in MailWizz makes PowerMTA accounting records carry the job identifier, which allows downstream analytics to correlate PowerMTA delivery records with MailWizz campaigns directly.
In MailWizz delivery server Additional Headers, add:
X-Job: [CAMPAIGN_UID]_[LIST_UID]_[CUSTOMER_UID]
MailWizz substitutes the placeholders at send time so each message carries a unique job identifier derived from campaign, list, and customer. PowerMTA logs this in the jobId column of accounting CSV (covered in our PowerMTA logging reference).
Downstream queries become powerful with X-Job present:
-- Complaint rate per MailWizz campaign
SELECT
jobId,
countIf(type = 'd') AS delivered,
countIf(type = 'f') AS complaints,
complaints / delivered AS complaint_rate
FROM pmta_accounting
WHERE timeLogged >= now() - INTERVAL 7 DAY
AND jobId != ''
GROUP BY jobId
ORDER BY complaint_rate DESC;
Without X-Job, the same analysis requires complex joins between PowerMTA accounting and MailWizz database. With X-Job set, a single ClickHouse query against accounting answers the question.
Marketing vs transactional separation
Production deployments typically separate marketing and transactional traffic into different delivery paths to prevent one from poisoning the other's reputation. The integration pattern:
Create two MailWizz delivery servers: "PowerMTA Marketing" injecting X-Virtual-MTA: marketing-pool and "PowerMTA Transactional" injecting X-Virtual-MTA: transactional-pool. In PowerMTA, define separate VMTA pools with separate IPs, separate throttling, separate authentication domains.
<virtual-mta-pool marketing-pool>
virtual-mta marketing-ip1
virtual-mta marketing-ip2
virtual-mta marketing-ip3
</virtual-mta-pool>
<virtual-mta-pool transactional-pool>
virtual-mta transactional-ip1
</virtual-mta-pool>
Assign delivery servers in MailWizz appropriately: marketing campaigns use the Marketing delivery server, transactional emails (welcome, password reset, receipts) use the Transactional delivery server. Reputation isolation is automatic.
This separation produces measurably better deliverability for both streams because marketing reputation issues (occasional spam complaints, list quality concerns) do not affect transactional deliverability (where receiving MTAs expect near-perfect engagement) and vice versa.
Bounce and FBL server setup
Bounces and feedback loop reports flow back through email infrastructure independently of the outbound path. MailWizz needs to know about them to update subscriber status correctly.
Bounce server. Configure a mailbox that receives bounce-backs (typically the Return-Path address). In MailWizz under Servers then Bounce Servers, add the IMAP credentials for the bounce mailbox. MailWizz's bounce-handler cron job polls this mailbox every 10 minutes and processes new messages.
The Return-Path you set in the delivery server (covered earlier) should point to a mailbox you control. Common pattern: bounce@yourdomain.com routed to a mailbox on the MailWizz server or a dedicated mailbox service. PowerMTA-generated bounces and receiving MTA bounces both arrive here.
FBL server. Configure mailboxes that receive ARF complaint reports from ISP feedback loops. In MailWizz under Servers then Feedback Loop Servers, add IMAP credentials per FBL. Microsoft SNDS-JMRP, Yahoo CFL, Comcast, AT&T all run separate feedback loops with separate report addresses.
The feedback-loop-handler cron job polls these mailboxes every 20 minutes and processes ARF messages, updating subscriber status to suppress complainers.
PowerMTA can also process FBL reports independently and write f-type records to accounting. Operators frequently configure both: PowerMTA captures FBL for accounting and reputation alerting, MailWizz captures FBL for subscriber suppression. The redundancy ensures complaints are not lost if one system has issues.
Common failure modes
The integration produces specific failure modes operators encounter repeatedly.
MailWizz shows delivered but recipient does not receive. Most common confusion. MailWizz reports delivered when PowerMTA accepts handoff. Check PowerMTA accounting log for the recipient and find the actual delivery outcome (d, b, t). See the FAQ above for the diagnostic workflow.
SMTP authentication failures. MailWizz cannot connect to PowerMTA. Verify PowerMTA listener is accepting connections on the configured port (telnet localhost 25 should work). Verify auth-group credentials match exactly. Check PowerMTA logs at /var/log/pmta/log for connection attempts.
X-Virtual-MTA header ignored. Messages route through default VMTA despite the header being set. Verify process-x-virtual-mta yes is set in both smtp-listener and source directives in PowerMTA config. Verify the VMTA name in the header exactly matches a VMTA defined in PowerMTA config (case-sensitive).
Throttling errors visible to MailWizz. PowerMTA returns SMTP errors when MailWizz hands off too fast. Set MailWizz delivery server hourly quota and pause-after-send to artificially limit MailWizz's pace below PowerMTA's capacity. Or increase PowerMTA's listener limits if the bottleneck is actually receiver-side.
Pickup directory permissions wrong. PowerMTA cannot read files MailWizz writes. Verify both processes run as compatible users (typically same user) and directory permissions allow read/write. Common issue: MailWizz writes as www-data but PowerMTA runs as pmta user, neither can read the other's files.
Bounces accumulate but MailWizz does not process. Bounce-handler cron is not running. Check MailWizz Misc then Cron Jobs for warnings. Verify IMAP credentials in bounce server config. Test manual IMAP connection from the MailWizz server to the bounce mailbox to verify network/auth.
Reports do not match between MailWizz and PowerMTA. MailWizz tracks opens and clicks based on tracking pixels and link rewrites; PowerMTA tracks SMTP-level delivery. The two reports are measuring different things. Reconciliation across both produces accurate operational picture but each individual report is incomplete on its own.
An operator we support reported "MailWizz says 95% delivery rate but customers are complaining about not receiving emails". The diagnostic took 5 minutes. Pull a sample of supposedly-delivered recipients from a recent campaign. Query PowerMTA accounting for those addresses. Result: 70% had type d records (actually delivered), 25% had type b records (bounced after MailWizz handoff, MailWizz unaware), 5% had no record at all (something happened between MailWizz and PowerMTA handoff). The 25% bounces had dsnDiag showing IP reputation issues at Microsoft. The 5% missing records traced to MailWizz delivery server hourly quota being set too low, causing MailWizz to queue messages it then never actually sent. Two fixes deployed: increased MailWizz delivery server quota to remove the artificial limit, addressed Microsoft reputation through queue-to consolidation (covered in our domain block reference). Customer complaints stopped within 48 hours. The lesson: when MailWizz and PowerMTA reports disagree, PowerMTA accounting is the ground truth for what actually happened to messages after handoff.
The integration between MailWizz and PowerMTA is straightforward once the patterns are understood. SMTP relay with X-Virtual-MTA injection and X-Job header for accounting correlation is the standard 2026 pattern that handles most operational scenarios cleanly. Multi-IP rotation at PowerMTA level rather than MailWizz level keeps reputation management coherent. Bounce and FBL handling through dedicated mailboxes with proper cron processing closes the feedback loop. Operators who set this up methodically have integrations that simply work; operators who improvise discover edge cases later that the methodical setup would have prevented.