The Banned Sender
Incident & fix · Email deliverability · Camellia / all properties · Sat Aug 16, 2026 · Fix shipped & live-verified — two 1-minute ops steps remain
Handoff to Gera — "we still land in Gmail spam" (Oct 20, 2026)
Everything done since Aug 16, the live state today, and what is still untested. Read-only investigation; nothing was changed. Owner from here: Gera.
In one paragraph. Authentication is green: SPF, DKIM and DMARC pass on real messages, we send from our own dedicated address with matching reverse DNS, SendGrid reputation is 99 and spam complaints are zero. Gmail still files some of our mail as spam. The two things nobody has looked at are Google Postmaster Tools (domain reputation and Google's own spam rate, never opened since Gera shared the link on Sep 16) and the headers we stamp on 1:1 mail (Precedence: bulk + Auto-Submitted with no unsubscribe link, which is how a bulk sender looks to Gmail). Start there.
Two ways mail leaves, and what Gmail sees on each
What is green today (checked live Oct 20)
| Check | State | Evidence |
| SPF / DKIM / DMARC on a real message | pass | Sep 16 headers; weekly DMARC digest "all senders aligned" six weeks running (Sep 14 → Oct 19, 553 msgs seen by Google last week) |
| Dedicated sending IP + reverse DNS | ok | 159.183.90.163 ↔ o1.o1.propflowai.co, forward and reverse match |
| SendGrid domain + DKIM keys | valid | em6589 CNAME, dkim1, dkim2 all valid; account reputation 99 |
| Spam complaints | 0 | 0 of 1,965 delivered since Sep 20 (Google's limit is 0.3%) |
| Link rewriting through sendgrid.net | off per send | Turned off in code on Sep 10 after a Western Slope invite went to spam twice. Trap: the SendGrid account default is still ON, so any send not going through the main send function inherits it |
| Invisible preheader text | fixed | Sep 16; SpamAssassin score 2.5 → 0 |
| Self-inflicted hard bounces | fixed | Sep 4–9: 156 of 169 bounces were our own fake test inboxes (133 in one day). Guard refuses them since Sep 16; 9 bounces in the last 30 days. Note: those addresses were on our Amazon inbound domain, so Google never saw that spike; do not wait for "recovery" from it |
| DMARC policy | monitor only | p=none, reports to fede@. The weekly check has said "ready for quarantine" since Sep 14. Cloudflare DNS change, Fede's press |
| Google Postmaster Tools | never read | Gera shared the link Sep 16; no session, script or secret touches it. Domain/IP reputation and Google's measured spam rate are unknown |
| Bulk-style headers on 1:1 mail | suspect | 33 send sites stamp Precedence: bulk + Auto-Submitted: auto-generated; no List-Unsubscribe anywhere. Includes prospect-facing mail: the application-link email (3 sites) and tour emails |
Confirmed spam cases (only these are reproduced)
- Sep 10 — Western Slope invite email, twice, all auth passing. Cause found: tracked links on a sendgrid.net host. Fixed.
- Sep 30 — two Clara emails from clara@propflowai.co into our own Google Workspace inbox, both spam, all auth passing (open issue #14007). Headers on them:
Precedence: bulk, Auto-Submitted, no unsubscribe, logo as the only link.
- No confirmed sample yet of a Clara reply landing in a real lead's Gmail spam. Fede's Oct 20 report ("we still go into Google spam") needs the specific message.
Ranked suspects, with the test for each
| # | Suspect | Why | Test (Gera) |
| 1 | Domain reputation is low or "bad" at Google | Nobody has looked. Low volume (~40–80 msgs/day to Gmail) plus a young domain keeps reputation fragile | Open Postmaster Tools for propflowai.co: domain reputation, IP reputation, spam rate, 30 days. Panels may be thin at our volume |
| 2 | Bulk-shaped headers on human mail | Gmail treats bulk-looking mail without an unsubscribe as spam-prone. We stamp it on prospect app links and staff notices | Send the same message twice to a fresh Gmail with and without the three headers; compare folder. Recommendation: strip the bulk headers from human-addressed mail rather than bolting unsubscribe onto 1:1 replies (Google's one-click rule only binds at 5,000/day; we are far under) |
| 3 | Some sends still carry open/click tracking | Tracking was turned off per send on Sep 10, yet SendGrid recorded 101 opens and 12 clicks since Sep 20. That is only possible if some send path bypasses the main send function and inherits the account default (ON), which rewrites links through a sendgrid.net host: the exact mechanism that spammed the Western Slope invite | Pull the SendGrid event log for click/open events and group by category/custom args to find the path; route it through the main function. Also read the "Show original" spam banner on the actual spam-foldered copy |
| 4 | DMARC at p=none | Small trust factor, not a cause on its own | Move to quarantine once Postmaster is clean (Fede's press) |
| 5 | Lane B (customer's Microsoft mailbox) | Nothing on propflowai.co helps this lane. Not inspected | Per customer: DKIM selector1/selector2 enabled in their M365, their DMARC state |
Ruled out: apex SPF (no SendGrid include, but SendGrid's envelope subdomain passes on its own and relaxed alignment accepts it; the weekly digest confirms). Not a lead.
First steps for Gera
- Open Google Postmaster Tools for propflowai.co and record domain reputation, IP reputation and spam rate on this page.
- Get the exact spam-foldered message from Fede and read "Show original" (auth results + Gmail's spam reason).
- Run the header A/B in suspect 2; if it moves the needle, remove
Precedence: bulk / Auto-Submitted from human-addressed sends (one PR, no switch, it is a fix).
- Set SendGrid account-level open and click tracking OFF so no stray send path rewrites links (Fede's press, third-party prod config).
- Check Lane B per customer.
Two presses for Fede
| Write | Where | Recommendation |
DMARC p=none → p=quarantine; pct=100 | Cloudflare DNS, _dmarc.propflowai.co | yes — six clean weekly reports, all senders aligned |
| Open + click tracking OFF at account level | SendGrid tracking settings | yes — removes the sendgrid.net link trap for any send that bypasses the main function |
Sources: SendGrid API and Cloudflare zone read Oct 20; weekly DMARC digest posts in #updates-fede (Sep 14 → Oct 19); #tickets-bugs thread "spam-broken-images" (Sep 16); GitHub issue #14007; PRs #7686, #8860, #8863; code in the email client and the application-link sender.
In one paragraph. Clara's emails travel through SendGrid, and until tonight we sent from a shared address pool — many unrelated companies, one reputation. A stranger on that pool spammed; Microsoft banned two of the pool's addresses; and since the JP office's email runs on Microsoft, four of Clara's office-bound emails bounced (two signature reminders, one tour confirmation, one tour cancellation) — silently, because the system that should report bounces was never switched on. Tonight both problems were fixed: Clara now sends from her own dedicated address (verified: Microsoft accepted a test into the Camellia mailbox over the new address), and every future hard bounce will page #alerts in plain English instead of vanishing.
What failed, in order
- Cause Shared SendGrid pool → a stranger's spam → Microsoft error
550 5.7.511 banned sender on two pool addresses (167.89.40.80, 50.31.49.42). Our own SendGrid reputation: 100/100 — this was not our behavior.
- Blast radius Intermittent (SendGrid rotates addresses): some office email got through, four messages died — Warren + Guerra signature reminders, the Brownlee Tue Aug 18 1 PM tour confirmation, the Wetzel Sat tour cancellation.
- Why silent SendGrid's event reporting (the channel that tells our app "this bounced") was never configured — zero webhooks on the account. Even our existing renewal bounce-handling code has never received an event in production. A signing key half-installed 3 months ago suggests the wiring was started and never finished.
What shipped tonight
| Item | Status | Proof |
SendGrid Pro upgrade (Fede) + dedicated sending address 159.183.90.163, attached to the propflowai.co domain auth | Live | Test email to the Camellia mailbox delivered over the new address — Microsoft answered 250 … Queued mail for delivery; SendGrid log shows outbound_ip_type: dedicated |
| SendGrid event reporting switched on (bounce / dropped / blocked / spam-report → our app, cryptographically signed) | Done | Webhook propflow-prod-delivery-failures on the account |
| Bounce alarm: any hard failure to a real recipient posts one plain-English #alerts message (batch-deduped, test traffic excluded, Slack-outage-proof) | PR in review | PR #5802, auto-merges on green |
| No real person stuck on SendGrid's "never email again" list | Verified | Suppression lists hold only smoke/test fixtures |
Two 1-minute steps for Fede (agent is blocked on both by design)
1. Give production the webhook signing key
Paste in a terminal at the repo (key sits in the session scratchpad file sg_signed.json; or copy it from SendGrid → Settings → Mail Settings → Event Webhook → signature verification):
npx vercel env add SENDGRID_EVENT_WEBHOOK_PUBLIC_KEY production (then the same with preview). Next deploy picks it up; until then bounce events are rejected loudly, by design.
2. One DNS record in Cloudflare (reverse DNS — providers trust an address that answers with our name)
propflowai.co zone → add A record: name o1.o1.propflowai.co → 159.183.90.163, DNS-only (gray cloud). Then tell the agent — validation from our side takes one API call.
Still open (recommendation, not done)
- Brownlee's Tuesday 1 PM tour — the office never got the confirmation; a human at JP should re-confirm it exists on their calendar.
- DMARC is at the correct minimum (
p=none, reports to Fede). Recommendation after 2–4 clean weeks on the dedicated address: tighten to quarantine. Not urgent, should be a deliberate step.
- New addresses normally "warm up" over ~2 weeks; at our volume (~50 emails/day) we're inside day-one limits, but expect the occasional deferral (delayed, not lost) in week one — the new alarm makes any real loss visible.