import { NextRequest, NextResponse } from "next/server"; import { supabase } from "@/lib/supabase"; import nodemailer from "nodemailer"; export const dynamic = "force-dynamic"; export const runtime = "nodejs"; const createTransporter = () => { const smtpHost = process.env.SMTP_HOST; const smtpPort = process.env.SMTP_PORT ? parseInt(process.env.SMTP_PORT) : 587; const smtpUser = process.env.SMTP_USER; const smtpPassword = process.env.SMTP_PASSWORD; const smtpFromEmail = process.env.SMTP_FROM_EMAIL || "BUILDMATE "; const smtpFromName = process.env.SMTP_FROM_NAME || "BUILDMATE"; if (!smtpHost || !smtpUser || !smtpPassword) { throw new Error("SMTP credentials are missing in environment variables."); } return nodemailer.createTransport({ host: smtpHost, port: smtpPort, secure: smtpPort === 465, auth: { user: smtpUser, pass: smtpPassword, }, }); }; export async function POST(request: NextRequest) { try { const { userId, newEmail } = await request.json(); if (!userId || !newEmail) { return NextResponse.json({ error: "User ID and new email are required" }, { status: 400 }); } const emailLower = newEmail.toLowerCase(); // Validate email format const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(emailLower)) { return NextResponse.json({ error: "Invalid email format" }, { status: 400 }); } // Get user info from Supabase const { data: user, error: userError } = await supabase .from("users") .select("user_name") .eq("user_id", userId) .single(); if (userError || !user) { return NextResponse.json({ error: "User not found" }, { status: 404 }); } // Check if an unexpired unverified code already exists const { data: existingCode } = await supabase .from("email_change_verification_codes") .select("*") .eq("email", emailLower) .eq("user_id", userId) .eq("verified", false) .gt("expires_at", new Date().toISOString()) // only unexpired codes .single(); if (existingCode) { return NextResponse.json({ success: true, message: "A verification code was already sent. Please check your email.", }); } // Generate 6-digit code const code = Math.floor(100000 + Math.random() * 900000).toString(); const expiresAt = new Date(Date.now() + 5 * 60 * 1000).toISOString(); // store as UTC // Insert into Supabase await supabase.from("email_change_verification_codes").insert({ user_id: userId, email: emailLower, code, expires_at: expiresAt, }); // Send email const transporter = createTransporter(); const fromEmailRaw = process.env.SMTP_FROM_EMAIL || "noreply@buildmate.com"; const fromName = process.env.SMTP_FROM_NAME || "BUILDMATE"; const fromEmail = fromEmailRaw.includes("<") ? fromEmailRaw.match(/<(.+)>/)?.[1] || fromEmailRaw : fromEmailRaw; const emailHtml = ` Email Change Verification Code

BUILDMATE

Email Change Verification Code

Hello ${user.user_name},

You requested to change the email address associated with your BUILDMATE account. Please use the verification code below to confirm this change:

${code}

This code will expire in 5 minutes

Security Notice: If you didn't request this email change, please ignore this message or contact support immediately if you're concerned about your account security.

This is an automated email from BUILDMATE. Please do not reply to this email.

© ${new Date().getFullYear()} BUILDMATE. All rights reserved.

`; await transporter.verify(); await transporter.sendMail({ from: `${fromName} <${fromEmail}>`, to: emailLower, subject: `BUILDMATE Email Change Verification Code`, html: emailHtml, }); return NextResponse.json({ success: true, message: "Verification code sent to new email" }); } catch (error: any) { console.error("Send email change code error:", error); return NextResponse.json({ error: error.message || "Internal server error" }, { status: 500 }); } }