When running a Postfix mail server that needs to handle both internal and external email routing, you often encounter situations where:
- Emails destined for your organization's domains should be delivered to a specific mail server (e.g., Exchange)
- All other emails should follow normal MX record resolution
The solution involves two main Postfix configuration files:
/etc/postfix/main.cf /etc/postfix/transport
First, edit your main.cf
file to include:
# Enable transport maps transport_maps = hash:/etc/postfix/transport
Then create or modify your transport
file:
# Format: domain destination example.com smtp:[mail.example.com] example.net smtp:[mail.example.com] subdomain.example.com smtp:[mail.example.com]
Here's a complete configuration example that handles multiple domains:
# /etc/postfix/main.cf additions transport_maps = hash:/etc/postfix/transport local_recipient_maps = relay_domains = $mydestination
# /etc/postfix/transport contents example.com smtp:[192.168.1.100] corp.com smtp:[mail.corp.com]:587 .internal smtp:[mx.internal]:2525 * :
After making these changes, run:
postmap /etc/postfix/transport postfix reload
For more complex scenarios, you might want to:
- Add authentication for the relay host
- Configure TLS for secure delivery
- Set up recipient verification
If emails aren't routing correctly, check:
postconf transport_maps postmap -q example.com /etc/postfix/transport
Also examine your mail logs for delivery attempts:
tail -f /var/log/mail.log
In many enterprise environments, you might have Postfix handling outgoing mail from applications while needing to route specific domain traffic differently. Here's a common setup:
- Applications generate emails for both internal (yourdomain.com) and external recipients
- Internal mail should be delivered to your Exchange server (mail.example.com)
- External mail should follow normal MX record resolution
The key is using Postfix's transport_maps
feature to override routing for specific domains:
# /etc/postfix/main.cf additions: transport_maps = hash:/etc/postfix/transport relayhost =
Create/edit /etc/postfix/transport
:
# Internal domains route to Exchange example.com smtp:[mail.example.com] sub.example.com smtp:[mail.example.com]
Important notes about the transport map format:
- Use square brackets [] to prevent MX lookups for the target host
- The left side matches domain names exactly (not subdomains unless specified)
- Empty relayhost tells Postfix to use MX records by default
After creating the transport file:
# Postmap and reload postmap /etc/postfix/transport systemctl reload postfix
Verify with Postfix's sendmail
test:
echo "Test internal" | sendmail -f sender@example.com recipient@example.com echo "Test external" | sendmail -f sender@example.com recipient@gmail.com
Check your mail logs (/var/log/mail.log
) to confirm routing:
grep 'to=' /var/log/mail.log grep 'to= ' /var/log/mail.log
To catch all subdomains without listing each one:
# In /etc/postfix/transport: .example.com smtp:[mail.example.com]
The leading dot acts as a wildcard for all subdomains.
If your Exchange server requires authentication, you'll need to configure SASL:
# /etc/postfix/main.cf additions: smtp_sasl_auth_enable = yes smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd smtp_sasl_security_options = noanonymous
Create /etc/postfix/sasl_passwd
:
[mail.example.com] username:password
# Secure and postmap the file: chmod 600 /etc/postfix/sasl_passwd postmap /etc/postfix/sasl_passwd