Email Greylisting: When It Helps and When It Just Delays Real Mail

Was this helpful?

The pain point: You’re on call. A customer says, “Your system never sent my password reset.” Your app logs say it did. Your MTA logs show a 451. And somewhere between “security” and “email,” greylisting is quietly doing what it was built to do: slow things down—sometimes the bad mail, sometimes the mail that pays your salary.

Greylisting is one of those operational tools that feels delightfully low-tech: ask unknown senders to come back later. Most spam doesn’t. Legitimate MTAs do. Great. Until your finance team misses invoices, your monitoring alerts arrive after the incident, and your marketing vendor mails you a screenshot of their “retries disabled” setting like it’s your problem.

What greylisting actually does on the wire

Greylisting is not spam detection. It’s a bet about sender behavior.

The bet: legitimate mail servers will retry delivery after a temporary failure; a lot of spam infrastructure historically wouldn’t bother. So you treat first-time senders as “maybe,” return a temporary error (usually 451 4.7.1 or similar), and wait for the sender to try again. On the retry, you accept.

The mechanism: a triplet and a timer

Classic greylisting tracks a “triplet”:

  • Sender IP address
  • MAIL FROM (envelope sender)
  • RCPT TO (envelope recipient)

First time you see a triplet, you temporarily reject it. If it comes back after a “minimum delay” (say 5–15 minutes), you accept and often whitelist it for some period (“auto-whitelist”).

Modern variants tweak the key. Some use sender IP only, or IP + sender domain, or include HELO, or leverage reputation. That matters because email delivery in 2026 includes shared outbound pools, NATs, SaaS relays, IPv6, and “sending domains” that don’t map cleanly to stable IPs.

SMTP semantics: what you are allowed to do

Greylisting relies on SMTP’s contract: a 4xx reply is temporary; the sender should retry. A 5xx is permanent; the sender should bounce. Greylisting lives in the 4xx range.

A good greylist response is specific but not chatty:

  • 451 4.7.1 Try again later
  • 450 4.2.0 Temporarily deferred

You want the sender’s MTA to retry, not to decide you are broken.

Where it sits in the mail pipeline

Greylisting is usually applied during SMTP connection time, before you accept the message data. On Postfix, it’s commonly implemented as a policy service in smtpd_recipient_restrictions or smtpd_data_restrictions, depending on the daemon and plugin. On Exim, it can be done via ACLs. On appliances, it’s often buried behind a checkbox labeled “Aggressive anti-spam,” which is how you know it will be fun.

Position matters. If you greylist too early and too broadly, you’ll delay lots of mail that would otherwise pass content filters. If you do it too late (after DATA), you’ve already spent bandwidth and CPU on spam you were trying to cheaply deter.

Why it worked (and why it works less now)

Greylisting’s original appeal was its asymmetry: it cost you almost nothing and cost the sender time. Spam engines used to be optimized for volume and speed, not persistence. Many didn’t retry. Legit MTAs did. Boom: spam drops.

But attackers read the same RFCs you do. Today, plenty of spam sends from “real” infrastructure (compromised hosts, cloud IPs, abused ESP accounts) that retries properly. Greylisting is still useful, but it’s not the spam guillotine it was in the mid-2000s.

In other words: greylisting aged like a bouncer who’s great at spotting fake IDs, but less great when the fake IDs start looking like real IDs. Still helpful at the door, not a full security program.

When greylisting helps in 2026

Greylisting helps when your threat model includes a meaningful portion of senders that don’t retry or retry poorly, and when a delivery delay of a few minutes is acceptable for most inbound mail.

1) Small and medium organizations with noisy inbound spam

If your domain receives a lot of direct-to-MX junk, greylisting can still shave off the bottom-feeders. Especially if you don’t have a big-budget filtering stack. The best part is not the “perfect block.” It’s the reduction in what the rest of your pipeline must process.

2) Mail servers that are CPU-bound on content scanning

If you run SpamAssassin, Rspamd, antivirus, attachment sandboxing, or DLP, then anything that reduces messages reaching those stages can be a win. Greylisting defers unknown senders before you spend cycles.

