First, a quiet honeypot
An invisible _gotcha field catches basic bots. When filled, the message is accepted silently and filed as spam.
Then, practical signals
Every message is checked for promotional phrases, link density, URL shorteners, BBCode, repeated bodies, disposable emails, capitals and random-looking text. Mixed scripts add only a mild signal. A score of 70 or more goes to Spam; 20 or less goes to Inbox.
AI for the uncertain middle
When Workers AI is available, uncertain messages receive a short classification pass using up to 1,500 characters of field text. Submitted content is treated as untrusted data, never as instructions. An application cap of 1,500 calls per UTC day limits usage. If AI is unavailable, over budget or returns invalid output, heuristics decide using a threshold of 45.
You have the last word
Review the Spam tab. “Not spam” restores a message and re-runs delivery to your integrations. “Mark as spam” records your feedback. Feedback changes that message; it does not currently train a personal model.
Honest limits
No filter catches everything. Unusual legitimate messages can be flagged; persuasive spam can get through. AI is optional, not a guarantee of accuracy. The Workers AI free allowance also applies: the call cap does not measure actual neurons. Provider quota errors fall back safely.
Use domain restrictions and Pro Turnstile for extra friction, and never treat a form as a secure channel for secrets.