Repository navigation
feat(leads): track opens, and read replies out of the mailbox - #152
Conversation
The funnel could count sends and nothing else, because a send is something this application does and a reply is something that happens elsewhere. Everything past "contacted" waited on somebody remembering to mark it, so a funnel left alone reported a reply rate of structurally zero — which reads as a verdict on the campaign rather than on the bookkeeping. Opens are tracked per send rather than per campaign. A campaign-level pixel can only say that somebody opened something, which is not a fact anybody can act on; per send it says which person opened which email, which is what decides who to chase. The honest caveat is built in rather than written on a help page: privacy proxies fetch every image the moment mail arrives, so loads carrying a proxy fingerprint or arriving implausibly fast are counted separately and kept out of the total. The number is a floor. The UI says so, and the open rate divides by tracked sends rather than by every send ever, so a healthy campaign does not appear to decline as its pre-tracking history accumulates behind it. Replies come from the mailbox connected in #126, which has stored IMAP settings all along and never been read. Two findings from running it against a real inbox, both now fixed and pinned: A cap on an oldest-first walk reads two-week-old mail forever and never reaches today. The first run scanned 200 messages and matched nothing; searching first and taking the newest slice found a match in the same window. And that match was wrong. A Huntress marketing blast came from a contacted domain, from a plausible address, and was counted as a reply — marking the prospect replied. Its headers say plainly what it was: List-Unsubscribe, Feedback-ID, no In-Reply-To, no Re:. So bulk fingerprints now count as automatic, and the domain fallback requires some evidence of being a response at all. Sends record their own Message-Id, so a reply that names it in In-Reply-To matches the exact send rather than being inferred from a domain. Auto-replies are recorded and flagged, never counted. Verified against the live mailbox: the newsletter no longer matches, and three helpdesk acknowledgements carrying Auto-Submitted: auto-replied are kept out of the reply rate. The bad row and the prospect status it changed have been reverted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
vu1nz Security Review0 finding(s) in PR #? No security issues found. |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Warning Review the following alerts detected in dependencies. According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.
|
Everything past "contacted" waited on somebody remembering to mark it, so a funnel left alone reported a reply rate of structurally zero — a number that reads as a verdict on the campaign rather than on the bookkeeping.
Opens: per send, and honest about the error bar
Per send, not per campaign — a campaign-level pixel only says somebody opened something, which nobody can act on.
Privacy proxies fetch every image the instant mail arrives. Those loads are counted separately and kept out of the total:
The number is a floor, and the UI says so. Open rate divides by tracked sends, not every send ever — otherwise a healthy campaign appears to decline as its pre-tracking history piles up behind it.
Replies: two findings from the live mailbox
The mailbox connected in #126 has had IMAP settings stored all along and was never read. Running it for real found two bugs that no unit test would have.
1. A cap on an oldest-first walk never reaches today.
2. That one match was wrong. A Huntress marketing blast, from a contacted domain, from a plausible address, marked the prospect
replied. Its own headers say what it was:Three independent signals. So: bulk fingerprints now count as automatic, and the domain fallback requires evidence of being a response at all. Sends also record their own
Message-Id, so a reply naming it inIn-Reply-Tomatches that exact send instead of being inferred from a domain.Verified against the live mailbox
The newsletter no longer matches. The three that do all carry
Auto-Submitted: auto-replied(helpdesk acknowledgements) — recorded, flagged, kept out of the reply rate. The bad row and the prospect status it changed have been reverted.Both of those also reference our real sent Message-Ids, confirming the threading path works.
Checks
tsc --noEmitclean · 1,014 tests pass (65 new) · build compilescrawlproof-outreach-repliesscheduled and activeimapflowadded, externalised innext.config.ts(raw TLS sockets, must not be bundled)🤖 Generated with Claude Code