From 4c562ed1847913b700367b3736a0137d2aabb19a Mon Sep 17 00:00:00 2001 From: Harry Turnbull <52940497+hturnbull93@users.noreply.github.com> Date: Fri, 14 Aug 2026 17:17:51 +0100 Subject: [PATCH] Add Turnstile protection to UK MP email form This form POSTs JSON directly to /api/uk-send-mp-email rather than going through a SvelteKit form action, so it had no anti-spam gate like the other forms. Adds the same honeypot + Turnstile check via a FormData shim into the shared checkNotSpam verifier. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01MfJodwSCVy9tEABpf3nfn3 --- src/lib/components/UKMPEmailForm.svelte | 48 +++++++++++++++++++++- src/routes/api/uk-send-mp-email/+server.ts | 23 ++++++++++- 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/src/lib/components/UKMPEmailForm.svelte b/src/lib/components/UKMPEmailForm.svelte index 83795308b..785166644 100644 --- a/src/lib/components/UKMPEmailForm.svelte +++ b/src/lib/components/UKMPEmailForm.svelte @@ -3,6 +3,8 @@ import { micromark } from 'micromark' import LoadingSpinner from './LoadingSpinner.svelte' import Link from '$lib/components/Link.svelte' + import Turnstile from '$lib/components/Turnstile.svelte' + import { turnstileSiteKey } from '$lib/turnstile' import { slide } from 'svelte/transition' interface Props { @@ -44,6 +46,16 @@ ${userPostcode.toUpperCase()}`) let submitStatus: 'idle' | 'success' | 'error' = $state('idle') let errorMessage = $state('') let confirmingSend = $state(false) + let honeypot = $state('') + let turnstileToken = $state('') + + // Bumped after each submission to remount the widget: Turnstile tokens are + // single-use, so a resubmit with the same token would be rejected. + let turnstileNonce = $state(0) + + // Without a configured site key (e.g. local development) there is no widget + // to wait for, and the server decides whether to accept the submission. + const canSubmit = $derived(!isSubmitting && (!turnstileSiteKey || turnstileToken !== '')) let htmlPreview = $derived(micromark(message)) @@ -178,7 +190,9 @@ ${userPostcode.toUpperCase()}`) senderPostcode: userPostcode, recipient: mp.email, subject: subject.trim(), - message: message.trim() + message: message.trim(), + nickname: honeypot, + turnstileToken }) }) @@ -198,6 +212,10 @@ ${userPostcode.toUpperCase()}`) console.error('Email submission error:', error) } finally { isSubmitting = false + + // The token has now been spent (or rejected) either way — get a fresh one. + turnstileToken = '' + turnstileNonce += 1 } } @@ -214,6 +232,18 @@ ${userPostcode.toUpperCase()}`) onsubmit?.(e) }} > +
+ + +
+

Send this email to {mp.name}?

+ {#key turnstileNonce} + + {/key}