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

@molecule/api-emails-sendgrid

v1.0.1

Published

SendGrid email provider for molecule.dev.

Readme

@molecule/api-emails-sendgrid

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

SendGrid email provider for molecule.dev.

Quick Start

import { setTransport } from '@molecule/api-emails'
import { provider } from '@molecule/api-emails-sendgrid'

setTransport(provider)

Type

provider

Installation

npm install @molecule/api-emails-sendgrid @molecule/api-bond @molecule/api-emails @molecule/api-secrets @sendgrid/mail

API

Interfaces

EmailMessage

Email message options.

interface EmailMessage {
  /**
   * Sender address.
   */
  from: string | EmailAddress
  /**
   * Recipient(s).
   */
  to: string | EmailAddress | (string | EmailAddress)[]
  /**
   * CC recipient(s).
   */
  cc?: string | EmailAddress | (string | EmailAddress)[]
  /**
   * BCC recipient(s).
   */
  bcc?: string | EmailAddress | (string | EmailAddress)[]
  /**
   * Reply-to address.
   */
  replyTo?: string | EmailAddress
  /**
   * Email subject.
   */
  subject: string
  /**
   * Plain text body.
   */
  text?: string
  /**
   * HTML body.
   */
  html?: string
  /**
   * File attachments.
   */
  attachments?: EmailAttachment[]
  /**
   * i18n key for the subject (for client-side translation).
   */
  subjectKey?: string
  /**
   * i18n key for the plain text body (for client-side translation).
   */
  textKey?: string
  /**
   * i18n key for the HTML body (for client-side translation).
   */
  htmlKey?: string
}

EmailSendResult

Result of sending an email.

interface EmailSendResult {
  /**
   * Whether the email was accepted for delivery.
   */
  accepted: string[]
  /**
   * Addresses that were rejected.
   */
  rejected: string[]
  /**
   * Message ID from the provider.
   */
  messageId?: string
  /**
   * Raw response from the provider.
   */
  response?: string
}

EmailTransport

Email transport interface.

All email providers must implement this interface.

interface EmailTransport {
  /**
   * Sends an email message.
   * @returns The send result.
   */
  sendMail(message: EmailMessage): Promise<EmailSendResult>
}

Functions

getClient()

Returns the SendGrid mail client, applying configuration from the environment on FIRST USE and memoizing each setting thereafter.

Configuration is deferred to the first send — NOT module load — so an app that resolves SENDGRID_API_KEY (and the optional SENDGRID_BASE_URL) into process.env AFTER this module is imported (late secrets resolution via a secrets bond) is honored: the value present at send time is the one applied. Reading the key at import time instead froze an empty/stale key and every request went out unauthenticated — an opaque SendGrid 401. Each env var is applied once, the first time it is seen set, so whichever arrives late is still picked up.

function getClient(): sgMail.MailService

Returns: The configured @sendgrid/mail client.

sendMail(message)

Sends an email through the SendGrid API.

function sendMail(message: EmailMessage): Promise<EmailSendResult>
  • message — The email message (to, from, subject, text/html, attachments).

Returns: Send result with accepted addresses, message ID, and status code.

Constants

emailsSendgridSecretDefinitions

Secret definitions required by the SendGrid email bond.

const emailsSendgridSecretDefinitions: SecretDefinition[]

provider

The SendGrid email provider implementing the standard interface.

const provider: EmailTransport

Core Interface

Implements @molecule/api-emails interface.

Bond Wiring

Setup function to register this provider with the core interface:

import { setTransport } from '@molecule/api-emails'
import { provider } from '@molecule/api-emails-sendgrid'

export function setupEmailsSendgrid(): void {
  setTransport(provider)
}

Injection Notes

Requirements

Peer dependencies:

  • @molecule/api-bond ^1.0.1
  • @molecule/api-emails ^1.0.1
  • @molecule/api-secrets ^1.0.1

Environment Variables

Runtime Dependencies

  • @molecule/api-bond

  • @molecule/api-emails

  • @molecule/api-secrets

  • @sendgrid/mail

  • Configuration is lazy and env-driven: SENDGRID_API_KEY (and the optional SENDGRID_BASE_URL) are read on the FIRST send via getClient() — NOT at import time — and applied once. So a key resolved into process.env AFTER this module is imported (late secrets resolution via a secrets bond) is honored: the value present at send time is the one used. If the key is genuinely absent at send time, sendMail() throws a tagged config-missing error (clean 503 / config.notConfigured) naming SENDGRID_API_KEY — never an opaque SendGrid 401.

  • SENDGRID_TEST_MODE=true enables SendGrid sandbox mode: the API validates and accepts the message (auth + payload exercised for real) but NOTHING is delivered. SENDGRID_BASE_URL (optional, read lazily on first send too) overrides the API base URL for brokers/compatible endpoints.

  • Stream attachments are not supported — Buffer/string content only; a stream throws. On success accepted echoes every to recipient (SendGrid returns no per-recipient verdict) and messageId is taken from the x-message-id response header.

E2E Tests

Integration checklist — drive the real UI (live preview, no mocks). The sandbox CAPTURES outbound email instead of sending — read each message with the read_activity tool (filter type 'email'); the verification/reset link is in its payload. Never mock the send or modify production code to expose it. Adapt each item to this app's actual screens/flows, and check every box off one by one. A box you can't check is an integration bug to fix — not a skip:

  • [ ] Each email-triggering flow (signup verification, password-reset request, invites/notifications the app defines) confirms the send in the UI ("check your inbox") and a message actually reaches the transport.
  • [ ] The password-reset round-trip completes: request a reset → open the captured message → follow its single-use link → set a new password → log in with it (and the old password no longer works).
  • [ ] The message body contains a LINK, never the raw token/secret, and renders with the app's real name/content (no undefined placeholders).
  • [ ] Requesting a reset for an unknown email shows the same neutral UI response as a known one (no account-existence oracle).
  • [ ] Account emails go only to the account's own address — no UI or endpoint lets an unauthenticated caller send to an arbitrary address.