- 实现 JWT Token 生成和验证 - 实现登录、注册、登出、重置密码 API - 实现邮箱验证码发送功能(配置从环境变量读取) - 实现密码加密和验证工具 - 支持获取当前用户信息
137 lines
4.5 KiB
TypeScript
137 lines
4.5 KiB
TypeScript
import nodemailer from 'nodemailer';
|
|
|
|
// 邮箱配置(从环境变量读取)
|
|
const SMTP_HOST = process.env.SMTP_HOST || 'smtp.qq.com';
|
|
const SMTP_PORT = parseInt(process.env.SMTP_PORT || '465');
|
|
const SMTP_USER = process.env.SMTP_USER || '';
|
|
const SMTP_PASS = process.env.SMTP_PASS || '';
|
|
|
|
// SMTP 配置
|
|
const transporter = nodemailer.createTransport({
|
|
host: SMTP_HOST,
|
|
port: SMTP_PORT,
|
|
secure: true,
|
|
auth: {
|
|
user: SMTP_USER,
|
|
pass: SMTP_PASS,
|
|
},
|
|
});
|
|
|
|
// 邮件模板类型
|
|
type EmailType = 'register' | 'login' | 'reset';
|
|
|
|
// 获取邮件主题
|
|
function getSubject(type: EmailType): string {
|
|
const subjects: Record<EmailType, string> = {
|
|
register: 'LionCode - 注册验证码',
|
|
login: 'LionCode - 登录验证码',
|
|
reset: 'LionCode - 重置密码验证码',
|
|
};
|
|
return subjects[type];
|
|
}
|
|
|
|
// 获取邮件内容
|
|
function getEmailContent(type: EmailType, code: string): string {
|
|
const typeText: Record<EmailType, string> = {
|
|
register: '注册账号',
|
|
login: '登录账号',
|
|
reset: '重置密码',
|
|
};
|
|
|
|
return `
|
|
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>验证码</title>
|
|
</head>
|
|
<body style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; background-color: #f5f5f5;">
|
|
<table role="presentation" style="width: 100%; border-collapse: collapse;">
|
|
<tr>
|
|
<td align="center" style="padding: 40px 0;">
|
|
<table role="presentation" style="width: 100%; max-width: 600px; border-collapse: collapse; background-color: #ffffff; border-radius: 12px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);">
|
|
<!-- Header -->
|
|
<tr>
|
|
<td style="padding: 40px 40px 20px; text-align: center;">
|
|
<h1 style="margin: 0; font-size: 28px; font-weight: 700; color: #1a1a1a;">LionCode</h1>
|
|
<p style="margin: 8px 0 0; font-size: 14px; color: #666;">智能 AI 对话助手</p>
|
|
</td>
|
|
</tr>
|
|
|
|
<!-- Content -->
|
|
<tr>
|
|
<td style="padding: 20px 40px;">
|
|
<p style="margin: 0 0 20px; font-size: 16px; color: #333; line-height: 1.6;">
|
|
您好!
|
|
</p>
|
|
<p style="margin: 0 0 20px; font-size: 16px; color: #333; line-height: 1.6;">
|
|
您正在进行<strong>${typeText[type]}</strong>操作,验证码如下:
|
|
</p>
|
|
|
|
<!-- Code Box -->
|
|
<div style="background: linear-gradient(135deg, #E06B3E 0%, #D4643E 100%); border-radius: 8px; padding: 24px; text-align: center; margin: 24px 0;">
|
|
<span style="font-size: 36px; font-weight: 700; letter-spacing: 8px; color: #ffffff;">${code}</span>
|
|
</div>
|
|
|
|
<p style="margin: 20px 0 0; font-size: 14px; color: #666; line-height: 1.6;">
|
|
验证码有效期为 <strong>5 分钟</strong>,请尽快完成验证。
|
|
</p>
|
|
<p style="margin: 12px 0 0; font-size: 14px; color: #999; line-height: 1.6;">
|
|
如果这不是您本人的操作,请忽略此邮件。
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
|
|
<!-- Footer -->
|
|
<tr>
|
|
<td style="padding: 20px 40px 40px; border-top: 1px solid #eee;">
|
|
<p style="margin: 0; font-size: 12px; color: #999; text-align: center;">
|
|
此邮件由系统自动发送,请勿回复。
|
|
</p>
|
|
<p style="margin: 8px 0 0; font-size: 12px; color: #999; text-align: center;">
|
|
© ${new Date().getFullYear()} LionCode. All rights reserved.
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</body>
|
|
</html>
|
|
`.trim();
|
|
}
|
|
|
|
// 发送验证码邮件
|
|
export async function sendVerificationEmail(
|
|
to: string,
|
|
code: string,
|
|
type: EmailType
|
|
): Promise<{ success: boolean; error?: string }> {
|
|
try {
|
|
await transporter.sendMail({
|
|
from: {
|
|
name: 'LionCode',
|
|
address: SMTP_USER,
|
|
},
|
|
to,
|
|
subject: getSubject(type),
|
|
html: getEmailContent(type, code),
|
|
});
|
|
|
|
return { success: true };
|
|
} catch (error) {
|
|
console.error('发送邮件失败:', error);
|
|
return {
|
|
success: false,
|
|
error: error instanceof Error ? error.message : '发送邮件失败',
|
|
};
|
|
}
|
|
}
|
|
|
|
// 生成6位数字验证码
|
|
export function generateVerificationCode(): string {
|
|
return Math.floor(100000 + Math.random() * 900000).toString();
|
|
}
|