From 8990548c6a7c9c351f29d37635c3f7eacf76641e Mon Sep 17 00:00:00 2001 From: Thatsaphorn Atchariyaphap Date: Sun, 27 Apr 2025 18:41:14 +0200 Subject: [PATCH] Refactor contact API route to enhance captcha validation --- app/api/contact/route.ts | 103 ++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 56 deletions(-) diff --git a/app/api/contact/route.ts b/app/api/contact/route.ts index b1597e2..ed31a57 100644 --- a/app/api/contact/route.ts +++ b/app/api/contact/route.ts @@ -1,63 +1,54 @@ -import {NextRequest, NextResponse} from "next/server"; -import nodemailer from "nodemailer"; +import {NextRequest, NextResponse} from 'next/server'; + +const HCAPTCHA_SECRET = process.env.HCAPTCHA_SECRET ?? ''; +const SHARED_API_KEY = process.env.SHARED_API_KEY ?? ''; export async function POST(req: NextRequest) { - const {captcha, ...data} = await req.json(); - const {name, email, company, phone, website, message} = data; - - const isDev = process.env.NODE_ENV === "development"; - const hCaptchaSecret = isDev - ? "0x0000000000000000000000000000000000000000" // hCaptcha test secret - : "ES_ff59a664dc764f92870bf2c7b4eab7c5"; - - // ✅ hCaptcha verification - const captchaRes = await fetch("https://hcaptcha.com/siteverify", { - method: "POST", - headers: {"Content-Type": "application/x-www-form-urlencoded"}, - body: `response=${captcha}&secret=${hCaptchaSecret}`, - }); - - const captchaResult = await captchaRes.json(); - if (!captchaResult.success) { - return NextResponse.json({success: false, error: "CAPTCHA-Verifizierung fehlgeschlagen."}, {status: 403}); - } - - // ✅ Send mail with Ethereal (for dev) or real SMTP later - const testAccount = await nodemailer.createTestAccount(); - const transporter = nodemailer.createTransport({ - host: testAccount.smtp.host, - port: testAccount.smtp.port, - secure: testAccount.smtp.secure, - auth: { - user: testAccount.user, - pass: testAccount.pass, - }, - }); - - const mailToMe = { - from: email, - to: "thatsaphorn@outlook.de", - subject: "Neue Nachricht vom Kontaktformular", - html: ` -

Name: ${name}

-

E-Mail: ${email}

-

Firma: ${company || "—"}

-

Telefon: ${phone || "—"}

-

Webseite: ${website || "—"}

-

Nachricht:

-

${message}

- `, - }; - try { - const info = await transporter.sendMail(mailToMe); + const body = await req.json(); + const origin = req.headers.get("origin") || "http://localhost:3000"; + const captchaToken = body.captcha; - return NextResponse.json({ - success: true, - previewUrl: nodemailer.getTestMessageUrl(info), + if (!captchaToken) { + return NextResponse.json({success: false, error: 'Captcha is required'}, {status: 400}); + } + + // Step 1: Verify hCaptcha token with their API + const verifyResponse = await fetch('https://api.hcaptcha.com/siteverify', { + method: 'POST', + headers: {'Content-Type': 'application/x-www-form-urlencoded'}, + body: new URLSearchParams({ + secret: HCAPTCHA_SECRET, + response: captchaToken, + }), }); - } catch (err) { - console.error("Mail send error:", err); - return NextResponse.json({success: false, error: "Mailversand fehlgeschlagen."}, {status: 500}); + + const captchaResult = await verifyResponse.json(); + + if (!captchaResult.success) { + return NextResponse.json({success: false, error: 'Captcha verification failed'}, {status: 403}); + } + + // Step 2: Forward valid contact request to Spring Boot backend + const backendRes = await fetch('http://localhost:8080/api/contact', { + method: 'POST', + headers: { + "Origin": origin, + 'Content-Type': 'application/json', + 'X-Frontend-Key': SHARED_API_KEY, + }, + body: JSON.stringify(body), + }); + + const backendText = await backendRes.text(); + + if (!backendRes.ok) { + return NextResponse.json({success: false, error: backendText}, {status: backendRes.status}); + } + + return NextResponse.json({success: true, message: backendText}); + } catch (err: any) { + console.error('[ContactAPI] error:', err); + return NextResponse.json({success: false, error: err.message}, {status: 500}); } }