{"id":379,"date":"2026-09-10T12:30:19","date_gmt":"2026-09-10T18:00:19","guid":{"rendered":"https:\/\/photonconsole.com\/blog\/?p=379"},"modified":"2026-09-10T18:01:19","modified_gmt":"2026-09-10T23:31:19","slug":"fixing-wordpress-not-sending-email-permanently","status":"publish","type":"post","link":"https:\/\/photonconsole.com\/blog\/fixing-wordpress-not-sending-email-permanently\/","title":{"rendered":"Fixing &#8220;WordPress Not Sending Email&#8221; Permanently"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Contact form submissions never arrive. Password reset links never reach users. WooCommerce order confirmations vanish, and customers email asking whether their purchase went through.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">WordPress reports no error. The form shows a success message. Nothing in the dashboard suggests a problem. This is one of the most common failures on self-hosted WordPress sites, and it is almost never caused by the plugin you are blaming.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The cause is how WordPress sends mail by default. This guide explains what actually happens when <code>wp_mail()<\/code> runs, why hosting providers block it, and how to configure authenticated SMTP so email delivery stops being something you have to keep fixing.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Quick Answer: Why Is WordPress Not Sending Email?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">WordPress uses the PHP <code>mail()<\/code> function by default. That function sends mail directly from your web server with no authentication, which most hosting providers block and most mailbox providers reject or filter as spam.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The fix is to route WordPress mail through an authenticated SMTP service instead:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ wp-config.php\ndefine( 'SMTP_HOST', 'smtp.photonrelay.com' );\ndefine( 'SMTP_PORT', 587 );\ndefine( 'SMTP_USER', 'your_project_api_user' );\ndefine( 'SMTP_PASS', 'your_secret_api_key' );\ndefine( 'SMTP_FROM', 'noreply@yourdomain.com' );\ndefine( 'SMTP_NAME', 'Your Site Name' );<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You can apply this with a plugin or with a small amount of code, both covered below. Either way, the change that matters is the same: WordPress stops sending mail itself and starts handing it to a service that is authorised to send on your domain&#8217;s behalf. An authenticated relay such as <a href=\"https:\/\/www.photonconsole.com\/\">PhotonConsole<\/a> handles that authorisation.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What wp_mail() Actually Does<\/h2>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"512\" src=\"https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/09\/ChatGPT-Image-Sep-10-2026-05_50_31-PM-1024x512.png\" alt=\"Diagram comparing WordPress sending through the unauthenticated PHP mail function against an authenticated SMTP relay\" class=\"wp-image-381\" style=\"aspect-ratio:1.7777777777777777;width:1200px;height:auto\" srcset=\"https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/09\/ChatGPT-Image-Sep-10-2026-05_50_31-PM-1024x512.png 1024w, https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/09\/ChatGPT-Image-Sep-10-2026-05_50_31-PM-300x150.png 300w, https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/09\/ChatGPT-Image-Sep-10-2026-05_50_31-PM-768x384.png 768w, https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/09\/ChatGPT-Image-Sep-10-2026-05_50_31-PM-1536x768.png 1536w, https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/09\/ChatGPT-Image-Sep-10-2026-05_50_31-PM.png 1774w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Default WordPress mail leaves unauthenticated. An SMTP relay sends with SPF and DKIM in place.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Every email WordPress sends \u2014 registration notices, password resets, comment notifications, plugin alerts, WooCommerce receipts \u2014 passes through a single function called <code>wp_mail()<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Internally, <code>wp_mail()<\/code> uses <a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/wp_mail\/\" target=\"_blank\" rel=\"noopener\">PHPMailer<\/a>. By default PHPMailer is configured to use PHP&#8217;s built-in <code>mail()<\/code> function, which hands the message to whatever mail transfer agent exists on the web server. On most shared hosting and cloud servers there either is no properly configured agent, or the one that exists sends from an IP address with no sending reputation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The message leaves. It just never arrives. If you want the underlying protocol explained first, see our guide to <a href=\"https:\/\/photonconsole.com\/blog\/what-is-smtp-direct-answer\/\">what SMTP is<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Why WordPress Email Fails<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Most email delivery failures on WordPress come down to authentication and server configuration rather than faults in WordPress itself. These are the causes worth checking, in order.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. No Authentication on the Sending Domain<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Without SPF and DKIM records, receiving mail servers cannot verify that your web server is allowed to send as your domain. Gmail, Outlook and Yahoo respond by filtering the message into spam or rejecting it outright, in line with <a href=\"https:\/\/support.google.com\/mail\/answer\/81126\" target=\"_blank\" rel=\"noopener\">Google&#8217;s sender guidelines<\/a>. This is the single most common cause. Our guide to <a href=\"https:\/\/photonconsole.com\/blog\/spf-dkim-dmarc-explained-simply\/\">SPF, DKIM and DMARC<\/a> covers the records in detail, and you can check what your domain currently publishes with the free <a href=\"https:\/\/www.photonconsole.com\/email-deliverability-checker.php\">email deliverability checker<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. The Default From Address Does Not Exist<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">WordPress sends from <code>wordpress@yourdomain.com<\/code> unless a <a href=\"https:\/\/developer.wordpress.org\/reference\/hooks\/wp_mail_from\/\" target=\"_blank\" rel=\"noopener\">filter<\/a> tells it otherwise. That mailbox usually does not exist, which means bounces go nowhere and DMARC alignment fails. Mailbox providers treat mail from a non-existent sender with suspicion.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. Your Host Has Disabled the mail() Function<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Many hosts disable PHP <code>mail()<\/code> entirely to prevent spam originating from compromised sites. When this happens <code>wp_mail()<\/code> returns false, but most plugins do not surface that failure to the user.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Hourly Sending Limits on Shared Hosting<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Shared hosting plans commonly cap outbound mail per hour. A store processing orders, or a site with an active membership area, hits that ceiling and the remaining mail is silently discarded for the rest of the hour.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Outbound SMTP Ports Are Blocked<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Cloud providers including AWS, Google Cloud and DigitalOcean block outbound port 25 by default, and some block 587 as well. AWS documents its <a href=\"https:\/\/repost.aws\/knowledge-center\/ec2-port-25-throttle\" target=\"_blank\" rel=\"noopener\">port 25 throttle removal process<\/a>, though removal does not solve the reputation problem underneath.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Quick Fix<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">WordPress Sends No Email At All<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Install an SMTP plugin and send its built-in test email to see the real error<\/li>\n\n\n\n<li>Confirm your host has not disabled the PHP <code>mail()<\/code> function<\/li>\n\n\n\n<li>Set a from address that exists on your domain, not <code>wordpress@<\/code><\/li>\n\n\n\n<li>Check your domain publishes SPF and DKIM records<\/li>\n\n\n\n<li>Try port 2525 if your host blocks 587 and 465<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Two Ways to Configure SMTP in WordPress<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Both approaches do the same thing. Choose based on who maintains the site.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Method<\/th><th>Best for<\/th><th>Trade-off<\/th><\/tr><\/thead><tbody><tr><td>SMTP plugin<\/td><td>Most sites, non-developers, client handovers<\/td><td>Another plugin to keep updated; credentials stored in the database<\/td><\/tr><tr><td>Code in an mu-plugin<\/td><td>Developer-managed sites, version-controlled deployments<\/td><td>No interface for the site owner; requires file access to change<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Method 1: Using an SMTP Plugin<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Install a mail SMTP plugin, open its settings, and enter the connection details:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Mailer:<\/strong> Other SMTP<\/li>\n\n\n\n<li><strong>SMTP Host:<\/strong> smtp.photonrelay.com<\/li>\n\n\n\n<li><strong>Encryption:<\/strong> TLS<\/li>\n\n\n\n<li><strong>SMTP Port:<\/strong> 587<\/li>\n\n\n\n<li><strong>Authentication:<\/strong> On<\/li>\n\n\n\n<li><strong>Username and Password:<\/strong> your relay credentials<\/li>\n\n\n\n<li><strong>From Email:<\/strong> an address on your own domain<\/li>\n\n\n\n<li><strong>From Name:<\/strong> your site name<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Then send the plugin&#8217;s test email before assuming it works. Most SMTP plugins display the raw server response, which tells you immediately whether the failure is authentication, connection or delivery.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Method 2: Using Code<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Add the credentials to <code>wp-config.php<\/code> so they sit outside the database:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ wp-config.php \u2014 add above the \"That's all, stop editing\" line\ndefine( 'SMTP_HOST', 'smtp.photonrelay.com' );\ndefine( 'SMTP_PORT', 587 );\ndefine( 'SMTP_USER', 'your_project_api_user' );\ndefine( 'SMTP_PASS', 'your_secret_api_key' );\ndefine( 'SMTP_FROM', 'noreply@yourdomain.com' );\ndefine( 'SMTP_NAME', 'Your Site Name' );<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then create <code>wp-content\/mu-plugins\/smtp-config.php<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\/**\n * Route wp_mail() through an authenticated SMTP relay.\n *\/\n\nadd_action( 'phpmailer_init', function ( $phpmailer ) {\n    $phpmailer-&gt;isSMTP();\n    $phpmailer-&gt;Host       = SMTP_HOST;\n    $phpmailer-&gt;Port       = SMTP_PORT;\n    $phpmailer-&gt;SMTPAuth   = true;\n    $phpmailer-&gt;Username   = SMTP_USER;\n    $phpmailer-&gt;Password   = SMTP_PASS;\n    $phpmailer-&gt;SMTPSecure = 'tls';   \/\/ 'ssl' if using port 465\n    $phpmailer-&gt;From       = SMTP_FROM;\n    $phpmailer-&gt;FromName   = SMTP_NAME;\n} );\n\n\/\/ Make sure WordPress itself stops using wordpress@yourdomain.com\nadd_filter( 'wp_mail_from', function () {\n    return SMTP_FROM;\n} );\n\nadd_filter( 'wp_mail_from_name', function () {\n    return SMTP_NAME;\n} );<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Common Mistake<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Putting this code in your theme&#8217;s <code>functions.php<\/code>. It will be wiped the next time the theme updates, and it stops working entirely if anyone switches themes. Email then breaks weeks later with no obvious cause. Use an <code>mu-plugins<\/code> file instead \u2014 it loads automatically, cannot be deactivated by accident, and survives theme changes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Add Your DNS Records<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">SMTP credentials alone are not enough. Your domain also has to state that the relay is allowed to send on its behalf.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>TXT    @                    v=spf1 include:relay.photonconsole.com ~all\nCNAME  photon._domainkey    dkim.photonconsole.com<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Note<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">DNS changes are not instant. SPF and DKIM records can take from a few minutes to 24-48 hours to propagate depending on your registrar and TTL settings. Confirm propagation with a lookup tool before assuming a record is wrong. Also check you do not already have a second SPF record \u2014 publishing two separate records starting with <code>v=spf1<\/code> breaks authentication completely.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 4: Send a Real Test<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use your SMTP plugin&#8217;s test function, or trigger a genuine password reset. Then confirm the message passed authentication rather than simply arriving. Tools such as <a href=\"https:\/\/www.mail-tester.com\/\" target=\"_blank\" rel=\"noopener\">Mail Tester<\/a> score a real send and show SPF and DKIM results, and <a href=\"https:\/\/mxtoolbox.com\/\" target=\"_blank\" rel=\"noopener\">MXToolbox<\/a> confirms your DNS records resolve as intended.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Fixing WooCommerce Order Emails<\/h2>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img decoding=\"async\" width=\"1024\" height=\"512\" src=\"https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/09\/ChatGPT-Image-Sep-10-2026-05_56_56-PM-1024x512.png\" alt=\"Checkpoints where a WooCommerce order email can fail: notification disabled, order status unchanged, WP-Cron not running, or hourly send limit reached\" class=\"wp-image-383\" style=\"aspect-ratio:1.7777777777777777;width:1200px;height:auto\" srcset=\"https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/09\/ChatGPT-Image-Sep-10-2026-05_56_56-PM-1024x512.png 1024w, https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/09\/ChatGPT-Image-Sep-10-2026-05_56_56-PM-300x150.png 300w, https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/09\/ChatGPT-Image-Sep-10-2026-05_56_56-PM-768x384.png 768w, https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/09\/ChatGPT-Image-Sep-10-2026-05_56_56-PM-1536x768.png 1536w, https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/09\/ChatGPT-Image-Sep-10-2026-05_56_56-PM.png 1774w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Four checkpoints an order email must pass before it reaches the customer.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">WooCommerce sends order confirmations, processing notices and shipping updates through <code>wp_mail()<\/code>, so everything above applies. There are a few additional causes specific to stores.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Emails disabled in settings.<\/strong> Check WooCommerce, then Settings, then Emails, and confirm each notification is enabled with a valid recipient.<\/li>\n\n\n\n<li><strong>Order status never changes.<\/strong> Customer emails fire on status transitions. If an order sits at pending payment, no confirmation is triggered because the transition never happened.<\/li>\n\n\n\n<li><strong>WP-Cron not running.<\/strong> Some notifications are scheduled rather than immediate. On low-traffic sites WP-Cron may not fire, so scheduled mail never sends. Replacing WP-Cron with a real server cron job resolves this.<\/li>\n\n\n\n<li><strong>Volume against hourly caps.<\/strong> A store sending order, invoice and shipping mail for every purchase reaches shared hosting limits quickly.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">For stores sending at volume, our <a href=\"https:\/\/www.photonconsole.com\/ecommerce-retail.php\">ecommerce email infrastructure page<\/a> covers the requirements in more depth.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Quick Fix<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">WooCommerce Order Emails Not Arriving<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Confirm the specific email type is enabled under WooCommerce settings<\/li>\n\n\n\n<li>Place a test order and check the order status actually changes<\/li>\n\n\n\n<li>Check the customer email address on the order is correct and deliverable<\/li>\n\n\n\n<li>Replace WP-Cron with a server cron job for scheduled notifications<\/li>\n\n\n\n<li>Install a mail logging plugin so you can see whether WordPress attempted the send<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Contact Form Delivery<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Contact form plugins hand their mail to <code>wp_mail()<\/code> as well, so a configured SMTP connection fixes most form delivery problems too. Two settings still cause failures after SMTP is working.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>The From field.<\/strong> Setting the form&#8217;s from address to the visitor&#8217;s own email address causes SPF and DMARC failures, because your server is not authorised to send as their domain. Send from your own address and put the visitor&#8217;s address in Reply-To instead.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Notification recipients on free mail providers.<\/strong> Sending notifications to a Gmail or Yahoo address from your own domain is more likely to be filtered than sending to an address on the same domain you send from.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Port Reference<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Port<\/th><th>Encryption<\/th><th>When to use<\/th><\/tr><\/thead><tbody><tr><td>587<\/td><td>TLS<\/td><td>Recommended default for WordPress<\/td><\/tr><tr><td>465<\/td><td>SSL<\/td><td>When the provider requires implicit SSL<\/td><\/tr><tr><td>2525<\/td><td>TLS<\/td><td>When the host blocks 587 and 465<\/td><\/tr><tr><td>25<\/td><td>None<\/td><td>Avoid \u2014 blocked by nearly all hosts<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Configuring WordPress With PhotonConsole<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The settings below work with either the plugin method or the code method above.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SMTP Host:      smtp.photonrelay.com\nSMTP Port:      587          (465 for SSL, 2525 if 587 is blocked)\nEncryption:     TLS\nAuthentication: On\nUsername:       your_project_api_user\nPassword:       your_secret_api_key\nFrom Address:   noreply@yourdomain.com\nFrom Name:      Your Site Name<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Port 2525 exists specifically for hosts that block the standard SMTP ports, which resolves the shared hosting and cloud provider problems described earlier. Every PhotonConsole account includes 5,000 free emails per month, which is enough for most WordPress sites to run indefinitely without paying anything, and enough for a store to validate the full setup before committing. Details are on the <a href=\"https:\/\/www.photonconsole.com\/relay.php\">PhotonRelay page<\/a>, and <a href=\"https:\/\/www.photonconsole.com\/pricing.php\">pricing<\/a> has no monthly minimum.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you are comparing options first, our analysis of <a href=\"https:\/\/photonconsole.com\/blog\/free-smtp-servers\/\">free SMTP servers<\/a> covers where each one stops being practical.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Host-Specific Notes<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Shared Hosting and cPanel<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Check your hourly mail limit in the hosting control panel before assuming a configuration fault. Sending through an external relay bypasses that cap entirely, because the mail no longer leaves through your host&#8217;s mail server.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Managed WordPress Hosting<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Several managed hosts disable <code>mail()<\/code> by policy and expect you to connect an external SMTP service. Check the host&#8217;s documentation before spending time debugging \u2014 on these platforms SMTP is the intended configuration, not a workaround.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Local Development<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use a mail catcher such as Mailpit or MailHog rather than sending real messages from a local environment. Local machines have no sending reputation, and test emails to real addresses can create spam complaints against your domain.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Multisite<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">An mu-plugin applies across the whole network, so a single configuration file covers every site. Confirm each site&#8217;s from address uses a domain you have authenticated, particularly when sites use mapped domains.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Pro Tips<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Install a mail logging plugin.<\/strong> Without a log there is no way to tell whether WordPress attempted a send at all, which is the first thing you need to know.<\/li>\n\n\n\n<li><strong>Use a subdomain for site mail.<\/strong> Sending from <code>mail.yourdomain.com<\/code> keeps your site&#8217;s sending reputation separate from your business email.<\/li>\n\n\n\n<li><strong>Store credentials in <code>wp-config.php<\/code>, not the database.<\/strong> A plugin storing an SMTP password in the options table exposes it to any admin user and to database exports.<\/li>\n\n\n\n<li><strong>Test after every migration.<\/strong> Moving hosts changes the sending IP and often the available ports. Email is one of the first things to break and one of the last things anyone checks.<\/li>\n\n\n\n<li><strong>Keep transactional and marketing mail separate.<\/strong> A newsletter plugin sending through the same connection as your order confirmations puts both at risk if complaint rates rise.<\/li>\n\n\n\n<li><strong>Re-check DNS after registrar changes.<\/strong> Moving DNS providers frequently drops TXT records, and SPF disappears without anyone noticing until delivery drops.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Related Issues You May Hit Next<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/photonconsole.com\/blog\/smtp-authentication-error\/\">SMTP authentication errors<\/a> when credentials are rejected despite looking correct<\/li>\n\n\n\n<li><a href=\"https:\/\/photonconsole.com\/blog\/smtp-not-working\/\">SMTP not working<\/a> across the ten most common failure modes<\/li>\n\n\n\n<li><a href=\"https:\/\/photonconsole.com\/blog\/why-emails-go-to-spam-in-gmail\/\">Emails landing in Gmail spam<\/a> despite sending successfully<\/li>\n\n\n\n<li><a href=\"https:\/\/photonconsole.com\/blog\/emails-sent-but-not-delivered\/\">Emails sent but not delivered<\/a> when the server reports success<\/li>\n\n\n\n<li><a href=\"https:\/\/photonconsole.com\/blog\/smtp-connection-timeout\/\">SMTP connection timeouts<\/a> when the connection hangs<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Frequently Asked Questions<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Do I need a plugin to fix WordPress email?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No. A plugin is the easiest route for most sites, but the same result can be achieved with a small mu-plugin and credentials in <code>wp-config.php<\/code>. The plugin is a convenience, not a requirement.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Why do my emails arrive in spam instead of the inbox?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Delivery and inbox placement are different things. A successful send only means the receiving server accepted the message. Missing SPF or DKIM records, or a from address that does not exist, are the usual reasons a delivered message still lands in spam.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Can I use Gmail to send WordPress email?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">For a small personal site, yes. For anything transactional, no. Google enforces low daily sending caps, throttles automated traffic, and can lock the account, which takes your password reset emails down with it.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Why did email work before and suddenly stop?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The three usual causes are a host migration that changed the sending IP, a DNS change that dropped the SPF record, or a theme update that removed code from <code>functions.php<\/code>. Check what changed around the date delivery stopped.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Does WordPress email failure affect security?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. If password reset emails do not arrive, locked-out administrators cannot regain access, and users cannot recover accounts. Email delivery is part of your site&#8217;s authentication path, not just a notification feature.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How many emails can WordPress send per hour?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">WordPress itself sets no limit. The cap comes from your hosting provider, and on shared hosting it is often between 50 and 500 per hour. Sending through an external relay removes that restriction.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Should the from address match my domain?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes, and the mailbox should exist. A from address on a domain you have authenticated, with a real inbox behind it, passes authentication checks and gives bounces somewhere to go.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">WordPress email problems feel unpredictable because the failure is silent. The form submits, the order completes, the reset is requested, and nothing surfaces to say the message never left. Once you know that <code>wp_mail()<\/code> defaults to an unauthenticated PHP function, the behaviour stops being mysterious.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The permanent fix has two halves, and both are needed. Route WordPress mail through an authenticated SMTP connection so the message is sent properly, and publish SPF and DKIM records so receiving servers trust it. Doing only the first still leaves mail in spam folders. Doing only the second changes nothing, because the mail is still coming from an unauthenticated server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Once both are in place, WordPress email stops being a recurring problem. A dedicated <a href=\"https:\/\/www.photonconsole.com\/relay.php\">transactional email solution<\/a> handles the authentication, routing and sending reputation, and works with the plugin or the code method shown above. Developers working on other stacks may also want our guides to <a href=\"https:\/\/photonconsole.com\/blog\/how-to-send-emails-in-node-js-with-nodemailer-a-production-setup-guide\/\">sending email in Node.js<\/a> and <a href=\"https:\/\/photonconsole.com\/blog\/sending-email-in-python-smtplib-vs-an-email-api-with-working-code\/\">sending email in Python<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Read More<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/www.photonconsole.com\/email-deliverability-checker.php\">Free Email Deliverability Checker<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/photonconsole.com\/blog\/spf-dkim-dmarc-explained-simply\/\">SPF, DKIM and DMARC Explained Simply<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/photonconsole.com\/blog\/smtp-configuration\/\">SMTP Configuration: Complete Setup Reference<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/photonconsole.com\/blog\/smtp-response-codes-explained\/\">SMTP Response Codes Explained<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/photonconsole.com\/blog\/improve-email-deliverability\/\">How to Improve Email Deliverability<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.photonconsole.com\/relay.php\">PhotonRelay: SMTP Relay Service<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.photonconsole.com\/pricing.php\">PhotonConsole Pricing<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Contact form submissions never arrive. Password reset links never reach users. WooCommerce order confirmations vanish, and customers email asking whether their purchase went through. WordPress reports no error. The form shows a success message. Nothing in the dashboard suggests a problem. This is one of the most common failures on self-hosted WordPress sites, and it [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":380,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[312],"tags":[517,520,516,519,518],"class_list":["post-379","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-email-engineering-guide","tag-woocommerce-emails-not-sending","tag-wordpress-contact-form-not-sending-email","tag-wordpress-not-sending-email","tag-wordpress-smtp-setup","tag-wp_mail-not-working"],"_links":{"self":[{"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/posts\/379","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/comments?post=379"}],"version-history":[{"count":1,"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/posts\/379\/revisions"}],"predecessor-version":[{"id":384,"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/posts\/379\/revisions\/384"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/media\/380"}],"wp:attachment":[{"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/media?parent=379"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/categories?post=379"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/tags?post=379"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}