SES Notifications
Notification provider for Medusa for sending email notifications via AWS SES (Simple Email Service).
Features
Section titled “Features”- Uses AWS api v3, SESv2Client
- Supports attachments up to 40mb
Installation
Section titled “Installation”Inside your medusa backend root folder:
yarn add medusa-plugin-sesReplace “yarn add” with the correct command for your package manager if you are using (for example) npm, pnpm, or bun.
Configuration
Section titled “Configuration”Enable in your medusa-config.js file. Example:
module.exports = defineConfig({ //... other config modules: [ { resolve: '@medusajs/medusa/notification', options: { providers: [ { resolve: 'medusa-plugin-ses', id: 'ses', options: { channels: ['email'], sesClientConfig: { region: process.env.SES_REGION, credentials: { accessKeyId: process.env.SES_ACCESS_KEY_ID, secretAccessKey: process.env.SES_SECRET_ACCESS_KEY } }, from: process.env.SES_FROM } } ] } } // ... other modules ]})Example Subscriber
Section titled “Example Subscriber”import type { SubscriberArgs, SubscriberConfig } from '@medusajs/framework'import { inviteUserWorkflow } from '../workflows/notifications/invite-user'
export const config: SubscriberConfig = { event: [ 'invite.created' // other events ]}
type EventPayloadWithId = { id: string }
type EventPayload = EventPayloadWithId | EventPayloadForWhatever | EventPayloadSomethingElse
export default async function emailDispatchHandler({ event: { data, name }, container}: SubscriberArgs<EventPayload>) { switch (name) { case 'invite.created': await inviteUserWorkflow(container).run({ input: (data as EventPayloadWithId).id }) break // ... other events default: break }}Example Workflow
Section titled “Example Workflow”You can use whatever templating flow you want to generate the HTML. This example uses React Email.
import { createWorkflow, WorkflowResponse, createStep, StepResponse} from '@medusajs/framework/workflows-sdk'import { ContainerRegistrationKeys, Modules } from '@medusajs/framework/utils'import { CreateNotificationDTO } from '@medusajs/framework/types'import { sendNotificationsStep } from '@medusajs/medusa/core-flows'import { render, pretty } from '@react-email/render'import getInviteTemplate from '../../templates/invite-user'import { getMedusaAdminUrl, getMedusaStorefrontUrl } from '../../utils'
const prepareInviteUserNotificationStep = createStep( 'prepare-invite-user-notification', async (id: string, { container }) => { const query = container.resolve(ContainerRegistrationKeys.QUERY)
const { data: [store] } = await query.graph({ entity: 'store', fields: ['name'] })
const { data: [invite] } = await query.graph({ entity: 'invite', fields: ['email', 'token'], filters: { id } })
const config = container.resolve(ContainerRegistrationKeys.CONFIG_MODULE) const adminUrl = getMedusaAdminUrl(config) const inviteUrl = `${adminUrl}/invite?token=${invite.token}`
const html = await pretty( await render( getInviteTemplate({ inviteUrl, storeName: store.name }) ) )
return new StepResponse([ { channel: 'email', to: invite.email, content: { html, subject: `You've been invited to join ${store.name}` } } ] as CreateNotificationDTO[]) })
export const sendNotificationStep = createStep( 'send-invite-admin-notification', async (notification: CreateNotificationDTO, { container }) => { const notificationModule = container.resolve(Modules.NOTIFICATION) await notificationModule.createNotifications(notification) })
export const inviteUserWorkflow = createWorkflow('invite-user-workflow', (id: string) => { const notifications = prepareInviteUserNotificationStep(id) sendNotificationsStep(notifications) return new WorkflowResponse(void 0)})