The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 2,948 other subscribers

Cleaning up bounces from /var/spool/mqueue using qtool

Posted by jpluimers on 2018/11/26

Part of my /var/spool/mqueue consist of administrative bounces to mail domains that fail for a long time.


First a few queries to filter the messages I want to move (the -h suppresses filename so you can aggregate with sort and uniq):

grep -h "MDeferred: Connection" /tmp/mqueue-junk/qf* | sort | uniq -c

It gives results like this:

     56 MDeferred: Connection refused by
      1 MDeferred: Connection reset by
     10 MDeferred: Connection timed out with

After blacklisting those domains, I’ve used to cleanup the mail queue.

As does not have “dry run” or log options, it’s best to test expressions on a copy of your mail queue first. I’ve made copies in /tmp/mqueue for this.

The query expression language on is complicated to get right: the documentation talks about using %msg which in fact is $msg and there is no official documentation on the mapping of qf files in the mqueue directory to expressions used in

Luckily that mapping is in itself as explained by A recent source is at where I copied the fragment further below from.

Now just see these commands:

./contrib/ -C /etc/ -e '$msg{message}[0] =~ /Deferred: Connection refused by/' /tmp/mqueue-junk/ /tmp/mqueue/


./contrib/ -C /etc/ -e '$msg{num_delivery_attempts} > 100' /tmp/mqueue-junk/ /tmp/mqueue/

Since there are two M lines per qf file, you have to index the {message} part. There is no need for that with the {num_delivery_attempts}.

Because of the =~ operator, the match expressions are of [WayBack] perlre – Perl regular expressions.

If you run this on the live /var/spool/mqueue directory, then you can get errors like this which means you should retry after a few minutes (or run with sendmail disabled):

Could not obtain fcntl lock on '/var/spool/mqueue//qfv4H9jv7M007291': Resource temporarily unavailable.
Could not obtain fcntl lock on '/var/spool/mqueue//qfv5DB2NkJ024360': Resource temporarily unavailable.

Note that the searching for Mhost map: lookup \(.*\): deferredfails, so I write this little script that shows which commands are going to be executed and how to execute them:

grep -l "^Mhost map: lookup \(.*\): deferred$" /var/spool/mqueue/qf* | xargs -n1 -I {} echo "./contrib/ -C /etc/ /var/spool/mqueue-junk/ {}"
grep -l "^Mhost map: lookup \(.*\): deferred$" /var/spool/mqueue/qf* | xargs -n1 -I {} ./contrib/ -C /etc/ /var/spool/mqueue-junk/ {}

It executes the once per grep output line.

References I’ve used to get to the above:

Mapping between qf and

   my %parse_table = 
        'A' => 'auth',
        'B' => 'body_type',
        'C' => 'controlling_user',
        'D' => 'data_file_name',
        'd' => 'data_file_directory',
        'E' => 'error_recipient',
        'F' => 'flags',
        'H' => 'parse_header',
        'I' => 'inode_number',
        'K' => 'next_delivery_time',
        'L' => 'content-length',
        'M' => 'message',
        'N' => 'num_delivery_attempts',
        'P' => 'priority',
        'Q' => 'original_recipient',
        'R' => 'recipient',
        'q' => 'quarantine_reason',
        'r' => 'final_recipient',
        'S' => 'sender',
        'T' => 'creation_time',
        'V' => 'version',
        'Y' => 'current_delay',
        'Z' => 'envid',
        '!' => 'deliver_by',
        '$' => 'macro'


# This script will prompt for sender domain and then purge the mail queue
# Requires
echo "Type the sender domain you would like to purge, followed by [ENTER]:"
read domain
echo "Got it. I'll purge all messages from $domain"
QIDS="$(mailq | grep -B1 $domain | grep '^[a-z]' | awk '{print $1}' | sed 's/\*$//')"
for q in $QIDS
/usr/local/bin/ -C /etc/mail/ -d /var/spool/mqueue/$q

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: