When dealing with bounced emails in Postfix, it's crucial to understand where and how messages are stored. The mail queue typically resides in /var/spool/postfix
with these key directories:
/var/spool/postfix/deferred/ # For deferred messages /var/spool/postfix/incoming/ # New messages being processed /var/spool/postfix/active/ # Messages currently being delivered
First, identify the queued messages using the mailq
command. For example:
$ mailq | grep "user@wrongdomain.com" -Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient------- ABC123DEF 1024 Fri Jan 12 14:23:41 sender@domain.com user@wrongdomain.com
For a single message, you can manually edit the queue file:
# Find the message file $ find /var/spool/postfix/deferred -name "ABC123DEF*" # Make a backup copy $ cp /var/spool/postfix/deferred/ABC123DEF . # Edit the recipient information $ postcat -q ABC123DEF > message.txt $ sed -i 's/user@wrongdomain.com/user@correctdomain.com/' message.txt # Re-inject into Postfix $ postfix -i < message.txt
For bulk operations, use the official Postfix tools:
# List all messages for a recipient $ postqueue -p | grep "user@wrongdomain.com" | awk '{print $1}' > queue_ids.txt # Create a processing script #!/bin/bash while read qid; do postcat -q "$qid" > temp_msg sed -i 's/user@wrongdomain.com/user@correctdomain.com/' temp_msg sendmail -G -i -f sender@domain.com user@correctdomain.com < temp_msg postsuper -d "$qid" done < queue_ids.txt
Always follow these precautions when modifying the mail queue:
- Make backups of queue files before modification
- Stop postfix during major queue operations (
systemctl stop postfix
) - Verify message integrity with
postcat -q
after changes - Consider using
postsuper -H
to hold messages during editing
For ongoing address corrections, implement a smtpd_recipient_restrictions filter:
# In main.cf smtpd_recipient_restrictions = check_recipient_access hash:/etc/postfix/recipient_map ...other restrictions... # Create recipient_map $ cat /etc/postfix/recipient_map user@wrongdomain.com user@correctdomain.com # Postmap and reload $ postmap /etc/postfix/recipient_map $ systemctl reload postfix
The Postfix mail queue stores messages in the /var/spool/postfix/
directory with several subdirectories:
/var/spool/postfix/
├── deferred/
├── active/
├── incoming/
├── hold/
└── corrupt/
First, locate the problematic message in the queue:
postqueue -p | grep "recipient@wrongdomain.com"
This will show you the queue ID of the message (e.g., A1B2C3D4EF
).
Postfix provides tools to edit messages in the queue. Here's the safest approach:
# 1. Create a copy of the message
postcat -q A1B2C3D4EF > message.txt
# 2. Edit the recipient in the file
sed -i 's/recipient@wrongdomain.com/recipient@correctdomain.com/' message.txt
# 3. Remove the original message from queue
postsuper -d A1B2C3D4EF
# 4. Inject the corrected message
sendmail -f sender@domain.com recipient@correctdomain.com < message.txt
For bulk modifications, use this bash script:
#!/bin/bash
OLD_ADDR="wrong@example.com"
NEW_ADDR="correct@example.com"
for ID in $(postqueue -p | grep "$OLD_ADDR" | awk '{print $1}' | tr -d '!*'); do
postcat -q $ID > temp_msg
sed -i "s/$OLD_ADDR/$NEW_ADDR/g" temp_msg
postsuper -d $ID
sendmail -f $(grep '^From:' temp_msg | cut -d'<' -f2 | cut -d'>' -f1) $NEW_ADDR < temp_msg
done
Common issues when modifying queue files directly:
- File permissions - ensure you're running as root or postfix user
- Queue corruption - always make backups before modifications
- Header integrity - maintain proper MIME structure when editing
For future prevention, consider setting up a header_check filter:
# In main.cf:
header_checks = regexp:/etc/postfix/header_checks
# In header_checks file:
/^To:.*wrong@example.com/ REPLACE To: correct@example.com
After making changes, verify the message is in queue with the correct recipient:
postqueue -p | grep "correct@example.com"