feat: add captcha verification to contact form
Added math-based captcha system to prevent spam on the contact form: - Created captcha API endpoint with simple arithmetic questions - Added captcha UI component with refresh functionality - Integrated captcha verification into contact form submission - Relaxed spam filters since captcha provides better protection 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { smtpService } from '@/lib/smtp'
|
||||
import { verifyCaptcha } from '@/lib/captcha'
|
||||
import { z } from 'zod'
|
||||
|
||||
export const runtime = 'nodejs'
|
||||
@@ -8,7 +9,9 @@ const contactSchema = z.object({
|
||||
name: z.string().min(1, 'Name is required').max(100),
|
||||
email: z.string().email('Invalid email address'),
|
||||
subject: z.string().min(1, 'Subject is required').max(200),
|
||||
message: z.string().min(10, 'Message must be at least 10 characters').max(5000)
|
||||
message: z.string().min(10, 'Message must be at least 10 characters').max(5000),
|
||||
captchaId: z.string().min(1, 'Captcha ID is required'),
|
||||
captchaAnswer: z.string().min(1, 'Captcha answer is required')
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
@@ -25,21 +28,26 @@ export async function POST(request: NextRequest) {
|
||||
}, { status: 400 })
|
||||
}
|
||||
|
||||
const { name, email, subject, message } = validationResult.data
|
||||
const { name, email, subject, message, captchaId, captchaAnswer } = validationResult.data
|
||||
|
||||
// Basic spam prevention - check for common spam indicators
|
||||
const spamIndicators = [
|
||||
message.includes('http://'),
|
||||
message.includes('https://'),
|
||||
message.includes('www.'),
|
||||
message.includes('bitcoin'),
|
||||
message.includes('cryptocurrency'),
|
||||
message.length < 10,
|
||||
name.length < 2
|
||||
]
|
||||
// Verify captcha
|
||||
const isValidCaptcha = verifyCaptcha(captchaId, captchaAnswer)
|
||||
|
||||
const spamScore = spamIndicators.filter(Boolean).length
|
||||
if (spamScore >= 2) {
|
||||
if (!isValidCaptcha) {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: 'Invalid captcha answer. Please try again.'
|
||||
}, { status: 400 })
|
||||
}
|
||||
|
||||
// Basic spam prevention - only check for obvious spam
|
||||
// Allow URLs in messages since users may want to share links
|
||||
const isSpam = (
|
||||
(message.includes('bitcoin') || message.includes('cryptocurrency')) &&
|
||||
(message.includes('http://') || message.includes('https://'))
|
||||
)
|
||||
|
||||
if (isSpam) {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: 'Message flagged as potential spam'
|
||||
|
||||
Reference in New Issue
Block a user