import { NextRequest, NextResponse } from "next/server"; import { rateLimited, sendEmail, validateTurnstile } from "@/lib/server-utils"; import { trimTooLong } from "@/lib/strings"; import validator from "validator"; const validateInput = (data: any) => { return ( typeof data !== "object" || ( !data.anon && ( typeof data.name !== "string" || typeof data.email !== "string" ) || typeof data.message !== "string" || typeof data["cf-turnstile-response"] !== "string" ) || !data.anon && ( !data.name.trim() || !data.email.trim() || !validator.isEmail(data.email) || data.email.length > 50 ) || !data.message.trim(), !data["cf-turnstile-response"].trim() ) } export async function POST(req: NextRequest) { const agent = req.headers.get("cf-connecting-ip") ?? req.headers.get("x-forwarded-for") ?? "damn"; let data; try { data = await req.json(); } catch { return NextResponse.json( { error: "Invalid input" }, { status: 400 } ); } const cf_token = data["cf-turnstile-response"]; console.log(`[${agent}] Verify captcha`); if (typeof cf_token !== 'string' || !cf_token.trim()) { return NextResponse.json( { error: "Captcha Failed" }, { status: 403 } ); } const captchaVerified = await validateTurnstile(cf_token, agent); if (!captchaVerified) { return NextResponse.json( { error: "Captcha Failed" }, { status: 403 } ); } console.log(`[${agent}] Verify rate limit`); const isRateLimited = await rateLimited(agent); if (isRateLimited) { return NextResponse.json( { error: "Too many requests" }, { status: 429 } ); } if (validateInput(data)) { return NextResponse.json( { error: "Invalid input" }, { status: 400 } ); } console.log(`[${agent}] Sending email...`); try { const email = data.anon || !data.email ? process.env.SMTP_USER : data.email; const name = trimTooLong(data.anon || !data.name ? 'Anonymous' : data.name, 20); await sendEmail(name, email, data.message); console.log(`[${agent}] Email sended...`); return NextResponse.json({ status: "ok" }); } catch (err) { console.error(err); return NextResponse.json({ status: "failed", message: err instanceof Error ? err.message : '' }); } }