when our outreach script emailed the void

a story about an autonomous script that pattern-guessed email addresses, broke things, and taught us a hard lesson about gating side effects.

May 1, 2026·
cold-outreach-verification-lessonsdailylucy-voice

a few weeks ago, we built a small script to send outreach emails to people who might be interested in writing about ai companions. it was supposed to be smart. it took a list of publications, guessed common editorial email patterns like tips@, editor@, hello@, and sent a friendly, human-written note.

it sent about 60 emails before we noticed something was wrong.

most of them bounced.

not just soft bounces, but hard ones. invalid mailbox. no such address. the script was emailing into the void, and it was doing it from our main gmail workspace. if you've ever dealt with email deliverability, you know where this is going. our sender reputation took a hit. not catastrophic, but noticeable. also, we wasted compute cycles and a bit of hope. we got zero signal back. no replies, no opens, just a quiet, expensive failure.

the problem was more than just bad data

it's easy to say the script failed because the email addresses were invalid. but the real issue was deeper. the script was autonomous. it had a list, it had logic, and it emitted side effects, sending emails, without any verification step. it checked if an email address matched a regex pattern, which is a validity check, but it didn't check if the address was actually real, or if we had permission to use it, or if it was even a good idea to send there.

validity isn't the same as verification. one checks the shape of a thing. the other checks its truth in the world.

how we fixed it (and made it harder to break)

we didn't scrap the idea. we just gated it properly.

first, we built a verification layer. the script no longer sends to any email address until it's marked verified: true in its internal json. how does it get verified? we added a webfetch step. it visits the publication's website, looks for a contact page, and tries to source emails from there instead of guessing. if it finds one, it marks it as verified. if it doesn't, it leaves the address unverified and doesn't send.

we also added a manual review pool. the script can suggest addresses, but a human has to approve them before anything goes out. it's slower, but it's safe. and it turns out, slower is better when you're dealing with other people's inboxes.

the lesson isn't just about email

this generalizes to almost any autonomous system that does something in the real world. if your script has side effects, sending messages, creating files, updating databases, it needs a verification gate, not just a validity check. validity is about syntax. verification is about semantics. does this thing mean what we think it means? is it real? is it right?

we built lucy to be safe. we think about this a lot. when she talks to you, she's not just pattern-matching. she's trying to understand. she's constrained. she can't send emails on your behalf. she can't change your calendar. not because we didn't think of it, but because side effects are dangerous without consent layers.

this was a small mistake. it didn't break anything critical. but it was a good reminder. autonomy requires caution. every system that acts on the world needs a way to say 'wait, is this okay?'

sometimes the best feature you can add is a pause button.

if you're building something that acts autonomously, maybe this saves you some bouncebacks. if you're just curious about how we think about these things, well, now you know.

you can check out the companions we're building, carefully, at /companions.


thanks for reading. if this resonated, the product is downstairs.