fix the email sent
This commit is contained in:
+1
-1
@@ -48,7 +48,7 @@ NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME=your-cloud-name
|
||||
|
||||
# ─── Resend (Email) ────────────────────────────────────────────
|
||||
RESEND_API_KEY=re_...
|
||||
EMAIL_FROM=noreply@rentaldrivego.com
|
||||
EMAIL_FROM=rentaldrivego@gmail.com
|
||||
EMAIL_FROM_NAME=RentalDriveGo
|
||||
|
||||
# ─── Twilio (SMS + WhatsApp) ───────────────────────────────────
|
||||
|
||||
@@ -5,11 +5,15 @@ import { prisma } from '../lib/prisma'
|
||||
import { redis } from '../lib/redis'
|
||||
import { NotificationType, NotificationChannel } from '@rentaldrivego/database'
|
||||
|
||||
const resend =
|
||||
process.env.RESEND_API_KEY && process.env.RESEND_API_KEY !== 're_...'
|
||||
? new Resend(process.env.RESEND_API_KEY)
|
||||
const resendApiKey =
|
||||
process.env.RESEND_API_KEY &&
|
||||
process.env.RESEND_API_KEY !== 're_...' &&
|
||||
process.env.RESEND_API_KEY.startsWith('re_')
|
||||
? process.env.RESEND_API_KEY
|
||||
: null
|
||||
|
||||
const resend = resendApiKey ? new Resend(resendApiKey) : null
|
||||
|
||||
const emailFromAddress =
|
||||
process.env.EMAIL_FROM && process.env.EMAIL_FROM !== 'noreply@example.com'
|
||||
? process.env.EMAIL_FROM
|
||||
@@ -125,6 +129,85 @@ function renderEmailHtml(body: string) {
|
||||
.join('')
|
||||
}
|
||||
|
||||
function resolveSmtpReplyTo() {
|
||||
if (!process.env.MAIL_REPLY_TO_ADDRESS || process.env.MAIL_REPLY_TO_ADDRESS.includes('${')) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
if (process.env.MAIL_REPLY_TO_NAME && !process.env.MAIL_REPLY_TO_NAME.includes('${')) {
|
||||
return `${process.env.MAIL_REPLY_TO_NAME} <${process.env.MAIL_REPLY_TO_ADDRESS}>`
|
||||
}
|
||||
|
||||
return process.env.MAIL_REPLY_TO_ADDRESS
|
||||
}
|
||||
|
||||
async function sendEmailWithProviders(opts: {
|
||||
to: string
|
||||
subject: string
|
||||
html: string
|
||||
text: string
|
||||
}) {
|
||||
const errors: string[] = []
|
||||
|
||||
if (resend) {
|
||||
try {
|
||||
if (!emailFromAddress || !emailFromName) {
|
||||
throw new Error('Email sender identity is not configured')
|
||||
}
|
||||
|
||||
const { data, error } = await resend.emails.send({
|
||||
from: `${emailFromName} <${emailFromAddress}>`,
|
||||
to: opts.to,
|
||||
subject: opts.subject,
|
||||
html: opts.html,
|
||||
text: opts.text,
|
||||
})
|
||||
|
||||
if (error) {
|
||||
throw new Error(error.message)
|
||||
}
|
||||
|
||||
return {
|
||||
provider: 'resend' as const,
|
||||
providerMessageId: data?.id ?? null,
|
||||
}
|
||||
} catch (err: any) {
|
||||
errors.push(`Resend: ${err?.message ?? String(err)}`)
|
||||
console.warn('[Notifications] Resend delivery failed, falling back if possible:', err?.message ?? String(err))
|
||||
}
|
||||
}
|
||||
|
||||
if (smtpTransport) {
|
||||
try {
|
||||
if (!smtpFromAddress) {
|
||||
throw new Error('SMTP sender identity is not configured')
|
||||
}
|
||||
|
||||
const info = await smtpTransport.sendMail({
|
||||
from: smtpFromName ? `${smtpFromName} <${smtpFromAddress}>` : smtpFromAddress,
|
||||
to: opts.to,
|
||||
subject: opts.subject,
|
||||
html: opts.html,
|
||||
text: opts.text,
|
||||
replyTo: resolveSmtpReplyTo(),
|
||||
})
|
||||
|
||||
return {
|
||||
provider: 'smtp' as const,
|
||||
providerMessageId: info.messageId ?? null,
|
||||
}
|
||||
} catch (err: any) {
|
||||
errors.push(`SMTP: ${err?.message ?? String(err)}`)
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.length) {
|
||||
throw new Error(errors.join(' | '))
|
||||
}
|
||||
|
||||
throw new Error('No email provider is configured')
|
||||
}
|
||||
|
||||
export async function sendNotification(opts: SendNotificationOptions) {
|
||||
const results: Array<{ channel: NotificationChannel; success: boolean; error?: string }> = []
|
||||
|
||||
@@ -148,44 +231,14 @@ export async function sendNotification(opts: SendNotificationOptions) {
|
||||
let success = false
|
||||
|
||||
if (channel === 'EMAIL' && opts.email) {
|
||||
if (resend) {
|
||||
if (!emailFromAddress || !emailFromName) {
|
||||
throw new Error('Email sender identity is not configured')
|
||||
}
|
||||
const { data, error } = await resend.emails.send({
|
||||
from: `${emailFromName} <${emailFromAddress}>`,
|
||||
to: opts.email,
|
||||
subject: opts.title,
|
||||
html: renderEmailHtml(opts.body),
|
||||
text: opts.body,
|
||||
})
|
||||
if (error) {
|
||||
throw new Error(error.message)
|
||||
}
|
||||
providerMessageId = data?.id ?? null
|
||||
success = true
|
||||
} else if (smtpTransport) {
|
||||
if (!smtpFromAddress) {
|
||||
throw new Error('SMTP sender identity is not configured')
|
||||
}
|
||||
const info = await smtpTransport.sendMail({
|
||||
from: smtpFromName ? `${smtpFromName} <${smtpFromAddress}>` : smtpFromAddress,
|
||||
to: opts.email,
|
||||
subject: opts.title,
|
||||
html: renderEmailHtml(opts.body),
|
||||
text: opts.body,
|
||||
replyTo:
|
||||
process.env.MAIL_REPLY_TO_ADDRESS && !process.env.MAIL_REPLY_TO_ADDRESS.includes('${')
|
||||
? process.env.MAIL_REPLY_TO_NAME && !process.env.MAIL_REPLY_TO_NAME.includes('${')
|
||||
? `${process.env.MAIL_REPLY_TO_NAME} <${process.env.MAIL_REPLY_TO_ADDRESS}>`
|
||||
: process.env.MAIL_REPLY_TO_ADDRESS
|
||||
: undefined,
|
||||
})
|
||||
providerMessageId = info.messageId ?? null
|
||||
success = true
|
||||
} else {
|
||||
throw new Error('No email provider is configured')
|
||||
}
|
||||
const emailResult = await sendEmailWithProviders({
|
||||
to: opts.email,
|
||||
subject: opts.title,
|
||||
html: renderEmailHtml(opts.body),
|
||||
text: opts.body,
|
||||
})
|
||||
providerMessageId = emailResult.providerMessageId
|
||||
success = true
|
||||
}
|
||||
|
||||
if (channel === 'SMS' && opts.phone) {
|
||||
@@ -259,30 +312,5 @@ export async function sendTransactionalEmail(opts: {
|
||||
html: string
|
||||
text: string
|
||||
}) {
|
||||
if (resend) {
|
||||
if (!emailFromAddress || !emailFromName) throw new Error('Email sender identity is not configured')
|
||||
const { error } = await resend.emails.send({
|
||||
from: `${emailFromName} <${emailFromAddress}>`,
|
||||
to: opts.to,
|
||||
subject: opts.subject,
|
||||
html: opts.html,
|
||||
text: opts.text,
|
||||
})
|
||||
if (error) throw new Error(error.message)
|
||||
return
|
||||
}
|
||||
|
||||
if (smtpTransport) {
|
||||
if (!smtpFromAddress) throw new Error('SMTP sender identity is not configured')
|
||||
await smtpTransport.sendMail({
|
||||
from: smtpFromName ? `${smtpFromName} <${smtpFromAddress}>` : smtpFromAddress,
|
||||
to: opts.to,
|
||||
subject: opts.subject,
|
||||
html: opts.html,
|
||||
text: opts.text,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
throw new Error('No email provider is configured')
|
||||
await sendEmailWithProviders(opts)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user