You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
89 lines
2.8 KiB
89 lines
2.8 KiB
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<SmtpConfig> {
|
|
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}` };
|
|
}
|
|
}
|
|
|