Fighting spam on three layers: rejecting well-known IPs via RBL/DNSBL at the start of the connection, forcing servers to talk with proper helo and identity, then scoring email content with SpamAssassin including bayes learning and greylisting to suppress incoming spam.

A mail server that lives on the internet will be bombarded with spam from the very first minute. Previous episodes prepared the authentication gate; now we build layered defense against spam.
The strategy has three layers: RBL/DNSBL rejects well-known IPs at the start of the connection, SpamAssassin scores email content with rule-based scoring, and greylisting slows down the impatient senders that typify spammers. We'll also learn to make SpamAssassin "learn" from the email you mark.
Spam comes from many sources: known IPs, botnets, new domains, and deceptive content. No single filter catches everything. The concept of defense in depth means each layer filters a portion:
The earlier a decision is made, the fewer resources it uses — so the first layer is always the cheapest.
RBL (Realtime Blackhole List) / DNSBL (DNS-based Blackhole List) are lists of IPs or domains known for sending spam. Rejection is done with a simple DNS query to the list server, for example Zen Spamhaus. In Postfix, install it via smtpd_recipient_restrictions:
sudo postconf -e 'smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, reject_rbl_client zen.spamhaus.org, permit'
sudo postfix reloadreject_rbl_client zen.spamhaus.org rejects connections from IPs listed in that list. Note the order: after the recipient is validated, the RBL is checked — this order prevents internal IPs (permit_mynetworks) from being caught by the RBL.
Test that the RBL works:
postmap -q 127.0.0.2 zen.spamhaus.org127.0.0.2 is a test IP that's always listed on Zen; if the query returns a value, your DNSBL connection works.
SpamAssassin examines email headers and body, then scores it based on hundreds of rules. Email scoring above a threshold (usually 5.0) is flagged as spam. Install and enable it:
sudo apt install -y spamassassin
sudo systemctl enable spamassassinSpamAssassin integrates with Postfix in one of two ways: via a milter, or via a content filter (usually Amavis — episode 15). For now, the core configuration is in /etc/spamassassin/local.cf:
required_score 5.0
rewrite_header Subject [SPAM]
report_safe 0required_score — the score threshold to be considered spam.rewrite_header — marks the subject so it's visible.report_safe 0 — deliver the original email with added headers, not a separate report.Test SpamAssassin with a sample message:
spamassassin -t < /tmp/contoh-email.txt | grep -i scoreSpamAssassin's strength is bayes: it learns from the email you mark. The more it's trained, the more accurate its scores. Train it with sa-learn:
sa-learn --spam /var/mail/vhosts/example.com/admin/Maildir/.Junk/cur/
sa-learn --ham /var/mail/vhosts/example.com/admin/Maildir/cur/Every time a user marks email as spam (--spam) or not-spam (--ham), add it to the corpus. Choose the right folder — in Roundcube, the spam folder is usually named .Junk or Spam.
Greylisting temporarily rejects email from unknown servers (the sender-IP/sender/recipient triplet) and asks for a redelivery a few minutes later. Legitimate mail servers will retry; automated spammers usually won't. Install Postgrey:
sudo apt install -y postgreyThen add it to the restrictions:
sudo postconf -e 'smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, reject_rbl_client zen.spamhaus.org, check_policy_service inet:127.0.0.1:10023, permit'
sudo postfix reloadcheck_policy_service inet:127.0.0.1:10023 contacts Postgrey for the triplet decision. The first connection is delayed a few minutes; legitimate senders retry, mass spammers don't.
Tip
Don't greylist local senders — add a skip for internal subnets. And remember, greylisting adds latency; for critical communication that needs instant response, consider whitelisting certain domains or IPs.
Combine all four layers into one coherent policy:
sudo postconf -e 'smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, reject_unknown_recipient_domain, reject_rbl_client zen.spamhaus.org, check_policy_service inet:127.0.0.1:10023, permit'
sudo postconf -e 'smtpd_helo_required = yes'
sudo postfix reloadNote the additions reject_unknown_recipient_domain (rejects destination domains that don't resolve) and smtpd_helo_required (forces clients to speak with a helo). Monitor the impact in the logs — episode 19 covers how to read each layer's effect.
Episode 14 is done. Key takeaways:
reject_rbl_client zen.spamhaus.org rejects well-known IPs at the gate.sa-learn.smtpd_recipient_restrictions determines effectiveness and performance.Spam is fought on three layers. In episode 15 we add the final layer: Antivirus & Content Filtering — ClamAV and Amavis — scanning every email for viruses and malware before it enters the mailbox. See you in episode 15!