Notification

SMTP

SMTP email notification provider — send transactional emails via any standard SMTP server.

The @commercejs/notification-smtp package implements the NotificationProvider interface for delivering emails via SMTP using nodemailer. Works with Gmail, Amazon SES, Postfix, Mailgun, or any standard SMTP server.

Installation

pnpm add @commercejs/notification-smtp

Quick Start

import { createSmtpProvider } from '@commercejs/notification-smtp'

const smtp = createSmtpProvider({
  host: 'smtp.gmail.com',
  port: 587,
  secure: false,
  auth: { user: 'you@gmail.com', pass: 'app-password' },
  from: 'My Store <noreply@mystore.com>',
})

With CommerceJS

import { createCommerce } from '@commercejs/core'

const commerce = createCommerce({
  adapter,
  notifications: { smtp },
  notificationRules: [
    {
      event: 'order.created',
      channel: 'email',
      provider: 'smtp',
      template: 'order_confirmation',
      buildMessage: (payload) => ({
        to: payload.order.customer.email,
        subject: 'Order confirmed',
        html: '<h1>Thank you for your order!</h1>',
      }),
    },
  ],
})

Configuration

OptionTypeRequiredDefaultDescription
hoststringYesSMTP server hostname
portnumberYesSMTP port
securebooleanNofalseUse implicit TLS (port 465)
auth.userstringNoSMTP username
auth.passstringNoSMTP password or app password
fromstringYesDefault sender address
replyTostringNoReply-to address
connectionTimeoutnumberNo10000Connection timeout (ms)
socketTimeoutnumberNo10000Socket timeout (ms)
transporterTransporterNoCustom nodemailer transporter

Common SMTP Servers

ProviderHostPortSecureNotes
Gmailsmtp.gmail.com587falseRequires app password
Amazon SESemail-smtp.{region}.amazonaws.com587falseIAM SMTP credentials
Outlooksmtp-mail.outlook.com587falseApp password or OAuth
Mailgunsmtp.mailgun.org587falseSMTP credentials from dashboard
Postfixlocalhost25falseLocal mail server

Usage Examples

HTML Email

await smtp.send('email', {
  to: 'customer@example.com',
  subject: 'Your order has shipped!',
  html: '<h1>Shipping Notification</h1><p>Your order is on the way.</p>',
})

Plain Text Email

await smtp.send('email', {
  to: 'customer@example.com',
  subject: 'Order update',
  text: 'Your order has been delivered.',
})

Multipart (HTML + Text Fallback)

await smtp.send('email', {
  to: 'customer@example.com',
  subject: 'Welcome!',
  html: '<h1>Welcome to our store</h1>',
  text: 'Welcome to our store',
})

SMTP vs Resend

AspectSMTPResend
SetupHost/port/auth configAPI key only
SpeedDepends on serverFast (HTTP API)
DeliverabilityYou manage reputationResend manages
CostFree with own serverFree tier + paid
Edge supportNode.js onlyWorks on edge
Best forSelf-hosted, existing infrastructureQuick setup, managed delivery

Error Handling

All errors are caught and returned as NotificationResult:

const result = await smtp.send('email', {
  to: 'customer@example.com',
  subject: 'Test',
  text: 'Hello',
})

if (!result.success) {
  console.error(result.error)
  // "Connection refused" or "Invalid login: 535 Authentication failed"
}

Testing

The package includes 11 tests with mocked transporters:

pnpm vitest run

Tests cover send success, plain text, HTML, multipart, reply-to, channel rejection, missing fields, auth errors, transport errors, and custom message IDs.