While Postfix's header_checks
can filter standard recipient addresses, it fails to intercept BCC recipients - a common pain point for sysadmins implementing email restrictions. The limitation stems from how BCC headers are processed differently in the SMTP transaction flow.
For comprehensive blocking (including BCC), we need to implement recipient restrictions at the SMTP protocol level. Add this to your main.cf
:
smtpd_recipient_restrictions = check_recip_access hash:/etc/postfix/blocked_recipients, permit_mynetworks, reject_unauth_destination
Create /etc/postfix/blocked_recipients
with contents like:
blocked@domain.com REJECT @spamdomain.com REJECT
Then compile the hash database:
postmap /etc/postfix/blocked_recipients systemctl reload postfix
Verify the blocking works for all cases:
# Test direct recipient echo "Test" | mail -s "Test" blocked@domain.com # Test BCC case echo "Test" | mail -s "Test" -b blocked@domain.com valid@example.com
For pattern-based blocking, use pcre:
tables instead of hash:
smtpd_recipient_restrictions = check_recip_access pcre:/etc/postfix/recipient_blocklist.pcre
Sample recipient_blocklist.pcre
:
/^.*@spamdomain\.com$/ REJECT /^user-\d+@domain\.com$/ REJECT
The solution adds minimal overhead since:
- Recipient checks occur early in SMTP conversation
- Hash/PCRE lookups are highly optimized in Postfix
- Rejected connections don't consume message processing resources
When implementing email restrictions in Postfix, administrators often discover that traditional methods like header_checks
fail to intercept BCC recipients. This creates a security gap where sensitive information might still leak to prohibited addresses.
The most reliable approach involves Postfix's smtpd_recipient_restrictions
parameter. Add these lines to your main.cf
:
smtpd_recipient_restrictions =
check_recip_access hash:/etc/postfix/recipient_block
permit_mynetworks
permit_sasl_authenticated
reject_unauth_destination
Then create /etc/postfix/recipient_block
with content:
blocked@domain.com REJECT
*.spamdomain.com REJECT
For BCC-specific scenarios, combine with header_checks
as fallback:
/etc/postfix/header_checks:
/^Bcc:.*blocked@domain.com/ REJECT
For more granular control, use transport maps:
main.cf:
transport_maps = hash:/etc/postfix/transport_block
/etc/postfix/transport_block:
blocked@domain.com discard:
Always test with:
postmap /etc/postfix/recipient_block
postfix reload
send test emails with various recipient combinations
check mail logs with: tail -f /var/log/mail.log