3) Inbound-only MX with predictable legitimate senders

Some domains receive mail mainly from large providers and a known partner set. Greylisting with a sane whitelist (big providers, partners, your ticketing vendor, your payroll vendor, etc.) can yield benefits with fewer “why is the CEO’s flight itinerary late” tickets.

4) As a speed bump during an abuse spike

Greylisting can be a short-term throttle. If you’re under a spam flood, enabling or tightening greylisting can buy time while you implement better controls (DNSBL tuning, rate limits, DMARC alignment decisions, etc.). It’s not pretty, but neither is a mailbox full of malware.

Joke #1: Greylisting is like telling your email, “Leave a message after the beep,” except the beep is an RFC and the message is 40,000 identical crypto scams.

When greylisting hurts (and how it fails)

Greylisting hurts when the mail you care about is time-sensitive, when the senders don’t retry the way you expect, or when your own configuration accidentally makes “first time” happen over and over.

Time-sensitive mail is not optional anymore

Password resets, MFA codes, account verification links, fraud alerts, pager notifications, on-call escalations, purchase confirmations, calendar invites—these are often used in flows where humans stare at the screen waiting.

A 10-minute delay is not “a small inconvenience.” It’s a broken workflow. Users don’t interpret it as “anti-spam is working.” They interpret it as “your product is unreliable.” They are not wrong.

Retry behavior is less uniform than you think

SMTP says retry. It doesn’t say how quickly, how often, or from which IP.

  • Some systems retry after 1 minute; some after 30.
  • Some retry from a different outbound IP (large pools).
  • Some use a different envelope sender (bounce/VERP patterns).
  • Some SaaS platforms front SMTP with HTTP APIs and then deliver via a relay that behaves “mostly like SMTP” but with policy quirks.

If your greylisting key is too strict (e.g., IP + full MAIL FROM + RCPT TO), a sender retrying from a different IP or with a different bounce address may never match the original triplet. You just invented an infinite deferral machine.

NAT, IPv6 privacy addresses, and outbound pools

Greylisting assumes some stability in sender identity. Outbound pools are designed for the opposite: distribute traffic and fail over smoothly. IPv6 often rotates addresses (privacy extensions) and large providers may use massive subnets.

As a result, “first time we’ve seen this IP” can become “first time every time.” If you greylist on IP alone, you’ll punish senders with huge pools. If you greylist on too many fields, you’ll punish senders that vary those fields.

Greylisting breaks monitoring and incident response

Alert email is usually the most latency-sensitive mail you have. And it’s the mail most likely to come from random-looking IPs (cloud monitoring vendors, multi-tenant systems). Greylisting makes incident response worse in a way that only shows up during incidents. Which is when your patience is at its lowest and your stakeholders’ expectations are at their highest.

Policy-layer greylisting can mask real deliverability problems

If a partner complains “we keep getting 451,” you might blame greylisting and whitelist them. Sometimes that’s correct. Sometimes your own MX is rate limiting, your DNS is slow, your TLS policy is too strict, or your reverse DNS checks are rejecting. Greylisting can be the loudest symptom while the actual bottleneck is elsewhere.

Joke #2: Nothing makes you feel alive like explaining “temporary rejection is normal” to an executive who only understands “did we lose money.”

Interesting facts and historical context

  • Greylisting became popular in the early-to-mid 2000s as a lightweight countermeasure when spam engines often didn’t retry after 4xx responses.
  • It’s based on SMTP’s original store-and-forward design: temporary failures are expected, and queues are part of “normal” email operation.
  • RFC 5321 doesn’t mandate retry timing; senders choose their own backoff schedules, which is why greylisting delay is unpredictable across providers.
  • Auto-whitelisting was introduced to reduce repeated delays, storing successful triplets for days or weeks so known senders don’t get re-greylisted.
  • Big senders use large outbound IP pools for capacity and reputation management; strict IP-based greylisting clashes with that design.
  • Some spam operations adapted by implementing retries, reducing greylisting’s effectiveness as a sole anti-spam control.
  • Greylisting can act as a primitive rate limiter, indirectly reducing inbound connection churn during spam bursts by forcing retries.
  • Mis-keyed greylisting can create “never accept” loops when senders retry with a different envelope sender (VERP) or different IP each attempt.
  • Large providers sometimes pre-warm or pre-validate flows (like “probe” deliveries); greylisting can delay or complicate these sanity checks.

