Browse Source

Add SMTP mailing.

pull/6/head
t123yh 7 years ago
parent
commit
79ce419ffa
  1. 44
      README.md
  2. 4
      config-example.json
  3. 28
      libs/email.js
  4. 13
      modules/api.js
  5. 5
      package-lock.json
  6. 5
      package.json

44
README.md

@ -118,3 +118,47 @@ systemctl stop syzoj-judge
systemctl restart syzoj systemctl restart syzoj
systemctl restart syzoj-judge systemctl restart syzoj-judge
``` ```
## 邮件配置
### register_mail
是否启用注册邮件验证。
### email\_jwt\_secret
用于 Email Token 签名的 secret,脸滚键盘随意填写即可。
### email
#### Sendmail 直接发送(成功率低,不推荐)
```js
"email": {
"method": "sendmail",
"options": {
"address": "xxxx", // 发件人地址
}
},
```
#### 阿里云邮件推送服务(成功率较高)
```js
"email": {
"method": "aliyundm",
"options": {
"AccessKeyId": "xxxx",
"AccessKeySecret": "xxxx",
"AccountName": "xxxx" // 发件邮箱
}
},
```
#### SMTP 服务
```js
"email": {
"method": "smtp",
"options": {
"host": "smtp.163.com",
"port": 465,
"username": "xxx@163.com",
"password": "xxx",
"allowUnauthorizedTls": false
}
},
```

4
config-example.json

@ -13,7 +13,6 @@
"register_mail": true, "register_mail": true,
"email": { "email": {
"method": "aliyundm", "method": "aliyundm",
"key": "test",
"options": { "options": {
"AccessKeyId": "xxxx", "AccessKeyId": "xxxx",
"AccessKeySecret": "xxxx", "AccessKeySecret": "xxxx",
@ -168,5 +167,6 @@
], ],
"session_secret": "233", "session_secret": "233",
"judge_server_addr": "http://127.0.0.1:5284", "judge_server_addr": "http://127.0.0.1:5284",
"judge_token": "233" "judge_token": "233",
"email_jwt_token": "test"
} }

28
libs/email.js

