Postfix Flush the Mail Queue

by on October 25, 2007 · 30 comments· LAST UPDATED October 11, 2010

in , ,

Traditionally you use the "sendmail -q" command to flush mail queue under Sendmail MTA. Under Postfix MTA, just enter the following command to flush the mail queue:
# postfix flush
OR
# postfix -f

To see mail queue, enter:
# mailq

To remove all mail from the queue, enter:
# postsuper -d ALL

To remove all mails in the deferred queue, enter:
# postsuper -d ALL deferred

postfix-delete.pl script

Following script deletes all mail from the mailq which matches the regular expression specified as the first argument (Credit: ??? - I found it on old good newsgroup)

#!/usr/bin/perl
 
$REGEXP = shift || die "no email-adress given (regexp-style, e.g. bl.*\@yahoo.com)!";
 
@data = qx</usr/sbin/postqueue -p>;
for (@data) {
  if (/^(\w+)(\*|\!)?\s/) {
     $queue_id = $1;
  }
  if($queue_id) {
    if (/$REGEXP/i) {
      $Q{$queue_id} = 1;
      $queue_id = "";
    }
  }
}
 
#open(POSTSUPER,"|cat") || die "couldn't open postsuper" ;
open(POSTSUPER,"|postsuper -d -") || die "couldn't open postsuper" ;
 
foreach (keys %Q) {
  print POSTSUPER "$_\n";
};
close(POSTSUPER);
 

For example, delete all queued messages from or to the domain called fackspamdomain.com, enter:
./postfix-delete.pl fackspamdomain.com
Delete all queued messages that contain the word "xyz" in the e-mail address:
./postfix-delete.pl xyz

Updated for accuracy.

TwitterFacebookGoogle+PDF versionFound an error/typo on this page? Help us!

{ 30 comments… read them below or add one }

1 Matt December 10, 2007 at 11:49 pm

The command for “To remove all bounced mail from Queue, enter:” is incorrect. That command will completely delete all the contents of your Mail Queue.

When I read this I thought it would eliminate only the bounced back emails that were sitting in my queue. I was wrong. It deleted all 6,000 of the emails sitting in my queue.

If this post is any sign of the type of information provided on this website, the readers are in for a big surprise…and some pink slips from their employer..

Reply

2 Harvey March 19, 2011 at 5:00 am

Wow – you seriously just run any commands you find in a forum on your job’s production servers? You deserved that pink slip.

Reply

3 MutluMaymun March 23, 2011 at 2:23 am

Wow – do you seriously have to write a comment to insult someone after 3 years? While what you said has been said a few lines below, years ago?

Reply

4 Callum February 28, 2014 at 2:58 pm

I agree adding a comment to something a few years ago is just plain stoopid!

Reply

5 Eric August 7, 2014 at 8:23 pm

I agree. Even commenting a few months later is not so bright.

Reply

6 nixCraft December 11, 2007 at 8:45 am

Matt,

thanks for the heads up. It was a typo. The post has been updated

Reply

7 Henk December 11, 2007 at 3:46 pm

I think matt deserves a pink slip from his employer, because he uses commands found on random sites without even checking what the effects are!

Reply

8 Jim April 24, 2008 at 6:30 pm

I’ve found this code on two different blogs and have received compilation errors both times similar to:

Unmatched right curly bracket at ./delete-queue line 9, at end of line
(Might be a runaway multi-line ;; string starting on line 5)
syntax error at ./postfix-delete.pl line 9, near “}”
Execution of ./postfix-delete.pl aborted due to compilation errors.

I’m more of a PHP person so Perl’s not my thing. I know syntax is really important and I’ve double and triple checked to make sure things are correct, including composing in vi, pico and bbedit editors.
??

Reply

9 Manuel May 2, 2008 at 1:20 am

Wow This is a seriously crappy coding job. Who writes this stuff? I cleaned this up to not only make sure this was scoped correctly, but also try to have a novice perl user understand it.

#!/usr/bin/perl

my $REGEXP = shift(@ARGV) || die “no email-adress given (regexp-style, e.g. bl.*\@yahoo.com)!”;

my %Q;
my $queue_id;
my @data = `/usr/sbin/postqueue -p`;
foreach my $line (@data) {
if ($line =~ /^(\w+)(\*|\!)?\s/) {
$queue_id = $1;
}
if($queue_id) {
if ($line =~ /$REGEXP/i) {
$Q{$queue_id} = 1;
$queue_id = “”;
}
}
}

open(POSTSUPER,”|postsuper -d -“) || die “couldn’t open postsuper” ;

foreach my $key (keys %Q) {
print POSTSUPER “$key\n”;
}
close(POSTSUPER);

Hopefully this helps.. I cannot confirm that this works, just cleaned it up so that it makes sense.

Reply

10 pd July 25, 2008 at 2:08 am

is there someone help me out? i need scripts to check how many emails bounced or deferred or sent?
if bounced or deferred then why? like full details message?

Reply

11 Sean November 7, 2008 at 3:27 pm

Manuel, learn to indent.

Reply

12 somono February 11, 2009 at 8:08 am

If a queue_id of – is specified, the program reads queue IDs from standard input. For example, to delete all mail with exactly one sender info@msn.com :

