WooCommerce order emails: fix deliverability with MailKite SMTP
WooCommerce sends 12+ email types through WordPress's wp_mail() — and most store owners have no idea they're going to spam. This tutorial shows how to route every WooCommerce email through MailKite's SMTP relay: order confirmations, shipping notifications, refund emails, all DKIM-signed from your own domain.
Your WooCommerce store sends 12+ different email types. Order confirmation, processing, completed, refunded, failed, cancelled, customer note, new order (admin), low stock, out of stock, backorder, password reset. Every one of them goes through wp_mail(). And if you haven’t configured an SMTP relay, every one of them is at risk of landing in spam.
Store owners fix the SMTP once and forget about it. But “once” often means never — or it means using a free SMTP service with daily limits that silently throttle your high-volume days. When a $500 order confirmation doesn’t arrive, the customer thinks you took their money and vanished.
MailKite fixes this with four DNS records and two settings. Here’s the full setup.
What WooCommerce’s default actually does
WooCommerce hooks into WordPress’s wp_mail() function. That function calls PHP’s mail(), which hands the message to whatever MTA your server runs — typically Postfix or Sendmail, with no DKIM signing, no SPF alignment, and a shared IP.
For a store, this is worse than a blog. Order confirmations are time-sensitive. A delayed or missing shipping notification damages trust more than a blog comment notification ever could. And WooCommerce doesn’t retry failed emails — if the MTA rejects it, the email is gone.
The fix: 4 records + 2 settings
1. Add your domain to MailKite
In the dashboard, add your store’s domain (e.g., yourstore.com). MailKite returns DNS records:
MX yourstore.com mx.mailkite.dev (priority 10)
TXT yourstore.com v=spf1 include:mailkite.dev ~all
TXT mailkite._domainkey.yourstore.com v=DKIM1; k=rsa; p=…
TXT _dmarc.yourstore.com v=DMARC1; p=none;
Add them to your DNS provider. The MX propagates in under 5 minutes.
2. Install WP Mail SMTP
WP Mail SMTP overrides wp_mail() to route through your chosen SMTP server. Install it from the WordPress plugin directory.
3. Configure the connection
Go to WP Mail SMTP → Settings:
| Setting | Value |
|---|---|
| From Email | orders@yourstore.com (on your verified domain) |
| From Name | Your store name |
| Mailer | Other SMTP |
| SMTP Host | smtp.mailkite.dev |
| Encryption | TLS |
| SMTP Port | 587 |
| Username | mailkite |
| Password | Your API key (mk_live_…) |
4. Verify which emails are covered
WP Mail SMTP intercepts every wp_mail() call on the site. That includes:
| WooCommerce email | Trigger |
|---|---|
| New order | Customer places an order |
| Processing order | Payment confirmed |
| Completed order | Order marked complete |
| Refunded order | Refund processed |
| Failed order | Payment failed |
| Customer note | Admin adds a note |
| Reset password | Customer requests password reset |
| Email address changed | Customer changes email |
Plus any WordPress core emails (user registration, comment notifications) and plugin emails (WPForms submissions, Yoast alerts, etc.).
5. Test it
WP Mail SMTP has a Email Test tab. Send a test to your Gmail or Outlook address and check the headers:
Authentication-Results: mx.google.com;
dkim=pass header.d=yourstore.com
spf=pass (google.com: domain of orders@yourstore.com designates ... as permitted sender)
dmarc=pass
All three should pass. If DKIM or SPF fails, double-check your DNS records.
Customize WooCommerce email templates
WooCommerce lets you customize email templates in WooCommerce → Settings → Emails. You can change colors, header text, and footer — but not the SMTP server. That’s handled by WP Mail SMTP, which runs before WooCommerce’s template engine.
To set a reply-to address on order emails (so customers reply to your support inbox, not the no-reply address), add this to functions.php:
add_action('woocommerce_email_headers', function ($headers, $email_id, $order) {
if (in_array($email_id, ['customer_processing_order', 'customer_completed_order'])) {
$headers .= 'Reply-To: support@yourstore.com' . "\r\n";
}
return $headers;
}, 10, 3);
Receiving customer replies
When a customer replies to an order confirmation, MailKite can POST the reply to your webhook as clean JSON. Add a webhook handler that extracts the order number from the subject and creates a WooCommerce order note:
<?php
// webhook-replies.php — receives MailKite inbound webhook
$payload = json_decode(file_get_contents('php://input'), true);
$sig = $_SERVER['HTTP_X_MAILKITE_SIGNATURE'] ?? '';
$secret = getenv('MK_WEBHOOK_SECRET');
$computed = hash_hmac('sha256', json_encode($payload), $secret);
if (!hash_equals($computed, $sig)) {
http_response_code(401);
exit;
}
if (preg_match('/Order #(\d+)/', $payload['subject'], $m)) {
$order = wc_get_order((int) $m[1]);
if ($order) {
$order->add_order_note(
"Customer reply from {$payload['from']}:\n\n{$payload['text']}"
);
}
}
http_response_code(200);
echo '{"ok":true}';
Customer replies appear directly in WooCommerce’s order notes — visible in the admin panel, tied to the right order.
How it compares
WP mail() default | WP Mail SMTP + MailKite | |
|---|---|---|
| DKIM signing | None | Automatic, per-domain |
| SPF alignment | Fails (shared server IP) | Passes (your domain) |
| Inbox placement | ~40–60% | ~95%+ |
| Retry on failure | None | MailKite retries |
| Delivery logs | Server mail.log only | Dashboard + API |
| Inbound replies | Not supported | Webhook → order notes |
| Daily send limits | Server capacity | Free tier scales |
FAQ
Will this affect WooCommerce email templates? No. WP Mail SMTP only changes how email is sent, not what WooCommerce puts in it. Templates, branding, and content stay the same.
What about bulk marketing emails? MailKite is for transactional email. Don’t use it for newsletters or marketing campaigns — that’s what Mailchimp, Klaviyo, or Brevo are for. Order confirmations, shipping updates, and password resets are transactional and belong on MailKite.
I’m using WooCommerce MailChimp/Klaviyo — will this conflict?
These plugins hook wp_mail() for marketing emails. WP Mail SMTP hooks it for transactional. As long as MailChimp/Klaviyo send to their own list (not wp_mail()), there’s no conflict. If they use wp_mail(), one hook wins — deactivate the one you don’t need.
Can I use this with multiple domains? Yes. Add each domain to MailKite, publish its DNS records, and use the same API key. MailKite handles DKIM signing per domain automatically.
Four DNS records, two settings, and your WooCommerce emails stop going to spam. Start free — unlimited domains, no credit card.
Related: Fix WordPress email deliverability — the general WordPress fix · Shopify email from your own domain — for Shopify stores · Set up email once, reuse every project — the architecture behind it