Files
medusa-store/packages/modules/providers/notification-sendgrid/src/services/sendgrid.ts
Christian a0b747e117 feat: allow html content for notifications (#9613)
* feat: allow passing provider specific metadata to notification module

* changed providerContext to snake cased

* rename provider_context to content
2024-10-18 11:36:22 +02:00

108 lines
2.9 KiB
TypeScript

import {
Logger,
NotificationTypes,
SendgridNotificationServiceOptions,
} from "@medusajs/framework/types"
import {
AbstractNotificationProviderService,
MedusaError,
} from "@medusajs/framework/utils"
import sendgrid from "@sendgrid/mail"
type InjectedDependencies = {
logger: Logger
}
type MailContent = Required<Omit<NotificationTypes.NotificationContent, "text">>
interface SendgridServiceConfig {
apiKey: string
from: string
}
export class SendgridNotificationService extends AbstractNotificationProviderService {
static identifier = "notification-sendgrid"
protected config_: SendgridServiceConfig
protected logger_: Logger
constructor(
{ logger }: InjectedDependencies,
options: SendgridNotificationServiceOptions
) {
super()
this.config_ = {
apiKey: options.api_key,
from: options.from,
}
this.logger_ = logger
sendgrid.setApiKey(this.config_.apiKey)
}
async send(
notification: NotificationTypes.ProviderSendNotificationDTO
): Promise<NotificationTypes.ProviderSendNotificationResultsDTO> {
if (!notification) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`No notification information provided`
)
}
const attachments = Array.isArray(notification.attachments)
? notification.attachments.map((attachment) => ({
content: attachment.content, // Base64 encoded string of the file
filename: attachment.filename,
content_type: attachment.content_type, // MIME type (e.g., 'application/pdf')
disposition: attachment.disposition ?? "attachment", // Default to 'attachment'
id: attachment.id ?? undefined, // Optional: unique identifier for inline attachments
}))
: undefined
const from = notification.from?.trim() || this.config_.from
let mailContent:
| MailContent
| {
templateId: string
}
if ("content" in notification && !!notification.content) {
mailContent = {
subject: notification.content?.subject,
html: notification.content?.html,
} as MailContent
} else {
// we can't mix html and templates for sendgrid
mailContent = {
templateId: notification.template,
}
}
const message: sendgrid.MailDataRequired = {
to: notification.to,
from: from,
dynamicTemplateData: notification.data as
| { [key: string]: any }
| undefined,
attachments: attachments,
...mailContent,
}
try {
// Unfortunately we don't get anything useful back in the response
await sendgrid.send(message)
return {}
} catch (error) {
const errorCode = error.code
const responseError = error.response?.body?.errors?.[0]
throw new MedusaError(
MedusaError.Types.UNEXPECTED_STATE,
`Failed to send email: ${errorCode} - ${
responseError?.message ?? "unknown error"
}`
)
}
}
}