mailq | tail +2 | grep -v '^ *(' | awk  'BEGIN { RS = "" }
              # $7=sender, $8=recipient1, $9=recipient2
               { if ($7 == "info@msn.com")
               print $1 }
              ' | tr -d '*!' | postsuper -d -

Reply

13 salman June 25, 2009 at 9:43 am

thanx alot alot ………………. for the script it works very very very well …… very very very well done …. !!!!!!!!!!!!!!

Reply

14 lemsx1 March 4, 2010 at 6:09 pm

Some say Perl is becoming a lost art ;-) Here is my Ruby re-write (a bit more efficient. it uses practically no memory)

Save as postfix-purge-queue and run every 1 min from a cron job.

Change the path to match your own binaries. This assumes Solaris (+ blastwave) paths:

#!/opt/csw/bin/ruby
# vi: ft=ruby :
#
#  !! lemsx1 $$@$$ gmail !! com
# 2010-03-04 12:20 EST
#
# Cleans postfix mail queue on Solaris
# set debug to true when testing regex:
debug = false
regex = "example\.(com|net|org)|Host\s+or\s+domain\s+name\s+not\s+found"
IO.popen("/opt/csw/sbin/postqueue -p") do |readme|
    q_id = nil
    readme.each do |line|
        if line =~ /^(\w+)(\*|\!)?\s/
            q_id = $1
        end
        if q_id
            if line =~ /#{regex}/
                if debug
                    puts "matching #{q_id}"
                else
                    `/opt/csw/sbin/postsuper -d #{q_id} > /dev/null 2>&1`
                end
            q_id=nil
            end
        end
    end
end

Reply

15 Alessandro April 5, 2010 at 12:02 pm

It’s works for me. Very nice Script VIVEK.

Reply

16 nxvir February 9, 2011 at 11:12 am

How to read mail in queue? I could not find that command. Like we do in
exim -Mvh id
exim -Mvb id

What is the command for postfix?

Reply

17 Patrick Matsumura May 27, 2011 at 10:21 am

Just use mailq

Reply

18 Kwex June 12, 2011 at 8:20 pm

I use Fedora and had problems running this script. I replaced with this line

open(POSTSUPER,”|/usr/sbin/postsuper -d -“) || die “couldn’t open postsuper” ;

and it worked fine.

Thanks!

Reply

19 Roman June 16, 2011 at 8:45 am

Cool, thanks for the script, worked just fine at my end, just change the paths in the script and that’s it.

Thanks again!

Reply

20 Luigi Molinaro November 8, 2011 at 11:30 am

Thanks fot your awesome works !

Reply

21 Ali Ramzan December 21, 2011 at 5:59 am

My requirement is postfix send 10emails in 1min.Whole postfix server send just 10 emails in 1min.

How can i do this ? any one help me?

Reply

22 Jose January 16, 2012 at 3:47 pm

All scripts in this thread are gonna FAIL because the lines provided by “postqueue -p” can generate the following two lines, being the second an explanation of the first:
0EE281EAE6C 78231 Mon Jan 16 00:35:08 aaa@hotmail.com
(line including for some reason a mail from yahoo, like recipient@yahoo.com )

and if you run it against the domain .*@yahoo.com, the script is gonna delete the entry from domain aaa@hotmail.com, when it shouldn’t.

To solve it, you should have this:

  if (/^(\w+)(\*|\!)?\s/) {
     $queue_id = $1;
  } else {
     $queue_id = "";
  }
Instead of just this:
  if (/^(\w+)(\*|\!)?\s/) {
     $queue_id = $1;
  } else {
     $queue_id = "";
  }

(The mighty Ruby script will fail for the same reason, and is gonna be fixed as well with the “else” help)

Reply

23 Steve August 20, 2012 at 4:04 pm

Maybe I’m missing something here, but your two code blocks are identical…what are you saying should be changed, Jose?

Reply

24 Ashish May 3, 2012 at 1:35 am

Hi Vivek,
Could you please guide me as to how to use the command to kill all the queue mails in the post fix, Sorry I am new to Linux and Perl, I have no idea what i am dealing with please help me out, Following your instruction above i created the perl file, when i tried the command ./postfix-delete.pl yahoo.com i received the error that
root@mail:/etc/perl# delete.pl yahoo.com
-bash: delete.pl: command not found.
Can anyone please help me out with this, I am receiving 25000 spams everyday.

Reply

25 Orango Tango July 20, 2012 at 1:36 pm

Thanks mate ! Script worked as a charm !

Reply

26 Leo G April 18, 2013 at 12:31 pm

Thanks a lot vivek, The script is awesome

Reply

27 middlewhere August 27, 2013 at 11:40 pm

saved me hours – thanks

Reply

28 Toff August 29, 2013 at 10:41 pm

mailq |awk ‘{print $1}’ |grep -E “[a-Z 0-9]{13}” |xargs -I {} postsuper -d {}

Reply

29 Mac October 15, 2013 at 10:35 pm

postsuper -d ALL deferred
Worked like a champ, I had forgotten the command trying to setup a smart host to relay through and had clogged up the mailq on the server.

: )

Reply

30 BetaBoy July 11, 2014 at 9:24 am

I think he mean the

} else {
$queue_id = “”;
}

part is added to prevent grepping the dest. server reject message.

Reply

Leave a Comment

Tagged as: , , , , , , , , , , , , ,

Previous post:

Next post: