RFC 6647 — Email Greylisting
How greylisting works (tuple mechanics, timing windows, reply codes), the IETF recommendations for greylisters, and what senders must do — same-IP retries, pool interactions — to pass it.
RFC 6647 (Standards Track BCP-style applicability statement, 2012) documents greylisting: temporarily degrading service to unknown email clients as an anti-abuse mechanism. It exploits the fact that much spamware fires-and-forgets and never retries after a 4xx temporary failure, while a compliant MTA queues and retries per RFC 5321 §4.5.4. For a sender, greylisting is the single most common reason a first delivery attempt to an unfamiliar receiver is deferred — and the reason retry design must be greylist-aware.
How greylisting is applied (the five variants)
The RFC catalogs greylisting by the SMTP stage at which the decision is made and what is recorded:
| Variant | What is recorded | Behavior toward unknown/under-aged entries |
|---|---|---|
| Connection-level | Source IP (or hostname) only | 421 and close, or 4yz to all further commands, until the source reaches a minimum age (e.g., 30 minutes) |
| HELO/EHLO-level | Tuple (source IP, HELO/EHLO parameter) | 4yz replies while tuple absent or under minimum age |
| MAIL-level | Tuple (source IP, RFC5321.MailFrom) | Same |
| RCPT-level | Tuple of recipient + any combination of source IP, MailFrom, other recipients | Same |
| DATA-level | Tuples adding RFC5322.From/To, Subject, message digests, body analysis; applied at DATA or after the final . |
Same — the most expensive form for both sides |
The canonical form — and the one the RFC recommends implementing — is the triplet (IP address, RFC5321.MailFrom, first RFC5321.RcptTo).
Reply codes
"Per RFC 5321, the only two reasonable choices are 421 if the implementation wishes to terminate the connection immediately, and 450 otherwise." A greylisting deferral therefore looks exactly like any other soft failure; nothing in the reply reliably identifies it as greylisting (some receivers say "greylisted" in the text — always log full reply text).
Timing parameters (Section 5 recommendations to greylisters)
| Parameter | RFC recommendation |
|---|---|
| Retry-acceptance window | MUST be configurable; default SHOULD be 1 minute to 24 hours (retry before the minimum delay restarts/extends nothing in the sender's favor; retry after the maximum finds the record expired) |
| Record lifetime after passing | Database-entry timeout MUST exist; default SHOULD be at least one week — IPs with no recent traffic are then deleted and must re-qualify |
| After a successful retry | Allow all further SMTP traffic from that IP address regardless of envelope information (i.e., passing once whitelists the IP, not just the tuple) |
Other MUST/SHOULD items for greylisters:
- All inbound border MTAs of an ADMD listed in DNS SHOULD share a common greylisting database and common policies — otherwise a sender retrying to a different MX starts the clock over, amplifying delay.
- MAY track CIDR blocks (e.g., /24) or domain-based groupings so clustered outbound farms qualify as a unit.
- MUST provide a manual override (exception list) for IPs/network blocks.
- Greylisting SHOULD NOT be applied on the submission service for authenticated clients, nor against any authenticated session.
Exceptions / whitelisting (Section 2.7)
Exception sets may name IP addresses, CIDR blocks, host names, or domain names exempt from greylisting. Candidates: hosts known to retry properly, and hosts that rarely send. DNS-based whitelist services (allowlists) can serve as a shared exception source.
What senders must do
RFC 6647's client-side position: a client cannot know why a 4xx came back — "greylisting could be in effect" — so a client needs to be equipped to retry in order to be considered fully capable. Operational consequences for an ESP:
- Retry from the same IP address. The tuple includes the source IP. If your MTA retries a deferred message from a different IP in the pool, the greylister sees a brand-new tuple and defers again — potentially forever, cycling through the pool. Queue/retry logic must pin a deferred message (or at least a deferred destination) to the IP that made the first attempt. This is the key interaction between greylisting and pool-based sending.
- Keep MailFrom stable across retries. VERP and per-message return-paths are fine (the tuple is per message anyway), but rewriting the envelope sender between attempts creates a new tuple.
- First retry timing: the RFC 5321 SHOULD of ≥30 minutes sits comfortably inside the 1-minute-to-24-hour default acceptance window. A first retry in the 5–30 minute range clears most greylisters quickly; retrying within seconds is wasted (still under minimum age) and looks like hammering.
- Expect per-MX inconsistency. Receivers that violate the shared-database SHOULD will defer you separately at each MX; a retry that lands on another MX host restarts the wait. This is a receiver defect, not yours — patience, not IP rotation, is the fix.
- Warm-up interaction: new IPs are by definition unknown everywhere, so the first send from a fresh IP to smaller receivers sees elevated deferral rates for the first hours. Budget for this in IP warm-up throughput expectations; it clears as tuples age in.
- Address changes defeat aging: senders on DHCP/rotating addresses appear as new sources on every change; conversely NAT makes distinct MTAs share one IP, so one machine's pass exempts the others (which is why receivers increasingly distrust greylisting alone).
- Time-critical mail (password resets, transactional): greylisting can delay first-contact delivery by minutes to hours. The RFC's own security section flags "unintentional and detrimental consequences for delivery of legitimate mail," particularly time-critical applications. Sending transactional mail from established, consistently used IPs (which will already be aged in or exception-listed) is the mitigation.
Security considerations (Section 8)
- Attackers rotating tuple parameters can bloat the greylisting database (a DoS on the receiver); implementations should define a failure policy for when the database is attacked or unavailable.
- Greylisting is a speed bump, not authentication: any retrying botnet passes it. Its value is filtering out the non-retrying fraction of abuse cheaply.
See also
- RFC 5321 — SMTP — the retry obligations greylisting piggybacks on (≥30-minute retry interval, 4–5 day give-up).
- Enhanced Status Codes — classifying
4xxdeferrals. - IP Warm-Up — why fresh IPs see more deferrals.