Send email with PHP

PHP's mail() function is where deliverability goes to die: no authentication, no feedback, no delivery events. Sending email from PHP properly is one authenticated HTTP request.

Verified By George Hartley, Co-founder · Updated July 20, 2026

Why mail() fails you

mail() looks free. It hands your message to whatever the server's sendmail is, unauthenticated, and reports success the moment it leaves PHP, not when it reaches an inbox. No SPF alignment, no DKIM signature, no bounce handling. Mailbox providers treat that kind of mail accordingly.

The usual next step is PHPMailer over SMTP, which fixes authentication and adds a dependency, credentials in config, and a connection to manage. The step after that is the one worth taking.

Authentication is also no longer a human chore. My own agent writes the SPF, DKIM, and DMARC records on a subdomain and verifies the alignment itself. The part of email PHP developers dread most is now a prompt.

One POST, and the send is handled

PHPPOST /v1/my/messages
$ch = curl_init("https://api.nitrosend.com/v1/my/messages");
curl_setopt_array($ch, [
  CURLOPT_HTTPHEADER => ["Authorization: Bearer $NITROSEND_API_KEY"],
  CURLOPT_POSTFIELDS => json_encode([
    "from" => "[email protected]",
    "to" => "[email protected]",
    "subject" => "Welcome",
    "html" => "<p>You're in.</p>",
  ]),
]);
curl_exec($ch);

cURL ships with PHP, the token lives in your environment, and delivery, authentication, and events are the platform's job. WordPress, Laravel, or plain PHP, the call is the same.

PHP developers are not a side audience for us. WooCommerce has more installs than any other ecommerce platform, and WooCommerce developers ask us more questions about the API than anyone else. This page exists because of them, and the platform slots into a PHP stack as the MAIL_DRIVER, so every transactional, marketing, and automated send lands in one place instead of scattered across plugins.

Full parameters, responses, and error codes live in the REST API docs and the API reference.

Python Node.js PHP Go Rust +5
send.py requests ยท stdlib-adjacent
import requests

requests.post(
  "https://api.nitrosend.com/v1/messages",
  headers={"Authorization": f"Bearer {KEY}"},
  json={"to": to, "subject": subj,
        "html": body})
202 ACCEPTED
{ "id": "msg_9f2c",
  "status": "accepted" }

And the part no library gives you

The same account exposes an MCP server, so the agent writing your code can also run your email. Point Claude, Cursor, or Codex at api.nitrosend.com/mcp and it composes, previews, and stages sends, with a human approving every one. The API is for your code. The MCP is for your agent. One platform either way.

Every send comes back with a message ID, and delivery events follow on your webhook: delivered, opened, bounced. No dashboard required to know what happened.

Go deeper

First send in thirty seconds.

Simple pricing. Unlimited contacts.

Every plan includes full stack emailing: Flows, Newsletter Campaigns and Transactional Email, plus our NitroWheel LLM and all agent integrations (Claude, ChatGPT, Codex, Cursor and others). Pay for what you send, not who you store.

Free
$0
forever
  • Emails 8,000then 500/mo
  • Email types Transactional & Marketing
  • AI actions 20/mo
  • Contacts Free & Unlimited
  • Brands 1
  • Seats 1
Start free
Ultra
$100
per month
  • Emails 125,000/month
  • AI actions 5,000/mo
  • Brands 5
  • Seats 10 · Domains 3
  • Frontier AI Included
  • Dedicated IP Available
Get started
Enterprise
$300
per month
  • AI actions Unlimited
  • Unlimited brands & domains Included
  • SSO / SAML Included
  • 99.9% SLA Included
Get started

Free forever. No credit card required. See full comparison →