How to Block Email from a Specific Sender in EXIM (With Smart Domain Filters, Pattern Matching, and Advanced Content Rules)
Keyword filtering in EXIM is a powerful but underused tool for fighting spam, scams, and policy violations. By inspecting subject lines, headers, or message bodies, administrators can block or quarantine emails that contain dangerous or unwanted terms - all without third-party filtering software.
In this guide, you’ll learn:
- How to block emails containing specific words (e.g. “Vi
agra”, “Cia lis”, “gambling”) - Where to configure keyword filters in EXIM
- How to match against various headers or body content
- How to manage dynamic keyword lists efficiently
- How to implement smarter keyword logic (e.g. per-sender, per-recipient)
- Bonus: Using keyword matches to score or quarantine suspicious messages
1. Where to Place Keyword Filtering Rules in EXIM
Keyword filtering is best handled in the ACL phase, typically in acl_check_data
, which evaluates content after the SMTP DATA command, when EXIM receives message headers and optionally the body.
File to edit:
Single config: /etc/exim4/exim4.conf.template
Split config: /etc/exim4/conf.d/acl/40_exim4-config_check_data
Make sure this ACL runs after any necessary SPF/DKIM checks, to avoid false positives from valid senders.
2. Basic Keyword Blocking Example (Subject Line Match)
Here's the simplest way to block messages based on spammy subject keywords:
deny
message = This message has been blocked because it contains spam keywords.
condition = ${if match{$h_subject:}{(?i)Viagra|Cialis|gambling}{yes}{no}}
Why it works:
${h_subject:}
reads the subject header.
(?i)
makes it case-insensitive (highly recommended).
match{}
returns yes
if any term is found.
This will block messages with Viagra, Cialis, or gambling in the subject line — a common spam vector.
3. Matching Keywords in Other Headers or Body Content
You can expand beyond subject lines by targeting:
$message_headers
— entire set of headers
$message_body
— full message body (slower, use with care)
$h_from:, $h_reply-to:, $h_to:
— specific fields
Example: block keywords in sender name or reply-to
deny
message = Blocked for spam keyword match in headers.
condition = ${if match{$message_headers}{(?i)CryptoInvestment|FreeMoney}{yes}{no}}
Body match (resource intensive — use only when needed):
deny
message = Blocked due to spam content in message body.
condition = ${if match{$message_body}{(?i)bitcoins\s+guaranteed|hot stock tip}{yes}{no}}
4. Smarter Keyword Lists (Dynamic File-Based Management)
Rather than hardcoding strings, load keywords from a file.
Create:
/etc/exim4/keyword_blacklist.txt
With entries like:
Via gra
Cia lis
Free Money
CryptoInvestment
bitcoins guaranteed
EXIM ACL:
deny
message = Blocked for matching blacklisted keyword.
condition = ${if match{$message_body}{${readfile{/etc/exim4/keyword_blacklist.txt}}}{yes}{no}}
This makes the list editable without reloading EXIM.
Automated tools (like spam traps or abuse reports) can add to this file dynamically.
5. Context-Aware Filtering: Combine Keyword Rules with Sender, IP, or Country
Let's say you only want to block gambling-related keywords from senders in .ru
or .cn
domains:
deny
message = Rejected: spam content from restricted region.
condition = ${if and{
{match{$h_subject:}{(?i)casino|poker|jackpot}}
{match_domain{$sender_address_domain}{*.ru:*.cn}}
}{yes}{no}}
You could also use GeoIP for more accurate region detection.
6. Using Regex Flags for Better Filtering
Use regex flags for smarter matching:
(?i)
— case-insensitive
\b
— word boundaries to avoid false matches
Example:
condition = ${if match{$h_subject:}{(?i)\b(viagra|cialis|lottery|loan)\b}{yes}{no}}
This avoids matching via
.
7. Logging and Alerting on Keyword Matches
Add a custom header for matched keywords:
add_header = X-Spam-Keyword-Match: matched keyword
Or log events asynchronously:
grep "Blocked for matching" /var/log/exim4/mainlog | while read line; do
curl -X POST -d "log=$line" https://your-internal-logger/api/keyword-matches
done
Useful for internal abuse dashboards or security alerts.
8. Advanced: Quarantine Instead of Rejecting
Instead of outright blocking, redirect messages to a quarantine inbox:
warn
condition = ${if match{$h_subject:}{(?i)lottery|crypto|pills}{yes}{no}}
redirect = spam-trap@yourdomain.com
message = Message redirected to quarantine due to suspicious keywords.
This helps avoid false positives while still preventing delivery to real users.
9. Bonus: Score-Based Filtering for Multi-Keyword Detection
You can stack checks and assign scores:
warn
set acl_m_spam_score = 0
warn
condition = ${if match{$h_subject:}{(?i)viagra}{yes}{no}}
set acl_m_spam_score = ${eval:$acl_m_spam_score + 5}
warn
condition = ${if match{$h_subject:}{(?i)lottery}{yes}{no}}
set acl_m_spam_score = ${eval:$acl_m_spam_score + 3}
deny
condition = ${if >{$acl_m_spam_score}{5}{yes}{no}}
message = Blocked: message exceeded spam keyword threshold.
Conclusion
Keyword-based filtering in EXIM is an incredibly flexible tool for spam prevention, policy enforcement, and abuse mitigation. By tailoring rules based on headers, bodies, sender domains, and scoring, you can intelligently intercept unwanted messages before they ever hit user inboxes.
See also: Learn how to integrate EXIM keyword filters with virus scanners and spamassassin for a layered security model.