Fast diagnosis playbook

This is the playbook you run when someone says “mail is delayed,” and you need to find the bottleneck before the meeting invite expires.

First: confirm it’s actually greylisting, not a queue or DNS problem

  1. Look for 4xx deferrals with “greylist” markers in MTA logs (Postfix policy service, Exim ACL message, appliance tag).
  2. Check whether the sender retried and whether the retry matched the greylist key (same IP? same envelope sender?).
  3. Check mail queue age distribution: if everything is deferred, you might have a general outbound/inbound blockage unrelated to greylisting.

Second: determine impact scope and blast radius

  1. Is it one sender domain (partner/vendor) or many?
  2. Is it time-sensitive mail (auth, monitoring, billing) or low-stakes (newsletters)?
  3. Are only some recipients affected (e.g., specific aliases routed differently)?

Third: make a safe immediate change

  1. Whitelist the known-good sender temporarily (domain/IP range, with expiry if your tool supports it).
  2. Reduce the minimum delay window if it’s globally hurting you (but don’t set it to near-zero; you’ll just annoy senders without filtering much).
  3. Fix the key if you detect IP pool mismatch: use a less brittle tuple (often IP + sender domain, or leverage SPF/HELO identity carefully).

Fourth: capture evidence for the postmortem

  1. Extract a timeline: first attempt, greylist reject, retry attempts, accept time.
  2. Record sender IPs used across retries.
  3. Note if your MX used multiple frontends and whether greylist state is shared.

One reliability quote belongs here because it’s the whole point of operating mail: “Hope is not a strategy.” — paraphrased idea often used in operations and engineering circles.

Practical tasks: commands, outputs, and decisions

These are hands-on tasks you can run on a Postfix-based Linux MX (or adapt to your stack). Each one includes: command, realistic output, what it means, and what you decide next.

Task 1: Find greylisting deferrals in Postfix logs

cr0x@server:~$ sudo grep -E "greylist|Greylist|4\.7\.1|temporar" /var/log/mail.log | tail -n 6
Jan 03 09:41:12 mx1 postfix/smtpd[22107]: NOQUEUE: reject: RCPT from mail-ot1-f45.google.com[209.85.210.45]: 451 4.7.1 Service unavailable - try again later; from=<alerts@partner.example> to=<oncall@example.com> proto=ESMTP helo=<mail-ot1-f45.google.com>
Jan 03 09:41:12 mx1 postfix/smtpd[22107]: warning: greylist: triplet blocked (209.85.210.45, alerts@partner.example, oncall@example.com)
Jan 03 09:48:58 mx1 postfix/smtpd[22301]: NOQUEUE: accept: RCPT from mail-ot1-f45.google.com[209.85.210.45]: 250 2.1.5 Ok; from=<alerts@partner.example> to=<oncall@example.com> proto=ESMTP helo=<mail-ot1-f45.google.com>

Meaning: This is classic greylisting: first attempt rejected with 451, later accepted.

Decision: If the delay is acceptable and limited to unknown senders, keep. If it’s on alert mail or auth mail, whitelist that sender or bypass greylisting for that recipient group.

Task 2: Confirm what policy services are active (Postfix)

cr0x@server:~$ sudo postconf -n | grep -E "smtpd_(recipient|data)_restrictions|check_policy_service"
smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination, check_policy_service inet:127.0.0.1:10023, permit

Meaning: A policy service is consulted at recipient stage; that’s where greylisting is likely implemented.

Decision: If troubleshooting, temporarily move the policy later/earlier or add exceptions (e.g., bypass for certain clients) rather than ripping it out blind.

Task 3: Test the greylist policy response directly (netcat to policy port)

