| name | outreach-status-sync |
| description | Daily reconciliation of the Exa Prospect Eval Notion tracker against Gmail. For prospects marked Drafted, checks whether the email was actually sent (Drafted → Sent, records Date Sent). For prospects marked Sent, checks whether they replied (Sent → Replied). Match is per-person via Contact Email. Use for the daily outreach status sync / "update my prospect statuses" / scheduled tracking run. Read-only against Gmail; only writes Status + Date Sent in Notion. |
Outreach Status Sync
Keeps the Prospect Eval Notion tracker honest by reconciling it against what actually happened in Gmail. Runs daily (Claude Code routine). Manual outreach is inconsistent — this closes the gap between "drafted" and "actually sent/replied" without the human updating statuses by hand.
Database: Prospect Eval, data source collection://cfa1565f-e69d-48d4-9022-22e71647078e.
Safety: read-only against Gmail (search only, never send/modify mail). In Notion, only ever writes Status and Date Sent. Never touches Contact Email, Notes, or any human-entered field. Never moves a status backwards (e.g. Replied → Sent).
Step 1 — Pull rows that need checking
Query the data source for rows where Status is Drafted OR Sent, AND Contact Email is not empty.
- Rows with blank
Contact Email are skipped — the human hasn't sourced the address yet, so nothing could have been sent. (These are expected and not errors.)
Drafted rows → candidates for the Sent check.
Sent rows → candidates for the Replied check.
Step 2 — Drafted → Sent
For each Drafted row with a Contact Email:
- Search Gmail:
in:sent to:<Contact Email>.
- If one or more sent messages exist:
- Set
Status = Sent.
- Set
Date Sent = the date of the earliest sent message to that address (the opener, not a later bump).
- If no sent message: leave the row as
Drafted (not yet sent — correct).
Step 3 — Sent → Replied
For each Sent row with a Contact Email (including rows just moved to Sent in Step 2):
- Search Gmail for a reply from that contact:
from:<Contact Email> within threads Hacktron started, OR check the thread of the original sent message for an inbound reply from that address.
- A reply = an inbound message authored by the contact (not an auto-reply/bounce — ignore messages from
mailer-daemon, postmaster, or with subjects like "Delivery Status Notification" / "Undeliverable" / "Out of office" / "Automatic reply").
- If a genuine reply exists: set
Status = Replied.
- If not: leave as
Sent.
Step 4 — Bounce awareness (report only, no status change)
While checking, if a sent message to a Contact Email produced a bounce (a mailer-daemon/postmaster message referencing that address), note it in the run summary so the human can re-source the address. Do NOT change the row's Status for a bounce (there's no Bounced option in this DB's Status field) — flag it in the summary instead.
Step 5 — Run summary
Output (and optionally post to #sales-marketing C0AMV9GT659 if run wants a record):
Outreach status sync — [date]
Drafted → Sent: [n]
- [Contact Name] ([Company]) — sent [date]
Sent → Replied: [n]
- [Contact Name] ([Company])
Bounced (needs re-source): [n or none]
- [Contact Name] ([Company]) — [email] bounced
Unchanged: [n] still Drafted (not yet sent), [n] still Sent (no reply yet)
Skipped (no Contact Email yet): [n]
Rules recap
- Read-only on Gmail; only
Status + Date Sent written in Notion.
- Match strictly on
Contact Email (per person). Never guess or infer from company domain.
- Skip rows with blank
Contact Email — not an error, just not sent yet.
- Never move a status backwards. Never overwrite human-entered fields.
- Ignore auto-replies, bounces, and out-of-office as "replies."
Date Sent = earliest genuine sent message to that address (the opener).
- Bounces are reported, not written as status (no Bounced option exists in this DB).