Radondocs

Attachments & scheduling

Attach files as Buffers or base64, embed inline images with content IDs, and schedule sends with sendAt — plus which providers support each.

Attachments

Attach files with the attachments array. Each entry needs a filename and content (a Node Buffer or a base64 string). Radon encodes it to whatever wire format the provider wants.

Attach a PDF
import { readFile } from "node:fs/promises";

const pdf = await readFile("./invoice.pdf"); // Buffer

await email.send({
  to: "ada@example.com",
  subject: "Your invoice",
  text: "The invoice is attached.",
  attachments: [
    { filename: "invoice.pdf", content: pdf },
  ],
});

Buffer vs. base64

content accepts either form:

// A Buffer — read from disk, generated in memory, fetched from storage.
{ filename: "report.csv", content: csvBuffer }

// A base64 string — already-encoded bytes (Radon assumes base64, not raw text).
{ filename: "logo.png", content: "iVBORw0KGgoAAAANSUhEUg..." }

A string content is treated as base64

When content is a string, Radon treats it as already base64-encoded bytes — it does not encode it for you. To attach raw text, wrap it: content: Buffer.from("hello,world", "utf8").

Content type

contentType is the MIME type. Omit it and Radon guesses from the filename extension, falling back to application/octet-stream.

{ filename: "data.json", content: buf }                                  // → application/json (guessed)
{ filename: "export.bin", content: buf, contentType: "application/x-custom" } // explicit

Guessed types cover the common extensions: pdf, png, jpg/jpeg, gif, webp, svg, csv, txt, html, json, zip, doc/docx, xls/xlsx, and ics.

Inline images

To embed an image in the HTML instead of listing it as a download, set disposition: "inline" and a contentId, then reference it from the HTML with cid:<id>.

Inline logo
await email.send({
  to: "ada@example.com",
  subject: "Newsletter",
  html: '<img src="cid:logo" alt="Acme" /><p>This month at Acme…</p>',
  attachments: [
    { filename: "logo.png", content: logoBuffer, disposition: "inline", contentId: "logo" },
  ],
});

Attachment fields

filenamestringrequired

File name shown to the recipient, e.g. "invoice.pdf".

contentstring | Bufferrequired

File bytes — a Buffer, or a base64-encoded string.

contentTypestring

MIME type. Guessed from the filename when omitted.

contentIdstring

Content-ID for inline embedding, referenced as cid:<id> in the HTML.

disposition"attachment" | "inline"default: "attachment"

"inline" for embedded images; "attachment" for downloads.

Provider support

Most providers support attachments. Two don't:

No attachments on Termii or Pinpoint

Termii (template/OTP email) and Amazon Pinpoint (SimpleEmail) carry no attachments — capabilities.attachments is false. Amazon SES does support them: Radon assembles a raw MIME message under the hood, since SES's simple content can't carry files. Check provider.capabilities.attachments before relying on it.

Scheduling

Pass a Date as sendAt to schedule delivery for the future. When the provider supports it, the result returns status: "scheduled".

Schedule a send
await email.send({
  to: "ada@example.com",
  subject: "Reminder",
  text: "Your trial ends tomorrow.",
  sendAt: new Date(Date.now() + 24 * 60 * 60 * 1000), // in 24 hours
});

Which providers schedule

Scheduling is supported on six providers:

Supports sendAtIgnores sendAt
Resend, SendGrid, Mailgun, Brevo, MailerSend, SparkPostPostmark, SES, Loops, Termii, Mailjet, Elastic Email, SMTP2GO, Pinpoint, ZeptoMail, SMTP

Unsupported providers send immediately

On a provider without scheduling (capabilities.scheduling is false), sendAt is silently ignored and the email goes out right away with a queued / sent status. Check the capability if a future send time is important, or route scheduled mail to a provider that supports it.

Next steps

On this page