Many development teams face this common scenario: your staging server's Postfix installation keeps sending test emails to real external addresses. This occurs because by default, Postfix is configured as a full mail transfer agent (MTA) capable of delivering messages to any valid domain.
The most reliable method involves modifying Postfix's transport maps. Add these lines to your main.cf file:
# Restrict delivery to example.com and its subdomains relay_domains = example.com, .example.com smtpd_recipient_restrictions = check_recipient_access hash:/etc/postfix/recipient_access, reject
Create /etc/postfix/recipient_access with:
example.com OK .example.com OK * REJECT
After creating these files, compile the hash database and reload Postfix:
postmap /etc/postfix/recipient_access systemctl reload postfix
For more granular control, implement transport maps:
# In main.cf transport_maps = hash:/etc/postfix/transport local_recipient_maps =
Then create /etc/postfix/transport:
example.com smtp: .example.com smtp: * discard:
Verify your setup using:
postmap -q example.com hash:/etc/postfix/transport postmap -q gmail.com hash:/etc/postfix/transport
Consider these extra precautions for development environments:
# Prevent non-local mail submission smtpd_restriction_classes = development_only development_only = check_sender_access hash:/etc/postfix/sender_access, reject # In main.cf smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination, check_recipient_access hash:/etc/postfix/recipient_access
During development cycles, we often need email functionality but want to prevent accidental emails reaching external recipients. Our Postfix dev server was freely delivering messages to any domain until I implemented these restrictions.
The solution primarily involves two configuration files:
/etc/postfix/main.cf /etc/postfix/transport
First, edit the main.cf file to implement relay restrictions:
# Force all outbound mail through our smart host smtp_generic_maps = hash:/etc/postfix/generic relayhost = [mail.ourdomain.com] # Restrict destination domains smtpd_recipient_restrictions = check_recipient_access hash:/etc/postfix/recipient_access, permit_mynetworks, reject_unauth_destination
Create /etc/postfix/recipient_access with content:
ourdomain.com OK .ourdomain.com OK * REJECT
Then compile it with:
postmap /etc/postfix/recipient_access
After reloading Postfix, test with:
echo "Test" | mail -s "Test local" user@ourdomain.com echo "Test" | mail -s "Test external" user@gmail.com
The second command should now fail with "Relay access denied" error.
For complete isolation in dev environments, consider:
# Disable external listening inet_interfaces = loopback-only # Enable detailed logging for troubleshooting debug_peer_level = 2 debug_peer_list = ourdomain.com
For more complex filtering, header checks can be added:
header_checks = regexp:/etc/postfix/header_checks
With regex patterns to match and reject external domains.