import nodemailer from "nodemailer"; import type { Transporter } from "nodemailer"; import { getGlobalConfigValue } from "#server/service/config"; import log4js from "logger"; const logger = log4js.getLogger("email"); export interface SmtpConfig { host: string; port: number; user: string; pass: string; from: string; secure: boolean; } export async function getSmtpConfig(): Promise { const [host, port, user, pass, from, secure] = await Promise.all([ getGlobalConfigValue("smtpHost"), getGlobalConfigValue("smtpPort"), getGlobalConfigValue("smtpUser"), getGlobalConfigValue("smtpPass"), getGlobalConfigValue("smtpFrom"), getGlobalConfigValue("smtpSecure"), ]); return { host, port, user, pass, from, secure }; } export function createTransporter(config: SmtpConfig): Transporter { return nodemailer.createTransport({ host: config.host, port: config.port, secure: config.secure, auth: config.user ? { user: config.user, pass: config.pass } : undefined, }); } export async function testSmtpConnection(config: SmtpConfig): Promise<{ success: boolean; message: string }> { if (!config.host || !config.port) { return { success: false, message: "SMTP 服务器地址和端口未配置" }; } try { const transporter = createTransporter(config); await transporter.verify(); return { success: true, message: "SMTP 连接测试成功" }; } catch (err: unknown) { const message = err instanceof Error ? err.message : "未知错误"; logger.error("SMTP connection test failed: %s", message); return { success: false, message: `SMTP 连接失败: ${message}` }; } } export interface SendMailOptions { to: string | string[]; subject: string; text?: string; html?: string; } export async function sendMail(options: SendMailOptions): Promise<{ success: boolean; message: string }> { const config = await getSmtpConfig(); if (!config.host || !config.port) { return { success: false, message: "SMTP 服务器未配置,请先在系统设置中配置邮件服务" }; } if (!config.from) { return { success: false, message: "发件人地址未配置" }; } try { const transporter = createTransporter(config); const info = await transporter.sendMail({ from: config.from, to: Array.isArray(options.to) ? options.to.join(", ") : options.to, subject: options.subject, text: options.text, html: options.html, }); logger.info("Email sent to %s, messageId: %s", options.to, info.messageId); return { success: true, message: "邮件发送成功" }; } catch (err: unknown) { const message = err instanceof Error ? err.message : "未知错误"; logger.error("Failed to send email to %s: %s", options.to, message); return { success: false, message: `邮件发送失败: ${message}` }; } }