ESEN
Tutorial · 8 min de lectura

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

  1. 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.
  2. Create an API key. Use sk_test_ to develop without sending anything real, and sk_live_ in production.
  3. Send. A POST request to /api/v1/emails like the one above.
  4. 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=none and move to quarantine).
  • A From: on your own domain, never @gmail.com.
  • List-Unsubscribe header 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.

Seguir leyendo

DKIM, SPF and DMARC explained (in plain English)

The three DNS records that decide whether your email lands in the inbox or in spam. What each one does, how to set them up and how to check them.

Why your emails land in spam (and how to fix it)

The 8 real reasons your transactional emails end up in spam, ranked by impact, with the fix for each.