90 lines
2.3 KiB
TypeScript
90 lines
2.3 KiB
TypeScript
// utils/mail.ts – simple wrapper around nodemailer
|
||
import nodemailer from 'nodemailer';
|
||
import { createAdminClient } from '@/lib/supabase/admin';
|
||
|
||
/**
|
||
* Send an email using database-configured SMTP settings (or environment variable fallback).
|
||
* If SMTP is not configured, logs a warning and gracefully skips sending instead of throwing.
|
||
* @param to Recipient address
|
||
* @param subject Subject line
|
||
* @param text Plain‑text body
|
||
* @param html Optional HTML body
|
||
*/
|
||
export async function sendMail({
|
||
to,
|
||
subject,
|
||
text,
|
||
html,
|
||
attachments,
|
||
}: {
|
||
to: string;
|
||
subject: string;
|
||
text: string;
|
||
html?: string;
|
||
attachments?: {
|
||
filename: string;
|
||
content: Buffer | string;
|
||
contentType?: string;
|
||
}[];
|
||
}) {
|
||
try {
|
||
// Query custom SMTP settings from database
|
||
const supabase = createAdminClient();
|
||
const { data: dbSettings } = await supabase
|
||
.from('settings')
|
||
.select('*')
|
||
.eq('id', 'smtp')
|
||
.maybeSingle();
|
||
|
||
// Resolve config from DB or environment variables
|
||
const host = dbSettings?.host || process.env.SMTP_HOST;
|
||
const port = dbSettings?.port
|
||
? Number(dbSettings.port)
|
||
: process.env.SMTP_PORT
|
||
? Number(process.env.SMTP_PORT)
|
||
: 587;
|
||
const secure = dbSettings
|
||
? !!dbSettings.secure
|
||
: process.env.SMTP_SECURE === 'true' || process.env.SMTP_SECURE === '1';
|
||
const user = dbSettings?.user || process.env.SMTP_USER;
|
||
const pass = dbSettings?.pass || process.env.SMTP_PASS;
|
||
|
||
if (!host || !user) {
|
||
console.warn(
|
||
`SMTP is not configured (missing host/user). E-Mail to "${to}" skipped.`
|
||
);
|
||
return { messageId: 'skipped-no-smtp-config', skipped: true };
|
||
}
|
||
|
||
// Create transporter dynamically on send request
|
||
const transporter = nodemailer.createTransport({
|
||
host,
|
||
port,
|
||
secure,
|
||
auth: {
|
||
user,
|
||
pass: pass || '',
|
||
},
|
||
tls: {
|
||
rejectUnauthorized: false,
|
||
},
|
||
});
|
||
|
||
const fromAddress = process.env.SMTP_FROM || user;
|
||
|
||
const info = await transporter.sendMail({
|
||
from: fromAddress,
|
||
to,
|
||
subject,
|
||
text,
|
||
html,
|
||
attachments,
|
||
});
|
||
|
||
return info;
|
||
} catch (err: any) {
|
||
console.error(`Failed to send email to "${to}":`, err.message || err);
|
||
return { messageId: 'failed-smtp-error', error: err.message || err };
|
||
}
|
||
}
|