91 lines
2.8 KiB
JavaScript
91 lines
2.8 KiB
JavaScript
// ═══════════════════════════════════════
|
|
// 铸渊开发Agent · 邮件通知模块
|
|
// QQ邮箱 SMTP · smtp.qq.com:465
|
|
// ═══════════════════════════════════════
|
|
|
|
const nodemailer = require("nodemailer");
|
|
|
|
let transporter = null;
|
|
|
|
function getTransporter() {
|
|
if (transporter) return transporter;
|
|
|
|
const user = process.env.ZY_SMTP_USER;
|
|
const pass = process.env.ZY_SMTP_PASS;
|
|
|
|
if (!user || !pass) {
|
|
console.warn("[EmailNotify] ZY_SMTP_USER 或 ZY_SMTP_PASS 未配置,邮件功能不可用");
|
|
return null;
|
|
}
|
|
|
|
transporter = nodemailer.createTransport({
|
|
host: "smtp.qq.com",
|
|
port: 465,
|
|
secure: true,
|
|
auth: { user, pass }
|
|
});
|
|
|
|
console.log("[EmailNotify] SMTP 已连接 · " + user);
|
|
return transporter;
|
|
}
|
|
|
|
/**
|
|
* 发送通知邮件
|
|
* @param {string} to - 收件人邮箱
|
|
* @param {string} planId - 规划ID
|
|
* @param {string} status - 状态: started / completed / failed
|
|
* @param {object} summary - { task_count, done_count, failed_count, errors, log_url }
|
|
*/
|
|
async function sendNotification(to, planId, status, summary = {}) {
|
|
const t = getTransporter();
|
|
if (!t) return { sent: false, reason: "SMTP未配置" };
|
|
|
|
const statusEmoji = { started: "🚀", completed: "✅", failed: "❌" };
|
|
const emoji = statusEmoji[status] || "📋";
|
|
|
|
const subject = emoji + " 铸渊DevAgent · " + planId + " · " + status;
|
|
|
|
const lines = [
|
|
"铸渊开发Agent · 任务执行报告",
|
|
"══════════════════════════════",
|
|
"",
|
|
"规划ID: " + planId,
|
|
"状态: " + status,
|
|
"时间: " + new Date().toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" }),
|
|
"",
|
|
];
|
|
|
|
if (summary.task_count !== undefined) {
|
|
lines.push("任务总数: " + summary.task_count);
|
|
lines.push("已完成: " + (summary.done_count || 0));
|
|
lines.push("失败: " + (summary.failed_count || 0));
|
|
}
|
|
|
|
if (summary.errors && summary.errors.length > 0) {
|
|
lines.push("", "错误详情:");
|
|
summary.errors.forEach(function(e, i) {
|
|
lines.push(" " + (i + 1) + ". " + e);
|
|
});
|
|
}
|
|
|
|
lines.push("", "══════════════════════════════", "铸渊 ICE-GL-ZY001 · 国作登字-2026-A-00037559");
|
|
|
|
const mailOptions = {
|
|
from: process.env.ZY_SMTP_USER,
|
|
to: to,
|
|
subject: subject,
|
|
text: lines.join("\n")
|
|
};
|
|
|
|
try {
|
|
const info = await t.sendMail(mailOptions);
|
|
console.log("[EmailNotify] 邮件已发送: " + info.messageId);
|
|
return { sent: true, messageId: info.messageId };
|
|
} catch (err) {
|
|
console.error("[EmailNotify] 发送失败:", err.message);
|
|
return { sent: false, reason: err.message };
|
|
}
|
|
}
|
|
|
|
module.exports = { sendNotification };
|