@ -1,6 +1,7 @@
const Promise = require('bluebird'); const Bluebird = require('bluebird');
const sendmail = Promise.promisify(require('sendmail')()); const sendmail = Bluebird.promisify(require('sendmail')());
const { DM } = require('waliyun'); const { DM } = require('waliyun');
const nodemailer = require('nodemailer');
let doSendEmail; let doSendEmail;
@ -33,6 +34,29 @@ if (syzoj.config.email.method === "sendmail") {
throw new Error("阿里云 API 错误:" + JSON.stringify(result)); throw new Error("阿里云 API 错误:" + JSON.stringify(result));
} }
} }
} else if (syzoj.config.email.method === "smtp") {
const smtpConfig = {
host: syzoj.config.email.options.host,
port: syzoj.config.email.options.port || 465,
secure: (syzoj.config.email.options.port === 465 || !syzoj.config.email.options.port) ? true : false,
auth: {
user: syzoj.config.email.options.username,
pass: syzoj.config.email.options.password,
},
tls: {
rejectUnauthorized: !syzoj.config.email.options.allowUnauthorizedTls,
},
};
const transporter = Bluebird.promisifyAll(nodemailer.createTransport(smtpConfig));
doSendEmail = async function send_smtp(to, subject, body) {
await transporter.sendMailAsync({
from: `"${syzoj.config.title}" <${syzoj.config.email.options.username}>`,
to: to,
subject: subject,
html: body
});
};
} else { } else {
doSendEmail = async () => { doSendEmail = async () => {
throw new Error("邮件发送配置不正确。"); throw new Error("邮件发送配置不正确。");

13
modules/api.js

@ -58,7 +58,7 @@ app.post('/api/forget', async (req, res) => {
userId: user.id, userId: user.id,
}; };
const token = jwt.sign(sendObj, syzoj.config.email.key, { const token = jwt.sign(sendObj, syzoj.config.email_jwt_secret, {
subject: 'forget', subject: 'forget',
expiresIn: '12h' expiresIn: '12h'
}); });
@ -76,7 +76,6 @@ app.post('/api/forget', async (req, res) => {
}); });
} }
throw 123;
res.send({ error_code: 1 }); res.send({ error_code: 1 });
} catch (e) { } catch (e) {
syzoj.log(e); syzoj.log(e);
@ -108,7 +107,7 @@ app.post('/api/sign_up', async (req, res) => {
email: req.body.email, email: req.body.email,
}; };
const token = jwt.sign(sendObj, syzoj.config.email.key, { const token = jwt.sign(sendObj, syzoj.config.email_jwt_secret, {
subject: 'register', subject: 'register',
expiresIn: '2d' expiresIn: '2d'
}); });
@ -150,7 +149,7 @@ app.post('/api/sign_up', async (req, res) => {
app.get('/api/forget_confirm', async (req, res) => { app.get('/api/forget_confirm', async (req, res) => {
try { try {
try { try {
jwt.verify(req.query.token, syzoj.config.email.key, { subject: 'forget' }); jwt.verify(req.query.token, syzoj.config.email_jwt_secret, { subject: 'forget' });
} catch (e) { } catch (e) {
throw new ErrorMessage("Token 不正确。"); throw new ErrorMessage("Token 不正确。");
} }
@ -170,7 +169,7 @@ app.post('/api/reset_password', async (req, res) => {
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
let obj; let obj;
try { try {
obj = jwt.verify(req.body.token, syzoj.config.email.key, { subject: 'forget' }); obj = jwt.verify(req.body.token, syzoj.config.email_jwt_secret, { subject: 'forget' });
} catch (e) { } catch (e) {
throw 3001; throw 3001;
} }
@ -196,7 +195,7 @@ app.get('/api/sign_up_confirm', async (req, res) => {
try { try {
let obj; let obj;
try { try {
obj = jwt.verify(req.query.token, syzoj.config.email.key, { subject: 'register' }); obj = jwt.verify(req.query.token, syzoj.config.email_jwt_secret, { subject: 'register' });
} catch (e) { } catch (e) {
throw new ErrorMessage('无效的注册验证链接: ' + e.toString()); throw new ErrorMessage('无效的注册验证链接: ' + e.toString());
} }
@ -238,7 +237,7 @@ app.get('/api/sign_up/:token', async (req, res) => {
try { try {
let obj; let obj;
try { try {
let decrypted = syzoj.utils.decrypt(Buffer.from(req.params.token, 'base64'), syzoj.config.email.key).toString(); let decrypted = syzoj.utils.decrypt(Buffer.from(req.params.token, 'base64'), syzoj.config.email_jwt_secret).toString();
obj = JSON.parse(decrypted); obj = JSON.parse(decrypted);
} catch (e) { } catch (e) {
throw new ErrorMessage('无效的注册验证链接。'); throw new ErrorMessage('无效的注册验证链接。');

5
package-lock.json generated

@ -1863,6 +1863,11 @@
"win-spawn": "2.0.0" "win-spawn": "2.0.0"
} }
}, },
"nodemailer": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-4.1.0.tgz",
"integrity": "sha512-pZg74CNQgnC0gZTfH0btXCxjKj7/2v5pea6hmMJ/iKyT48Z81TXZua7c65clwqKIlWfMfYBQG3OkrKxycIdXTw=="
},
"nodemailer-fetch": { "nodemailer-fetch": {
"version": "1.6.0", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz",

5
package.json

@ -45,6 +45,7 @@
"multer": "^1.2.0", "multer": "^1.2.0",
"mysql": "^2.11.1", "mysql": "^2.11.1",
"node-7z": "^0.4.0", "node-7z": "^0.4.0",
"nodemailer": "^4.1.0",
"pygmentize-bundled-cached": "^1.1.0", "pygmentize-bundled-cached": "^1.1.0",
"randomstring": "^1.1.5", "randomstring": "^1.1.5",
"request": "^2.74.0", "request": "^2.74.0",
@ -55,9 +56,7 @@
"sqlite3": "^3.1.4", "sqlite3": "^3.1.4",
"syzoj-divine": "^1.0.2", "syzoj-divine": "^1.0.2",
"tmp-promise": "^1.0.3", "tmp-promise": "^1.0.3",
"waliyun": "^3.1.1",
"xss": "^0.3.3" "xss": "^0.3.3"
},
"optionalDependencies": {
"waliyun": "^3.1.1"
} }
} }

Loading…
Cancel
Save