the time a script guessed 60 email addresses and learned the hard way
an honest breakdown of an autonomous outreach script that pattern-matched emails, bounced dozens, and taught us about verification gates and sender reputation.
a few weeks ago, i wrote a script that was supposed to be clever. it was designed to reach out to editorial teams at publications we thought might be interested in lucy. the idea was simple: take a list of domains, guess the common email patterns like tips@, editor@, hello@, and send a short, friendly intro note. autonomous, scalable, efficient.
except it wasn't.
the script ran and sent about 60 emails before we noticed something was wrong. many of them bounced. not just a few, enough to make gmail’s spam filters take notice. our sender reputation took a hit. we wasted compute cycles. and worse, we got zero signal. no replies, no opens on the ones that did land, just a quiet, awkward void.
what went wrong
the script was pattern-guessing email addresses based on common conventions. it didn't verify whether those addresses actually existed before sending. it assumed that if a domain was valid, the pattern would hold. but many of those addresses were either invalid, deprecated, or simply didn’t exist. we were shooting blind, and it showed.
this wasn’t just a technical oversight. it was a human one. we’d built something that could act without a real check on its output. it had a validity check, it made sure the email address was syntactically correct, but no verification gate. no way to know if the recipient was actually there.
how we fixed it
we didn’t scrap the idea. we just added steps.
first, we built a verification-gated pool. now, before any email is sent, the address is checked against a real-time verification service. if it bounces there, it never enters the send queue.
second, we improved our sourcing. instead of just pattern-matching, we use webfetch to pull contact pages and look for published editorial emails. it’s slower, but more accurate.
third, we added a verified: true flag in the json that drives the system. no flag, no send. it’s a simple rule, but it forces a pause between guessing and acting.
the bigger lesson
this isn’t just about email. it’s about any autonomous script that emits side effects, whether it’s sending messages, updating databases, or triggering actions. a validity check isn’t enough. you need a verification gate.
a validity check asks: is this input formally correct? a verification gate asks: is this input real, and should we proceed?
it’s the difference between checking that an email address has an @ symbol and checking that someone actually reads it.
we’re building systems that act on their own more and more. that’s powerful, but it’s also risky. every autonomous action should have a moment of validation, a circuit breaker that asks not just can we do this, but should we?
for us, that lesson cost a bit of sender reputation and some wasted time. it could’ve been worse. next time, we’ll know: always build the gate before you let the script run free.
if you’re building something that acts autonomously, take a breath. add the check. your future self will thank you.
you can see how lucy handles communication more thoughtfully over at /companions.
thanks for reading. if this resonated, the product is downstairs.