15

I have a server with multiple domains. How can I clear all Postfix queue messages for a specific domain?

7 Answers 7

27

UPDATE 2021-04-18:

mailq | tail -n +2 | grep -v '^ *(' | awk  'BEGIN { RS = "" } { if ($8 ~ /@example\.com/ && $9 == "") print $1 }' | tr -d '*!' | postsuper -d -

Whereas $7=sender, $8=recipient1, $9=recipient2. You can also adapt the rule for other recipients ($9) to your needs.

The command is based on an example of the postsuper manpage which an example command matching a full recipient mail address:

mailq | tail -n +2 | grep -v '^ *(' | awk  'BEGIN { RS = "" } { if ($8 == "[email protected]" && $9 == "") print $1 }' | tr -d '*!' | postsuper -d -

Old content:

This command deletes all mails sent from or to addresses that end with @example.com:

sudo mailq | tail -n +2 | awk 'BEGIN { RS = "" } /@example\.com$/ { print $1 }' | tr -d '*!' | sudo postsuper -d - 
4
  • 2
    On Linux, use tail -n +2 instead of tail +2. Jun 12, 2017 at 15:28
  • The tr -d can be refactored into the Awk script, too. Replace { print $1 } with { r = $1; gsub(/[!*]/, "", r); print r }
    – tripleee
    Oct 26, 2018 at 10:07
  • If you copy, edit and paste the example from postsuper man page, you'll avoid unwanted side effects.
    – symcbean
    Mar 26, 2021 at 16:14
  • @symcbean Thanks for the hint, I've updated my answer!
    – sebix
    Apr 18, 2021 at 10:13
11

Grep solution

mailq | grep example.com -B1 | grep -oE "^[A-Z0-9]{10,11}" | sudo postsuper -d -

assumes ID is between 10 and 11 digits, (based on inodes)

8

I have tried this solution in ubuntu 12.04, and it doesn't work this way:

sudo mailq | tail +2 | awk 'BEGIN { RS = "" } / @example\.com$/ { print $1 }' | tr -d '*!' | sudo postsuper -d -

I need to change to this way:

postqueue -p | tail -n +2 | awk 'BEGIN { RS = "" } /@example\.com/ { print $1 }' | tr -d '*!' | postsuper -d -
1
  • yes, you have to eliminate the space before the "@".
    – Alex
    Nov 23, 2017 at 12:52
2

Look at pfdel.pl, a mandatory tool to manage the queue. It takes a regexp and remove the mails waiting in queue corresponding to your domain.

2

I want to give a "more modern" answer parsing the json output of postqueue -j. It depends on the package jq to filter the output and is much more understandable (and debuggable):

postqueue -j | jq -rc 'select(.recipients[].address | match(".*@example\\.com$"))["queue_id"]' | postsuper -d -

# For an exact Mail match
postqueue -j | jq -rc 'select(.recipients[].address == "[email protected]")["queue_id"]' | postsuper -d -

Another less related argument for this solution besides readability is it's easy adaptability:

# Filter on delay_reason being "Connection timed out"
postqueue -j | jq -rc 'select(.recipients[].delay_reason | match(".*Connection timed out$"))["queue_id"]' | postsuper -d -

# Filter on arrival_time being older than certain age
postqueue -j | jq -rc 'select(.arriveal_time < 1710265065)["queue_id"]' | postsuper -d -

# Filter on the size of messages
postqueue -j | jq -rc 'select(.message_size > 100000)["queue_id"]' | postsuper -d -

This is the full json, showing all filterable values:

{
  "queue_name": "deferred",
  "queue_id": "4TwLyJ4Gpyz2xVB",
  "arrival_time": 1710407000,
  "message_size": 15932,
  "forced_expire": false,
  "sender": "MAILER-DAEMON",
  "recipients": [
    {
      "address": "[email protected]",
      "delay_reason": "delivery temporarily suspended: connect to mail.example.com[111.222.333.444]:25: Connection timed out"
    }
  ]
}
0

When you want to delete messages from or to e-mail addresses at a specific domain, this command works for me:

mailq | \
  tail -n +2 | \
  awk 'BEGIN { RS = "" } / @example\.com$/ { print $1 }' | \
  tr -d '*!' | \
  postsuper -d -

Also works for deleting e-mails from or to specific e-mail addresses by supplying for example mail@example\.com$/ instead of @example\.com$/.

Taken from a comment on howtoforge.com. See there for related solutions and the command in one line. (I used bash line continuation for readability).

A very similar command that allows to make deletion dependent on whether the address appears as sender, recipient etc. is found in man postsuper, where it says about -d:

For example, to delete all mail with exactly one recipient [email protected]:

mailq | \
  tail -n +2 | \
  grep -v '^ *(' | \
  awk 'BEGIN { RS = "" } { if ($8 == "[email protected]" && $9 == "") print $1 }' | \
  tr -d '*!' | \
  postsuper -d -

(The variables mean: $7=sender, $8=recipient1, $9=recipient2. I changed the quote to use tail -n +2, since their tail +2 does not work any more, at least on some modern systems.)

2
  • The space before @example\.com seems wrong.
    – tripleee
    Oct 26, 2018 at 10:04
  • 1
    The backslashes at the end of line are not actually necessary; the shell understands that the command continues on the next line if the last token is | (or || or && or a bunch of others).
    – tripleee
    Oct 26, 2018 at 10:10
-3

I've modified it little bit:

mailq | grep -B1 | grep -oE "^[A-Z0-9]{12}" | xargs -I% postsuper -d %

2
  • 3
    Then please explain why and what this is supposed to do.
    – Sven
    Apr 12, 2018 at 15:40
  • Running hundreds of instances of postsuper is not an improvement at all. xargs is nice when you use it properly, but this is not one of those situations.
    – tripleee
    Oct 26, 2018 at 10:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .