How to Set Up Email on WordPress

Most WordPress sites cannot send email reliably out of the box. The default configuration depends on PHP’s mail() function, which in turn depends on the server having a working mail transfer agent, and most modern hosting environments either lack one or actively block outbound mail. The result: password reset emails vanish, contact form submissions disappear, WooCommerce order confirmations never arrive, and the site administrator finds out only when a customer complains.

Fixing this requires understanding the delivery chain, then replacing the broken link. The chain runs: WordPress wp_mail() → PHPMailer → PHP mail() → local MTA (sendmail/Postfix) → recipient’s MX server. On most hosts, the chain breaks at step three or four. The fix is to bypass the local MTA entirely by routing mail through an external email service via SMTP or API, using a mailer plugin to make the connection, then publishing SPF, DKIM, and DMARC records so receivers trust the result.

This guide covers A transactional email is the automated message a WordPress site sends in response to a single user action – a password reset, an order confirmation, a form receipt – addressed to the user who triggered it. Read full reference →: the messages WordPress generates automatically (password resets, form notifications, order confirmations, admin alerts). Marketing email (newsletters, drip campaigns, broadcast sends) runs on separate infrastructure; products like MailPoet, Mailchimp, ConvertKit, and MailerLite handle that work, and the boundary is real: setting up transactional email does not give a site newsletter capability, and configuring a newsletter platform does not fix wp_mail(). The transactional email reference covers the boundary, including the legal carve-out that makes transactional and marketing email regulated differently.

Why WordPress email breaks

WordPress sends all its email through a single PHP function: wp_mail(), defined in wp-includes/pluggable.php. Under the hood, wp_mail() uses the PHPMailer library (bundled with WordPress core since the early 2.x releases; upgraded to PHPMailer 6 in WordPress 5.5) to compose and dispatch messages. By default, PHPMailer calls PHP’s native mail() function, which hands the message to whatever mail transfer agent the server’s sendmail_path directive points to, typically sendmail or Postfix on Linux hosts. The How email works reference covers the full five-stage delivery chain.

This default path fails for three common reasons.

The host blocks outbound mail. Cloud infrastructure providers block SMTP ports by default on new instances to prevent abuse, but the specifics vary. DigitalOcean blocks all three standard submission ports (25, 465, 587) on every Droplet, which leaves API-based sending through an external service as the only option there. AWS EC2 restricts port 25 to private IP addresses by default (a request can be submitted to lift this) but allows 587 and 465. Google Cloud Compute and Azure VMs similarly block port 25 while leaving 587 and 465 open. A WordPress site on a fresh DigitalOcean Droplet cannot send mail over SMTP at all; on AWS, GCP, or Azure, it can send via ports 587 or 465 once an external service is configured. Per-host port status lives on each host’s email page.

The host provides no MTA. Many managed WordPress hosts and containerised environments ship without sendmail or Postfix installed. PHP’s mail() function returns false, WordPress logs nothing by default, and messages silently fail. The site appears to work (pages load, plugins activate), but email is dead.

The host’s MTA sends mail, but it lands in spam. Even hosts that do provide a working MTA typically send from a shared IP address with no SPF, DKIM, or DMARC records for the sending domain. Receiving servers (Gmail, Outlook, Yahoo) see an unauthenticated message from an IP shared by hundreds of unrelated sites, and route it accordingly: the spam folder, or the void.

The practical upshot: relying on the default WordPress email path is viable only on the small subset of hosts that explicitly provision and maintain outbound email for their customers. Kinsta is the best-known example, offering transactional email as part of its hosting package via MailChannels with proper authentication. WordPress.com-hosted sites and Pressable (both Automattic properties) handle outbound email natively as well; the WordPress.com vs WordPress.org email reference covers who owns the sending pipeline on each platform. These hosts are exceptions. For the majority of hosts (shared, VPS, and managed alike), the fix is to route mail through an external service.

The fix: external service + mailer plugin

The solution has two parts:

  1. An external email service that accepts messages from the WordPress site and delivers them to recipients. These services maintain their own sending infrastructure: dedicated IPs, sender reputation built on volume and compliance history, and authentication already configured.
  2. A mailer plugin that connects WordPress to that service. The plugin hooks into wp_mail(), replacing the default PHPMailer transport with either an SMTP connection or the service’s HTTP API.

For most sites that is the right two-part solution. Sites that would rather not run an SMTP plugin (developer-control preference, plugin-sprawl avoidance, or a host whose bundled relay already delivers) can take the minority path; nanoPost’s WordPress without the plugin hub covers the no-plugin slices of this and four other jobs WordPress sites typically install a plugin for.

Choosing an email service

For a site that just needs email to work, Brevo’s free tier is the lowest-friction starting point. It allows 300 emails per day, more than enough for most WordPress sites, requires no credit card, and connects through both SMTP and API. SMTP2GO provides 1,000 emails per month on its free plan with a clean dashboard and solid documentation. Mailgun offers 1,000 per month on its flex plan, though Mailgun’s pricing page rewards careful reading beyond the first month.

For sites with higher volume or stricter deliverability requirements, nanoPost maintains a curated comparison of SMTP email services with per-provider details on pricing, free tiers, API support, and WordPress integration. The free SMTP servers roundup compares free-tier ceilings specifically.

A WordPress site sending through any reputable external service will deliver more reliably than one sending through a shared host’s MTA.

If you already use Google Workspace or Microsoft 365

A common operator question: the site’s domain is already on Workspace or Microsoft 365 for mailboxes; can WordPress just send through that, instead of signing up for a separate transactional provider? Sometimes. The constraints are sharp.

Google Workspace. SMTP relay through smtp.gmail.com works for Workspace accounts that have 2-Step Verification enabled, with either OAuth (the modern path) or a 16-character Gmail App Password as the credential. The daily sending limit is 2,000 messages per 24 hours measured as a rolling window per Google’s Workspace sending limits documentation; on free Gmail, the limit is 500 per 24 hours. Beyond the limit, Gmail returns transient failures regardless of authentication. Workspace mailboxes also rewrite the From address in some configurations, which breaks DMARC alignment for senders that depend on d=example.com. For sites under the daily cap whose mail is genuinely from the Workspace user (a small-business owner’s notifications, an agency’s contact form to a single address), the relay is reasonable. For sites sending on behalf of the domain at higher volume (WooCommerce stores, multi-user form submissions), a dedicated transactional provider is the right answer.

Microsoft 365 and Outlook.com. Microsoft is retiring SMTP AUTH. Per the Exchange Team’s updated deprecation timeline, the remaining default-on access for existing Exchange Online tenants is scheduled to be disabled by default at the end of December 2026, with the final removal date to be announced in the second half of 2027. New Microsoft 365 tenants created after December 2026 will not have SMTP AUTH available at all. Personal Outlook.com accounts created in 2026 already ship with SMTP AUTH disabled with no user-facing toggle to re-enable it. Any WordPress site relying on Microsoft 365 for outbound SMTP should plan a migration to a dedicated provider or to a mailer plugin’s OAuth integration before the December 2026 cutoff.

The app-password edge. Workspace operators whose Gmail SMTP setups stopped authenticating after May 2025 are typically hitting Google’s Less Secure App deadline for Workspace, not the 2022 consumer-Gmail cutoff. The fix is the same in both cases: generate an App Password (with 2-Step Verification enabled) or configure OAuth. The Gmail App Passwords guide covers the four account states where the option is hidden and the silent-failure pattern where a routine account password rotation revokes every existing App Password. For the broader trade-off between App Passwords and OAuth (App Passwords are simpler, OAuth survives password rotations), see Gmail OAuth vs App Passwords.

Choosing a mailer plugin

The mailer plugin replaces the default wp_mail() transport: instead of handing messages to PHP’s mail() function, the plugin sends them over SMTP or via the service’s API endpoint.

WP Mail SMTP is the most widely installed and the easiest first choice for a site that wants setup done in under five minutes. FluentSMTP is the better pick for operators uncomfortable with Awesome Motive’s upselling; the free version covers logging and routing the WP Mail SMTP free version does not. Post SMTP is the only plugin in the category whose first-class feature is “tell the operator when something is wrong”: push notifications to Chrome, Slack, and Twilio SMS, with a resend-from-log button in the free tier. All three connect to every major email service. The best WordPress SMTP plugins roundup covers the field in depth, including the four lesser plugins and the per-tier feature splits.

Once configured, the plugin’s effect is global: every call to wp_mail() routes through the external service automatically: WordPress core, WooCommerce, contact form plugins, any plugin that uses the standard WordPress email function. Plugins that bypass wp_mail() and call PHP’s mail() directly remain unaffected; the transactional email reference covers how to spot that bypass.

For operators who prefer to skip the plugin entirely and configure the SMTP connection in code, WordPress SMTP without a plugin walks through the phpmailer_init action hook with credentials in wp-config.php. It works, but foregoes the logging and diagnostic features that a dedicated plugin provides.

Authenticating your sending domain (SPF, DKIM, DMARC)

Connecting to an external service gets messages delivered. Authenticating the sending domain gets them past the spam folder.

Email authentication works through DNS records that tell receiving servers which infrastructure is authorised to send mail for a domain. Three standards matter: SPF (which IP addresses may send for this domain), DKIM (a cryptographic signature proving the message was sent by an authorised system and was not modified in transit), and DMARC (the policy that tells receiving servers what to do when SPF or DKIM checks fail, plus aggregate reporting back to the domain owner).

DNS for WordPress email covers the syntax and configuration of each record type in detail, including the alignment trap, the 10-DNS-lookup limit, and the migration from p=none monitoring to p=reject enforcement. The single most common DNS authentication mistake is the SPF merge step. SPF requires exactly one record per domain. A site that already has an SPF record for Google Workspace and adds a second record for Brevo ends up with two SPF records, and RFC 7208 § 3.2 prohibits multiple records that would cause an authorisation check to select more than one. The result is a PermError: SPF evaluation fails, and receivers treat the domain as unauthenticated. The fix is to merge the include: directives into a single record:

v=spf1 include:_spf.google.com include:sendinblue.com ~all

The domain owner often doesn’t notice. There is no bounced email, no error message in WordPress. Messages just land in spam, and the PermError is visible only in the receiving server’s authentication results.

The alignment problem

The DMARC failure pattern that confuses operators most is spf=pass, dkim=pass, dmarc=fail. Both authentication checks passed, but DMARC failed alignment. SPF passes against the provider’s bounce domain (bounces.sendgrid.net), not the From-domain. DKIM signs with the provider’s own d= (sendgrid.net) instead of the site’s domain. Neither alignment check is satisfied, DMARC fails despite both checks passing, and messages land in spam.

The fix is provider-side: enable domain authentication (variously called “sender domain authentication,” “branded links,” or “sending domain verification” depending on the provider) so DKIM signs with d=example.com matching the From-header domain. The DNS records have nothing to authenticate against until that provider-side configuration is in place. The DNS guide covers the alignment trap and the report patterns that diagnose it.

DMARC reporting

A DMARC record published at _dmarc.example.com includes an rua= tag pointing to a mailbox that collects aggregate reports. A minimal starting record:

v=DMARC1; p=none; rua=mailto:[email protected]

p=none is the correct starting policy: receivers report failures back without taking enforcement action. Aggregate reports arrive as gzipped XML attachments, one per receiver per day, listing every IP that sent mail claiming to be from the domain and whether each row passed or failed alignment. Reading raw XML at any volume is impractical; the DMARC aggregate reports guide covers the parsing tools (Postmark’s free DMARC service, dmarcian, Valimail Monitor) and the diagnostic loop that turns reports into fixes.

Reports regularly surface sending IPs operators didn’t know existed: backup MTAs that fire when the SMTP plugin fails, legacy plugins that were deactivated but not uninstalled and still call mail() directly, third-party services (monitoring tools, Zapier, notification relays) that send from the domain without going through the configured relay. Identifying these IPs before advancing the policy beyond p=none is the entire purpose of the monitoring phase.

The 2024 bulk-sender requirements

Google’s 2024 requirements, effective February 2024, mandate that senders delivering more than 5,000 messages per day to Gmail accounts have DMARC published at a minimum of p=none. Yahoo’s parallel bulk sender requirements match. A combined WordPress site (transactional email, plugin-triggered notifications, contact form submissions, any marketing automation on the same domain) can reach that threshold faster than operators expect. The threshold is per receiver, not per domain: a site sending 3,000 to Gmail and 3,000 to Yahoo crosses both. Sites that exceed the threshold without DMARC published do not get a courteous warning; their mail is throttled or bulked silently.

Contact forms and the database safeguard

Contact form plugins (Contact Form 7, WPForms, Gravity Forms, Fluent Forms, Ninja Forms) all send submissions through wp_mail(), so the external service and mailer plugin handle their delivery automatically. The one safeguard worth adding: store submissions in the WordPress database, not only in email. If email delivery fails for any reason (a misconfigured service, an expired API key, a DNS change), the submissions remain accessible. Some contact form plugins store submissions natively. For Contact Form 7, the Flamingo plugin adds this capability.

