X Enterprises
fastify-x-twilio

email.send / email.sendTemplate / email.sendWithAttachments / email.sendBulk / email.sendPersonalizedBulk

Send transactional emails via SendGrid — plain HTML, dynamic templates, attachments, and bulk campaigns.

email.send / sendTemplate / sendWithAttachments / sendBulk / sendPersonalizedBulk

Five SendGrid email sending methods covering every delivery pattern: plain HTML emails, dynamic template-based emails, emails with attachments, identical bulk campaigns, and personalized one-to-one campaigns at scale.

Signatures

fastify.email.send(
  to: string | string[],
  subject: string,
  html: string,
  text?: string,
  extraOptions?: object
): Promise<{ success: boolean; statusCode: number; messageId: string }>

fastify.email.sendTemplate(
  to: string | string[],
  subject: string,
  templateId: string,
  dynamicData?: Record<string, unknown>,
  extraOptions?: object
): Promise<{ success: boolean; statusCode: number; messageId: string }>

fastify.email.sendWithAttachments(
  to: string | string[],
  subject: string,
  html: string,
  attachments: Array<{ content: string; filename: string; type?: string; disposition?: string }>
): Promise<{ success: boolean; statusCode: number }>

fastify.email.sendBulk(
  to: string[],
  subject: string,
  html: string
): Promise<{ success: boolean; count: number; statusCode: number }>

fastify.email.sendPersonalizedBulk(
  messages: Array<{ to: string; subject: string; html: string; text?: string }>
): Promise<Array<{ success: boolean; to: string; statusCode?: number; error?: string }>>

Params

send

NameTypeRequiredDescription
tostring | string[]YesRecipient email(s).
subjectstringYesEmail subject line.
htmlstringYesHTML body.
textstringNoPlain text alternative. Auto-stripped from HTML if omitted.
extraOptionsobjectNoAdditional SendGrid msg fields.

sendTemplate

NameTypeRequiredDescription
tostring | string[]YesRecipient email(s).
subjectstringYesSubject line. Also injected as {{ subject }} into dynamic data.
templateIdstringYesSendGrid dynamic template ID (e.g., "d-abc123").
dynamicDataobjectNoTemplate variable substitutions.
extraOptionsobjectNoAdditional SendGrid msg fields.

sendWithAttachments

NameTypeRequiredDescription
tostring | string[]YesRecipient email(s).
subjectstringYesSubject line.
htmlstringYesHTML body.
attachmentsarrayYesNon-empty array of attachment objects.
attachments[].contentstringYesBase64-encoded file content.
attachments[].filenamestringYesAttachment filename.
attachments[].typestringNoMIME type.
attachments[].dispositionstringNo"attachment" (default) or "inline".

sendBulk

NameTypeRequiredDescription
tostring[]YesNon-empty array of recipient emails. Same HTML sent to all.
subjectstringYesSubject line.
htmlstringYesHTML body.

sendPersonalizedBulk

NameTypeRequiredDescription
messagesarrayYesNon-empty array of { to, subject, html, text? } objects. Uses Promise.allSettled — failures are captured in results, not thrown.

Returns

All methods return success indicators and SendGrid response metadata. sendPersonalizedBulk returns an array of per-message results.

Examples

send — basic transactional email

const result = await fastify.email.send(
  "user@example.com",
  "Your order has been placed",
  "<h1>Order Confirmed</h1><p>Thanks for your purchase!</p>"
);

console.log(result.messageId); // SendGrid message ID for tracking

sendTemplate — dynamic template

await fastify.email.sendTemplate(
  "user@example.com",
  "Welcome to Example!",
  "d-abc123xyz",
  {
    firstName: "Alice",
    confirmUrl: "https://app.example.com/confirm?token=abc",
  }
);

sendWithAttachments — PDF invoice

const pdfBuffer = await generateInvoicePdf(invoiceId);

await fastify.email.sendWithAttachments(
  "customer@example.com",
  "Invoice #1001",
  "<p>Please find your invoice attached.</p>",
  [
    {
      content: pdfBuffer.toString("base64"),
      filename: "invoice-1001.pdf",
      type: "application/pdf",
    },
  ]
);

sendBulk — newsletter blast

const subscribers = await db.newsletter.getActiveSubscribers();

const result = await fastify.email.sendBulk(
  subscribers.map((s) => s.email),
  "May Product Updates",
  renderNewsletterHtml({ month: "May" })
);

console.log(`Sent to ${result.count} subscribers`);

sendPersonalizedBulk — per-user digest

const users = await db.users.findWithActivityThisWeek();

const results = await fastify.email.sendPersonalizedBulk(
  users.map((u) => ({
    to: u.email,
    subject: `${u.firstName}, here's your weekly summary`,
    html: renderDigestHtml(u),
  }))
);

const failed = results.filter((r) => !r.success);
if (failed.length > 0) {
  fastify.log.warn({ failed }, "Some digest emails failed to send");
}

Throws

  • [xTwilio] email.send: to is required
  • [xTwilio] email.send: subject (string) is required
  • [xTwilio] email.send: html (string) is required
  • [xTwilio] email.sendTemplate: templateId (string) is required
  • [xTwilio] email.sendWithAttachments: attachments must be a non-empty array
  • [xTwilio] email.sendBulk: to must be a non-empty array of emails
  • [xTwilio] email.sendPersonalizedBulk: messages must be a non-empty array
  • [xTwilio] Failed to send email: <message> — SendGrid API error

See also

AI Context

package: "@xenterprises/fastify-xtwilio"
decorator: fastify.email
methods: send, sendTemplate, sendWithAttachments, sendBulk, sendPersonalizedBulk
use-when: Send transactional emails via SendGrid through the xTwilio plugin
Copyright © 2026