feat: 邮件中枢增加单独发送/一键发送双模式 + 用户邮箱列表 + 详细功能清单
- email-hub.js: 新增 update-notify-single 单用户发送命令 - email-hub.js: 新增 list-emails 列出所有用户邮箱 - email-hub.js: 更新通知邮件支持分号分隔多条内容自动渲染功能清单 - infinity-evolution.yml: 新增 send-update-notify-single 和 list-user-emails 工作流选项 - infinity-evolution.yml: 新增 email 输入字段供选择目标邮箱 Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/90aad306-0211-4a5b-b8b2-a130ae758c92 Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com>
This commit is contained in:
parent
5e96f19350
commit
809f65c9ac
|
|
@ -31,10 +31,16 @@ on:
|
||||||
- status
|
- status
|
||||||
- send-monthly-reset
|
- send-monthly-reset
|
||||||
- send-update-notify
|
- send-update-notify
|
||||||
|
- send-update-notify-single
|
||||||
- send-traffic-warn
|
- send-traffic-warn
|
||||||
|
- list-user-emails
|
||||||
default: 'status'
|
default: 'status'
|
||||||
message:
|
message:
|
||||||
description: '附加消息 (update-notify描述 / traffic-warn百分比)'
|
description: '附加消息 (update-notify描述 / traffic-warn百分比) · 描述支持分号分隔多条内容'
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
email:
|
||||||
|
description: '目标邮箱 (send-update-notify-single时需要 · 可先用list-user-emails查看)'
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
|
|
@ -67,6 +73,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
ACTION: ${{ github.event.inputs.action || 'monthly-evolution' }}
|
ACTION: ${{ github.event.inputs.action || 'monthly-evolution' }}
|
||||||
MESSAGE: ${{ github.event.inputs.message || '' }}
|
MESSAGE: ${{ github.event.inputs.message || '' }}
|
||||||
|
EMAIL: ${{ github.event.inputs.email || '' }}
|
||||||
ZY_SMTP_USER: ${{ secrets.ZY_SMTP_USER }}
|
ZY_SMTP_USER: ${{ secrets.ZY_SMTP_USER }}
|
||||||
ZY_SMTP_PASS: ${{ secrets.ZY_SMTP_PASS }}
|
ZY_SMTP_PASS: ${{ secrets.ZY_SMTP_PASS }}
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -143,7 +150,7 @@ jobs:
|
||||||
;;
|
;;
|
||||||
|
|
||||||
send-update-notify)
|
send-update-notify)
|
||||||
echo "发送更新通知..."
|
echo "一键发送更新通知 (全部用户)..."
|
||||||
$SSH_CMD "
|
$SSH_CMD "
|
||||||
cd $PROXY_DIR
|
cd $PROXY_DIR
|
||||||
export ZY_SMTP_USER='$ZY_SMTP_USER'
|
export ZY_SMTP_USER='$ZY_SMTP_USER'
|
||||||
|
|
@ -152,6 +159,21 @@ jobs:
|
||||||
"
|
"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
send-update-notify-single)
|
||||||
|
if [ -z "$EMAIL" ]; then
|
||||||
|
echo "❌ 请提供目标邮箱 (email字段)"
|
||||||
|
echo "💡 可先使用 list-user-emails 查看所有用户邮箱"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "单独发送更新通知给: $EMAIL ..."
|
||||||
|
$SSH_CMD "
|
||||||
|
cd $PROXY_DIR
|
||||||
|
export ZY_SMTP_USER='$ZY_SMTP_USER'
|
||||||
|
export ZY_SMTP_PASS='$ZY_SMTP_PASS'
|
||||||
|
node service/email-hub.js update-notify-single '$EMAIL' '${MESSAGE:-系统已更新}'
|
||||||
|
"
|
||||||
|
;;
|
||||||
|
|
||||||
send-traffic-warn)
|
send-traffic-warn)
|
||||||
echo "发送流量预警..."
|
echo "发送流量预警..."
|
||||||
$SSH_CMD "
|
$SSH_CMD "
|
||||||
|
|
@ -162,6 +184,14 @@ jobs:
|
||||||
"
|
"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
list-user-emails)
|
||||||
|
echo "查询所有用户邮箱..."
|
||||||
|
$SSH_CMD "
|
||||||
|
cd $PROXY_DIR
|
||||||
|
node service/email-hub.js list-emails
|
||||||
|
"
|
||||||
|
;;
|
||||||
|
|
||||||
*)
|
*)
|
||||||
echo "❌ 未知操作: $ACTION"
|
echo "❌ 未知操作: $ACTION"
|
||||||
exit 1
|
exit 1
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,12 @@
|
||||||
//
|
//
|
||||||
// 用法:
|
// 用法:
|
||||||
// node email-hub.js monthly-reset — 发送月初重置邮件给所有用户
|
// node email-hub.js monthly-reset — 发送月初重置邮件给所有用户
|
||||||
// node email-hub.js update-notify <desc> — 发送更新通知给所有用户
|
// node email-hub.js update-notify <desc> — 一键发送更新通知给所有用户
|
||||||
|
// node email-hub.js update-notify-single <email> <desc> — 发送更新通知给单个用户
|
||||||
// node email-hub.js traffic-warn <pct> — 发送流量预警给所有用户
|
// node email-hub.js traffic-warn <pct> — 发送流量预警给所有用户
|
||||||
// node email-hub.js security-warn <email> <msg> — 发送安全提醒给单用户
|
// node email-hub.js security-warn <email> <msg> — 发送安全提醒给单用户
|
||||||
// node email-hub.js feedback-ack <email> — 发送反馈确认给单用户
|
// node email-hub.js feedback-ack <email> — 发送反馈确认给单用户
|
||||||
|
// node email-hub.js list-emails — 列出所有启用用户的邮箱
|
||||||
//
|
//
|
||||||
// 运行方式: CLI调用 (由auto-evolution.js调度)
|
// 运行方式: CLI调用 (由auto-evolution.js调度)
|
||||||
// ═══════════════════════════════════════════════
|
// ═══════════════════════════════════════════════
|
||||||
|
|
@ -270,14 +272,26 @@ function generateMonthlyResetEmail(config) {
|
||||||
function generateUpdateNotifyEmail(description, config) {
|
function generateUpdateNotifyEmail(description, config) {
|
||||||
const now = new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' });
|
const now = new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' });
|
||||||
|
|
||||||
|
// 支持用分号或换行符分隔的多条更新内容,自动渲染为功能清单
|
||||||
|
const items = description.split(/[;\n]/).map(s => s.trim()).filter(Boolean);
|
||||||
|
let detailHtml;
|
||||||
|
if (items.length > 1) {
|
||||||
|
detailHtml = `
|
||||||
|
<ul style="margin: 0; padding-left: 20px; color: #333; line-height: 2;">
|
||||||
|
${items.map(item => `<li>${escapeHtml(item)}</li>`).join('\n ')}
|
||||||
|
</ul>`;
|
||||||
|
} else {
|
||||||
|
detailHtml = `<p style="margin: 0; color: #333; line-height: 1.8;">${escapeHtml(description).replace(/\n/g, '<br>')}</p>`;
|
||||||
|
}
|
||||||
|
|
||||||
const content = `
|
const content = `
|
||||||
<div style="background: #cce5ff; border: 1px solid #b8daff; border-radius: 8px; padding: 15px; margin: 15px 0;">
|
<div style="background: #cce5ff; border: 1px solid #b8daff; border-radius: 8px; padding: 15px; margin: 15px 0;">
|
||||||
<strong style="color: #004085;">🔄 系统已完成升级</strong>
|
<strong style="color: #004085;">🔄 系统已完成升级</strong>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3 style="color: #333;">📋 本次更新内容</h3>
|
<h3 style="color: #333;">📋 本次更新内容</h3>
|
||||||
<div style="background: #f8f9fa; border-radius: 8px; padding: 15px; color: #333; line-height: 1.8;">
|
<div style="background: #f8f9fa; border-radius: 8px; padding: 15px; line-height: 1.8;">
|
||||||
${escapeHtml(description).replace(/\n/g, '<br>')}
|
${detailHtml}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p style="color: #666; font-size: 13px; margin-top: 15px;">
|
<p style="color: #666; font-size: 13px; margin-top: 15px;">
|
||||||
|
|
@ -519,6 +533,36 @@ async function sendFeedbackAckEmail(email) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送更新通知给单个用户 (分别发送模式)
|
||||||
|
* @param {string} email 目标邮箱
|
||||||
|
* @param {string} description 更新说明
|
||||||
|
*/
|
||||||
|
async function sendUpdateNotifySingleEmail(email, description) {
|
||||||
|
const config = loadConfig();
|
||||||
|
const html = generateUpdateNotifyEmail(description, config);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await sendEmail(email, '🌐 光湖语言世界 · 系统已升级', html);
|
||||||
|
console.log(`[邮件中枢] ✅ 更新通知已发送: ${email}`);
|
||||||
|
logEmail('update-notify-single', email, true, null);
|
||||||
|
return { sent: 1, failed: 0 };
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`[邮件中枢] ❌ 更新通知发送失败: ${err.message}`);
|
||||||
|
logEmail('update-notify-single', email, false, err.message);
|
||||||
|
return { sent: 0, failed: 1 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 列出所有启用用户的邮箱 (供下拉选择)
|
||||||
|
* @returns {string[]} 邮箱列表
|
||||||
|
*/
|
||||||
|
function listUserEmails() {
|
||||||
|
const users = getEnabledUsers();
|
||||||
|
return users.map(u => u.email);
|
||||||
|
}
|
||||||
|
|
||||||
// ═══════════════════════════════════════════════
|
// ═══════════════════════════════════════════════
|
||||||
// CLI 主入口
|
// CLI 主入口
|
||||||
// ═══════════════════════════════════════════════
|
// ═══════════════════════════════════════════════
|
||||||
|
|
@ -528,11 +572,16 @@ async function main() {
|
||||||
if (!action) {
|
if (!action) {
|
||||||
console.log('📧 光湖语言世界 · 邮件通信中枢');
|
console.log('📧 光湖语言世界 · 邮件通信中枢');
|
||||||
console.log('用法:');
|
console.log('用法:');
|
||||||
console.log(' node email-hub.js monthly-reset — 月初重置通知');
|
console.log(' node email-hub.js monthly-reset — 月初重置通知 (全部用户)');
|
||||||
console.log(' node email-hub.js update-notify <描述> — 更新升级通知');
|
console.log(' node email-hub.js update-notify <描述> — 一键发送更新通知 (全部用户)');
|
||||||
console.log(' node email-hub.js traffic-warn <百分比> — 流量预警通知');
|
console.log(' node email-hub.js update-notify-single <邮箱> <描述> — 单独发送更新通知');
|
||||||
console.log(' node email-hub.js security-warn <邮箱> <消息> — 安全风险提醒');
|
console.log(' node email-hub.js traffic-warn <百分比> — 流量预警通知 (全部用户)');
|
||||||
console.log(' node email-hub.js feedback-ack <邮箱> — 反馈确认回复');
|
console.log(' node email-hub.js security-warn <邮箱> <消息> — 安全风险提醒 (单用户)');
|
||||||
|
console.log(' node email-hub.js feedback-ack <邮箱> — 反馈确认回复 (单用户)');
|
||||||
|
console.log(' node email-hub.js list-emails — 列出所有用户邮箱');
|
||||||
|
console.log('');
|
||||||
|
console.log('💡 描述支持分号分隔多条内容,自动渲染为功能清单:');
|
||||||
|
console.log(' node email-hub.js update-notify "新增智能选路;优化连接速度;修复断连问题"');
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -549,7 +598,18 @@ async function main() {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
const result = await sendUpdateNotifyEmail(arg1);
|
const result = await sendUpdateNotifyEmail(arg1);
|
||||||
console.log(`📧 更新通知: ${result.sent}成功 / ${result.failed}失败`);
|
console.log(`📧 更新通知 (一键发送): ${result.sent}成功 / ${result.failed}失败`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'update-notify-single': {
|
||||||
|
if (!arg1 || !arg2) {
|
||||||
|
console.error('❌ 请提供邮箱和更新描述');
|
||||||
|
console.error('用法: node email-hub.js update-notify-single <邮箱> <描述>');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
const result = await sendUpdateNotifySingleEmail(arg1, arg2);
|
||||||
|
console.log(`📧 更新通知 (单独发送): ${result.sent}成功 / ${result.failed}失败`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -582,6 +642,19 @@ async function main() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'list-emails': {
|
||||||
|
const emails = listUserEmails();
|
||||||
|
if (emails.length === 0) {
|
||||||
|
console.log('[邮件中枢] 暂无启用用户');
|
||||||
|
} else {
|
||||||
|
console.log(`📧 当前启用用户邮箱 (${emails.length}位):`);
|
||||||
|
emails.forEach((email, i) => {
|
||||||
|
console.log(` ${i + 1}. ${email}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
console.error(`❌ 未知操作: ${action}`);
|
console.error(`❌ 未知操作: ${action}`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
|
@ -592,10 +665,12 @@ async function main() {
|
||||||
module.exports = {
|
module.exports = {
|
||||||
sendMonthlyResetEmail,
|
sendMonthlyResetEmail,
|
||||||
sendUpdateNotifyEmail,
|
sendUpdateNotifyEmail,
|
||||||
|
sendUpdateNotifySingleEmail,
|
||||||
sendTrafficWarnEmail,
|
sendTrafficWarnEmail,
|
||||||
sendSecurityWarnEmail,
|
sendSecurityWarnEmail,
|
||||||
sendFeedbackAckEmail,
|
sendFeedbackAckEmail,
|
||||||
getEnabledUsers,
|
getEnabledUsers,
|
||||||
|
listUserEmails,
|
||||||
sendEmail
|
sendEmail
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue