Email SDK
Adapters

JetEmail

Send through the JetEmail transactional API over fetch — CC, BCC, reply-to, custom headers, and base64 attachments, with idempotent retries.

The JetEmail adapter calls JetEmail's transactional POST /email endpoint over fetch — no extra dependency. JetEmail runs its own sending infrastructure (anycast IPs, managed reputation), and the adapter maps the normalized EmailMessage straight onto its REST payload.

JetEmail logo
JetEmail
@opencoredev/email-sdk/jetemail
OfficialAPI testedRequest tested
Open website

Configure

Create a JetEmail transactional API key (prefixed transactional_) in the JetEmail dashboard and verify the domain you send from.

lib/email.ts
import { createEmailClient } from "@opencoredev/email-sdk";
import { jetemail } from "@opencoredev/email-sdk/jetemail";

export const email = createEmailClient({
  adapters: [jetemail({ apiKey: process.env.JETEMAIL_API_KEY! })],
});

Prop

Type

Send

JetEmail accepts up to 50 recipients each across to, cc, and bcc, and maps headers to custom email headers. Attachments are base64-encoded automatically (40MB total).

const result = await email.send({
  from: "Acme <hello@acme.com>",
  to: [{ email: "user@example.com", name: "Ada" }],
  cc: "team@acme.com",
  replyTo: "support@acme.com",
  subject: "Welcome to Acme",
  html: "<p>Thanks for joining Acme.</p>",
  text: "Thanks for joining Acme.",
});

console.log(result.id); // JetEmail message id, e.g. "19424fd2acd0004210"

From requires a display name

JetEmail rejects a bare email in from — it requires the "Name <email>" form. The adapter fails fast with an EmailValidationError when from has no display name, so pass from: "Acme <hello@acme.com>" or from: { email: "hello@acme.com", name: "Acme" }.

No tags or metadata

JetEmail's send API has no tags or metadata field, so the adapter rejects tags and metadata with an EmailValidationError before the request. Check field support before using JetEmail in a fallback route.

Idempotent sends

Pass an idempotencyKey and the adapter forwards it as JetEmail's Idempotency-Key header, so a retried send with the same key and body replays the original response instead of sending twice.

await email.send(message, { idempotencyKey: "receipt:order_123" });

Verify from the CLI

JETEMAIL_API_KEY="transactional_..." npx email-sdk doctor --adapter jetemail
JETEMAIL_API_KEY="transactional_..." npx email-sdk send \
  --adapter jetemail \
  --from "Acme <hello@acme.com>" \
  --to user@example.com \
  --subject "JetEmail smoke test" \
  --text "It works" \
  --dry-run

Drop --dry-run for one real smoke send — the only check that proves the API key and sender domain are ready.

On this page