When building mail processing systems, we often need to route incoming emails differently based on recipient addresses. A common scenario involves having Postfix handle general mail delivery while forwarding specific domains/subdomains to specialized processors like Lamson (Python mail server). Here's how to implement this properly.
Internet → Postfix (port 25) → ├──→ Lamson (port 10025) for special@domain.com └──→ Local delivery for others
Edit /etc/postfix/main.cf
:
# Enable transport maps transport_maps = hash:/etc/postfix/transport # Lamson relay configuration lamson_destination = localhost:10025 # Other standard Postfix settings mydestination = $myhostname, localhost.$mydomain, localhost relayhost = inet_interfaces = all
Create /etc/postfix/transport
:
# Format: pattern transport:destination specialdomain.com smtp:[127.0.0.1]:10025 .subdomain.org smtp:[127.0.0.1]:10025 * :
Then compile the map:
postmap /etc/postfix/transport
Verify with Postfix's built-in checker:
postfix check postmap -q "test@specialdomain.com" hash:/etc/postfix/transport
Basic Lamson server setup (server.py):
import lamson.server class BasicReceiver(lamson.handlers.Base): def handle(self, message): print("Received message to:", message['to']) if __name__ == "__main__": lamson.server.run( receiver=BasicReceiver(), host='localhost', port=10025 )
For more complex routing, use pcre
transport maps:
# In main.cf transport_maps = pcre:/etc/postfix/transport_pcre
Sample PCRE map:
/^user-\d+@special\.com$/ smtp:[127.0.0.1]:10025 /^.*@marketing\.com$/ smtp:[192.168.1.100]:25
For high-volume systems:
# In main.cf default_process_limit = 100 smtpd_client_connection_count_limit = 20 smtpd_client_connection_rate_limit = 30
Use these commands to monitor mail flow:
tail -f /var/log/mail.log postqueue -p # View mail queue postsuper -d ALL # Flush queue in emergencies
Essential security settings for the proxy:
smtpd_delay_reject = yes smtpd_helo_required = yes smtpd_sender_restrictions = reject_unknown_sender_domain smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination
When building mail processing systems, we often need to route incoming emails to different handlers based on destination addresses. In this case, we want to:
- Use Postfix as the primary MTA listening on port 25
- Proxy specific emails to Lamson (listening on port 10025)
- Process remaining emails normally through Postfix
The solution involves using Postfix's transport_maps
feature to create routing rules. Here's the step-by-step approach:
# /etc/postfix/main.cf
transport_maps = hash:/etc/postfix/transport
local_recipient_maps =
Define which domains or addresses should be proxied to Lamson:
# /etc/postfix/transport
lamson.example.com smtp:[127.0.0.1]:10025
.example.com smtp:[127.0.0.1]:10025
* :
Ensure Postfix can communicate with Lamson by adding this to your master.cf:
127.0.0.1:10025 inet n - n - - smtpd
-o smtpd_authorized_xforward_hosts=127.0.0.0/8
-o smtpd_client_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
After making changes, remember to:
postmap /etc/postfix/transport
postfix reload
Test the routing by sending emails to both Lamson-handled addresses and regular addresses while monitoring mail logs.
For more complex routing, consider using check_recipient_access
with regular expressions:
smtpd_recipient_restrictions =
check_recipient_access regexp:/etc/postfix/recipient_access
...other restrictions...
# /etc/postfix/recipient_access
/^user-.*@lamson\.example$/ FILTER smtp:[127.0.0.1]:10025
Implement proper error handling for cases when Lamson is unavailable:
# /etc/postfix/main.cf
lamson_destination_recipient_limit = 1
lamson_transport_retry_time = 60s