How to Restrict Postfix Mail Delivery to a Single Domain on Development Server


2 views

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.