route.ts 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. import { NextRequest, NextResponse } from 'next/server';
  2. import { findUserByEmail, createVerificationToken } from '@/lib/user-service';
  3. import { sendEmail, generatePasswordResetEmailHtml } from '@/lib/email';
  4. import { isValidEmail } from '@/lib/auth-utils';
  5. export async function POST(request: NextRequest) {
  6. try {
  7. const { email, locale = 'zh' } = await request.json();
  8. // 验证输入
  9. if (!email) {
  10. return NextResponse.json(
  11. { error: '邮箱地址是必填项' },
  12. { status: 400 }
  13. );
  14. }
  15. if (!isValidEmail(email)) {
  16. return NextResponse.json(
  17. { error: '邮箱格式不正确' },
  18. { status: 400 }
  19. );
  20. }
  21. // 查找用户
  22. const user = await findUserByEmail(email.toLowerCase().trim());
  23. // 无论用户是否存在,都返回成功消息(安全考虑)
  24. // 这样可以防止恶意用户通过此接口探测哪些邮箱已注册
  25. if (user) {
  26. // 生成密码重置令牌(24小时有效)
  27. const resetToken = await createVerificationToken(
  28. user.email,
  29. 'password_reset',
  30. 24
  31. );
  32. if (resetToken) {
  33. // 发送密码重置邮件
  34. const resetUrl = `${process.env.NEXTAUTH_URL}/${locale}/auth/reset-password?token=${resetToken}`;
  35. const emailHtml = generatePasswordResetEmailHtml(resetUrl, locale);
  36. const emailResult = await sendEmail({
  37. to: user.email,
  38. subject: locale === 'zh' ? 'Aiartools - 密码重置' : 'Aiartools - Password Reset',
  39. html: emailHtml,
  40. });
  41. if (!emailResult.success) {
  42. console.error('密码重置邮件发送失败:', emailResult.error);
  43. return NextResponse.json(
  44. { error: '邮件发送失败,请稍后重试' },
  45. { status: 500 }
  46. );
  47. }
  48. }
  49. }
  50. return NextResponse.json({
  51. message: '如果该邮箱地址已注册,您将收到密码重置链接。',
  52. });
  53. } catch (error) {
  54. console.error('找回密码错误:', error);
  55. return NextResponse.json(
  56. { error: '服务器内部错误' },
  57. { status: 500 }
  58. );
  59. }
  60. }