Send email over SMTP
Send transactional emails over Cloudflare Email Service SMTP using curl, Nodemailer, Python smtplib, or PHPMailer.
Send transactional emails over Cloudflare Email Service authenticated SMTP (smtp.mx.cloudflare.net:465) from any SMTP-capable language or client.
- A domain onboarded for Email Sending.
- A Cloudflare API token with the Email Sending: Edit permission. Set it as
CF_API_TOKENin your environment. The token is used as the SMTP password; the username is the literal stringapi_token.
cat > mail.txt <<EOFFrom: welcome@yourdomain.comTo: recipient@example.comSubject: Welcome to our service!
Thanks for signing up.EOF
curl --ssl-reqd \ --url "smtps://smtp.mx.cloudflare.net:465" \ --user "api_token:$CF_API_TOKEN" \ --mail-from "welcome@yourdomain.com" \ --mail-rcpt "recipient@example.com" \ --upload-file mail.txtThe sender domain must be onboarded for Email Sending on the account that owns the API token.
Install Nodemailer ↗ with npm install nodemailer.
import nodemailer from "nodemailer";
const transporter = nodemailer.createTransport({ host: "smtp.mx.cloudflare.net", port: 465, secure: true, // implicit TLS auth: { user: "api_token", pass: process.env.CF_API_TOKEN, },});
const info = await transporter.sendMail({ from: '"Acme" <welcome@yourdomain.com>', to: "user@example.com", subject: "Welcome to Acme", text: "Thanks for signing up.", html: "<h1>Welcome to Acme</h1><p>Thanks for signing up.</p>",});
console.log("Message sent:", info.messageId);const info = await transporter.sendMail({ from: '"Acme Billing" <billing@yourdomain.com>', to: "customer@example.com", subject: "Your invoice", text: "Please find your invoice attached.", attachments: [ { filename: "invoice-2026-04.pdf", path: "./invoices/invoice-2026-04.pdf", contentType: "application/pdf", }, ],});Total message size (including base64-encoded attachments) must not exceed 5 MiB. See Limits.
Nodemailer rejects the promise with an Error whose .responseCode reflects the SMTP reply code. See SMTP response codes and Troubleshooting.
try { await transporter.sendMail({ /* ... */ });} catch (err) { console.error(err.responseCode, err.message);}Uses the standard-library smtplib ↗ (Python 3.8 or later).
import osimport smtplibfrom email.message import EmailMessage
msg = EmailMessage()msg["From"] = "Acme <welcome@yourdomain.com>"msg["To"] = "user@example.com"msg["Subject"] = "Welcome to Acme"msg.set_content("Thanks for signing up.")msg.add_alternative( "<h1>Welcome to Acme</h1><p>Thanks for signing up.</p>", subtype="html",)
with smtplib.SMTP_SSL("smtp.mx.cloudflare.net", 465) as s: s.login("api_token", os.environ["CF_API_TOKEN"]) s.send_message(msg)smtplib.SMTP_SSL opens an implicit-TLS connection on port 465, which is what Cloudflare's SMTP endpoint requires. Do not use smtplib.SMTP with starttls(); STARTTLS is not supported.
msg["To"] = ", ".join([ "user1@example.com", "user2@example.com", "user3@example.com",])A single SMTP session can deliver to up to 50 RCPT TO addresses. See Limits.
from pathlib import Path
pdf = Path("invoice-2026-04.pdf").read_bytes()msg.add_attachment( pdf, maintype="application", subtype="pdf", filename="invoice-2026-04.pdf",)smtplib raises subclasses of smtplib.SMTPException with the SMTP reply code attached. See SMTP response codes and Troubleshooting.
try: with smtplib.SMTP_SSL("smtp.mx.cloudflare.net", 465) as s: s.login("api_token", os.environ["CF_API_TOKEN"]) s.send_message(msg)except smtplib.SMTPAuthenticationError as e: print(f"Auth failed: {e.smtp_code} {e.smtp_error!r}")except smtplib.SMTPResponseException as e: print(f"SMTP error: {e.smtp_code} {e.smtp_error!r}")<?phpuse PHPMailer\PHPMailer\PHPMailer;
require 'vendor/autoload.php';
$mail = new PHPMailer(true);$mail->isSMTP();$mail->Host = 'smtp.mx.cloudflare.net';$mail->Port = 465;$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;$mail->SMTPAuth = true;$mail->Username = 'api_token';$mail->Password = getenv('CF_API_TOKEN');
$mail->setFrom('welcome@yourdomain.com', 'Acme');$mail->addAddress('recipient@example.com');$mail->Subject = 'Welcome to our service!';$mail->Body = 'Thanks for signing up.';$mail->send();- SMTP reference — connection details, authentication, response codes, and troubleshooting.
- Specify recipients — multiple recipients, CC and BCC, and named addresses.
- Limits — account, message, and session limits.