SendGrid
Send through the Twilio SendGrid Mail Send API with the fullest field support of any adapter.
The SendGrid adapter calls the Twilio SendGrid Mail Send API with plain fetch. It supports every EmailMessage field: recipients land in a personalizations entry, metadata becomes custom_args, and tags become categories.
@opencoredev/email-sdk/sendgridConfigure
Create an API key with Mail Send permission in the SendGrid dashboard and verify the sender identity or domain you use in from.
import { createEmailClient } from "@opencoredev/email-sdk";
import { sendgrid } from "@opencoredev/email-sdk/sendgrid";
export const email = createEmailClient({
adapters: [sendgrid({ apiKey: process.env.SENDGRID_API_KEY! })],
});Prop
Type
Send
Everything maps: cc, bcc, headers, attachments, tags, metadata, and even multiple replyTo addresses (sent as reply_to_list). sendAt schedules the send natively as send_at (a Unix timestamp in seconds); SendGrid accepts at most 72 hours in the future.
const result = await email.send({
from: "Acme <security@acme.com>",
to: [{ email: "user@example.com", name: "Ada" }],
subject: "Reset your password",
html: "<p>Click the link below to reset your password.</p>",
text: "Use the link below to reset your password.",
metadata: { userId: "user_123", flow: "password-reset" },
tags: [{ name: "type", value: "password-reset" }],
});
console.log(result.id); // SendGrid message id from the x-message-id headerSendGrid's send endpoint returns 202 Accepted with an empty body, so the adapter reads result.id from the x-message-id response header. metadata values arrive in SendGrid event webhooks as custom_args; tag values arrive as categories.
Batch sends with recipient variables
Pass recipientVariables and the adapter emits one personalizations entry per recipient with SendGrid substitutions, so one API call personalizes every recipient (up to 1000, SendGrid's personalizations cap). SendGrid substitutes %recipient.key% tokens in subject, html, and text on its side:
await email.send({
from: "Acme <hello@acme.com>",
to: ["ada@example.com", "linus@example.com"],
subject: "Hi %recipient.name%",
html: '<a href="https://acme.com/unsub?id=%recipient.id%">Unsubscribe</a>',
recipientVariables: {
"ada@example.com": { name: "Ada", id: "u_1" },
"linus@example.com": { name: "Linus", id: "u_2" },
},
});Verify from the CLI
SENDGRID_API_KEY="SG...." npx email-sdk doctor --adapter sendgridSENDGRID_API_KEY="SG...." npx email-sdk send \
--adapter sendgrid \
--from "Acme <hello@acme.com>" \
--to user@example.com \
--subject "SendGrid smoke test" \
--text "It works" \
--dry-runDrop --dry-run for one real send. SendGrid account review and sender verification can block delivery even when the payload validates, and only a live send proves they are done.
