Docs / Integrations
Connect PowerMTA to MailWizz
To integrate PowerMTA with MailWizz: add the MailWizz server's IP as a trusted source in PowerMTA, then in MailWizz create a delivery server of type PowerMTA pointing at the PowerMTA host and port. Set the X-Virtual-MTA header to choose the IP pool, configure bounce/FBL processing via the accounting file, and send a test before scaling.
MailWizz is a self-hosted email marketing application; PowerMTA is the engine that actually delivers. Connecting them is straightforward once you know the two halves: trust the MailWizz host in PowerMTA, then add PowerMTA as a delivery server in MailWizz. The detail that trips people up is bounce and feedback-loop processing — there are three ways to wire it, and a caveat that surprises almost everyone — so we cover that explicitly.
PowerMTA side: trust the MailWizz host
Add a source block for the MailWizz server's IP so it may relay and select virtual MTAs:
<source 10.0.0.20> # the MailWizz server
always-allow-relaying yes
process-x-virtual-mta yes
default-virtual-mta pool-marketing
</source> Note the port PowerMTA listens on (commonly 2525, or 25/587) — you'll enter it in MailWizz.
Trusting the IP is the simplest model and fine when MailWizz and PowerMTA sit on the same private network. If
MailWizz is remote, or you’d rather not relay on IP alone, require authentication instead and define an
<smtp-user> that MailWizz logs in with:
<smtp-user mailwizz>
password a-long-random-secret
source {mw-auth}
</smtp-user>
<source {mw-auth}>
require-auth true
always-allow-relaying yes
process-x-virtual-mta yes
</source> Then MailWizz authenticates with that username and password rather than being trusted by IP — the safer choice whenever the two servers don’t share a locked-down network. Pair it with TLS so the credentials aren’t sent in the clear.
MailWizz side: add the delivery server
In MailWizz, create a delivery server and choose the PowerMTA type where available — it can read PowerMTA's accounting files for native bounce processing.
| Field | Value |
|---|---|
| Type | PowerMTA (preferred) or SMTP |
| Hostname | Your PowerMTA server IP / host |
| Port | 2525 (or 25 / 587) |
| Force from | Your authenticated sending domain |
| Custom headers | X-Virtual-MTA: pool-marketing |
Bounce & FBL handling
PowerMTA logs delivery, bounce and feedback events to its accounting file. The MailWizz PowerMTA delivery server reads those events to update stats and suppress bad addresses. If you use the plain SMTP type instead, add a bounce handler that pipes the acct-file and reports back. Either way, the non-negotiable outcome is that hard bounces and complaints are removed from your lists — list hygiene is what keeps you in the inbox.
Three ways to process bounces and complaints
The line above hides real choice, so here are the three approaches in practice, from newest to most established.
1. Native delivery server with a webhook. A pmta-smtp delivery server in current
MailWizz pairs with PowerMTA’s webhook accounting output: an <acct-file> with an
http-webhook-url posts delivery, bounce, rebound and feedback records as JSON to a MailWizz endpoint,
and MailWizz processes them. When you create the delivery server, MailWizz shows the webhook URL to use.
<acct-file /var/log/pmta/webhook.json>
http-webhook-url https://your-mailwizz/webhook
records b, d, rb, f
</acct-file> 2. Accounting file piped to a PHP handler. The long-established method pipes the bounce records straight into a script that calls the MailWizz API to unsubscribe the address:
<acct-file |/usr/bin/php /opt/pmta/bouncehandler.php>
records b
record-fields b timeQueued,bounceCat,vmta,orig,rcpt,jobId,dsnStatus,dsnDiag
</acct-file> 3. Plain SMTP delivery server plus a bounce mailbox. If you use the generic SMTP type rather than the PowerMTA type, MailWizz can’t read the accounting file, so you add a bounce server (a mailbox MailWizz polls) and let it process returned messages the traditional way. It works, but it misses the rich per-message data the other two methods carry.
Mapping a bounce back to the subscriber
Whichever method you use, the handler has to know which MailWizz subscriber bounced. MailWizz stamps identifying headers on each message — a subscriber UID and the list ID — and a well-written handler reads those back from the bounce record to unsubscribe the exact subscriber from the exact list. The native webhook does this for you; a PHP handler reads the subscriber UID header (and uses the MailWizz API) to do the same.
Feedback-loop complaints work the same way, with a wrinkle: some providers rewrite or strip the original recipient, so the processor maps a provider-specific header (Outlook’s original-recipient header, for instance) back to your subscriber. The point is that the mapping is what makes processing actionable — a bounce you can’t tie to a subscriber is just a statistic. The conceptual side of all this, including the bounce categories and the suppression list, applies exactly as it does for any PowerMTA setup; MailWizz is simply the system that owns the list.
Test
Send a small campaign to a seed inbox, confirm spf=pass, dkim=pass, dmarc=pass in the headers, and verify a forced bounce registers in MailWizz before you scale.
The async bounce caveat
Here’s the detail that surprises almost everyone: a large share of bounces — often 40 to 60 percent — never appear
in PowerMTA’s synchronous bounce log at all. These are asynchronous bounces: the receiver accepts
the message at SMTP time (so PowerMTA logs a delivery) and only later decides it can’t deliver, emitting a bounce
message to your envelope Return-Path minutes or hours afterward. The webhook or accounting handler
never sees those, because as far as the connection was concerned, the message was delivered.
The consequence is that the accounting feed alone catches only the bounces that happen during the SMTP
conversation. To catch the rest you also need a bounce mailbox — a real inbox your
Return-Path points at, polled and processed (by MailWizz’s bounce server or your handler) for the
asynchronous bounce messages. Combine the two: the accounting feed for synchronous failures and the bounce mailbox
for asynchronous ones. Skip the mailbox and you’ll silently miss half your bounces, your list will rot, and your
reputation will erode with no obvious cause in the PowerMTA stats. VERP
on the Return-Path is what lets the mailbox processor identify which recipient each async bounce belongs to.
Hard bounce means unsubscribe everywhere
However a bounce reaches MailWizz, the rule for a hard bounce is the same: the address is dead, so remove it from every list, rather than only the campaign that triggered the bounce. A mailbox or domain that no longer exists won’t exist for your other lists either, and continuing to mail it anywhere keeps generating bounces that drag your reputation down. MailWizz can blocklist an address globally; use that rather than removing it from a single list.
Soft bounces get the gentler treatment — retried by PowerMTA, and suppressed by MailWizz only after they persist — but a confirmed hard bounce is final. This is the same global, append-only suppression principle covered in bounce & FBL handling, expressed through MailWizz’s blocklist: one dead address, removed from everything, permanently.
FBL registration and processing
Complaints need their own wiring. Register a dedicated complaint address — something like
[email protected] — with each provider’s feedback-loop program, so that when a recipient marks
your mail as spam, the provider forwards an ARF report to that address. PowerMTA captures these as
feedback-loop records (or your handler reads the mailbox), and the processor unsubscribes the
complainer.
The mapping matters here too: the FBL processor reads the subscriber identifier you stamped on the original message to know who complained, then removes them from MailWizz globally. A complainer is, if anything, more urgent to suppress than a hard bounce — they’ve actively told a provider they don’t want your mail, and continuing to send is the fastest route to a blocklist. The background on which providers offer FBLs and how ARF works is in what is a feedback loop.
Multiple delivery servers and routing
A single PowerMTA install happily serves many MailWizz delivery servers, and this is how you segment streams. Make
one delivery server per pool, each setting a different X-Virtual-MTA header, all pointing at the same
PowerMTA host — transactional to one pool, marketing to another — so a heavy campaign on the marketing servers
can’t touch the IPs your transactional mail uses.
MailWizz also has its own per-delivery-server sending quota and hourly rate, which sits above PowerMTA’s per-domain throttling. The two are complementary: MailWizz controls how fast it hands messages to PowerMTA, and PowerMTA controls how fast it releases them to each provider. Set the MailWizz quota generously and let PowerMTA’s throttling and back-off do the per-ISP shaping, rather than trying to rate-limit at both layers and fighting yourself.
Cron and operational notes
MailWizz runs on cron, and the integration only works if the right jobs are scheduled. The sending cron drains campaigns into PowerMTA; the bounce-handling and feedback-loop crons poll mailboxes and process records; and the list-cleaning jobs act on what they find. If sending works but bounces never register, a missing or failing cron is the usual cause — check it before suspecting the PowerMTA side.
A few operational habits keep the pairing healthy: confirm the bounce handler or webhook endpoint is actually receiving and processing records rather than merely configured, watch that the accounting files rotate and don’t fill the disk, and keep an eye on MailWizz’s own delivery and bounce stats alongside PowerMTA’s. When something looks off, the question to ask is which layer owns it — MailWizz handles the list, the campaign and the schedule; PowerMTA handles the queue, the throttling and the actual delivery — and that split tells you where to look.
KumoMTA with MailWizz
The same pattern works with KumoMTA, since MailWizz feeds any MTA over SMTP. You add a KumoMTA SMTP listener, create an SMTP-type delivery server in MailWizz pointing at it, and route streams with a header KumoMTA reads to select an egress pool. The delivery half is identical; only the engine behind the SMTP port changes.
Bounce and complaint handling differs in mechanism: KumoMTA emits structured log events and can post webhooks that you feed into MailWizz, in place of PowerMTA’s accounting files. The async-bounce caveat still applies — you still need a bounce mailbox for the asynchronous failures regardless of engine. Whichever you run, the Auto PMTA Configurator wires the delivery server, stream routing and bounce processing for you, so MailWizz and the engine agree from the first send.
Why MailWizz plus PowerMTA
The pairing is popular for a clear reason: it splits the job along its natural seam. MailWizz owns the parts a marketer touches — lists, segmentation, campaigns, templates, automations, reporting — while PowerMTA owns the part that decides whether mail reaches the inbox — queueing, per-ISP throttling, IP and domain reputation, bounce classification. Each tool does what it’s best at, and neither tries to be the other.
The economic case follows the same logic as self-hosting generally: above a certain volume, running your own MailWizz and PowerMTA is far cheaper per message than a hosted ESP, and you keep full control of your data, your IPs and your sending policy. The trade is responsibility — you own the warm-up, the authentication, the bounce processing and the list hygiene that an ESP would otherwise handle. This integration is where that responsibility is met: wire it correctly and you get ESP-grade deliverability on infrastructure you control, for legitimate, opt-in sending.
Common integration mistakes
A handful of errors account for most broken setups. No bounce mailbox — relying on the accounting
feed alone — silently loses the asynchronous half of your bounces, the single most common and most damaging
mistake. The MailWizz IP not whitelisted (or auth not configured) in PowerMTA’s
<source> means mail is refused outright. No X-Virtual-MTA header
leaves everything on the default pool, so stream separation quietly doesn’t happen.
The subtler ones: using the plain SMTP delivery type when the PowerMTA type was available, giving up native bounce data; rate-limiting at both layers so MailWizz and PowerMTA fight each other; and per-list instead of global suppression, so a hard-bounced address keeps receiving your other campaigns. Each maps to a fix already covered above — add the mailbox, whitelist or authenticate, set the header, prefer the PowerMTA type, throttle in PowerMTA, and blocklist globally.
End to end at a glance
Assembled, the whole flow reads in one line of cause and effect: MailWizz builds a campaign and hands it over SMTP
to PowerMTA (authenticated, with an X-Virtual-MTA header) → PowerMTA assigns it to a virtual MTA in
the named pool, DKIM-signs it, and throttles delivery per provider → successes, synchronous bounces and complaints
flow back through the accounting feed or webhook → asynchronous bounces arrive at the Return-Path mailbox → both
paths map each event to a subscriber and remove hard bounces and complainers from every list in MailWizz.
Every step in that chain has a home: authentication and stream routing in the handoff, reputation and rate in PowerMTA, list hygiene in MailWizz. When all of them are wired, the system runs itself — campaigns go out at the speed providers accept, and the list stays clean without manual intervention. The work is in the wiring; once it’s done, the day-to-day is just sending good mail to people who asked for it.
Choosing the bounce method
With three ways to process bounces, which to pick comes down to your MailWizz and PowerMTA versions and how much you want to maintain. The native webhook is the cleanest if you’re on a current MailWizz and a PowerMTA that supports webhook accounting — no script to host, and MailWizz handles the records directly. It’s the default recommendation when both sides support it.
The piped PHP handler suits setups that want full control over how records map to subscribers, or that run an older PowerMTA without webhook output; it’s battle-tested but it’s code you own and monitor. The plain SMTP type plus a bounce mailbox is the fallback when the PowerMTA delivery type isn’t available, and it’s the most limited because it forgoes the accounting feed’s per-message detail. Whichever you choose, the bounce mailbox for asynchronous failures is not optional — it sits alongside all three, because none of them sees the bounces that arrive after the SMTP conversation ends. Pick the synchronous method that fits your versions, then always add the mailbox on top.
The bottom line
Connecting MailWizz to PowerMTA is two halves plus the part everyone underestimates. Trust the MailWizz host in
PowerMTA (by IP, or better, with an authenticated <smtp-user>), add a PowerMTA-type delivery
server in MailWizz pointing at the host and port, and route each stream to a pool with an
X-Virtual-MTA header. Then process bounces and complaints — by native webhook, by a piped accounting
handler, or by SMTP-plus-bounce-mailbox — mapping each one back to the subscriber and removing hard bounces and
complainers from every list.
The detail that makes or breaks it is the asynchronous bounce: the accounting feed alone misses up to half of
them, so pair it with a bounce mailbox on your Return-Path. Authenticate, segment streams with
multiple delivery servers, let MailWizz schedule and PowerMTA throttle, and verify a real test before scaling.
KumoMTA fits the same way over SMTP. If you’d rather not wire all of this by hand, our
setup service connects PowerMTA to your MailWizz end to end —
delivery server, stream routing and full bounce/FBL processing — and the
installer ships it preconfigured — delivery server, authenticated source, stream routing, both bounce paths and FBL processing — so a new install sends, suppresses and stays clean without a day of manual wiring. Get the handoff, the routing and especially the two-path bounce processing right, and MailWizz plus PowerMTA gives you a marketing platform and a delivery engine that each excel at their own half of the job — the marketer’s familiar campaign interface on one side, ESP-grade deliverability and reputation control on the other, all of it running on infrastructure you fully own and pay a small fraction of hosted-ESP prices to operate — for legitimate, opt-in sending.
Frequently asked questions
How do I connect PowerMTA to MailWizz? +
Add the MailWizz server's IP as a trusted
Which delivery server type should I use in MailWizz — SMTP or PowerMTA? +
Use the PowerMTA type when available: it understands PowerMTA's accounting files and can process bounces and feedback loops natively, which a plain SMTP server can't. The plain SMTP type works for delivery but you'll need a separate bounce handler.
How does bounce handling work between PowerMTA and MailWizz? +
PowerMTA records delivery, bounce and feedback events in its accounting file. MailWizz's PowerMTA delivery server reads those events to update campaign stats and suppress bad addresses. Alternatively, pipe the acct-file to a bounce handler script that calls back into MailWizz. Either way, the goal is that hard bounces and complaints are removed from your lists.
Can one PowerMTA serve multiple MailWizz delivery servers? +
Yes. Create one delivery server per IP pool in MailWizz, each setting a different X-Virtual-MTA, all pointing at the same PowerMTA host. PowerMTA routes each to the correct pool. This is how you segment streams (for example transactional vs marketing) from a single MailWizz install.
Related