67 lines
1.8 KiB
TypeScript
67 lines
1.8 KiB
TypeScript
|
|
import { NextRequest, NextResponse } from 'next/server'
|
||
|
|
import nodemailer from 'nodemailer'
|
||
|
|
import { checkRateLimit } from '@/lib/rate-limit'
|
||
|
|
|
||
|
|
const MAIL_DOMAIN = process.env.POSTE_MAIL_DOMAIN || 'monaco-opc.com'
|
||
|
|
const SMTP_HOST = process.env.SMTP_HOST || 'localhost'
|
||
|
|
const SMTP_PORT = parseInt(process.env.SMTP_PORT || '587')
|
||
|
|
|
||
|
|
export async function POST(request: NextRequest): Promise<NextResponse> {
|
||
|
|
const ip = request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() || 'unknown'
|
||
|
|
const rateLimit = checkRateLimit(`email-verify:${ip}`, 5, 15 * 60 * 1000)
|
||
|
|
|
||
|
|
if (!rateLimit.success) {
|
||
|
|
return NextResponse.json(
|
||
|
|
{ error: 'Too many attempts. Please try again later.' },
|
||
|
|
{ status: 429 }
|
||
|
|
)
|
||
|
|
}
|
||
|
|
|
||
|
|
try {
|
||
|
|
const body = await request.json()
|
||
|
|
const { email, password } = body as { email: string; password: string }
|
||
|
|
|
||
|
|
if (!email || !password) {
|
||
|
|
return NextResponse.json(
|
||
|
|
{ error: 'Email and password are required.' },
|
||
|
|
{ status: 400 }
|
||
|
|
)
|
||
|
|
}
|
||
|
|
|
||
|
|
const emailLower = email.toLowerCase().trim()
|
||
|
|
|
||
|
|
if (!emailLower.endsWith(`@${MAIL_DOMAIN}`)) {
|
||
|
|
return NextResponse.json(
|
||
|
|
{ error: `Email must be an @${MAIL_DOMAIN} address.` },
|
||
|
|
{ status: 400 }
|
||
|
|
)
|
||
|
|
}
|
||
|
|
|
||
|
|
const transporter = nodemailer.createTransport({
|
||
|
|
host: SMTP_HOST,
|
||
|
|
port: SMTP_PORT,
|
||
|
|
secure: SMTP_PORT === 465,
|
||
|
|
auth: {
|
||
|
|
user: emailLower,
|
||
|
|
pass: password,
|
||
|
|
},
|
||
|
|
connectionTimeout: 10000,
|
||
|
|
greetingTimeout: 10000,
|
||
|
|
})
|
||
|
|
|
||
|
|
try {
|
||
|
|
await transporter.verify()
|
||
|
|
return NextResponse.json({ valid: true })
|
||
|
|
} catch {
|
||
|
|
return NextResponse.json({ valid: false, error: 'Invalid email or password.' })
|
||
|
|
} finally {
|
||
|
|
transporter.close()
|
||
|
|
}
|
||
|
|
} catch {
|
||
|
|
return NextResponse.json(
|
||
|
|
{ error: 'Invalid request.' },
|
||
|
|
{ status: 400 }
|
||
|
|
)
|
||
|
|
}
|
||
|
|
}
|