-
Notifications
You must be signed in to change notification settings - Fork 283
Expand file tree
/
Copy pathmessage_sender.js
More file actions
131 lines (116 loc) · 4.39 KB
/
message_sender.js
File metadata and controls
131 lines (116 loc) · 4.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import axios from 'axios';
import nodemailer from 'nodemailer';
export default class MessageSender {
static TYPE = {
DINGDING: 0,
WECHAT: 1,
QQEMAIL: 2,
// 未来可扩展更多类型...
};
/**
* 发送消息
* @param {string|object} text 消息文本(字符串或邮件配置对象)
* @param {number} type 消息类型(0: 钉钉,1: 企业微信,2: QQ邮箱),默认 0
*/
static async send(text, type = MessageSender.TYPE.DINGDING) {
if (!text) {
console.warn('[MessageSender] 消息内容不能为空');
return;
}
// QQ邮箱只允许对象,其他类型必须为字符串
if (type === MessageSender.TYPE.QQEMAIL && typeof text !== 'object') {
console.warn('[MessageSender] QQ邮箱类型只支持配置对象');
return;
}
if (type !== MessageSender.TYPE.QQEMAIL && typeof text !== 'string') {
console.warn('[MessageSender] 非邮箱类型消息内容必须是字符串');
return;
}
switch (type) {
case MessageSender.TYPE.DINGDING:
await this.#sendDingDing(text);
break;
case MessageSender.TYPE.WECHAT:
await this.#sendWeChat(text);
break;
case MessageSender.TYPE.QQEMAIL:
await this.#sendQQEmail(text);
break;
default:
console.warn(`[MessageSender] 不支持的消息类型: ${type}`);
}
}
static async #sendDingDing(text) {
const {dingding_webhook} = process.env;
if (!dingding_webhook) {
console.log('[MessageSender] 未配置 dingding_webhook,跳过钉钉发送');
return;
}
try {
await axios.post(dingding_webhook, {
msgtype: 'text',
text: {content: text}
});
console.log('[MessageSender] 钉钉消息已发送');
} catch (err) {
console.error('[MessageSender] 钉钉消息发送失败:', err.message);
}
}
static async #sendWeChat(text) {
const {wechat_webhook} = process.env;
if (!wechat_webhook) {
console.log('[MessageSender] 未配置 wechat_webhook,跳过企业微信发送');
return;
}
try {
await axios.post(wechat_webhook, {
msgtype: 'text',
text: {content: text}
});
console.log('[MessageSender] 企业微信消息已发送');
} catch (err) {
console.error('[MessageSender] 企业微信消息发送失败:', err.message);
}
}
/**
* 发送QQ邮件(支持文本/HTML/多收件人)
* @param {object} config 邮件配置对象
* @property {string} [to] 收件人邮箱,默认使用环境变量QQ_EMAIL
* @property {string} [subject] 邮件主题,默认"系统通知"
* @property {string} [text] 纯文本内容
* @property {string} [html] HTML内容
* @property {Array} [attachments] 邮件附件
*/
static async #sendQQEmail(config) {
const {QQ_EMAIL, QQ_SMTP_AUTH_CODE} = process.env;
if (!QQ_EMAIL || !QQ_SMTP_AUTH_CODE) {
console.log('[MessageSender] 未配置QQ邮箱或SMTP授权码,跳过邮件发送');
return;
}
// 创建带连接池的邮件传输器
const transporter = nodemailer.createTransport({
//pool: true, // 启用连接池
host: 'smtp.qq.com',
port: 465,
secure: true,
auth: {
user: QQ_EMAIL,
pass: QQ_SMTP_AUTH_CODE
}
});
try {
// 构建邮件选项,保护关键字段并提供默认值
const mailOptions = {
from: `"系统通知" <${QQ_EMAIL}>`, // 固定发件人
to: config.to || QQ_EMAIL, // 允许自定义收件人
...config
};
const info = await transporter.sendMail(mailOptions);
console.log('[MessageSender] QQ邮件已发送: %s', info.accepted);
} catch (err) {
console.error('[MessageSender] QQ邮件发送失败:', err.message);
} finally {
transporter.close(); // 关闭连接池
}
}
}