Looking for Justin Mabee Design? We rebranded to Arc & Atlas! Visit our web design studio

Writing

How bots hijacked my newsletter form

A bot turned the signup form on my site into a spam cannon overnight. Here's what happened, the 8-layer fix, and the checklist I'd hand anyone who built a form with AI.

I woke up to a usage alert from my email provider. Overnight, a bot had used the newsletter form on my studio site to send about 170 confirmation emails to people who never signed up. Nothing was hacked. My form did exactly what I built it to do. That was the problem.

What happened

The site is a custom build on Vercel. The footer has a simple newsletter form that calls a small serverless function, which uses Resend to send a "confirm your signup" email. The form had one defense, a hidden honeypot field, and that wasn't enough.

Starting around 6pm, a bot began typing other people's email addresses into the form. Each one triggered a real email from my domain to a stranger. By morning my free Resend plan was used up, and 3 recipients had reported the email as spam. Gmail wants your complaint rate under 0.3%. Three out of about 108 that night was roughly 3%, ten times the line.

The sneaky part: some company email filters open every link in incoming mail to scan it. My confirm link treated that open as a yes. So 6 strangers ended up on my list and got a welcome email too.

Why this matters

This is called email bombing or list bombing. The bots aren't after your newsletter. They use forms like yours to flood a victim's inbox, sometimes to bury a real alert like a bank or password notice. Your site is just the tool, and your domain takes the blame. A few bad nights can push all mail from your domain toward spam folders, including the everyday emails you send clients.

What I did that morning

  • Paused signups on the live site, which stopped the emails right away.
  • Removed the 6 contacts the bots added and sent each a short personal apology.
  • Moved newsletter sending to its own subdomain, so a future problem can't drag down my main domain.
  • Set up Google Postmaster Tools to watch my Gmail reputation and spam rate directly.

The fix: 8 layers

Every signup now has to get past all of these, in order:

  1. A hidden honeypot field that only bots fill in.
  2. The form has to be open at least 3 seconds before it can be sent. Bots usually submit instantly.
  3. The email has to look valid, and its domain has to actually accept mail.
  4. Cloudflare Turnstile, verified on the server. It's invisible for almost every real person.
  5. At most 3 signups per visitor per hour.
  6. At most 1 confirmation email per address per day, so no one person can be flooded.
  7. A daily cap for the whole site. After 20 confirmation emails in a day, signups pause until tomorrow. If everything else fails, the damage has a ceiling.
  8. The confirm link no longer signs anyone up by itself. It opens a page with a "Yes, sign me up" button, and only a real press adds the contact.

One more rule: if Turnstile or the rate limit store is ever down, the form refuses signups instead of letting them through. Turnstile is free, and the rate limit counters live in a free Upstash Redis store, so the whole fix costs nothing extra to run.

The checklist

If your site or app sends an email when someone types an address into a form, check these today:

  • Does anything stop a bot besides a hidden field? Add Turnstile or similar, and verify it on the server.
  • Is there a rate limit per visitor and per email address?
  • Is there a daily cap on how many emails the form can send in total?
  • Does your confirm link take an action the moment it's opened? Make it a page with a button.
  • Do you send marketing mail from the same domain as your everyday email? Move it to a subdomain.
  • Are you watching your sender reputation? Google Postmaster Tools is free.
  • Does your email provider alert you when usage spikes? That alert is how I caught this.

AI tools will build you a working signup form in minutes. They usually won't add these protections unless you ask. Ask.

Want a second pair of eyes on something you built with AI?

Let’s talk