cr0x@server:~$ printf "request=smtpd_access_policy\nprotocol_state=RCPT\nprotocol_name=SMTP\nclient_address=209.85.210.45\nsender=alerts@partner.example\nrecipient=oncall@example.com\n\n" | nc -w 2 127.0.0.1 10023
action=defer_if_permit 451 4.7.1 Greylisted, please try again later

Meaning: Policy service is indeed greylisting and would defer that triplet right now.

Decision: If that sender is business-critical, add it to the policy service whitelist mechanism (domain/IP) and retest.

Task 4: Check if greylist state is shared across MX frontends

cr0x@server:~$ sudo postconf -n | grep -E "proxy_read_maps|smtpd_policy_service"
proxy_read_maps =

Meaning: This doesn’t prove state sharing, but it hints you may not be proxying lookups. Many greylist daemons use local SQLite. If you have multiple MX nodes behind a load balancer, each node may “learn” separately.

Decision: If you have multiple MX, confirm the greylist backend is centralized (Redis/SQL) or use consistent hashing / sender-based stickiness. Otherwise you get repeat deferrals when retries land on a different node.

Task 5: Inspect mail queue for deferred messages (Postfix)

cr0x@server:~$ sudo postqueue -p | head -n 18
-Queue ID-  --Size-- ----Arrival Time---- -Sender/Recipient-------
3F2C21A0B7*    2190 Fri Jan  3 09:38:02  alerts@partner.example
                                         oncall@example.com
                                         (host mx1[127.0.0.1] said: 451 4.7.1 Greylisted, please try again later (in reply to RCPT TO command))
9A77F1B9CC     1046 Fri Jan  3 09:37:11  billing@vendor.example
                                         ap@corp.example
                                         (connect to mx.remote.example[203.0.113.40]:25: Connection timed out)

Meaning: You have at least one deferred due to greylisting and another due to outbound network issues. Not all delay is greylisting.

Decision: Split the incident: fix greylisting policy for inbound deferrals; fix network/DNS/routing for outbound timeouts. Don’t blame one mechanism for everything.

Task 6: Identify the oldest deferred messages to gauge user impact

cr0x@server:~$ sudo postqueue -p | awk 'BEGIN{RS="";FS="\n"} {print $0 "\n---"}' | grep -E "Arrival Time|Greylist|Queue ID" | head -n 30
-Queue ID-  --Size-- ----Arrival Time---- -Sender/Recipient-------
3F2C21A0B7*    2190 Fri Jan  3 09:38:02  alerts@partner.example
(host mx1[127.0.0.1] said: 451 4.7.1 Greylisted, please try again later (in reply to RCPT TO command))
---

Meaning: Queue timestamps tell you whether this is a 5-minute annoyance or an hour-long outage.

Decision: If deferred ages exceed your acceptable latency (for alerts/auth, that might be 1–2 minutes), you should bypass greylisting for those streams immediately.

Task 7: Verify DNS resolution latency (slow DNS looks like mail delay)

cr0x@server:~$ time dig +tries=1 +timeout=2 mx partner.example
;; ANSWER SECTION:
partner.example.        300     IN      MX      10 mx.partner.example.

real    0m0.412s
user    0m0.018s
sys     0m0.010s

Meaning: DNS resolution is quick here. If you see multi-second times or timeouts, you may be stalling SMTP sessions, which can combine badly with greylisting and connection limits.

Decision: If DNS is slow, fix resolver path/caching before tuning greylisting. Otherwise you’ll misattribute delays.

Task 8: Check whether postscreeen or connection throttling is also in play

cr0x@server:~$ sudo postconf -n | grep -E "^postscreen|smtpd_client_connection_rate_limit"
postscreen_greet_action = enforce
smtpd_client_connection_rate_limit = 30

Meaning: You’re using connection-level controls as well as greylisting. Good. But the combined effect can be “legitimate sender gets slowed twice.”

Decision: If legitimate mail is delayed, consider exempting known senders from postscreen/greeting delay and from greylisting, rather than loosening everything globally.

Task 9: Confirm your greylisting exception/whitelist files are actually loaded

