npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@xenterprises/fastify-xemail

v1.3.0

Published

Fastify plugin for email via Postmark or SendGrid (legacy) — transactional emails, templates, bulk sending, validation, and contact management.

Readme

@xenterprises/fastify-xemail

Fastify 5 plugin for email via Postmark or SendGrid (legacy) — send transactional, template, attachment, and bulk emails through one fastify.xEmail decorator. SendGrid additionally supports address validation and Marketing contacts/lists. For Fastify apps that need email with the least possible wiring.

Migration note: SendGrid support is legacy. New integrations should use provider: 'postmark'; existing SendGrid registrations keep working unchanged.

Install

npm install @xenterprises/fastify-xemail fastify@5

fastify@^5.0.0 is a peer dependency.

TypeScript declarations ship with the package — importing the plugin types the fastify.xEmail decorator automatically (index.d.ts).

Minimal example

import Fastify from 'fastify';
import xEmail from '@xenterprises/fastify-xemail';

const fastify = Fastify();

await fastify.register(xEmail, {
  provider: 'postmark', // or 'sendgrid' (legacy default)
  apiKey: 'your-postmark-server-token',
  fromEmail: '[email protected]',
});

await fastify.xEmail.send(
  '[email protected]',
  'Welcome!',
  '<h1>Welcome!</h1><p>Thanks for signing up.</p>'
);

The plugin reads no environment variables. All configuration arrives via the register options object; reading process.env.POSTMARK_SERVER_TOKEN and passing it in is the consumer's job.

Providers

| Provider | Status | Sending methods | validate, contacts, lists | |----------|--------|-----------------|------------------------------| | postmark | Migration target | send, sendTemplate, sendWithAttachments, sendBulk, sendPersonalizedBulk | Throw "not supported by provider 'postmark'" | | sendgrid | Legacy (default) | All sending methods | Fully supported |

Postmark's API has no equivalents for email validation or contact/list management, so those methods exist in the decorator under Postmark but throw [xEmail] '<method>()' is not supported by provider 'postmark'.

Options

| Name | Type | Default | Required | Description | |------|------|---------|----------|-------------| | provider | 'sendgrid' \| 'postmark' | 'sendgrid' | No | Email provider. sendgrid is legacy; postmark is the migration target | | apiKey | string | — | Yes | SendGrid API key (needs Mail Send; Marketing APIs for contact/list methods) or Postmark server API token | | fromEmail | string | — | Yes | Verified sender email address | | fromName | string | — | No | Sender display name | | active | boolean | true | No | Set false to disable the plugin entirely (no decorator is added) |

Invalid options fail fast at registration with errors like:

xemail: option `apiKey` must be a string, e.g. `app.register(xEmail, { apiKey: 'SG.your-api-key' })`

Decorators

The plugin adds one decorator: fastify.xEmail. No request decorators.

send(to, subject, html, text?, extraOptions?)

Send an email. Plain text is auto-generated from the HTML if text is omitted. Under SendGrid, extraOptions is merged into the message (e.g. replyTo, cc, categories). Under Postmark, extraOptions accepts replyTo, cc, bcc, headers, and messageStream (mapped to Postmark's PascalCase fields). Returns { success, statusCode, messageId } (Postmark reports a fixed statusCode: 200 on success and throws on failure).

sendTemplate(to, subject, templateId, dynamicData?, extraOptions?)

Send using a provider template. SendGrid: templateId is the dynamic template ID (d-xxx) and dynamicData is sent as dynamicTemplateData. Postmark: templateId is a template alias (string) or numeric template ID and dynamicData becomes the TemplateModel. The subject is always included in the template data. Returns { success, statusCode, messageId }.

sendWithAttachments(to, subject, html, attachments)

Send an email with attachments. Each attachment needs content (base64), filename, and type (MIME type); disposition defaults to 'attachment'. Returns { success, statusCode, messageId }.

sendBulk(to, subject, html)

Send the same email to an array of recipients. SendGrid uses one sgMail.sendMultiple call; Postmark sends one email per recipient in chunks of 500 concurrent requests. Returns { success, count, statusCode }.

sendPersonalizedBulk(messages)

Send different content per recipient. messages is an array of { to, subject, html, text? }. Never throws on individual failures — returns one result per recipient: { success: true, to, statusCode } or { success: false, to, error }. Postmark uses the batch endpoint (chunked at 500 messages); a failure of the whole batch call marks that chunk's recipients as failed instead of throwing.

validate(email) — SendGrid only

Validate an address via the SendGrid Email Validation API. Returns { email, valid, verdict, score, result }. On API failure it returns a soft result { email, valid: false, verdict: 'Unknown', error } instead of throwing. Throws under provider: 'postmark'.

addContact(email, data?, listIds?) — SendGrid only

Add or update a SendGrid Marketing contact. data accepts firstName/lastName (or first_name/last_name) and customFields (spread into the contact); listIds is an array of list IDs. Returns { success, jobId, email }.

searchContact(email) — SendGrid only

Search for a contact by email. Returns { found: true, contact } or { found: false }.

deleteContact(contactId) — SendGrid only

Delete a contact by ID. Returns true on success (HTTP 200/202), false otherwise.

createList(name) — SendGrid only

Create a marketing contact list. Returns { success, list }.

getLists() — SendGrid only

Get all contact lists. Returns an array (empty when none exist).

deleteList(listId) — SendGrid only

Delete a list by ID. Returns true on success (HTTP 200/202/204), false otherwise.

Routes

None. This plugin adds no routes.

Error behavior

  • Registration throws fail-fast Errors naming the plugin and the option, with a registration example (see Options above).
  • Method argument validation throws synchronously-rejecting Errors prefixed with [xEmail], e.g. [xEmail] 'to' is required for send().
  • SendGrid API failures are logged via fastify.log.error (structured error, never the API key) and re-thrown wrapped: [xEmail] Failed to send email: <reason>. validate() is the exception — it returns a soft result instead of throwing, since validation failures are expected in normal operation. Postmark failures are wrapped the same way.
  • SendGrid-only methods under Postmark throw [xEmail] '<method>()' is not supported by provider 'postmark'.
  • With active: false the plugin returns before registering anything, so fastify.xEmail is undefined.

Requirements

  • Node.js >= 20
  • Fastify ^5.0.0 (peer dependency)

License

Proprietary — All Rights Reserved, X Enterprises. See LICENSE.