When working with Postfix mail servers, one particularly frustrating issue occurs when bounce messages trigger a loopback error. The specific error message:
status=bounced (mail for domain loops back to myself)
This typically happens under these conditions:
- When sending to non-existent addresses at providers like Yahoo (immediate rejection)
- When using VERP (Variable Envelope Return Path) addresses
- When the bounce notification tries to return to a sender address that resolves back to your own server
Let's examine the key differences between working and failing scenarios from the logs:
Successful Case (RealTSP)
Oct 6 16:46:08 milford postfix/bounce[58483]: 5027DD6E971: sender non-delivery notification: EA68FD6EAB7 Oct 6 16:46:08 milford postfix/qmgr[57929]: EA68FD6EAB7: from=<failures-xxxxx=news.t1ps@news.t1ps>, size=11600, nrcpt=1 (queue active) Oct 6 16:46:09 milford postfix/lmtp[58484]: EA68FD6EAB7: to=<user@news.t1ps>, relay=smtp.news.t1ps[/var/imap/socket/lmtp], status=sent
Failing Case (Yahoo)
Oct 6 16:42:10 milford postfix/bounce[57756]: 33EBBD6EE87: sender non-delivery notification: A083ED6EA01 Oct 6 16:42:10 milford postfix/qmgr[57598]: A083ED6EA01: from=<failures-xxxxx=news.t1ps@news.t1ps>, size=11696, nrcpt=1 (queue active) Oct 6 16:42:10 milford postfix/smtp[57631]: A083ED6EA01: to=<user@news.t1ps>, status=bounced (mail for news.t1ps loops back to myself)
The root cause lies in how Postfix handles VERP addresses during bounce processing. Here are the key configuration elements involved:
main.cf Settings That Matter
myhostname = smtp.news.t1ps virtual_mailbox_domains = news.t1ps, domain2, domain3.co.uk, domain4 virtual_alias_maps = hash:/usr/local/etc/postfix_rsh/virtual virtual_mailbox_maps = hash:/usr/local/etc/postfix_rsh/virtual_mailbox_maps
Virtual Mailbox Maps
failures@news.t1ps dummy
To fix this issue, we need to implement several configuration changes:
- Create a dedicated bounce handler domain
- Configure proper transport mapping
- Update the virtual mailbox maps
Implementation Steps
Step 1: Add a bounce domain to your DNS and Postfix configuration
# In /etc/postfix/main.cf bounce_notice_recipient = postmaster@news.t1ps bounce_service_name = defer
Step 2: Modify your transport maps
# /usr/local/etc/postfix_rsh/transport news.t1ps lmtp:unix:/var/imap/socket/lmtp bounces.t1ps local:
Step 3: Update your virtual_mailbox_maps
# /usr/local/etc/postfix_rsh/virtual_mailbox_maps failures@news.t1ps dummy @bounces.t1ps dummy
After implementing these changes, test with both scenarios:
# Test with immediate rejection (Yahoo case) echo "Test" | mailx -s "Test Yahoo" nonexistent@yahoo.com # Test with delayed rejection (RealTSP case) echo "Test" | mailx -s "Test RealTSP" nonexistent@realtsp.com
For systems using VERP, add these additional settings:
# In main.cf recipient_delimiter = + default_verp_delimiters = += verp_delimiter_filter = +=
And create a dedicated VERP bounce handler:
# In master.cf verp-bounce unix - n n - - pipe flags=R user=verp argv=/usr/local/libexec/verp-bounce ${sender} ${recipient}
After all changes, run these commands to verify:
postmap /usr/local/etc/postfix_rsh/virtual_mailbox_maps postmap /usr/local/etc/postfix_rsh/transport postfix reload
The key is ensuring your bounce messages have a clear path that doesn't create a loopback to your primary mail domain.
When working with Postfix mail servers, you might encounter a particularly stubborn issue where bounce messages trigger the error:
Sep 30 13:38:53 postfix/smtp[62566]: DB8E6D6F9EA: to=<user@domain>, relay=none, delay=0, delays=0/0/0/0, dsn=5.4.6, status=bounced (mail for domain loops back to myself)
This occurs when:
- A message sent to an invalid recipient gets immediately rejected by the destination server (like Yahoo's 554 error)
- Postfix attempts to generate a bounce notification
- The bounce message's Return-Path points back to your own domain
- Postfix detects this as a mail loop and rejects its own notification
From your configuration files, several relevant settings stand out:
# main.cf myhostname = smtp.news.t1ps virtual_mailbox_domains = news.t1ps, domain2, domain3.co.uk, domain4 virtual_mailbox_maps = hash:/usr/local/etc/postfix_rsh/virtual_mailbox_maps
# virtual_mailbox_maps failures@news.t1ps dummy
Your logs show two distinct behaviors:
Working Case (RealTSP)
Oct 6 16:46:08 milford postfix/smtp[57936]: 5027DD6E971: to=<nonexistent@milford.realtsp>, relay=milford.realtsp[89.187.108.21]:25, delay=0.64, dsn=5.1.1, status=bounced (host milford.realtsp[89.187.108.21] said: 550 5.1.1 User unknown in virtual mailbox table)
Failing Case (Yahoo)
Oct 6 16:42:10 milford postfix/smtp[57631]: A083ED6EA01: to=<failures@news.t1ps>, relay=none, delay=0.01, dsn=5.4.6, status=bounced (mail for news.t1ps loops back to myself)
The fundamental issue stems from how different mail servers handle immediate rejections versus delayed bounces. When Yahoo immediately rejects with a 554 error during the SMTP conversation, Postfix tries to send the bounce notification to the Return-Path address (which in your VERP case points back to your domain).
Here's how to properly configure your Postfix instance to handle these cases:
# In main.cf bounce_notice_recipient = postmaster@yourdomain.com error_notice_recipient = postmaster@yourdomain.com notify_classes = bounce, delay, policy, protocol, resource, software # For VERP addresses specifically allow_percent_hack = no
Additionally, modify your virtual mailbox maps to ensure proper delivery:
# /usr/local/etc/postfix_rsh/virtual_mailbox_maps failures@news.t1ps OK bounces@news.t1ps OK postmaster@news.t1ps OK
For more control, create a custom bounce handler script:
#!/bin/sh # /usr/local/bin/custom_bounce_handler # Read the bounce message from stdin cat > /tmp/bounce.$$ # Extract important information FROM=$(grep '^From:' /tmp/bounce.$$ | head -1) TO=$(grep '^To:' /tmp/bounce.$$ | head -1) SUBJECT=$(grep '^Subject:' /tmp/bounce.$$ | head -1) # Process the bounce logger -t postfix/bounce "Handled bounce: $SUBJECT (From: $FROM, To: $TO)" # Clean up rm -f /tmp/bounce.$$ exit 0
Then configure Postfix to use it:
# In master.cf bounce unix - - n - 0 bounce -o bounce_service_name=custom_bounce custom_bounce unix - n n - - pipe flags=R user=nobody argv=/usr/local/bin/custom_bounce_handler
After making changes, test with:
postmap /usr/local/etc/postfix_rsh/virtual_mailbox_maps postfix reload
Send test messages to both valid and invalid addresses to verify proper bounce handling.
- Ensure all bounce-related addresses exist in virtual_mailbox_maps
- Verify your mydestination and virtual_mailbox_domains settings don't overlap
- Consider using a separate subdomain for bounces (e.g., bounces.yourdomain.com)
- Monitor logs closely after changes