feat: add email notification channel

This commit is contained in:
Kirill
2026-05-18 11:28:46 +05:00
parent 79c85b0a88
commit 8f3d1ae5ef
2 changed files with 68 additions and 8 deletions
+31 -8
View File
@@ -4,14 +4,8 @@ function hasSmtpEnv() {
return Boolean(process.env.SMTP_HOST && process.env.SMTP_PORT && process.env.SMTP_USER && process.env.SMTP_PASS) return Boolean(process.env.SMTP_HOST && process.env.SMTP_PORT && process.env.SMTP_USER && process.env.SMTP_PASS)
} }
export async function sendLoginCodeEmail({ to, code }) { function createTransporter() {
if (!hasSmtpEnv()) { return nodemailer.createTransport({
// dev fallback
console.log(`[DEV] login code for ${to}: ${code}`)
return
}
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST, host: process.env.SMTP_HOST,
port: Number(process.env.SMTP_PORT), port: Number(process.env.SMTP_PORT),
secure: process.env.SMTP_SECURE === 'true', secure: process.env.SMTP_SECURE === 'true',
@@ -20,7 +14,15 @@ export async function sendLoginCodeEmail({ to, code }) {
pass: process.env.SMTP_PASS, pass: process.env.SMTP_PASS,
}, },
}) })
}
export async function sendLoginCodeEmail({ to, code }) {
if (!hasSmtpEnv()) {
console.log(`[DEV] login code for ${to}: ${code}`)
return
}
const transporter = createTransporter()
const from = process.env.MAIL_FROM || process.env.SMTP_USER const from = process.env.MAIL_FROM || process.env.SMTP_USER
await transporter.sendMail({ await transporter.sendMail({
@@ -31,3 +33,24 @@ export async function sendLoginCodeEmail({ to, code }) {
}) })
} }
export async function sendNotificationEmail({ to, subject, html }) {
if (!hasSmtpEnv()) {
console.log(`[DEV] notification email to ${to}: ${subject}`)
return { success: true }
}
try {
const transporter = createTransporter()
const from = process.env.MAIL_FROM || process.env.SMTP_USER
await transporter.sendMail({
from,
to,
subject,
html,
})
return { success: true }
} catch (err) {
return { success: false, error: err.message }
}
}
@@ -0,0 +1,37 @@
// server/src/lib/notifications/channels/email-channel.js
import { sendNotificationEmail } from '../../email.js'
import {
renderOrderCreatedEmail,
renderOrderStatusChangedEmail,
renderOrderMessageEmail,
renderPaymentStatusChangedEmail,
renderAdminOrderCreatedEmail,
renderAdminNewReviewEmail,
renderAuthCodeEmail,
} from '../templates/email-templates.js'
const templateRenderers = {
'order:created': renderOrderCreatedEmail,
'order:statusChanged': renderOrderStatusChangedEmail,
'orderMessage:adminReply': renderOrderMessageEmail,
'payment:statusChanged': renderPaymentStatusChangedEmail,
'order:created:admin': renderAdminOrderCreatedEmail,
'orderMessage:sent': renderOrderMessageEmail,
'review:created': renderAdminNewReviewEmail,
'auth:codeRequested': renderAuthCodeEmail,
}
export const emailChannel = {
name: 'email',
async send({ recipient, eventType, payload }) {
const renderer = templateRenderers[eventType]
if (!renderer) {
return { success: false, error: `No email template for event: ${eventType}` }
}
const { subject, html } = renderer(payload)
const result = await sendNotificationEmail({ to: recipient, subject, html })
return result
},
}