整合資料庫、完成登入註冊忘記密碼功能

This commit is contained in:
2025-09-09 12:00:22 +08:00
parent af88c0f037
commit 32b19e9a0f
85 changed files with 11672 additions and 2350 deletions

View File

@@ -0,0 +1,101 @@
// =====================================================
// 郵件服務
// =====================================================
import nodemailer from 'nodemailer';
// 郵件配置
const emailConfig = {
host: process.env.SMTP_HOST || 'smtp.gmail.com',
port: parseInt(process.env.SMTP_PORT || '587'),
secure: false, // true for 465, false for other ports
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
};
// 創建郵件傳輸器
const transporter = nodemailer.createTransport(emailConfig);
export class EmailService {
// 發送密碼重設郵件
static async sendPasswordResetEmail(email: string, resetToken: string, userName: string) {
try {
const resetUrl = `${process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000'}/reset-password?token=${resetToken}`;
const mailOptions = {
from: `"${process.env.NEXT_PUBLIC_APP_NAME || 'AI 展示平台'}" <${emailConfig.auth.user}>`,
to: email,
subject: '密碼重設請求',
html: `
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 30px; text-align: center;">
<h1 style="color: white; margin: 0; font-size: 24px;">密碼重設請求</h1>
</div>
<div style="padding: 30px; background: #f9f9f9;">
<h2 style="color: #333; margin-top: 0;">親愛的 ${userName}</h2>
<p style="color: #666; line-height: 1.6;">
我們收到了您的密碼重設請求。請點擊下方按鈕來重設您的密碼:
</p>
<div style="text-align: center; margin: 30px 0;">
<a href="${resetUrl}"
style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 15px 30px;
text-decoration: none;
border-radius: 5px;
display: inline-block;
font-weight: bold;">
重設密碼
</a>
</div>
<p style="color: #666; line-height: 1.6; font-size: 14px;">
如果按鈕無法點擊,請複製以下連結到瀏覽器中:<br>
<a href="${resetUrl}" style="color: #667eea; word-break: break-all;">${resetUrl}</a>
</p>
<div style="background: #fff3cd; border: 1px solid #ffeaa7; padding: 15px; border-radius: 5px; margin: 20px 0;">
<p style="color: #856404; margin: 0; font-size: 14px;">
<strong>注意:</strong>此連結將在 1 小時後過期,請盡快完成密碼重設。
</p>
</div>
<p style="color: #666; line-height: 1.6; font-size: 14px;">
如果您沒有請求密碼重設,請忽略此郵件。您的密碼將保持不變。
</p>
</div>
<div style="background: #333; color: white; padding: 20px; text-align: center; font-size: 12px;">
<p style="margin: 0;">此郵件由 ${process.env.NEXT_PUBLIC_APP_NAME || 'AI 展示平台'} 系統自動發送</p>
</div>
</div>
`,
};
const result = await transporter.sendMail(mailOptions);
console.log('密碼重設郵件發送成功:', result.messageId);
return { success: true, messageId: result.messageId };
} catch (error) {
console.error('發送密碼重設郵件失敗:', error);
return { success: false, error: error.message };
}
}
// 測試郵件配置
static async testEmailConfig() {
try {
await transporter.verify();
console.log('郵件配置驗證成功');
return { success: true };
} catch (error) {
console.error('郵件配置驗證失敗:', error);
return { success: false, error: error.message };
}
}
}