Skip to content

List quality: verify before sending, 2% bounce gate, retire bounced addresses - #126

Merged
ralyodio merged 1 commit into
mainfrom
feat/planner-list-quality
Oct 7, 2026
Merged

ralyodio merged 1 commit into
mainfrom
feat/planner-list-quality

Conversation

@ralyodio

@ralyodio ralyodio commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

First of the Hunter outreach-planner features, fully automated (no new settings).

What it does

  • Verify before sending. Each address is checked before its first message and again after 90 days: MX lookup, then an SMTP RCPT probe if port 25 allows it. If the port is blocked, the address is sent on MX alone. Verdicts are cached in email_verifications (valid / catch_all / unverified / invalid). Each run makes at most 25 fresh checks.
  • Bounces retire the address. When a delivery report names the address that bounced (or the headers confirm the bounce), that address is marked invalid permanently and the person's active cadences stop. The candidate query skips invalid addresses, so a person with a second address falls back to it.
  • 2% gate per campaign. If more than 2% of a campaign's emails bounce, once it has 50+ sends, it pauses itself (campaign_list_health) and re-verifies everything still queued. The first complete pass with nothing left to re-check resumes it on a fresh window. Pause and resume both show up in the live event feed.
  • Accept-all addresses are a separate list. They are held while the campaign's bounce rate is above 1%, so they can never be what trips the gate.
  • Surfaces: GET /autogtm/campaigns/:id/list-health (in the OpenAPI doc), og leads health <campaignId>, MCP get_list_health.

Policy stays deterministic, and none of these gates call a model. Migration 0053 adds two new tables and alters nothing that exists.

Tests: list-quality.test.ts (9 tests, using a fake resolver and prober, so no network). autopilot, receive-email, mcp and cli suites all pass locally (108 tests). Typecheck and formatting are clean.

🤖 Generated with Claude Code

…retire bounced addresses

Hunter's outreach planner, run by the worker instead of remembered by a person:

- Every address is verified before its first message and again after 90 days
  (MX, then an SMTP RCPT probe where port 25 allows; a blocked port sends on
  MX alone). Verdicts are cached in email_verifications, 25 fresh checks per run.
- A bounce the delivery report pins to an address marks it invalid for good
  and stops the person's cadences. The sender query skips invalid addresses.
- A campaign whose bounce rate passes 2% over 50+ sends pauses itself,
  re-verifies every queued address, drops the failures and resumes on a fresh
  window once a complete pass finds nothing waiting (campaign_list_health).
- Accept-all addresses send only while the campaign bounces at or under 1%.
- GET /autogtm/campaigns/:id/list-health, og leads health, MCP get_list_health.

Migration 0053.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ralyodio
ralyodio merged commit 7279672 into main Oct 7, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant