Postfix Email Redirect: How to Route All Outbound Emails to a Single Test Address


2 views

When developing web applications that send email notifications, we often need to test with real customer data. The last thing we want is accidental emails reaching actual customers during testing cycles. This is particularly critical for:

  • E-commerce platforms sending order confirmations
  • SaaS applications sending password reset links
  • CRM systems sending customer communications

The most reliable approach is to modify Postfix's transport map to intercept all outgoing emails. Here's how to implement it:

# Step 1: Create transport map file
sudo nano /etc/postfix/transport

# Add these lines (replace test@yourdomain.com with your testing address):
*    local:testuser
.*   smtp:[127.0.0.1]:8025

After creating the transport map, we need to compile it and modify main.cf:

# Compile the transport map
sudo postmap /etc/postfix/transport

# Edit main configuration
sudo nano /etc/postfix/main.cf

# Add these parameters:
transport_maps = hash:/etc/postfix/transport
default_transport = error:No valid transport configured
local_recipient_maps =
local_transport = virtual
virtual_alias_maps = hash:/etc/postfix/virtual

For more sophisticated testing scenarios, you can implement header checks:

# In /etc/postfix/header_checks
/^To:.*/ REPLACE To: test@yourdomain.com
/^Cc:.*/ REPLACE Cc: test@yourdomain.com
/^Bcc:.*/ REPLACE Bcc: test@yourdomain.com

# Then in main.cf:
header_checks = regexp:/etc/postfix/header_checks

After making these changes, always verify your configuration:

# Check configuration syntax
sudo postfix check

# Reload Postfix
sudo systemctl reload postfix

# Test email delivery
echo "Test email" | mail -s "Test Subject" customer@example.com

For development environments where you don't need any email delivery at all:

# In main.cf:
default_transport = error:No mail delivery in dev environment
relayhost =
mynetworks = 127.0.0.0/8
inet_interfaces = loopback-only

When developing or testing web applications that handle email notifications, we often need to work with real customer data to ensure proper functionality. However, this creates a significant risk of accidentally sending test emails to actual customers - a scenario that could damage client relationships and violate data protection regulations.

Postfix provides an elegant solution through its transport mapping feature. This allows us to intercept and redirect all outgoing emails to a designated test address while maintaining the original email structure for debugging purposes.

# Main configuration in /etc/postfix/main.cf
transport_maps = hash:/etc/postfix/transport
default_transport = smtp:[127.0.0.1]:10025  # Optional safety net

Here's how to implement email redirection in a production-like test environment:

# 1. Edit /etc/postfix/transport
# Redirect all emails to test@example.com
*       smtp:[127.0.0.1]:10025
.test.example.com       smtp:[127.0.0.1]:10025
example.com       smtp:[127.0.0.1]:10025

# 2. Create transport map database
sudo postmap /etc/postfix/transport

# 3. Configure master.cf for local delivery
127.0.0.1:10025 inet n - n - - smtpd
  -o receive_override_options=no_unknown_recipient_checks
  -o smtpd_recipient_restrictions=permit_mynetworks,reject
  -o mynetworks=127.0.0.0/8
  -o smtpd_restriction_classes=
  -o local_recipient_maps=
  -o relay_recipient_maps=

For more complex scenarios, consider these additional parameters:

# In main.cf
sender_canonical_maps = regexp:/etc/postfix/sender_canonical
recipient_canonical_maps = regexp:/etc/postfix/recipient_canonical

# Example regex maps:
/^(.*)$/    test+${1}@example.com

After implementing these changes, verify your configuration:

# Check configuration
sudo postfix check
sudo postconf -n

# Test email sending
echo "Test email" | mail -s "Test Subject" realcustomer@example.com

# View mail logs
tail -f /var/log/mail.log

For completely isolated test environments, you might consider a null client configuration:

# In main.cf
default_transport = error:Test environment - no external mail delivery
relayhost = [127.0.0.1]:10025