How to send transactional email in PHP (2026 guide)
Sending an email from PHP is easy. Getting that email to the inbox instead of spam is the hard part. This guide takes you from the old approach (mail()) to the right way in 2026.
The problem with mail() and DIY SMTP
PHP's mail() function hands the message to the local server and forgets about it. It does not sign with DKIM, align SPF, or handle bounces and complaints, and on shared hosting port 25 is usually blocked. The result: your signup and password-reset emails never arrive, and you never find out.
Running your own SMTP server does not fix the root issue either: IP reputation. A new or shared IP with no history goes straight to the spam folder at Gmail and Outlook.
The right way: a transactional email API
A transactional email provider handles reputation, DKIM signing, bounce suppression and delivery tracking. You just make one HTTP call. With an API like Zend24's, sending looks like this:
// Send an email with cURL (no dependencies) $ch = curl_init("https://zend24.com/api/v1/emails"); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer sk_live_YOUR_API_KEY", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode([ "from" => "Billing <billing@yourdomain.com>", "to" => "customer@example.com", "subject" => "Your October invoice", "html" => "<h1>Thanks for your purchase</h1>", ]), ]); $res = json_decode(curl_exec($ch), true); echo $res["id"]; // 01J2ZK7QW9...
No libraries, no Composer, no SMTP setup. The response includes an id you can use to check status (delivered, bounced, opened) or receive signed webhooks in real time.
Step by step
- Verify your domain. Add a few DNS records (DKIM, SPF, DMARC) once. With Zend24 you can connect Cloudflare, OVH or GoDaddy and they are created for you.
- Create an API key. Use
sk_test_to develop without sending anything real, andsk_live_in production. - Send. A POST request to
/api/v1/emailslike the one above. - Listen for events. Set up a webhook to react to bounces and complaints and keep your list clean.
Templates and variables
Don't put HTML in your code. Store the template once and send just the variables:
{
"from": "App <noreply@yourdomain.com>",
"to": "ana@example.com",
"template": "welcome",
"variables": { "name": "Ana" }
}Variable escaping is automatic to prevent HTML injection.
Deliverability checklist
- Domain verified with aligned DKIM and SPF.
- DMARC record published (start with
p=noneand move toquarantine). - A
From:on your own domain, never@gmail.com. List-Unsubscribeheader where applicable.- Bounce handling and automatic suppression.
To understand why DKIM, SPF and DMARC matter, read our guide to email authentication.
Zend24 is a transactional email API with European infrastructure, automatic DKIM and 3,000 free emails per month. Create your free account and send your first email in 10 seconds.
Preguntas frecuentes
Can I use PHP's mail() function in production?
Not recommended. mail() does not sign with DKIM, handle bounces or retries, and usually ends up in spam or blocked by the host. For production use an API or authenticated SMTP from a provider with good reputation.
What is the difference between transactional and marketing email?
Transactional email is triggered by a user action (signup, invoice, password reset) and goes to one person. Marketing email is bulk and promotional. They use different routes and reputations: mixing them hurts the deliverability of the important ones.