diff --git a/server/.eslintrc.js b/server/.eslintrc.js
index 82f82c9..8551d51 100644
--- a/server/.eslintrc.js
+++ b/server/.eslintrc.js
@@ -31,7 +31,9 @@ module.exports = {
'no-redeclare': ['error', { builtinGlobals: true }], // 禁止重复对象声明
'no-multi-assign': 0,
'no-restricted-globals': 0,
+ 'no-case-declarations': 0,
'space-before-function-paren': 0, // 函数定义时括号前面空格
+ 'no-async-promise-executor': 0, // 允许在回调中使用async函数
'one-var': 0, // 允许连续声明
// 'no-undef': 0, // 允许未定义的变量【会使env配置无效】
'linebreak-style': 0, // 检测CRLF/LF检测【默认LF】
diff --git a/server/app/controller/notify.js b/server/app/controller/notify.js
index d1ac504..925b765 100644
--- a/server/app/controller/notify.js
+++ b/server/app/controller/notify.js
@@ -1,5 +1,5 @@
const { readNotifyConfig, writeNotifyConfig, readNotifyList, writeNotifyList } = require('../utils')
-const { sctTest, emailTest } = require('../utils/notify')
+const { sendServerChan, sendEmail } = require('../utils/notify')
// const commonTemp = require('../template/commonTemp')
async function getNotifyConfig({ res }) {
@@ -13,10 +13,10 @@ async function updateNotifyConfig({ res, request }) {
try {
switch(type) {
case 'sct':
- await sctTest(noticeConfig[type])
+ await sendServerChan(noticeConfig[type]['sendKey'], 'EasyNode通知测试', '这是一条测试通知')
break
case 'email':
- await emailTest(noticeConfig[type])
+ await sendEmail(noticeConfig[type], 'EasyNode通知测试', '这是一条测试通知')
break
}
await writeNotifyConfig(noticeConfig)
diff --git a/server/app/controller/user.js b/server/app/controller/user.js
index 57cd392..b2f30e5 100644
--- a/server/app/controller/user.js
+++ b/server/app/controller/user.js
@@ -1,6 +1,7 @@
const jwt = require('jsonwebtoken')
const axios = require('axios')
-const { getNetIPInfo, readKey, writeKey, RSADecryptSync, AESEncryptSync, SHA1Encrypt, sendEmailToConfList, getNotifySwByType } = require('../utils')
+const { getNetIPInfo, readKey, writeKey, RSADecryptSync, AESEncryptSync, SHA1Encrypt, getNotifySwByType } = require('../utils')
+const { asyncSendNotice } = require('../utils/notify')
const getpublicKey = async ({ res }) => {
let { publicKey: data } = await readKey()
@@ -24,9 +25,8 @@ const login = async ({ res, request }) => {
loginErrTotal++
if (loginErrCount >= allowErrCount) {
const { ip, country, city } = await getNetIPInfo(clientIp)
- // 发送通知&禁止登录
- let sw = getNotifySwByType('err_login')
- if (sw) sendEmailToConfList('登录错误提醒', `重新登录次数: ${ loginErrTotal }
地点:${ country + city }
IP: ${ ip }`)
+ // 异步发送通知&禁止登录
+ asyncSendNotice('err_login', 'EasyNode登录错误提醒', `错误登录次数: ${ loginErrTotal }
地点:${ country + city }
IP: ${ ip }`)
forbidLogin = true
loginErrCount = 0
@@ -82,8 +82,7 @@ const beforeLoginHandler = async (clientIp, jwtExpires) => {
consola.info('登录成功:', new Date(), { ip, country, city })
// 邮件登录通知
- let sw = getNotifySwByType('login')
- if (sw) sendEmailToConfList('登录提醒', `地点:${ country + city }
IP: ${ ip }`)
+ asyncSendNotice('login', 'EasyNode登录提醒', `地点:${ country + city }
IP: ${ ip }`)
global.loginRecord.unshift(clientIPInfo)
if (global.loginRecord.length > 10) global.loginRecord = global.loginRecord.slice(0, 10)
@@ -103,8 +102,7 @@ const updatePwd = async ({ res, request }) => {
keyObj.pwd = newPwd
await writeKey(keyObj)
- let sw = getNotifySwByType('updatePwd')
- if (sw) sendEmailToConfList(`登录信息修改提醒, 新用户名: ${ newLoginName }`)
+ asyncSendNotice('updatePwd', 'EasyNode用户密码修改提醒', `原用户名:${ user }
更新用户名: ${ newLoginName }`)
res.success({ data: true, msg: 'success' })
}
diff --git a/server/app/utils/notify.js b/server/app/utils/notify.js
index be67a54..3785bbb 100644
--- a/server/app/utils/notify.js
+++ b/server/app/utils/notify.js
@@ -1,27 +1,34 @@
const nodemailer = require('nodemailer')
const axios = require('axios')
+const { getNotifySwByType, readNotifyConfig } = require('../utils')
-module.exports.sctTest = function ({ sendKey }) {
- // eslint-disable-next-line no-async-promise-executor
+function sendServerChan(sendKey, title, content) {
+ if (!sendKey) return consola.error('发送server酱通知失败, sendKey 为空')
return new Promise((async (resolve, reject) => {
- consola.info('server酱通知测试: ', sendKey)
try {
- let { data } = await axios.get(`https://sctapi.ftqq.com/${ sendKey }.send?title=messagetitle`)
+ consola.info('server酱通知预发送: ', title)
+ const url = `https://sctapi.ftqq.com/${ sendKey }.send`
+ const params = new URLSearchParams({ text: title, desp: content })
+ let { data } = await axios.post(url, params, {
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded'
+ }
+ })
resolve(data)
- consola.success('测试成功')
+ consola.info('server酱通知发送成功: ', title)
} catch (error) {
reject(error)
- consola.error('测试失败: ', error)
+ consola.error('server酱通知发送失败: ', error)
}
}))
+
}
-module.exports.emailTest = function (conf) {
- // eslint-disable-next-line no-async-promise-executor
+function sendEmail({ service, user, pass }, title, content) {
+ if (!service || !user || !pass) return consola.info('发送通知失败, 邮箱配置信息不完整: ', { service, user, pass })
return new Promise((async (resolve, reject) => {
- consola.info('邮箱通知测试: ', conf)
try {
- const { service, user, pass } = conf
+ consola.info('邮箱通知预发送: ', title)
let transporter = nodemailer.createTransport({
service,
auth: {
@@ -29,19 +36,52 @@ module.exports.emailTest = function (conf) {
pass
}
})
- let info = await transporter.sendMail({
+ await transporter.sendMail({
from: user,
to: user,
- subject: 'EasyNode: 测试邮件通知',
- text: '测试邮件',
- html: '测试邮件'
+ subject: title,
+ // text: '', // 纯文本版本内容,如果收件人的邮件客户端不支持HTML显示,就会显示这个文本
+ html: content
})
- consola.info('Message sent: %s', info.messageId)
+ consola.info('邮件通知发送成功: ', title)
resolve()
- consola.success('测试成功')
} catch (error) {
reject(error)
- consola.error('测试失败: ', error)
+ consola.error('邮件通知发送失败: ', error)
}
}))
}
+
+// 异步发送通知
+async function asyncSendNotice(noticeAction, title, content) {
+ try {
+ let sw = await getNotifySwByType(noticeAction) // 获取对应动作的通知开关
+ if (!sw) return
+ let notifyConfig = await readNotifyConfig()
+ let { type } = notifyConfig
+ if (!type) return consola.error('通知类型不存在: ', type)
+ content += `
通知发送时间:${ new Date() }`
+ switch (type) {
+ case 'sct':
+ let { sendKey } = notifyConfig['sct']
+ if (!sendKey) return consola.info('未发送server酱通知, sendKey 为空')
+ await sendServerChan(sendKey, title, content)
+ break
+ case 'email':
+ let { service, user, pass } = notifyConfig['email']
+ if (!service || !user || !pass) return consola.info('未发送邮件通知通知, 未配置邮箱: ', { service, user, pass })
+ await sendEmail({ service, user, pass }, title, content)
+ break
+ default:
+ break
+ }
+ } catch (error) {
+ consola.error('通知发送失败: ', error)
+ }
+}
+
+module.exports = {
+ asyncSendNotice,
+ sendServerChan,
+ sendEmail
+}
\ No newline at end of file