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 };