A form notification crosses five hands before it is read
A form plugin accepts the visitor's entry and asks WordPress to send a notification. WordPress itself has no mail server: the Mail handbook explains that it supplies a wrapper, wp_mail(), which formats the message and passes it to a mail library, historically PHPMailer. By default that library calls the server's own mail function, which depends on a sendmail-compatible program being installed and allowed to send. If instead an SMTP plugin is installed, it replaces that route and sends through a remote mail service. From there the message must be accepted by the receiving server and survive the mailbox's filters. A thank-you page proves only the first step.
- Step 1: the form accepted and, ideally, saved the entry.
- Step 2: WordPress built the message and chose the sender and recipient.
- Step 3: the server or the SMTP service accepted it for delivery.
- Step 4: the receiving system accepted it.
- Step 5: the mailbox delivered it to the inbox rather than junk.
The default sender is a common quiet cause
Unless a form sets its own sender, WordPress builds one: wordpress@ followed by your site's domain, with the name WordPress. The Mail handbook says that if you keep the default you should check that you can actually receive mail at that address, and the reference page for the sender filter says it is highly recommended that the from domain matches your website, because otherwise mail is more likely to be marked as spam. It adds that some hosts insist the sender is a real address. Reply-To is the same as From unless a header says otherwise, which is why a form that wants replies to go to the visitor has to set Reply-To explicitly.
- A From address on Gmail or Outlook.com, sent by your own server, is a mismatch.
- The same address in To and From can be treated as suspicious by some providers.
- Changing the sender needs both the address and the display name, through the two sender filters or the form plugin's settings.
Authentication decides whether the receiver trusts the message
The handbook mentions several reasons mail may not be delivered even when WordPress is behaving: no mail server set up where the site runs, outside factors such as IP reputation, a message routed to spam or discarded, and some old receivers that check the From address (a check it says is becoming less common). SPF is a DNS record listing the hosts allowed to send for your domain, DKIM adds a signature checked against a public key in DNS, and DMARC tells receivers what to do when those checks fail. For SPF specifically, the handbook says that when mail leaves through several servers, WordPress included, you need to add all the addresses to the SPF record, and it calls setting up SPF, DKIM and DMARC records a critical step for deliverability. This guide's reading is that the usual repair is therefore to send through an authenticated mail service and publish the records that service asks for, not to buy a bigger server.
- Records are entered by whoever controls your domain's DNS; a form fix cannot do that for them.
- Inspect the header of one received test message for the SPF and DKIM results before changing anything.
How to see a failure instead of guessing
When the mail library throws an exception, WordPress fires the wp_mail_failed action, passing an error object that holds the exception message and the details of the email that failed. It has existed since WordPress 4.4.0, and a short function hooked to it can write the message to a log on a staging copy. Because the details include the recipient, subject and body, treat any such log as sensitive, keep it on staging, and delete it after the investigation. A success from the library is not proof of delivery: it means the next system accepted the message.
- Log on staging, not on a live site that handles real enquiries.
- Test with made-up content so no real visitor data enters the log.
Where this guide stops and the paid job begins
If the form does not even save an entry, the fault is in the form or a plugin conflict, not in sending. If your whole domain's mail lands in junk, that is the domain-wide authentication job. If the site is custom PHP rather than WordPress, a different job applies. The WordPress sending job is a published test price of GBP 175 for up to three forms on one single site: it configures authenticated sending, sets the sender and Reply-To, and is accepted when a marked test from each form reaches the agreed mailbox with the SPF and DKIM results recorded. Inbox placement is recorded, not promised.
- Send the form addresses and your answers, never passwords or API keys.
- The price is an untested proposal and payment follows the agreed checks.
Sources and limits
- WordPress developer handbook: Mail Checked 2026-10-11.
- WordPress ships with no mail client or server; wp_mail() formats a message and passes it to a mail library, and PHPMailer by default calls PHP mail(), which needs a sendmail-compatible program.
- The default sender is wordpress@ on the site's domain with the name WordPress, changed by the wp_mail_from and wp_mail_from_name filters; Reply-To matches From unless headers say otherwise.
- A badly configured SPF record can get mail rejected as spam, an invalid DKIM signature can get it rejected, and the page calls setting up SPF, DKIM and DMARC records a critical step for deliverability; for SPF it says that when mail leaves through several servers you need to add all the addresses to the SPF record. Reasons it gives for non-delivery include no mail server where the site runs, outside factors such as IP reputation, routing to spam or discarding, and some old receivers that check the From address. SMTP plugins override default wp_mail() behaviour.
- WordPress developer reference: wp_mail_from Checked 2026-10-11.
- The reference says it is highly recommended that the from domain matches your website to avoid being marked as spam, and that some hosts may insist on a real working sender address.
- WordPress developer reference: wp_mail_failed Checked 2026-10-11.
- The action fires after a PHPMailer exception is caught, passes a WP_Error containing the exception message and the email details, and dates from WordPress 4.4.0.