Two configuration details on contact forms cause more deliverability damage than any other plugin category. First, plugins that set the message From: header to the visitor’s email address (taken from a form field) break DKIM alignment: the signature’s d= is the site’s domain, the From-header is a gmail.com address. The fix is to set From to a fixed address on the site’s domain and put the visitor’s address in Reply-To; the contact form reply-to guide covers the configuration per plugin. Second, sites that route Contact Form 7 submissions to multiple recipients can do it without a plugin via cc/bcc headers and pipe-separated dropdown routing; the multi-address routing guide covers the mechanics.

Verifying the setup

All three mailer plugins named above include a “Send Test Email” function in their settings. Use it. When the test message arrives, check the headers. Look for spf=pass and dkim=pass in the Authentication-Results header, and dmarc=pass once DMARC is published. If any of the three shows fail or none, the DNS records need attention before going further.

For a more thorough check, the WordPress email test suite walks through testing every category of WordPress-generated email: password resets, new-user notifications, WooCommerce order emails, and form submissions. Running even two or three of these tests confirms that the mailer plugin is intercepting wp_mail() correctly across different calling contexts. Check that WordPress can send emails is the shorter version: a single test that proves the core path works.

Three command-line and sandbox tools cover the cases the in-plugin test does not.

  • swaks sends an SMTP message from the command line with the full session printed to stdout. It proves the port is open, the credentials authenticate, and the server accepts the message, independently of WordPress, PHP, and the mailer plugin. When a test send fails, swaks isolates whether the problem is in the relay or in the WordPress configuration.
  • Mailtrap for WordPress captures outbound mail in a sandbox inbox instead of delivering it. Useful on staging environments where real sends would alarm real users, and during initial setup where the operator wants to inspect headers and bodies before flipping to a production relay.
  • Inbox placement testing answers the question the in-plugin test cannot: did the message reach the inbox, or the spam folder, or the void. Mail-Tester is the standard tool; the guide covers reading its output and acting on the score.

When things break

The diagnostic ladder, fastest to most involved: misconfigured admin settings, host blocking outbound SMTP, SMTP plugin misconfiguration, host sending limits, DNS authentication failure. Troubleshoot WordPress email walks the ladder in full, with the common SMTP error codes (421, 535, 550, 552, 554) mapped to where the fix lives, plus the captured-error pattern that uses the wp_mail_failed action hook to surface the underlying PHPMailer exception.

When a captured SMTP session is in hand and the response codes are not self-explanatory, How to read an SMTP session log decodes the EHLO/STARTTLS/AUTH/MAIL FROM/RCPT TO/DATA sequence and identifies the exact line where the failure begins. The SMTP field manual catalogues bounce codes from the major mailbox providers and filters when the receiving server’s response text needs interpretation.

For password reset emails specifically (the highest-volume failure mode WordPress operators report), see Users not receiving password reset emails. For form-to-Gmail-but-not-Office-365 (a recurring contact-form pattern), see Form not sending to Gmail but sending to Office 365.

Going beyond the basics

With the foundation in place (external service, mailer plugin, authenticated domain, verified delivery), four directions are worth knowing about even if most sites never need them.

Logging. A site that wants to know whether a specific email actually left WordPress needs a log. WP Mail SMTP gates this behind Pro. FluentSMTP and Post SMTP include logging in their free tiers. Standalone options include Check & Log Email and Log Emails, both of which hook wp_mail() and record every send regardless of which mailer plugin (if any) is configured.

Queueing. Every wp_mail() call blocks the PHP process until the SMTP handshake completes. On a WooCommerce site with high order volume, that per-order latency adds up. WordPress email queues covers when async sending matters and the plugins that address it.

Webhooks. External relays expose delivery events (bounces, complaints, deliveries) via webhooks that can connect back into WordPress for logging, retry logic, or list hygiene. Email service webhooks and WordPress covers the integration patterns and the verification step that prevents spoofed webhook calls.

The full WordPress email surface. WordPress core sends transactional email from four locations; WooCommerce adds a larger set; every plugin in the ecosystem can add more. Every email WordPress sends (and how to control each one) catalogues the hooks and filters that override sender, subject, and body per email type. For the WooCommerce subset specifically, see WooCommerce transactional email.


Reference links

Provider details (free-tier allowances, port-blocking policies, sending limits) and the Microsoft 365 SMTP AUTH timeline verified June 2026.