import { NextRequest, NextResponse } from 'next/server' import { supabase } from '@/lib/supabase' import nodemailer from 'nodemailer' // Initialize nodemailer transporter with Supabase SMTP configuration 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 if (!smtpHost || !smtpUser || !smtpPassword) { return null } return nodemailer.createTransport({ host: smtpHost, port: smtpPort, secure: smtpPort === 465, auth: { user: smtpUser, pass: smtpPassword, }, }) } // Store reset codes temporarily (in production, use Redis or database) const resetCodes = new Map() // Clean up expired codes every 10 minutes setInterval(() => { const now = Date.now() for (const [key, value] of resetCodes.entries()) { if (value.expiresAt < now) { resetCodes.delete(key) } } }, 10 * 60 * 1000) export async function POST(request: NextRequest) { try { const { email } = await request.json() if (!email) { return NextResponse.json( { error: 'Email is required' }, { status: 400 } ) } // Validate email format const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ if (!emailRegex.test(email)) { return NextResponse.json( { error: 'Invalid email format' }, { status: 400 } ) } // Validate that email is from a real email provider (Gmail, Yahoo, Outlook, etc.) const emailDomain = email.trim().toLowerCase().split('@')[1] const realEmailProviders = [ 'gmail.com', 'googlemail.com', 'yahoo.com', 'yahoo.co.uk', 'yahoo.co.jp', 'ymail.com', 'rocketmail.com', 'outlook.com', 'hotmail.com', 'live.com', 'msn.com', 'icloud.com', 'me.com', 'mac.com', 'protonmail.com', 'proton.me', 'aol.com', 'mail.com', 'email.com' ] const isValidProvider = realEmailProviders.some(provider => emailDomain === provider || emailDomain.endsWith('.' + provider) ) if (!isValidProvider) { return NextResponse.json( { error: 'Please use a verified email address from a real email provider (Gmail, Yahoo, Outlook, etc.)', details: 'We only send verification codes to verified email addresses for security' }, { status: 400 } ) } // Check if user exists in database const { data: user, error: userError } = await supabase .from('users') .select('email, user_name') .eq('email', email.trim().toLowerCase()) .single() // For security, don't reveal if email exists // But we'll still send a code if email format is valid if (userError || !user) { // Return success message even if user doesn't exist (security best practice) return NextResponse.json({ success: true, message: 'If an account exists with this email, a password reset code has been sent.' }) } // Generate 6-digit reset code const code = Math.floor(100000 + Math.random() * 900000).toString() const expiresAt = Date.now() + 10 * 60 * 1000 // 10 minutes // Store code with email as key (ensure code is stored as string, trimmed) const emailKey = email.trim().toLowerCase() resetCodes.set(emailKey, { code: code.trim(), // Ensure code is trimmed when stored expiresAt, email: emailKey }) console.log('✅ Reset code generated for email:', emailKey) console.log('✅ Code stored:', code) console.log('✅ Code expires at:', new Date(expiresAt).toISOString()) console.log('✅ Total codes in memory:', resetCodes.size) // Send reset code via email using Supabase SMTP const transporter = createTransporter() if (!transporter) { console.error('❌ SMTP not configured. SMTP credentials are missing in environment variables.') console.log('💡 To fix: Configure SMTP in Supabase Dashboard → Authentication → SMTP Settings') if (process.env.NODE_ENV === 'development') { console.log('🔐 Password reset code for', email, ':', code) return NextResponse.json({ success: true, message: 'Password reset code generated (check console). Configure SMTP to send emails.', code: code }) } return NextResponse.json( { error: 'Email service not configured. Please configure SMTP in Supabase Dashboard.' }, { status: 500 } ) } try { // Parse from email (supports both "Name " and "email" formats) 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 console.log('📧 Sending password reset code via Supabase SMTP to:', email.trim().toLowerCase()) console.log('📧 From email:', `${fromName} <${fromEmail}>`) console.log('📧 SMTP Host:', process.env.SMTP_HOST) const mailOptions = { from: `${fromName} <${fromEmail}>`, to: email.trim().toLowerCase(), subject: 'BUILDMATE - Password Reset Code', html: ` Password Reset

BUILDMATE

Password Reset

Hello ${user.user_name || 'User'},

You requested to reset your password. Please use the verification code below to proceed:

Your password reset code is:

${code}

This code will expire in 10 minutes. If you didn't request this reset, please ignore this email and your password will remain unchanged.

Security Notice: Never share this code with anyone. BUILDMATE will never ask for your reset code.

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

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

`, } const info = await transporter.sendMail(mailOptions) console.log('✅ Password reset code email sent successfully via Supabase SMTP:', info.messageId) return NextResponse.json({ success: true, message: 'Password reset code sent to your verified email address' }) } catch (emailError: any) { console.error('❌ Error sending email via Supabase SMTP:', emailError) console.error('Error details:', JSON.stringify(emailError, null, 2)) // Even if email fails, the code is still stored in memory // In development, return the code so user can test if (process.env.NODE_ENV === 'development') { console.log('⚠️ Email sending failed, but code is stored in memory') console.log('🔐 Password reset code for', emailKey, ':', code) console.log('💡 You can still verify this code (until server restarts or code expires)') return NextResponse.json({ success: true, message: 'Email sending failed, but code generated (check console). Fix SMTP configuration to send emails.', code: code, error: emailError.message || 'Email sending failed', note: 'Code is stored in memory. You can verify it even if email failed (until server restarts).' }) } // In production, don't expose the code but still store it // User might have received email before the error console.log('⚠️ Email sending failed, but code is stored in memory for:', emailKey) return NextResponse.json( { success: true, message: 'Password reset code may have been sent. If you did not receive it, please check your spam folder or try again.', details: 'The code is stored and valid for 10 minutes. If email failed, please check SMTP configuration.' }, { status: 200 } ) } } catch (error: any) { console.error('Send reset code error:', error) return NextResponse.json( { error: error.message || 'Internal server error' }, { status: 500 } ) } } // Export resetCodes for use in verify route export { resetCodes }