← All @molecule/* packages · App templates
@molecule/api-emailsCore interface · email · API (Node) · v1.0.1 · Apache-2.0
Transactional email (password reset, notifications)
npm install @molecule/api-emails@molecule/api-emails is the email core interface on the API (Node) side: the API your app calls, with no vendor inside.
Choose the implementation by bonding one of its 6 providers: @molecule/api-emails-capture, @molecule/api-emails-mailgun, @molecule/api-emails-resend, @molecule/api-emails-sendgrid, @molecule/api-emails-sendmail, @molecule/api-emails-ses.
import { sendMail } from '@molecule/api-emails'
// Account email → the authenticated user's OWN address (not a client-named one).
await sendMail({
// `emailFrom`: a domain VERIFIED with your provider, read from config (see @remarks) —
// e.g. `getConfig('EMAIL_FROM', `no-reply@${MAILGUN_DOMAIN}`)`, never a placeholder.
from: emailFrom,
to: user.email, // validated, owned by the session
subject: 'Reset your password',
html: `<a href="${resetLink}">Reset</a>`, // a single-use link, not the raw token
})Providers (6): @molecule/api-emails-capture, @molecule/api-emails-mailgun, @molecule/api-emails-resend, @molecule/api-emails-sendgrid, @molecule/api-emails-sendmail, @molecule/api-emails-ses
Works with: @molecule/api-bond, @molecule/api-i18n
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.tsJSDoc, not this file.
Email core interface for molecule.dev.
Defines the standard interface for email providers.
import { sendMail } from '@molecule/api-emails'
// Account email → the authenticated user's OWN address (not a client-named one).
await sendMail({
// `emailFrom`: a domain VERIFIED with your provider, read from config (see @remarks) —
// e.g. `getConfig('EMAIL_FROM', `no-reply@${MAILGUN_DOMAIN}`)`, never a placeholder.
from: emailFrom,
to: user.email, // validated, owned by the session
subject: 'Reset your password',
html: `<a href="${resetLink}">Reset</a>`, // a single-use link, not the raw token
})
core
npm install @molecule/api-emails @molecule/api-bond @molecule/api-i18n
EmailAddressEmail address with optional display name.
interface EmailAddress {
name?: string
address: string
}
EmailAttachmentEmail file attachment (filename, content as string/Buffer/stream, MIME type, optional CID for inline).
interface EmailAttachment {
filename: string
content: string | Buffer | NodeJS.ReadableStream
contentType?: string
encoding?: string
cid?: string
}
EmailMessageEmail 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
}
EmailSendResultResult 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
}
EmailTransportEmail transport interface.
All email providers must implement this interface.
interface EmailTransport {
/**
* Sends an email message.
* @returns The send result.
*/
sendMail(message: EmailMessage): Promise<EmailSendResult>
}
getTransport()Retrieves the bonded email transport, throwing if none is configured.
function getTransport(): EmailTransport
Returns: The bonded email transport.
hasTransport()Checks whether an email transport is currently bonded.
function hasTransport(): boolean
Returns: true if an email transport is bonded.
sendMail(message)Sends an email message using the bonded transport.
function sendMail(message: EmailMessage): Promise<EmailSendResult>
message — The email message to send, including recipients, subject, and body.Returns: The send result containing accepted/rejected addresses and message ID.
setTransport(transport)Registers an email transport as the active singleton. Called by bond packages during application startup.
function setTransport(transport: EmailTransport): void
transport — The email transport implementation to bond.| Provider | Package |
|---|---|
| Capture | @molecule/api-emails-capture |
| Mailgun | @molecule/api-emails-mailgun |
| Resend | @molecule/api-emails-resend |
| SendGrid | @molecule/api-emails-sendgrid |
| Sendmail | @molecule/api-emails-sendmail |
| AWS SES | @molecule/api-emails-ses |
Peer dependencies:
@molecule/api-bond ^1.0.1@molecule/api-i18n ^1.0.1@molecule/api-bond@molecule/api-i18nSend through {@link sendMail} (the bonded transport) — never hardcode SMTP creds or an API key; they come from config/secrets and stay SERVER-SIDE.
to/from/subject is header injection (silent BCCs, spoofed headers) —
validate the address and strip control characters; don't let a user set arbitrary headers.SITE_ORIGIN (config),
NOT req.headers.origin/host/x-forwarded-host — those are caller-controlled, so a
forged header poisons the emailed link (host-header injection: the token-carrying URL
sent to a victim points at the attacker's domain → token leak + phishing). e.g.
const origin = getConfig('SITE_ORIGIN', '') || 'http://localhost:3000'.from domain must be one you VERIFIED with your provider (Mailgun/SendGrid/SES),
or the send is rejected / lands in spam (SPF+DKIM won't align on an unowned domain). Do
NOT hardcode a placeholder like noreply@example.com or an arbitrary domain: read the
sender from config and default it to your verified sending domain — e.g.
const from = process.env.EMAIL_FROM ?? `no-reply@${process.env.MAILGUN_DOMAIN ?? 'localhost'}`
(the exact env var for the sending domain is provider-specific; MAILGUN_DOMAIN for
Mailgun). One canonical EMAIL_FROM override + a default derived from the verified
domain = email that delivers out of the box.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:
undefined placeholders).Translation strings are provided by @molecule/api-locales-emails.