Build email templates with Unsend
Run the following command to install the plugin with npm:
Or with yarn:
This plugin is only for MedusaJS v2.19.0 or newer.
If you are using MedusaJS v2.4.0 - v2.18.x, please use the v1.0.8 version of this plugin.
If you are using MedusaJS v2.3.1 or older, please use the older version of this plugin.
Add the plugin to your file:
Instead of the path, you can also use the exported constant, which resolves to the same provider:
Add the environment variables to your and file:
If you want to use with the from this README, use the following values:
The plugin automatically loads email templates from the directory in your project root (or a custom directory specified in the configuration). Each template consists of two files:
The email subject is determined in the following order of precedence:
For example, if you have a template named , the subject will fall back to if no other subject is specified.
The template name will be derived from the filename (without the .tsx extension). For example, will be available as the template named .
The JSON file is optional and can contain the following fields:
The email subject is determined in the following order of precedence:
For example, if you have a template named , the subject will fall back to if no other subject is specified.
Attachments are passed as a top-level field of the call. Each attachment requires a and a base64-encoded :
Passing the attachments in is still supported for backwards compatibility. Unsend only accepts and , so any other field of the Medusa attachment (, , ) is ignored.
You must add the following subscribers to the :
You can add the following configuration for Unsend to your :
npm install --save @rokmohar/medusa-plugin-unsendyarn add @rokmohar/medusa-plugin-unsend1import { loadEnv, defineConfig } from '@medusajs/framework/utils'2
3loadEnv(process.env.NODE_ENV || 'development', process.cwd())4
5module.exports = defineConfig({6 // ... other config7 plugins: [8 // ... other plugins9 {10 resolve: '@rokmohar/medusa-plugin-unsend',11 options: {12 // Required options13 url: process.env.UNSEND_URL ?? '',14 api_key: process.env.UNSEND_API_KEY ?? '',15 from: process.env.UNSEND_FROM ?? '',16
17 // Optional configuration18 templateDir: 'custom/templates/path', // Custom template directory19 retry: {20 maxAttempts: 5, // Number of retry attempts for failed sends21 delay: 2000, // Delay between retries in milliseconds22 },23 rateLimit: {24 maxPerMinute: 30, // Maximum emails per minute25 },26 // Environment configurations based on NODE_ENV27 environment: {28 development: {29 // Development-specific overrides30 from: 'dev@example.com',31 rateLimit: {32 maxPerMinute: 25,33 },34 },35 staging: {36 // Staging-specific overrides37 from: 'stage@example.com',38 rateLimit: {39 maxPerMinute: 50,40 },41 },42 production: {43 // Production-specific overrides44 from: 'prod@example.com',45 rateLimit: {46 maxPerMinute: 100,47 },48 },49 },50 },51 },52 ],53 modules: [54 // ... other modules55 {56 resolve: '@medusajs/medusa/notification',57 dependencies: ['unsend'],58 options: {59 providers: [60 // ... other providers61 {62 resolve: '@rokmohar/medusa-plugin-unsend/providers/notification',63 id: 'unsend',64 options: {65 channels: ['email'],66 },67 },68 ],69 },70 },71 ],72})1import { UNSEND_PROVIDER_PATH } from '@rokmohar/medusa-plugin-unsend'2
3// ...4{5 resolve: UNSEND_PROVIDER_PATH,6 id: 'unsend',7 options: {8 channels: ['email'],9 },10}1# ... others vars2UNSEND_URL=3UNSEND_API_KEY=4UNSEND_FROM=1# ... others vars2UNSEND_URL=http://localhost:30003UNSEND_API_KEY=test_1234567894UNSEND_FROM=no-reply@example.org1// src/templates/emails/ProductUpsert.tsx2import React from 'react'3
4const ProductUpsertEmail = (props: any) => {5 return (6 <div>7 <h1>Product Updated</h1>8 <p>Product ID: {props.productId}</p>9 </div>10 )11}12
13// Set email subject14ProductUpsertEmail.Subject = 'Products upserted'15
16export default ProductUpsertEmail1// src/templates/emails/ProductUpsert.json2{3 "version": "1.0.0",4 "subject": "Product upsert",5 "description": "Email template for product updates",6 "tags": ["product", "update"],7 "category": "product-notifications"8}1await notificationModuleService.createNotifications({2 to: 'first.last@example.org',3 channel: 'email',4 template: 'product-upsert',5 attachments: [6 {7 filename: 'invoice.pdf',8 content: base64EncodedContent,9 },10 ],11})1import { SubscriberArgs, SubscriberConfig } from '@medusajs/framework'2import { IProductModuleService } from '@medusajs/framework/types'3import { Modules } from '@medusajs/framework/utils'4import { ProductEvents } from '@medusajs/framework/utils'5import { UnsendService } from '@rokmohar/medusa-plugin-unsend'6
7export default async function productCreatedHandler({ event: { data }, container }: SubscriberArgs<{ id: string }>) {8 const productId = data.id9
10 // Make sure template is registered, before creating email notifications11 const unsendService: UnsendService = container.resolve('unsend')12
13 const notificationModuleService = container.resolve(Modules.NOTIFICATION)14 await notificationModuleService.createNotifications({15 to: 'first.last@example.org',16 channel: 'email',17 // Use name of the registered template18 template: 'product-upsert',19 // Set email subject20 content: {21 subject: 'Product upserted',22 },23 })24}25
26export const config: SubscriberConfig = {27 event: [ProductEvents.PRODUCT_CREATED, ProductEvents.PRODUCT_UPDATED],28}1services:2 # ... other services3
4 unsend:5 image: 'unsend/unsend:latest'6 ports:7 - '3000:3000'