cr0x@server:~$ sudo grep -R "whitelist" /etc/postfix | head -n 8
/etc/postfix/main.cf:smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination, check_policy_service inet:127.0.0.1:10023, permit
/etc/postfix/greylist-whitelist:partner.example
/etc/postfix/greylist-whitelist:203.0.113.0/24

Meaning: You have a whitelist file, but this does not prove the greylist daemon reads it.

Decision: Find the greylist service config and ensure it references this file; otherwise you’re editing a comforting placebo.

Task 10: Inspect systemd service status for the greylist daemon

cr0x@server:~$ sudo systemctl status postgrey --no-pager
● postgrey.service - Postgrey greylisting policy server
     Loaded: loaded (/lib/systemd/system/postgrey.service; enabled)
     Active: active (running) since Fri 2026-01-03 07:12:11 UTC; 2h 34min ago
   Main PID: 1189 (postgrey)
     Memory: 42.1M
     CGroup: /system.slice/postgrey.service
             └─1189 /usr/sbin/postgrey --inet=127.0.0.1:10023 --delay=300

Meaning: Greylisting delay is 300 seconds (5 minutes). Service is running.

Decision: If your business requires near-instant mail, 5 minutes may already be too high unless you have tight whitelists for sensitive streams.

Task 11: Validate the sender’s retry pattern from logs (did they retry? from where?)

cr0x@server:~$ sudo grep -E "from=.*vendor\.example|client=.*203\.0\.113" /var/log/mail.log | tail -n 8
Jan 03 09:10:01 mx1 postfix/smtpd[21001]: NOQUEUE: reject: RCPT from relay1.vendor.example[203.0.113.10]: 451 4.7.1 Greylisted, please try again later; from=<bounce+ab12@vendor.example> to=<ap@corp.example>
Jan 03 09:25:44 mx1 postfix/smtpd[21477]: NOQUEUE: reject: RCPT from relay2.vendor.example[203.0.113.22]: 451 4.7.1 Greylisted, please try again later; from=<bounce+cd34@vendor.example> to=<ap@corp.example>
Jan 03 09:41:05 mx1 postfix/smtpd[22192]: NOQUEUE: reject: RCPT from relay3.vendor.example[203.0.113.35]: 451 4.7.1 Greylisted, please try again later; from=<bounce+ef56@vendor.example> to=<ap@corp.example>

Meaning: Sender is retrying, but each retry comes from a different IP and a different bounce address (VERP). If your greylist key includes IP and full MAIL FROM, they will never pass.

Decision: Loosen the key (e.g., sender domain + recipient) or whitelist the vendor’s sending domain/IP ranges. This is a structural mismatch, not “give it more time.”

Task 12: Measure whether your greylist database is growing out of control

cr0x@server:~$ sudo ls -lh /var/lib/postgrey
total 96M
-rw------- 1 postgrey postgrey 95M Jan  3 09:30 postgrey.sqlite
-rw-r--r-- 1 root     root     1.2K Dec 12 14:02 whitelist_clients.local

Meaning: The DB is 95MB. That’s not inherently bad, but growth can affect performance if the host is resource-constrained or the storage is slow.

Decision: If you see big growth plus high I/O wait, consider pruning/aging settings, moving to a faster disk, or switching backend to Redis/SQL if you need shared state.

Task 13: Check I/O wait and disk latency (because policy lookups hit disk)

