CrawlCheck

Findings · 2026-09-30 · By · 0 views

Five days of our alerts went to an address with no mailbox

Every alert was accepted by the sending API and dropped by a suppression list, because the operator address had no mailbox after a mail migration. What passed, what was measured, and the canary that would have caught it.

From 19 to 24 September 2026 every operational alert from crawlcheck.io was accepted by the send-email binding and dropped, because hello@crawlcheck.io had no mailbox after the domain's mail moved to Google Workspace: the first message hard-bounced and the address was suppressed. Logs said sent; the daily brief cron reported success; every check measured sending, none measured receipt. Fixed by routing alerts to a mailbox that exists and clearing the suppression; the alias itself is still to be created. The check that catches this is a daily canary confirmed on receipt.

For five days in September every alert this service sends to its own operator was accepted by the sending API, recorded as sent, and never read by anyone, because the address it was sent to did not have a mailbox behind it. Nothing errored. The daily brief ran on schedule and reported success. This post is what happened, why every check we had passed while it was happening, and the one check that would have caught it on day one.

The setup #

crawlcheck.io sends mail from a Cloudflare Worker through Cloudflare's send-email binding. The messages are the operational kind: a new lead, a scan that changed grade, a daily brief from the monitoring worker, a comment waiting for approval. The destination for the operator copies was hello@crawlcheck.io, which was also the address printed on the site, in DNS records and in third-party profiles. On 18 September the domain's mail was moved onto Google Workspace: MX records changed, an admin mailbox created. hello@ was going to be an alias on that mailbox. The alias was not created that day.

What a hard bounce does to a sending system #

The next message to hello@ reached Google's servers, which now held the domain's MX, and Google answered that the user did not exist. That is a hard bounce, a permanent failure, and a sending system treats it the way it should: it puts the address on a suppression list so it does not keep hammering a mailbox that is not there. From that moment, every message the Worker addressed to hello@ was accepted by the binding, marked as suppressed on the sending side, and dropped. The Worker's own logs said sent. The binding did not error, because from its point of view the call succeeded; suppression is a delivery decision, not a send failure.

LayerWhat it reportedWhat was true
Worker codeemail sent, no exceptionthe call was accepted
send-email bindingacceptedaddress suppressed after the first hard bounce
Google Workspace MXuser unknown (once)no alias existed
daily brief cronran, successran, wrote a message nobody received
monitoringevery check greenevery check measured the sending side

Why nothing caught it #

Every check in place measured the act of sending. The cron had run. The function had returned. The count of messages sent that day was the expected count. None of them measured receipt, and receipt is the only thing that matters for an alert. This is the same failure shape as the timestamp proofs that said pending for 26 days: the monitoring confirmed the job ran and never opened the result. The earlier email post, one character of undeliverable email, had already shown that a sending address can be wrong by a character and still return success; this was the receiving address, wrong by an entire mailbox, with the same outcome.

How it was found #

Not by an alert. On 24 September, while verifying that the monitoring worker's daily brief was carrying its first real change findings, the question was asked directly: did the brief arrive? It had not, for five days. The suppression entry was found on the sending side, dated 19 September. The lead notifications, grade-change alerts and comment-moderation links from those five days had all gone the same way. The leads themselves were stored, since the Worker writes the record before it sends the notification, so nothing was lost that could not be recovered by reading the records; what was lost was five days of knowing.

The fix, and what is still open #

Two changes the same day. The operator destination was pointed at a mailbox that verifiably existed, and the suppression entry was cleared so the binding would attempt delivery again. A test message was sent and its arrival confirmed by reading it, not by reading the send log. The alias itself, hello@ on the Workspace mailbox, is the piece that turns this from a workaround into a fix, and as of this writing it is still to be created; until it is, the operator copies go to the mailbox that exists and the address printed on the site is one that bounces. That is stated here rather than smoothed over because the site's proposition is that claims should be checkable, and a contact address that does not receive mail is a checkable claim.

Why the address was wrong in the first place #

The migration was done in the right order for mail: MX first, then mailboxes. It was done in the wrong order for alerts, because the alert destination was already in production and pointing at an address that only existed on paper. Before the MX change, mail to hello@ went to the previous provider, where it was delivered; the change of MX moved the address to a provider that had never heard of it. Nothing in the migration checklist asked which addresses the Worker was already sending to. The fix to the process is a line in that checklist, and it is now there: list every address the code sends to, and confirm each one receives before the MX record moves.

The check that would have caught it #

A canary: one message per day to the operator address, from the same binding, carrying a token, and a receiver that reads the mailbox and confirms the token arrived. The alert is on the absence of the token, not on the failure of the send, because the send never fails. It is a small amount of code and it is the only kind of check that measures the thing an alert is for. The trust center lists which addresses send from this domain and how each authenticates; the sending-side facts there were all true throughout the five days, which is the point.

Live, as you read this: the corpus now holds 7,808 domains across 2,465 scans. The figures in this piece were measured on the date above; this line is not.

Every figure above came out of this scanner.

Point it at your own domain and see the same measurements, free.

Scan a domain — free

The main product

Found this on your own site? We fix it for $749.

Scan free to see where you stand. The fix is one site, every finding implemented and re-measured, with a sealed before and after.

Questions this post answers

What happened to the alerts?

The operator address had no mailbox behind it after the domain's mail moved to Google Workspace. The first message hard-bounced, the sending system suppressed the address, and every later message was accepted and dropped for five days.

Why did the Worker's logs say sent?

The send-email binding accepted each call. Suppression after a hard bounce is a delivery decision on the sending side, not a send failure, so nothing raised an exception.

Were any leads lost?

No. The Worker stores the lead record before it sends the notification, so the records were intact. What was lost was five days of the operator knowing about them promptly.

How was it discovered?

By asking whether the monitoring worker's daily brief had actually arrived, while verifying an unrelated change. It had not arrived for five days.

What was changed?

The operator destination was pointed at a mailbox that verifiably exists, the suppression entry was cleared, and a test message's arrival was confirmed by reading it. The hello@ alias on the Workspace mailbox is still to be created.

What check catches this class of failure?

A daily canary message carrying a token, with a receiver that confirms the token arrived, alerting on absence of receipt rather than on failure of the send.

Related findings

How anything measured in this article was measured15client identitiesone second, one address5machine filesapex and www114named agentsresolved from robots.txt24sections scoredreach, read, quoteHow anything measured here was measured15 client identities5 machine files114 named agents24 sections scoredone second, one addressapex and wwwresolved from robots.txtreach, read, quote
No account, nothing installed, and the same sequence on every domain — which is what makes one scan comparable to another. Run it on your own site.

Comments

Comments are read before they appear. Nothing is published automatically, and no account is needed.

Writing about this? Facts, live figures and marks — every number on that page is dated and traceable to a scan.

All findings · The dataset · How the dataset works