How to Block Email from a Specific IP Address in EXIM (With Custom Messages, Dynamic Filters, and Logging)
If you're running your own mail server with EXIM, chances are you'll want fine-grained control over who can send mail to your domain. One of the most effective measures is blocking specific IP addresses—whether for abuse, spam, or internal policy.
In this guide, we'll cover:
- How to block a specific IP address in EXIM
- Where to apply the rule in the config
- How to set a static or dynamic rejection message
- Best practices for blacklist management (static and dynamic)
- How to log rejections for monitoring and abuse tracking
- Advanced ideas like combining blocks with DNSBLs, rate limits, and geofencing
1. Where to Block IPs in EXIM
EXIM's configuration is modular, and IP-based blocking is best handled in the Access Control Lists (ACLs). The main file to edit is usually:
/etc/exim4/exim4.conf.template
Or, if using split configuration:
/etc/exim4/conf.d/acl/40_exim4-config_check_rcpt
You'll want to place your block rule in the acl_check_rcpt
section, which is evaluated when a client issues the RCPT TO:
command.
2. Blocking a Specific IP with a Static Message
Here's a simple example to block 123.123.123.123:
deny
message = Your message has been rejected because the sender is blacklisted.
condition = ${if eq{$sender_host_address}{123.123.123.123}{yes}{no}}
Explanation:
deny
stops message delivery.
message
defines what the sender will see.
condition
checks the sender's IP and returns yes
to trigger the block.
Place this block early in acl_check_rcpt
to act fast and reduce resource usage.
3. Using Dynamic Rejection Messages
Sometimes, a static message isn't enough. A dynamic message can help:
- Identify why an IP is blocked (e.g. RBL, country block, temporary ban).
- Include timestamps or internal references for traceability.
- Assist legitimate users in appealing a block with context.
Example:
deny
message = Message blocked. IP: $sender_host_address is on our internal blacklist. Ref: ${sg{${lookup{$sender_host_address}lsearch{/etc/exim4/blacklist.txt}}}{ }{}}.
condition = ${if exists{/etc/exim4/blacklist.txt}{${if match{$sender_host_address}{${lookup{$sender_host_address}lsearch{/etc/exim4/blacklist.txt}}}{yes}{no}}}{no}}
This loads the reason from a file dynamically and shows it in the rejection.
4. Managing Blacklists (Static and Dynamic)
Static Blacklist:
Maintain a file like:
/etc/exim4/blacklist.txt
With entries such as:
123.123.123.123 : Spammer
111.111.111.111 : Internal Abuse
Then use lsearch to look up IPs.
Dynamic Blacklist:
You can build a script that:
- Watches EXIM logs for abuse
- Adds IPs to the blacklist temporarily (e.g. for 24 hours)
- Syncs with fail2ban or other security tools
Use cron, systemd timers, or even inotify for auto-updates.
5. Logging and Reporting Rejection Hits
To monitor blocks without flooding your logs, pipe hits to a lightweight logger.
Example using add_header
and log tailing:
deny
message = Access denied.
condition = ...
add_header = X-Blocked-IP: $sender_host_address
Then, tail logs and extract:
grep "X-Blocked-IP" /var/log/exim4/mainlog | while read line; do
echo "$line" | nc logger.mycompany.internal 9000
done
Or send asynchronously to an ELK stack, InfluxDB, or Loki via vector/logstash.
6. Advanced: Combine with DNSBL, Rate Limits, or Country Blocks
EXIM's flexibility allows chaining rules.
Example: Block IP if on Spamhaus AND in China (via MaxMind):
deny
message = Blocked due to spam or geolocation policy.
condition = ${if or{
{def:sender_host_address}
{match{$sender_host_address}{${lookup dnsdb{zen.spamhaus.org}{$value}{}}}}
{match{${lookup{$sender_host_address}lsearch{/etc/exim4/geo_blacklist.txt}}}{CN}}
}}
Conclusion
Blocking by IP in EXIM isn't limitd to writing one line at a time, manually, you can use it to improve your layered security strategy. Use static IP blocks for known bad actors, dynamic blacklists for behavioural filtering, and make your messages smart enough to help both users and your abuse team.
See also: How to sync EXIM with Fail2Ban for brute force protection, and integrating GeoIP blocking for GDPR compliance.