cr0x@server:~$ iostat -xz 1 2
Linux 6.6.0 (mx1) 	01/03/2026 	_x86_64_	(4 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          3.21    0.00    1.12   18.44    0.00   77.23

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   w_await  aqu-sz  %util
nvme0n1          2.10     64.0     0.00   0.00   1.21    30.5      58.2   2200.0    19.80    1.15   92.4

Meaning: High iowait and high device utilization. If your greylist policy uses SQLite on this disk, policy decisions may slow SMTP sessions, increasing timeouts and connection churn.

Decision: Fix storage performance (move DB to faster disk, tune retention, or change backend). Greylisting that makes your SMTP server slow is self-harm.

Task 14: Confirm the actual SMTP response with a live session

cr0x@server:~$ nc -w 3 mx1.example.com 25
220 mx1.example.com ESMTP Postfix
EHLO test.example
250-mx1.example.com
250-PIPELINING
MAIL FROM:<alerts@partner.example>
250 2.1.0 Ok
RCPT TO:<oncall@example.com>
451 4.7.1 Service unavailable - try again later
QUIT
221 2.0.0 Bye

Meaning: The RCPT stage is where the temporary reject happens. This aligns with policy restriction placement.

Decision: If you need exceptions, implement them in the same stage (recipient restrictions) to avoid surprising interactions.

Three corporate-world mini-stories

Mini-story 1: The incident caused by a wrong assumption

The company ran a customer portal with email-based password resets. The SRE team had inherited an on-prem MX, and an old anti-spam playbook recommended greylisting because it “cuts spam by 80%.” That sentence became a talisman. Nobody asked the second question: “80% of what, and at what cost?”

During a Monday morning traffic spike—new product announcement, lots of signups—the password reset flow started “randomly failing.” Support saw tickets: users requested a reset, never received it, requested again, still nothing. Engineering checked the app logs: resets were generated and sent to the MTA. They blamed the email provider. They were half right, in the way that keeps incidents alive.

In the mail logs, every reset was greylisted on first contact. That was expected. The wrong assumption was that retries would come from the same sender identity. The reset mail actually came from a SaaS relay with a large IP pool and variable envelope senders. Every retry looked new. Greylisting wasn’t delaying delivery; it was preventing it indefinitely.

The incident’s operational damage came from the slow realization cycle. People waited “a few more minutes” because that’s what greylisting does. When you design a system where failure looks like normal delay, you’ve built a liar. By the time they whitelisted the vendor’s relay range and relaxed the tuple to domain-based matching, the signup window had passed and the marketing team had moved on to blaming “infra.”

The fix was unglamorous: a targeted bypass for password reset sender domains and a rule that any mail tied to authentication flows must not be greylisted. Also, a test harness that does a real SMTP injection from the vendor’s pool during staging. The real lesson: never treat email delivery properties as stable across vendors.

Mini-story 2: The optimization that backfired

A different org had a classic “we can save money” project: consolidate two MX nodes into one bigger VM with faster CPU, keep the same spam controls, and call it a day. Greylisting stayed. They even tightened it: longer delay window, longer auto-whitelist, more strict tuple. “Let’s reduce junk and reduce CPU scanning,” they said.

For a week, it looked great. Spam volume dropped. CPU dropped. The weekly report looked like a win.

Then came the quarterly close. Accounts Payable complained that invoices from a handful of vendors were arriving hours late. Not bounced. Not missing. Just late enough to cause payment workflow churn and enough phone calls to justify an escalation.

The optimization had two hidden costs. First, the larger VM ran on shared storage with noisy neighbors; the greylist database lived on that storage, and policy lookups started stalling under load. Second, the stricter tuple meant that vendors using VERP-style bounce addresses never matched prior attempts. Mail did arrive eventually, but only after enough retries happened to coincide with a stable combination of IP and envelope sender. It wasn’t deterministic; it was roulette.

They rolled back the stricter tuple and moved the greylist backend to Redis on local NVMe. Spam scanning CPU went up a bit, but invoice latency returned to boring. That’s the correct trade in most corporate environments: spend compute to keep business mail timely. Compute is cheaper than trust.

Mini-story 3: The boring but correct practice that saved the day

A third company ran their own MX as an inbound gateway in front of a hosted mailbox provider. They had greylisting enabled, but they treated it like a change-controlled component, not a folklore setting. The mail team maintained a small “critical senders” list: monitoring, HR/payroll, SSO provider, ticketing system, and top vendors. Each entry had an owner, a reason, and a review date. Dull. Effective.

One afternoon, a regional network event caused intermittent packet loss to one of their MX nodes. The load balancer kept sending some traffic to the flaky node. Normally, that’s bad enough. With greylisting, it can be worse: first attempt hits broken node and gets deferred due to timeouts, retry hits healthy node and is treated as “new,” gets greylisted, then subsequent retries bounce between nodes. Suddenly, you’ve built a delay amplifier.

But because they centralized greylist state (shared backend) and had health checks that pulled the broken node out quickly, the blast radius stayed small. Their fast diagnosis wasn’t guesswork: queue age stayed within their SLA; logs showed a clean pattern; critical senders bypassed greylisting entirely. Incident resolved before anyone outside IT noticed.

The practice that “saved the day” wasn’t a fancy ML spam filter. It was: shared state, whitelists with ownership, and a load balancer health check that actually represented SMTP usability, not just “port 25 is open.” Boring is a feature.

Common mistakes (symptoms → root cause → fix)

1) Symptom: Password reset emails arrive 10–30 minutes late (or never)

