Verify your cold email list every morning before sending

Every weekday at 6am, verify every pending cold email, sort the list into ready-to-send and do-not-send tabs, and post a summary in Slack.

Deterministic Code
Waterfall.ioGoogle SheetsSlack BotSalesOperationsEmail AutomationData SyncDaily Digests

Every weekday at 6:00 AM Eastern Time, run a deterministic email verification workflow that cleans up the day's cold email list before my outreach tool picks it up. Build this as a code workflow with discrete nodes and explicit branching by status. No judgment calls or AI drafting — pure CRUD.

Step 1. Read pending rows from Google Sheets. Use Get Values on the 'pending-verification' tab of my Google Sheet. The sheet has these columns in this order: email, status, smtp_provider, mx_records, verified_at. Filter in the workflow to only the rows where the status column is empty — those are the ones that still need verification.

Step 2. Verify each pending email with Waterfall.io. For each pending row, call Waterfall.io Email Verification with the email address. This endpoint is synchronous and returns status (one of valid, invalid, risky, unknown), smtp_provider, and mx_records. Capture all three plus the current ISO 8601 timestamp as verified_at.

Step 3. Write the results back. Use Google Sheets Batch Update Values to write status, smtp_provider, mx_records, and verified_at to the matching rows on the 'pending-verification' tab in one batched call (not row-by-row).

Step 4. Bucket rows by status. Group the just-verified rows by status. Use Google Sheets Batch Update Spreadsheet to move rows by status: rows with status 'valid' get appended to the 'ready-to-send' tab and deleted from 'pending-verification'; rows with status 'invalid' get appended to the 'do-not-send' tab and deleted from 'pending-verification'. Rows with status 'risky' or 'unknown' stay on the 'pending-verification' tab for human review. Do the appends and deletes in batched operations so the sheet stays consistent.

Step 5. Post a Slack summary. Using the Slack Bot integration, send one message to the #cold-email-ops channel containing today's date, the count of rows in each bucket (valid, invalid, risky, unknown), and a clickable link to the spreadsheet. Keep it to a single short message — no thread, no follow-ups.

Edge cases to handle: if there are zero pending rows, skip Waterfall.io and the sheet writes entirely but still post a brief Slack message saying 'No emails to verify today' with the date and spreadsheet link. If a Waterfall.io call returns a provider error, leave that row's status empty so it gets retried on the next run, and include an 'errors' count in the Slack summary if any occurred.

Additional information

What does this prompt do?
  • Reads new email addresses from your verification tab every weekday morning before your outreach tool sends to them.
  • Checks each address for deliverability and labels it as valid, invalid, risky, or unknown.
  • Moves clean addresses to a ready-to-send tab and bad ones to a do-not-send tab so you stop wasting sends.
  • Posts a short summary in your ops Slack channel with today's counts and a link to the spreadsheet.
What do I need to use this?
  • A Google Sheet with one tab for emails to verify and two tabs for clean and bad addresses.
  • A Waterfall.io account for email verification.
  • A Slack workspace where the bot can post to your cold email ops channel.
How can I customize it?
  • Change the run time or which days it runs (for example, every hour during business days, or seven days a week).
  • Pick a different Slack channel for the summary, or send it as a direct message instead.
  • Decide how risky and unknown addresses are handled, such as auto-skipping them or leaving them for human review.

Frequently asked questions

Will this stop my cold emails from bouncing?
Yes. Sending to invalid addresses is the main driver of bounce rates and domain reputation damage. By verifying every address before your outreach tool picks it up, you only send to mailboxes that are confirmed deliverable.
How does it know which emails are new?
It reads only the rows where the status column is empty. Once a row has been verified, the status is filled in and the row is skipped on the next run.
What happens to addresses marked risky or unknown?
They stay on the verification tab so you can decide manually. Only confirmed valid addresses move to ready-to-send, and only confirmed invalid ones move to do-not-send.
Can I use this with my own cold email tool like Smartlead or Instantly?
Yes. Your outreach tool just reads from the ready-to-send tab. This workflow's job is to keep that tab clean and current every morning before sending starts.
What does the Slack summary look like?
One short post in your ops channel with today's date, a count for each status (valid, invalid, risky, unknown), and a link to the spreadsheet so anyone can dig into the details.

Stop sending cold emails to bad addresses.

Connect Google Sheets, Waterfall.io, and Slack once, and Geni verifies every address before your outreach tool sends to them.