www/apps/resources/app/infrastructure-modules/notification/sendgrid/page.mdx
import { Table, Prerequisites } from "docs-ui"
export const metadata = {
title: SendGrid Notification Module Provider,
}
The SendGrid Notification Module Provider integrates SendGrid to send emails to users and customers.
<Note title="Looking for managed email service?">Cloud offers Medusa Emails, a managed email service that allows you to send transactional emails with zero configuration. It is built on top of the Notification Module and provides an easy way to manage email notifications in your Cloud projects with insights and deliverability features.
</Note><Prerequisites items={[ { text: "SendGrid account", link: "https://signup.sendgrid.com", }, { text: "Setup SendGrid single sender", link: "https://docs.sendgrid.com/ui/sending-email/sender-verification", }, { text: "SendGrid API Key", link: "https://docs.sendgrid.com/ui/account-and-settings/api-keys", }, ]} />
Add the module into the providers array of the Notification Module:
Only one provider can be defined for a channel.
</Note>module.exports = defineConfig({
// ...
modules: [
{
resolve: "@medusajs/medusa/notification",
options: {
providers: [
// ...
{
resolve: "@medusajs/medusa/notification-sendgrid",
id: "sendgrid",
options: {
channels: ["email"],
api_key: process.env.SENDGRID_API_KEY,
from: process.env.SENDGRID_FROM,
},
},
],
},
},
],
})
Make sure to add the following environment variables:
SENDGRID_API_KEY=<YOUR_SENDGRID_API_KEY>
SENDGRID_FROM=<YOUR_SENDGRID_FROM>
When you send a notification, you must specify the ID of the template to use in SendGrid.
Refer to this SendGrid documentation guide on how to create templates for your different email types.
This feature is available since Medusa v2.14.0.
</Note>You can use SendGrid's personalizations feature to send customized emails to multiple recipients or include additional SendGrid-specific options.
Personalizations are useful for scenarios like:
Pass the personalizations in the provider_data when creating a notification:
await notificationModuleService.createNotifications({
channel: "email",
template: "custom-template",
provider_data: {
personalizations: [
{
to: [{ email: "[email protected]", name: "John Doe" }],
dynamic_template_data: {
name: "John",
customField: "value1",
},
subject: "Custom Subject for John",
},
{
to: [{ email: "[email protected]", name: "Jane Smith" }],
dynamic_template_data: {
name: "Jane",
customField: "value2",
},
subject: "Custom Subject for Jane",
},
],
},
})
When personalizations are provided, they take precedence over the to field and data field in the notification. Each personalization can include:
to: Array of recipient objects with email and optional namedynamic_template_data: Template variables specific to this recipient groupsubject: Custom subject line for this personalizationcc, bcc, headers, etc.You still need to pass to at the root level of the createNotifications parameter, but it will be ignored when personalizations are provided.
To test the module out, you'll listen to the product.created event and send an email when a product is created.
Create a subscriber at src/subscribers/product-created.ts with the following content:
export const highlights = [
["11", "notificationModuleService", "Resolve the Notification Module."],
["14", "product", "Retrieve the product's details."],
["22", "createNotifications", "Create the notification to be sent."],
[
"24",
'"email"',
"By specifying the email channel, SendGrid will be used to send the notification.",
],
["25", '"product-created"', "The ID of the template defined in SendGrid."],
["26", "data", "The data to pass to the template defined in SendGrid."],
]
import type {
SubscriberArgs,
SubscriberConfig,
} from "@medusajs/framework"
import { Modules } from "@medusajs/framework/utils"
export default async function productCreateHandler({
event: { data },
container,
}: SubscriberArgs<{ id: string }>) {
const notificationModuleService = container.resolve(Modules.NOTIFICATION)
const query = container.resolve("query")
const { data: [product] } = await query.graph({
entity: "product",
fields: ["*"],
filters: {
id: data.id,
},
})
await notificationModuleService.createNotifications({
to: "[email protected]",
channel: "email",
template: "product-created",
data: {
product_title: product.title,
product_image: product.images[0]?.url,
},
})
}
export const config: SubscriberConfig = {
event: "product.created",
}
In this subscriber, you:
createNotifications method of the Notification Module's main service to create a notification to be sent to the specified email. By specifying the email channel, the SendGrid Notification Module Provider is used to send the notification.template property of the createNotifications method's parameter specifies the ID of the template defined in SendGrid.data property allows you to pass data to the template in SendGrid. For example, the product's title and image.Then, start the Medusa application:
npm run dev
And create a product either using the API route or the Medusa Admin. This runs the subscriber and sends an email using SendGrid.
Medusa emits other events that you can handle to send notifications using the SendGrid Notification Module Provider, such as order.placed when an order is placed.
Refer to the Events Reference for a complete list of events emitted by Medusa.
You can also send an email using SendGrid in any workflow. This allows you to send emails within your custom flows.
You can use the sendNotificationsStep in your workflow to send an email using SendGrid.
For example:
import { createWorkflow } from "@medusajs/framework/workflows-sdk"
import {
sendNotificationsStep,
useQueryGraphStep,
} from "@medusajs/medusa/core-flows"
type WorkflowInput = {
id: string
}
export const sendEmailWorkflow = createWorkflow(
"send-email-workflow",
({ id }: WorkflowInput) => {
const { data: products } = useQueryGraphStep({
entity: "product",
fields: [
"*",
"variants.*",
],
filters: {
id,
},
})
sendNotificationsStep({
to: "[email protected]",
channel: "email",
template: "product-created",
data: {
product_title: product[0].title,
product_image: product[0].images[0]?.url,
},
})
}
)
This workflow works similarly to the subscriber. It retrieves the product's details using Query and sends an email using SendGrid (by specifying the email channel) to the [email protected] email.
You can also execute this workflow in a subscriber. For example, you can execute it when a product is created:
import type {
SubscriberArgs,
SubscriberConfig,
} from "@medusajs/framework"
import { Modules } from "@medusajs/framework/utils"
import { sendEmailWorkflow } from "../workflows/send-email"
export default async function productCreateHandler({
event: { data },
container,
}: SubscriberArgs<{ id: string }>) {
await sendEmailWorkflow(container).run({
input: {
id: data.id,
},
})
}
export const config: SubscriberConfig = {
event: "product.created",
}
This subscriber will run every time a product is created, and it will execute the sendEmailWorkflow to send an email using SendGrid.