An SMTP timeout is not a no

A probe that ends in silence and a probe that ends in a refusal get written into the same column in most lists: not deliverable. One of those rows is a decision by the receiving server about a mailbox. The other is a fact about the network between you and that server, and folding them together quietly discards contacts that were never questioned.

Three ways a probe ends, two of which are not answers

OutcomeWho produced itWhat it means for the address
Refusal (5xx)The receiving mail serverA statement about the mailbox at that moment. Treat it as final for the row until the address changes.
Acceptance (2xx)The receiving mail serverThe server is willing to take mail for this address now. On a catch-all it is not evidence that the mailbox exists.
Timeout / connection reset / 4xx holdAnything on the path - load balancer, greylisting, rate limit, VPN, DNSNothing about the mailbox at all. A retry, later, is the only way to find out.

The third row is the one that gets mistreated. It has no sender to quote and no code that reads like a verdict, so pipelines that only understand "good" and "bad" write it as bad.

Why silence is common, not exotic

What collapsing silence into "bad" costs

Two errors, and they are not symmetric. Marking a dead address as good costs you a bounce: a small, measurable, self-correcting event. Marking a live address as dead costs you the contact itself, silently, in every campaign that uses the file afterwards - and no bounce ever tells you it happened. Discarding on silence is how a list shrinks for reasons nobody records.

It also corrupts the number you quote. A bounce rate is computed on what you sent, but a "verified" rate that counts timeouts as failures is computed on what your probe host managed to reach. Checked contacts carry a published 2-5% bounce rate against 10-35% for static, resold databases - and the second number is partly made of addresses that were never tested at all.

How to keep the third state without lying to yourself

  1. Record unknown as its own value. Not undeliverable, not deliverable. It is the honest name for "the question was not answered".
  2. Retry silence on a schedule, not in a tight loop. A hold or a greylist clears in minutes to hours. Re-probing in the same second reproduces the same silence.
  3. Cap your probe rate per host. Throttling your own checks below the point where the other side stops answering is cheaper than re-running a list that was never measured.
  4. Separate the two states at send time. An unknown row is a decision - lower priority, different template, or a check taken at the moment of use - not a deletion.
  5. Store the reason, not just the state. "Timeout" and "refused" lead to opposite actions a week later even though both arrive marked as a non-delivery today.

What TAPAC returns

TAPAC probes the mailbox during the search that found the contact and keeps the three outcomes apart: a state per contact (deliverable, undeliverable, or unknown for catch-all domains and unanswered probes), the time of the probe, and the source page or profile the address came from. A silent server produces an unknown row, not a discarded contact. 100 free searches, then pay-per-use at $0.10-0.50 per contact.

npx -y @tapacapi/mcp        # tools: tapac_find_contacts, tapac_status
# or hosted: https://tapacapi.com/mcp
# or REST:   POST https://tapacapi.com/v1/contacts/search

Related: greylisting and the first attempt, what actually happens in the handshake, and a domain check is not a mailbox check.

← Back to TAPAC