Greylisting and email verification: why some checks come back unknown
· 4 min read · Email validation
Greylisting is an anti-spam technique where a mail server temporarily refuses mail from a sender it hasn't seen before, with a 4xx "try again later" reply. Legitimate mail servers retry and get through; many spam tools don't. For email verification it means the first check of an address on a greylisting server often gets no answer at all. The correct result is unknown, not invalid, and the fix is to check again later.
What greylisting actually does
RFC 6647 defines greylisting as providing temporarily degraded service to unknown email clients as an anti-abuse mechanism. In its common form:
- A sending server connects and starts a delivery.
- The receiving server looks at a tuple, typically the connecting IP address, the
MAIL FROMaddress and the firstRCPT TO. - If it hasn't seen that tuple before, it replies with a temporary failure, usually
450(or421if it closes the connection), and remembers the tuple. - When the sender retries within the accepted window, the server lets it through.
The RFC recommends the accepted retry window default to between one minute and 24 hours. Retries outside that window are treated as new. The RFC also notes that the refusal can happen at several points in the conversation, including at RCPT TO, which is exactly where a verifier asks its question.
The design relies on a real mail server's retry queue. RFC 6647 points out that some popular mail servers don't retry for an hour or more, which delays mail but does get it delivered.
Why it trips up email verification
An SMTP verifier connects, sends MAIL FROM and RCPT TO, reads the reply and disconnects without sending anything. (We walk through the full conversation in SMTP mailbox verification limits.) When the server greylists:
- The reply to
RCPT TOis a 4xx. It says nothing about whether the mailbox exists. - The verifier has no message in a queue to retry. It has to come back later and ask again, from the same IP and with the same
MAIL FROM, or the server treats it as a new tuple. - If the server greylists the catch-all probe too, the verifier can't tell whether the domain accepts every address.
A verifier that turns a 4xx into "invalid" is wrong, and you'll suppress real contacts. A verifier that turns it into "valid" is also wrong, and you'll send to addresses nobody checked.
How pingutil handles it
pingutil's /v1/verify returns status: "unknown" with reason: "greylisted" when the mail server answers with a greylisting response. Two related reasons land in the same bucket: blocked (the server refused the prober itself) and rate_limited (too many checks to that server).
curl -X POST https://pingutil.com/v1/verify \
-H "Authorization: Bearer $PINGUTIL_KEY" \
-H "Content-Type: application/json" \
-d '{"email": "someone@example-greylisting-domain.com"}'
{
"status": "unknown",
"reason": "greylisted",
"checks": { "mailbox": "unknown", "catch_all": null },
"smtp": { "code": 450, "enhanced": "4.2.0", "message": "..." },
"cached": false
}
The response above is trimmed and illustrative. Read the real smtp field to see exactly what the server said.
We cache greylisted, blocked and rate_limited results for one hour, against 30 days for definite answers. So a re-check within the hour returns the cached unknown, and a re-check after it goes back to the mail server. Every request still counts against your daily verification budget, so don't loop on it. The full list of unknown reasons is in the status reference.
What to do with greylisted addresses
The right move depends on where the address came from:
| Source | Suggested handling |
|---|---|
| Signup form | Accept the signup. Your confirmation email is a real message with a real retry queue, so greylisting only delays it. |
| CRM or lead import | Keep the contact, tag it unverified, and re-check after an hour or two. |
| Outbound list | Re-check once later. If it's still unknown, send to it in a small, separate batch and let the bounce result decide. |
| List cleaning before a campaign | Never suppress on unknown. Re-check, then treat persistent unknowns like catch-all addresses. |
A simple pattern for background jobs: store checked_at and reason with the contact, and have a scheduled job pick up rows where reason = 'greylisted' and checked_at is more than an hour old. Re-verify each once, and stop there. If you're building that job, our API integration checklist covers retries, rate limits and caching.
How common is it?
It varies too much by list to quote a number, and we won't invent one. Greylisting is a server-side choice, so it clusters by domain: a list heavy in small companies running their own mail is more likely to see it than a list of Gmail and Outlook users. Count reason = 'greylisted' in your own results and group by domain. If one domain dominates, you're looking at one server's policy rather than a data quality problem.
Greylisting is one of several reasons honest verifiers can't promise an answer for every address. For the rest, see email verification accuracy explained, or try a few addresses in the verification demo.
Questions people ask
- Does greylisting mean the email address is invalid?
- No. Greylisting is a temporary refusal aimed at the sender, not a statement about the recipient. The mailbox may be perfectly real. Treat a greylisted result as unknown and re-check later.
- How long should I wait before re-verifying a greylisted address?
- RFC 6647 says the default window in which a retry is accepted should run from one minute to 24 hours, but each server picks its own settings. Re-checking after an hour or so is a reasonable default; pingutil caches greylisted results for one hour for that reason.