Root cause: Greylisting applied to transactional mail from SaaS relays with large IP pools and variable envelope senders; the tuple never matches.

Fix: Bypass greylisting for transactional sender domains/IP ranges; loosen keying (domain-based) if your tool supports it; or disable greylisting on the MX that handles transactional streams.

2) Symptom: Partner says “we keep getting 451” and provides repeated attempt logs

Root cause: Minimum delay window longer than their retry schedule, or they retry from different IPs each time and you key strictly.

Fix: Reduce minimum delay to 60–180 seconds for unknowns; add partner to whitelist; adjust tuple.

3) Symptom: Repeated first-time delays from big providers (Gmail, Microsoft)

Root cause: IP-based greylisting penalizes outbound pools; each message comes from a “new” IP.

Fix: Whitelist major provider IP ranges cautiously (or whitelist by authenticated signals if your gateway supports it). Alternatively, don’t greylist at all for these providers; rely on reputation/content filtering.

4) Symptom: Mail sometimes passes immediately, sometimes delayed, with multiple MX nodes

Root cause: Greylist state is local per node; retries land on a different node and get treated as new.

Fix: Centralize greylist state (shared DB/Redis) or use load balancer stickiness per sender IP. Better: centralize state.

5) Symptom: Incoming connections spike and remote MTAs time out

Root cause: Greylisting plus slow policy backend causes long SMTP sessions; remote MTAs open more parallel connections; your server hits connection limits; chaos ensues.

Fix: Fix backend performance (disk/I/O), reduce policy lookup cost, tune concurrency limits, and shorten SMTP time spent per session.

6) Symptom: Spam volume drops, but complaints about late invoices rise

Root cause: Greylisting is doing its job, but you didn’t exempt business-critical senders; also, AP vendors often use quirky relays.

Fix: Maintain a “business critical” whitelist with ownership, and measure delivery latency for those domains.

7) Symptom: Greylisting seems ineffective; spam still arrives

Root cause: Modern spammers retry properly; your greylisting is only adding delay to everyone.

Fix: Reduce reliance on greylisting; invest in reputation checks, content filtering, DMARC alignment policy decisions, and rate limits.

Checklists / step-by-step plan

Checklist A: Decide whether you should run greylisting at all

  1. Inventory time-sensitive mail flows: auth, monitoring, ticketing, finance, legal. If you can’t list them, assume you have them and they matter.
  2. Measure current inbound spam composition: direct-to-MX vs relayed; how much is stopped by other controls.
  3. Estimate acceptable latency: define targets for different classes (alerts: <2 minutes; password reset: <1 minute; newsletters: whatever).
  4. Assess sender diversity: many small senders with stable MTAs? Greylisting might help. Mostly big providers and SaaS? Greylisting will mostly annoy you.
  5. Decide your policy: “greylist unknown direct-to-MX senders except whitelisted categories” is a reasonable middle ground.

Checklist B: Implement greylisting without shooting your own foot

  1. Pick a conservative minimum delay: 60–180 seconds if you have a modern environment; 300 seconds is often too much for transactional flows.
  2. Enable auto-whitelisting with a sensible TTL (days to weeks), so normal correspondents aren’t repeatedly delayed.
  3. Centralize state if you have more than one MX.
  4. Whitelists with ownership: every entry has an owner and a review date. Otherwise it becomes a landfill.
  5. Bypass for critical flows: monitoring senders, SSO, password reset vendors, finance vendors. Hard rule: auth mail should not be greylisted.
  6. Instrument latency: log and graph “first seen” → “accepted” time. If you don’t measure, you’ll argue about anecdotes.

