Blog · Guides

WordPress Email That Actually Arrives: SMTP Done Right

Password resets that never show up. WooCommerce order confirmations sitting in a customer’s spam folder. Contact form submissions that vanish into nothing. If you have ever chased down a “missing email” complaint on a WordPress site, the root cause is almost always the same: WordPress’s default mail function was never built to prove its emails are legitimate, and modern inboxes have stopped trusting mail that can’t prove that.

Why wp_mail() Lands in Spam or Never Arrives

WordPress sends mail through the wp_mail() function, which by default hands the message to PHP’s built-in mail() function. That function does not send email itself, it passes the message to whatever local mail transfer agent is installed on the server. On many hosts that MTA is minimally configured, has no sending reputation, and is not authorized to send mail on behalf of your domain.

That last part is the real issue. Gmail, Outlook, and every other major provider now check whether the server sending a message is actually allowed to send mail for that domain. If your site’s “From” address is [email protected] but the message arrives from a generic hosting server with no matching DNS record, receiving servers treat that as a strong spam signal, or they drop the message with no bounce at all. You never see an error. The email just disappears.

The Real Fix: Send Through an Authenticated Service

The fix is to stop relying on the local mail() function and send through a service designed for deliverability. There are two common approaches:

  • SMTP relay: WordPress authenticates to a real mail account (like a transactional email provider) over port 587 with TLS, the same way an email client connects to a mail server.
  • HTTP API: WordPress sends the message via an API call with a key instead of the SMTP protocol. This skips SMTP port restrictions entirely and is often faster to set up.

Providers like SendGrid, Mailgun, Postmark, Amazon SES, and Brevo specialize in exactly this. They manage sending IP reputation, handle bounces and complaints, and give you the DNS records you need to authenticate your domain. Plugins like WP Mail SMTP, Post SMTP, and FluentSMTP make wiring any of these into WordPress a matter of filling in a form rather than writing code.

Configuring SMTP in WordPress

If you would rather not add a plugin, you can hook into PHPMailer directly in a plugin file or in your theme’s functions.php:

add_action( 'phpmailer_init', function( $phpmailer ) {
    $phpmailer->isSMTP();
    $phpmailer->Host       = 'smtp.yourprovider.com';
    $phpmailer->SMTPAuth   = true;
    $phpmailer->Port       = 587;
    $phpmailer->Username   = 'apikey';
    $phpmailer->Password   = getenv( 'SMTP_PASSWORD' );
    $phpmailer->SMTPSecure = 'tls';
    $phpmailer->From       = '[email protected]';
    $phpmailer->FromName   = 'Your Site Name';
} );

Keep the password out of version control, an environment variable or a constant defined in wp-config.php works well. Whichever method you choose, always send a test message right after setup:

wp eval 'wp_mail("[email protected]", "Test", "Hello from WP-CLI");'

If that test email arrives, WordPress is successfully connecting to your sending service. That is only half the job. The other half lives in your DNS.

Authenticating Your Domain: SPF, DKIM, and DMARC

Even a correctly configured SMTP connection will get flagged if your domain has not told the internet who is allowed to send mail on its behalf. Three DNS records handle this:

  • SPF (Sender Policy Framework): a TXT record listing which mail servers or services are authorized to send for your domain. Example: v=spf1 include:spf.yourprovider.com ~all
  • DKIM (DomainKeys Identified Mail): a cryptographic signature attached to each outgoing message, verified against a public key published in your DNS. It proves the message was not altered in transit and genuinely came from an authorized sender.
  • DMARC (Domain-based Message Authentication, Reporting and Conformance): a policy record that tells receiving servers what to do when SPF or DKIM checks fail, and where to send reports about mail claiming to be from your domain. Example: v=DMARC1; p=quarantine; rua=mailto:[email protected]

Your transactional email provider’s dashboard will give you the exact SPF include, DKIM CNAME or TXT values, and a suggested DMARC record to add. Add each one in your DNS zone, then wait for propagation before testing.

Testing Delivery

Once the records are in place, verify them directly:

dig TXT yourdomain.com +short
dig TXT _dmarc.yourdomain.com +short

Confirm the SPF and DMARC records show up exactly as expected. For DKIM, check the specific selector record your provider gave you, since DKIM records live at a subdomain like selector._domainkey.yourdomain.com.

Then send a real test message to a tool like mail-tester.com, which grades the message and shows explicitly whether SPF, DKIM, and DMARC passed, along with whether your sending IP appears on any blacklists. A score in the high range with all three checks green is what you are aiming for. If any check fails, the report usually tells you exactly which record is missing or misconfigured.

For an ongoing check, trigger something WordPress actually sends in production, like a password reset or a WooCommerce order notification, and confirm it lands in the primary inbox rather than spam.

A Note on Cloudflare and DNS

If Cloudflare sits in front of your site for edge caching and WAF protection, that only affects HTTP traffic. SPF, DKIM, and DMARC are TXT records, and MX records for receiving mail are DNS-only by nature. Cloudflare’s proxy (the orange cloud) applies to A, AAAA, and CNAME records used for web traffic, not to mail-related DNS entries, so there is nothing extra to configure there. Just make sure any mail-related CNAME your provider asks for is left as DNS-only if the interface gives you that option.

On a managed platform like ServerBorn, the server-side mail transfer agent and TLS setup are already handled for you, but the domain-level SPF, DKIM, and DMARC records for whichever sending service you choose still need to be added in your DNS zone, since that authentication is tied to your domain, not to the server.

The Takeaway

Default PHP mail() is the single most common reason WordPress email disappears. Fixing it takes two steps: send through an authenticated SMTP relay or API-based provider instead of the local server, and publish SPF, DKIM, and DMARC records so receiving servers can verify the mail is really from you. Test both after any change, plugin update, or provider switch. A five minute test email is a lot cheaper than a customer who never got their order confirmation.