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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@bkosm/medusa-notification-ses

v1.2.0

Published

AWS SES notification provider for Medusa

Readme

Medusa Provider - Notification SES

Send emails from your Medusa application through AWS Simple Email Service. Supports SES sandbox, attachments and handlebars templates.

Installation

npm install @bkosm/medusa-notification-ses

Configuration

Register the provider in your Medusa project:

import { LocalTemplateProvider } from '@bkosm/medusa-notification-ses/template-providers'

export default defineConfig({
  modules: [
    {
      resolve: "@medusajs/medusa/notification",
      options: {
        providers: [
          {
            resolve: "@bkosm/medusa-notification-ses",
            id: "notification-ses",
            options: {
              channels: ["email"],
              // Nodemailer send options, passed on each sent message
              nodemailerConfig: {
                from: "[email protected]",
              },
              // Use a template provider for email templates (see below)
              templateProvider: new LocalTemplateProvider("./email-templates"),
              // Enables SES sandbox mode with automatic email address verification
              sandboxConfig: {},
            },
          },
        ],
      },
    },
  ],
});

See the example Medusa app how it looks in practice.

SES Sandbox Mode

When using AWS SES in sandbox mode (common in development/staging environments), emails can only be sent to verified email addresses. This provider includes automatic email verification support that integrates seamlessly with Medusa's workflow retry mechanisms.

Configuration

Enable sandbox mode by defining the sandboxConfig option.

How Sandbox Mode Works

  1. Address Verification Check: Before sending emails, all recipient addresses (to, cc, bcc) are checked against SES verification status
  2. Automatic Verification: Unverified addresses automatically trigger verification emails via VerifyEmailIdentity API
  3. Retryable Errors: Throws MedusaError.Types.INVALID_DATA for pending verifications, signaling Medusa workflows to retry

To re-request verification on every send, define sandboxConfig.verifyOnEachSend: false in the configuration.

Template Providers

The provider has built-in support for handlebars templates through a pluggable provider system. Two providers are included: LocalTemplateProvider and S3TemplateProvider.

The template system uses a directory-based structure where each template ID maps to a folder containing:

  1. handlebars.template.html - Pre-compiled MJML template with Handlebars placeholders
  2. data.schema.json - JSON schema for validating template data

LocalTemplateProvider

This provider loads templates from the local filesystem.

Configuration

import { LocalTemplateProvider } from '@bkosm/medusa-notification-ses/template-providers'

// ...
  // Path to your templates directory
  templateProvider: new LocalTemplateProvider("./email-templates"),
// ...

Example template setup

With the configuration above, your directory structure should look like this:

email-templates/welcome-email/handlebars.template.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Welcome to {{companyName}}</title>
  </head>
  <body>
    <h1>Welcome {{firstName}}!</h1>
    <p>
      Thank you for joining {{companyName}}. We're excited to have you on board.
    </p>
    <p>Your email address is: {{email}}</p>
    {{#if hasPromo}}
    <p>
      Use promo code <strong>{{promoCode}}</strong> for 20% off your first
      order!
    </p>
    {{/if}}
    <p>Best regards,<br />The {{companyName}} Team</p>
  </body>
</html>
email-templates/welcome-email/data.schema.json
{
  "type": "object",
  "properties": {
    "firstName": {
      "type": "string",
      "minLength": 1
    },
    "email": {
      "type": "string",
      "format": "email"
    },
    "companyName": {
      "type": "string",
      "minLength": 1
    },
    "hasPromo": {
      "type": "boolean"
    },
    "promoCode": {
      "type": "string"
    }
  },
  "required": ["firstName", "email", "companyName"],
  "additionalProperties": false,
  "if": {
    "properties": {
      "hasPromo": { "const": true }
    }
  },
  "then": {
    "required": ["promoCode"]
  }
}

S3TemplateProvider

This provider loads templates from an S3 bucket. This is useful for production environments where you might want to manage templates centrally without deploying new code.

Configuration

import { S3TemplateProvider } from '@bkosm/medusa-notification-ses/template-providers'

// ...
  templateProvider: new S3TemplateProvider({
    clientConfig: { region: 'us-east-1' }, // AWS S3 client config
    bucket: 'your-s3-bucket-name',
    prefix: 'email-templates/', // Optional prefix for your templates in the bucket
  }),
// ...

The S3 bucket should have the same directory structure as the local provider. For example: s3://your-s3-bucket-name/email-templates/welcome-email/handlebars.template.html.

Template Processing Flow

  1. Startup: Templates are loaded from the configured provider and validated when the service initializes.
  2. Runtime: When sending emails with templates:
    • Template ID is validated against available templates.
    • Data is validated against the template's JSON schema.
    • Handlebars template is rendered with provided data.
    • Rendered HTML replaces the notification's HTML content.
  3. Caching: Templates are cached in memory for optimal performance.

Usage

Basic Email Sending

Use Medusa's notification module to send emails with raw HTML:

import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http";
import { INotificationModuleService } from "@medusajs/framework/types";
import { Modules } from "@medusajs/framework/utils";

export async function POST(req: MedusaRequest, res: MedusaResponse) {
  const notificationService: INotificationModuleService = req.scope.resolve(
    Modules.NOTIFICATION
  );

  await notificationService.createNotifications({
    to: "[email protected]",
    channel: "email",
    content: {
      subject: "Order Confirmed",
      text: "Your order has been confirmed",
      html: "<p>Your order has been confirmed</p>",
    },
    attachments: [
      {
        filename: "receipt.pdf",
        content: pdfBufferBase64String,
        content_type: "application/pdf",
      },
    ],
  });

  res.json({ success: true });
}

Template-Based Email Sending

Send emails using pre-defined templates with dynamic data:

await notificationService.createNotifications({
  to: "[email protected]",
  channel: "email",
  template: "order-confirmation",
  data: {
    customerName: "John Doe",
    orderNumber: "ORD-123",
    items: [
      { name: "Product A", quantity: 2, price: 29.99 },
      { name: "Product B", quantity: 1, price: 15.5 },
    ],
    total: 75.48,
    deliveryDate: "2024-01-15",
  },
  content: {
    subject: "Order Confirmation #ORD-123",
  },
});

Configuration Options

sesClientConfig

AWS SES client configuration (optional).

See the full set of options here: https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-ses/Interface/SESClientConfig

nodemailerConfig

Nodemailer send options (from is required).

See the full set of options here: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/nodemailer/v3/index.d.ts#L104-L177 Only subject, text and html are substituted for runtime values at all times. Fields like to, attachments are concatenated with runtime values.

templateProvider

An instance of a template provider (optional). If not provided, the templating feature is disabled. This provider is responsible for loading and caching templates.

  • LocalTemplateProvider: Loads templates from the local filesystem.
    • directory: path to a local directory with expected templates structure
  • S3TemplateProvider: Loads templates from an S3 bucket.
    • clientConfig: AWS S3 client configuration.
    • bucket: The S3 bucket name.
    • prefix: An optional key prefix for the templates within the bucket.

sandboxConfig

SES sandbox mode configuration (optional):

  • verifyOnEachSend (boolean, default: false) - When true, bypasses verification cache and checks SES on every send

Disables sandbox feature if the object is not set (will fail on unverified addresses at runtime if the account uses SES sandbox).