Checklist C: Respond to a greylisting-related incident

  1. Confirm: look for 451 in logs with a greylist tag.
  2. Check sender retry behavior: same IP? same envelope sender? same MX node?
  3. Whitelist immediately for business-critical sender.
  4. Reduce delay window if broad impact.
  5. Fix tuple/state sharing permanently.
  6. Write down: what mail was delayed, for whom, and how long.

FAQ

1) Is greylisting “safe” from a security perspective?

It’s not a security control in the classic sense. It’s a traffic-shaping mechanism. It can reduce exposure to low-effort spam, but it won’t stop targeted phish or compromised legitimate senders.

2) How long should the greylisting delay be?

For most modern environments: 60–180 seconds is the practical range. Longer delays hurt user workflows and don’t reliably increase filtering effectiveness against modern spam.

3) Why do some legitimate senders never get through?

Because your key is too strict or your state isn’t shared. If the sender retries from different IPs or changes envelope sender, the “same triplet” never repeats, and your system keeps treating them as new.

4) Should I greylist Gmail/Microsoft?

Usually no. They retry correctly, but they use outbound pools. You’ll mostly introduce delay without meaningful spam reduction. Whitelist them or rely on other filtering layers.

5) Does greylisting help against botnets?

Sometimes. Low-quality botnet senders might not retry. But many do now. Consider greylisting a minor layer, not the foundation.

6) Where in Postfix should greylisting be applied?

Typically via check_policy_service in smtpd_recipient_restrictions. That rejects before DATA, saving resources. But apply exceptions carefully, especially for trusted networks and critical sender domains.

7) Can greylisting cause duplicate email?

Indirectly, yes. If a sender times out, retries aggressively, or an application layer resends because it didn’t get a fast “delivered” signal, you can see duplicates. Greylisting isn’t the only cause, but it can contribute.

8) What metrics should I monitor if I enable greylisting?

Track: number of 4xx deferrals by reason, accept-after-greylist count, median and p95 delay from first attempt to acceptance, and inbound connection concurrency. Also monitor policy backend latency and disk I/O.

9) Is greylisting appropriate for outbound mail?

No. Greylisting is an inbound policy for your MX. Outbound deliverability depends on your reputation, authentication (SPF/DKIM/DMARC), and error handling—different game.

10) What’s the cleanest way to exempt “critical mail”?

Separate it by sender domain/IP, recipient address group, or by routing critical flows through a different MX policy path. The key is: exemptions must be explicit, reviewed, and tested.

Next steps you can actually do this week

  1. Classify your mail: list the top 20 sender domains by business impact, not by volume. Alerts, auth, finance, ticketing, exec travel—yes, really.
  2. Run the log search for 451 deferrals and compute delays for those critical senders. If you can’t compute it, sample manually from timestamps.
  3. Fix structural issues first: if you have multiple MX nodes and local greylist state, centralize it. If your policy backend is on slow disk, move it.
  4. Set a sane delay: if you’re at 300 seconds, consider 120 seconds and compensate with better filtering layers.
  5. Create a whitelist process: owner + reason + review date. This is not bureaucracy; it’s preventing future you from spelunking a decade-old config file at 3 a.m.
  6. Test with real retries: pick one vendor with known IP pool behavior and validate acceptance on retry across MX nodes. If it fails, adjust the tuple or whitelist.

Greylisting is neither hero nor villain. It’s a blunt instrument that can still be useful when you understand what it costs: time, predictability, and the occasional heated meeting. Use it where delay is acceptable, bypass it where delay is damage, and measure it like you mean it.

← Previous
Docker “OCI runtime create failed”: decode it and fix the real cause
Next →
Docker: DNS inside containers is broken — systemd-resolved fixes that stick

Leave a comment