Adapters
Configure one of 23 provider API adapters or the built-in SMTP transport, 24 adapters total.
A strong default for developer-first transactional email.
Use one API for transactional email and email sequences.
A focused transactional email API for product teams.
Use when your product already sends through Primitive.
Straightforward transactional email with a simple API.
Transactional and marketing email for SaaS, with a REST API and editor.
Great for focused transactional email and deliverability.
Best when your product already runs on Twilio SendGrid.
A good fit for AWS teams sending at high volume.
Use with an existing Mailgun setup or sending domain.
A simple API with a friendly dashboard for growing teams.
Use transactional email alongside your Brevo marketing stack.
Best for products already using Mailchimp Transactional.
Use when SparkPost already powers your email delivery.
Useful when testing and production email live in Mailtrap.
Send directly from apps running on Cloudflare Workers.
A lightweight choice for straightforward product email.
A natural fit for apps hosted in the Scaleway ecosystem.
Use transactional email alongside Zoho and ZeptoMail.
A simple transactional email API for smaller products.
Best for lifecycle email managed through Iterable.
Send product and lifecycle email through your Loops account.
An open-source-friendly option for product email.
Connect any existing SMTP server or self-hosted mail system.
Compare support
| Requirement | Check first |
|---|---|
| Monthly cost from 1K to 1M emails | Pricing comparison |
| CC, BCC, reply-to, attachments, tags, or metadata | Field support |
| Repeated headers, scheduled delivery, native idempotency, or personalized fanout | Delivery capabilities |
| Existing SMTP service | SMTP |
Add more than one provider
import { createEmailClient } from "@opencoredev/email-sdk";
import { resend } from "@opencoredev/email-sdk/resend";
import { smtp } from "@opencoredev/email-sdk/smtp";
export const email = createEmailClient({
adapters: [
resend({ apiKey: process.env.RESEND_API_KEY! }),
smtp({
name: "backup",
host: process.env.SMTP_HOST!,
auth: {
user: process.env.SMTP_USER!,
pass: process.env.SMTP_PASS!,
},
}),
],
fallback: { adapters: ["backup"] },
});Email SDK checks every fallback before sending. If your backup cannot handle part of the message, you get an error instead of a half-broken email.
Check your setup without sending
npx email-sdk adapters
npx email-sdk doctor --adapter resenddoctor checks your credentials and required settings. send --dry-run checks the whole message without sending it.
