How to delete all MAILER-DAEMON emails from your Postfix queue, when it matches a sender or recipient email address condition. When a large scale spam run was sent through your mail servers, you need to clean up and remove those spam messages. Doing so guarantees normal, valid email messages being sent quickly, and the spam messages never leave your queue. In Postfix, there are various similar commands to delete messages from the Postfix mail queue. Based on the Message-ID and/or email address…
Here is how you can delete mail from the mail queue in Postfix, based on a condition. For example all MAILER-DAEMON emails or spam, by sender or recipient address.
How to delete all emails from a Postfix queue when it matches an address condition
I use this regularly to remove spam from my Postfix SMTP server mail queue. These oneliners are nice to have in Bash.
If you want to delete emails from your Postfix queue based on a sender address – spammer@example.com for example – you need to feed the mailq
output to awk
. The result is fed to postsuper
for deletion:
mailq | tail -n +2 | awk 'BEGIN { RS = "" }
{ if ( $7 == "spammer@example.com" ) print $1 }
' | tr -d '*!' | postsuper -d -
Code language: Bash (bash)
mailq | tail -n +2 | awk 'BEGIN { RS = "" }
{ if ( $7 ~ "@example.com" ) print $1 }
' | tr -d '*!' | postsuper -d -
Code language: Bash (bash)
Here, $7
represents the sender address (7th awk field), either full (spammer@example.com) or matched by regular expression (~ @example.com
).
Do you want to delete message sent to a particular address? Use $8
or $9
as they represent recipient addresses:
mailq | tail -n +2 | awk 'BEGIN { RS = "" }
{ if ( $8 == "spammer@example.com" ) print $1 }
' | tr -d '*!' | postsuper -d -
Code language: Bash (bash)
mailq | tail -n +2 | awk 'BEGIN { RS = "" }
{ if ( $8 == "spammer@example.com" && $9 == "" ) print $1 }
' | tr -d '*!' | postsuper -d -
Code language: Bash (bash)
mailq | tail -n +2 | awk 'BEGIN { RS = "" }
{ if ( $8 == "spammer@example.com" || $8 == "spammer2@example2.com" ) print $1 }
' | tr -d '*!' | postsuper -d -
Code language: Bash (bash)
and so on.
But what if those spam mails already left your system? And can’t be delivered? Then you’re stuck with hundreds of thousands MAILER-DAEMON messages. Of course you can delete all those mails from your Postfix queue: just use MAILER-DAEMON as sender address in the above scripts.
But doing so, you probably also delete other, possibly valid MAILER-DAEMON mails informing you about undeliverable emails. Therefore you need to build in a condition.
The following shell script scans through the Postfix mail queue – using the mailq
command – looking for messages sent by MAILER-DAEMON, or any other email address you provide as argument. Of those message-id’s it scans to see if the recipient condition is matched.
Those messages are then deleted from the queue by executing postsuper -d -
.
The following example script takes the recipient email address as input, and deletes all mails where MAILER-DAEMON is the sender:
#!/bin/bash
EMAILADDY=$1
if [ -z "$EMAILADDY" ]
then
echo "Usage: $0 <email adres>"
exit
fi
echo "Delete all emails addressed to $EMAILADDY, and sent by MAILER-DAEMON, from our Postfix queue."
mailq | tail -n +2 | grep -v '^ *(' | awk -v "address=$EMAILADDY" 'BEGIN { RS = "" }
{
# example conditions:
# if ( $7 == "MAILER-DAEMON && $8 == address && $9 == "" )
# if ( $7 == "MAILER-DAEMON && $8 == "" && $9 == address )
# if ( $7 == "MAILER-DAEMON && $8 == address || $9 == address )
if ( $7 == "MAILER-DAEMON && $8 == address )
print $1
}
' | tr -d '*!' | postsuper -d -
Code language: Bash (bash)
Call your script on the command line providing a recipient email address:
sh ./delete-mail-from-queue.sh spammer@example.com
Code language: Bash (bash)
Postfix, delete all mails from the queue queue sent by spammer@example.com:
#!/bin/bash
EMAILADDY=$1
if [ -z "$EMAILADDY" ]
then
echo "Usage: $0 <email address>"
exit
fi
echo "Delete all emails addressed to $EMAILADDY from our Postfix queue."
mailq | tail -n +2 | grep -v '^ *(' | awk -v "address=$EMAILADDY" 'BEGIN { RS = "" }
{
# example conditions:
# if ( $8 == address && $9 == "" )
# if ( $8 == address || $9 == address )
if ( $8 == address )
print $1
}
' | tr -d '*!' | postsuper -d -
Code language: Bash (bash)
Call your script on the command line providing an email address:
sh ./delete-mail-from-queue.sh spammer@example.com
Code language: Bash (bash)
To use a regular expression in Awk, suppose you want to match all emails from various @example.com addresses, change the line if ($8 == address)
to:
# the sender is the 7th Awk field, thus $7
if ($7 ~ address)
Code language: Bash (bash)
and provide only example.com as a parameter:
sh ./delete-mail-from-queue.sh example.com
Code language: JavaScript (javascript)
Again, use $8
and/or $9
to match recipients, assuming MAILER-DAEMON is the sender / $7
.
Remove mail from multiple Postfix instances queues
When you are using multiple Postfix instances, and control them with postmulti, then you can use command line arguments in your script. For example:
#!/bin/bash
QUEUETYPE=$1
EMAILADDY=$2
if [ -z "$QUEUETYPE" ] || [ -z "$EMAILADDY" ]
then
echo "Usage: $0 <queuetype web|smtp|incoming> <email address>"
exit
fi
echo "Delete all emails addressed to $EMAILADDY from our Postfix $QUEUETYPE queue."
postmulti -i $QUEUETYPE -x mailq | tail -n +2 | grep -v '^ *(' | awk -v "address=$EMAILADDY" 'BEGIN { RS = "" }
{
if ( $7 == address )
print $1
}
' | tr -d '*!' | postmulti -i $QUEUETYPE -x postsuper -d -
Code language: Bash (bash)
Example usage is: sudo ./clean-mailqueue incoming MAILER-DAEMON
.
Always be careful when messing with mail queues, and especially regular expressions.
Hi testerblogersTest, and thank you for your comment (which I edited for syntax highlighting).
Strange, you shouldn’t get a syntax error… I’ve checked and tested my own code, which works fine. Line 18 is exactly the same. Maybe a copy/paste or line-ending conversion error?
Note: I’ve changed $8 (recipient) to $7 (sender):