190 lines
5.1 KiB
JavaScript
190 lines
5.1 KiB
JavaScript
/**
|
||
* 邮件服务
|
||
* 使用QQ邮箱SMTP服务发送邮件
|
||
*/
|
||
|
||
const nodemailer = require('nodemailer');
|
||
const config = require('../../config/config.js');
|
||
|
||
// 创建邮件传输器
|
||
let transporter = null;
|
||
|
||
/**
|
||
* 初始化邮件传输器
|
||
*/
|
||
function init_transporter() {
|
||
if (transporter) {
|
||
return transporter;
|
||
}
|
||
|
||
// QQ邮箱SMTP配置
|
||
const email_config = config.email || {
|
||
host: 'smtp.qq.com',
|
||
port: 465,
|
||
secure: true, // 使用SSL
|
||
auth: {
|
||
user: process.env.QQ_EMAIL_USER || '', // QQ邮箱账号
|
||
pass: process.env.QQ_EMAIL_PASS || '' // QQ邮箱授权码(不是密码)
|
||
}
|
||
};
|
||
|
||
transporter = nodemailer.createTransport({
|
||
host: email_config.host,
|
||
port: email_config.port,
|
||
secure: email_config.secure,
|
||
auth: email_config.auth
|
||
});
|
||
|
||
return transporter;
|
||
}
|
||
|
||
/**
|
||
* 发送邮件
|
||
* @param {Object} options 邮件选项
|
||
* @param {string} options.to 收件人邮箱
|
||
* @param {string} options.subject 邮件主题
|
||
* @param {string} options.html 邮件HTML内容
|
||
* @param {string} options.text 邮件纯文本内容(可选)
|
||
* @returns {Promise<{success: boolean, message?: string, messageId?: string}>}
|
||
*/
|
||
async function send_email(options) {
|
||
try {
|
||
const transporter_instance = init_transporter();
|
||
|
||
if (!transporter_instance) {
|
||
return {
|
||
success: false,
|
||
message: '邮件服务未配置'
|
||
};
|
||
}
|
||
|
||
// 如果没有配置邮箱账号,返回错误
|
||
const email_config = config.email || {};
|
||
if (!email_config.auth || !email_config.auth.user || !email_config.auth.pass) {
|
||
console.warn('[邮件服务] QQ邮箱未配置,使用模拟发送');
|
||
// 开发环境可以模拟发送
|
||
if (config.env === 'development') {
|
||
console.log(`[模拟邮件] 发送到 ${options.to}`);
|
||
console.log(`[模拟邮件] 主题: ${options.subject}`);
|
||
console.log(`[模拟邮件] 内容: ${options.text || options.html}`);
|
||
return {
|
||
success: true,
|
||
message: '邮件已发送(模拟)',
|
||
messageId: 'mock-' + Date.now()
|
||
};
|
||
}
|
||
return {
|
||
success: false,
|
||
message: '邮件服务未配置,请联系管理员'
|
||
};
|
||
}
|
||
|
||
// 发送邮件
|
||
const mail_options = {
|
||
from: `"${email_config.fromName || '自动找工作系统'}" <${email_config.auth.user}>`,
|
||
to: options.to,
|
||
subject: options.subject,
|
||
html: options.html,
|
||
text: options.text || options.html.replace(/<[^>]*>/g, '') // 如果没有text,从html提取
|
||
};
|
||
|
||
const info = await transporter_instance.sendMail(mail_options);
|
||
|
||
console.log(`[邮件服务] 邮件发送成功: ${options.to}, MessageId: ${info.messageId}`);
|
||
|
||
return {
|
||
success: true,
|
||
message: '邮件发送成功',
|
||
messageId: info.messageId
|
||
};
|
||
} catch (error) {
|
||
console.error('[邮件服务] 发送邮件失败:', error);
|
||
return {
|
||
success: false,
|
||
message: error.message || '发送邮件失败'
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 发送验证码邮件
|
||
* @param {string} email 收件人邮箱
|
||
* @param {string} code 验证码
|
||
* @returns {Promise<{success: boolean, message?: string, messageId?: string}>}
|
||
*/
|
||
async function send_verification_code(email, code) {
|
||
const subject = '【自动找工作系统】注册验证码';
|
||
const html = `
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<style>
|
||
body {
|
||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
|
||
line-height: 1.6;
|
||
color: #333;
|
||
}
|
||
.container {
|
||
max-width: 600px;
|
||
margin: 0 auto;
|
||
padding: 20px;
|
||
background: #f5f5f5;
|
||
}
|
||
.content {
|
||
background: #ffffff;
|
||
padding: 30px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||
}
|
||
.code-box {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
padding: 20px;
|
||
border-radius: 8px;
|
||
text-align: center;
|
||
margin: 20px 0;
|
||
font-size: 32px;
|
||
font-weight: bold;
|
||
letter-spacing: 8px;
|
||
}
|
||
.tip {
|
||
color: #666;
|
||
font-size: 14px;
|
||
margin-top: 20px;
|
||
padding-top: 20px;
|
||
border-top: 1px solid #eee;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<div class="content">
|
||
<h2>验证码</h2>
|
||
<p>您好,</p>
|
||
<p>您正在注册自动找工作系统,验证码为:</p>
|
||
<div class="code-box">${code}</div>
|
||
<p>验证码有效期为 <strong>5分钟</strong>,请勿泄露给他人。</p>
|
||
<div class="tip">
|
||
<p>如果这不是您的操作,请忽略此邮件。</p>
|
||
<p>此邮件由系统自动发送,请勿回复。</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</body>
|
||
</html>
|
||
`;
|
||
|
||
return await send_email({
|
||
to: email,
|
||
subject: subject,
|
||
html: html
|
||
});
|
||
}
|
||
|
||
module.exports = {
|
||
send_email,
|
||
send_verification_code,
|
||
init_transporter
|
||
};
|