DevOps · K8s · Volleyball · Travel  •  DevOps · K8s · Volleyball · Travel  •  DevOps · K8s · Volleyball · Travel
Explore NY Stream

How to flush postfix mail queue and its various operations

— ny_wk

How to flush postfix mail queue and its various operations

To flush the Postfix mail queue, run postqueue -f (or its alias postfix flush) as root, which forces Postfix to attempt immediate redelivery of every message sitting in the deferred and active queues. The same toolset lets you inspect, hold, release, requeue, and delete individual messages, giving an administrator full manual control over mail flow.

Managing the Postfix mail queue is a core skill for anyone running a Mail Transfer Agent (MTA). When remote servers go offline, DNS misbehaves, or a flood of mail backs up, messages pile up on disk and Postfix retries them on its own schedule. Knowing the right commands means you can clear a backlog, quarantine suspicious mail, or surgically remove a single bad message instead of waiting hours for the next retry cycle.

How Postfix Organizes Its Queues

Postfix does not use a single flat queue. It splits mail across several on-disk directories under /var/spool/postfix/, each representing a distinct stage of processing. Understanding these stages explains exactly what each command acts on.

  • maildrop — Locally submitted mail (for example, output from the sendmail command or a script) lands here first. The pickup daemon scans it and moves messages forward.
  • incoming — New mail arriving over the network from smtpd, or promoted from maildrop, is written here. After the cleanup daemon rewrites headers and adds tracking information, the message becomes a candidate for delivery.
  • active — A limited-size, in-memory-backed working set of messages that Postfix is actively trying to deliver right now. The qmgr (queue manager) controls how many messages are pulled into active at once to protect system resources.
  • deferred — Messages that could not be delivered on a previous attempt (the recipient server was down, greylisting, a temporary 4xx error). Postfix retries these later with an exponentially growing back-off, so a message may sit in deferred for hours or days before the next try.
  • hold — A manual quarantine. Nothing in hold is ever delivered or expired automatically; messages stay there until you release or delete them. This is the queue you use to pause mail for inspection.
  • corrupt — A safety net where Postfix stores queue files it cannot read, so a single damaged file never blocks the whole system.

The normal flow is therefore maildrop \u2192 incoming \u2192 active \u2192 (delivered, or deferred on failure). The hold queue sits to the side and is entirely operator-driven.

The two tools you will use

Almost everything you do involves two commands. postqueue is the user-facing tool for listing the queue and triggering delivery (it talks to the queue manager safely without needing the files to be touched directly). postsuper is the superuser maintenance tool that physically manipulates queue files: deleting, holding, releasing, and requeuing them. The old mailq command still works and is simply an alias that Postfix maps to postqueue -p.

Inspecting the Mail Queue

Before changing anything, look at what is actually queued. None of the inspection commands modify mail, so they are safe to run any time.

  • mailq — Print the queue in the classic Sendmail-style listing.
  • postqueue -p — Identical output; the native Postfix form. Each entry shows the queue ID, message size, arrival time, sender, any delivery error reason (in parentheses), and the recipients.
  • postqueue -j — Emit the queue as JSON, one object per message. Ideal for scripting or feeding into monitoring.
  • postqueue -p | tail -n 1 — A quick way to read the summary footer, which reports the total number of requests (messages) and bytes in the queue.
  • qshape deferred — A bundled diagnostic that buckets deferred mail by domain and age, perfect for spotting which destination is causing a backlog.

A single queue entry looks roughly like this: the first column is the queue ID, an asterisk after the ID means the message is in the active queue, an exclamation mark means it is on hold, and a dash or nothing means it is deferred or incoming.

Reading an individual message

To see the full headers and body of one queued message, use postcat with its queue ID:

  • postcat -q ABCD1234EF — Display the contents of message ABCD1234EF directly from the spool. The -q flag tells postcat to locate the file by queue ID rather than by path.
  • postcat -qbh ABCD1234EF — Show only the body (-b) and headers (-h), skipping Postfix's internal envelope records, which is the cleanest way to view the actual email.
  • postcat -e ABCD1234EF — Include the envelope (sender/recipient) records when you need to debug routing.

Flushing the Queue (Forcing Delivery)

Flushing tells Postfix to stop waiting for its retry timer and attempt delivery of deferred and active mail now. This is the most common operation after fixing whatever caused a backlog (a restored network link, a corrected DNS record, a recipient server coming back online).

  • postqueue -f — Flush the entire queue: schedule immediate delivery of every deferred message.
  • postfix flush — The traditional alias; behaves the same as postqueue -f.
  • postqueue -i ABCD1234EF — Flush a single message by queue ID, useful when you only fixed delivery for one specific item.
  • postqueue -s example.com — Flush only the mail destined for a particular site/domain (the per-site flush). This is gentler than a full flush because it does not stampede every other destination at once.

Important caveat: a full flush can be counter-productive. If hundreds of messages are deferred because a remote server is genuinely down, flushing repeatedly just hammers that dead host and wastes connections. Flush only after you have a reason to believe delivery will now succeed, and prefer the per-site -s form when you can.

Holding and Releasing Mail

The hold queue is your quarantine. Moving mail to hold freezes it so nothing is delivered, expired, or bounced; you decide its fate later. This is invaluable during a spam outbreak, while investigating a compromised account, or when you want to pause outbound mail during maintenance.

  • postsuper -h ALL — Move every message from the active, incoming, and deferred queues to hold.
  • postsuper -h ALL deferred — Hold only the messages currently in the deferred queue, leaving freshly arriving mail alone.
  • postsuper -h ABCD1234EF — Hold a single message by its queue ID.
  • postsuper -H ALL — Release all held messages back into the normal flow (note the capital H). Released messages re-enter deferred and are delivered on the next queue run.
  • postsuper -H ABCD1234EF — Release one specific held message.

A reliable pattern is to hold everything, inspect with postcat, delete what is clearly junk, and then release the rest with postsuper -H ALL.

Requeuing Mail

Requeuing forces Postfix to re-process messages through the cleanup daemon as if they had just been submitted. This re-evaluates headers, address rewriting, and transport routing rules \u2014 exactly what you want after editing main.cf, transport maps, or header_checks, so existing queued mail picks up the new configuration.

  • postsuper -r ALL — Requeue all messages from the active, deferred, hold, and incoming queues. Each one is rewritten back into maildrop/incoming for a fresh trip through cleanup.
  • postsuper -r ABCD1234EF — Requeue a single message by queue ID.
  • postsuper -r ALL deferred — Requeue only the deferred queue.

Note that requeuing assigns the message a new queue ID, so the identifier you saw before will change. Requeuing also resets the message's age, which can affect when (or whether) it eventually expires under maximal_queue_lifetime.

Deleting Mail from the Queue

Deletion is permanent \u2014 there is no undo and no bounce is generated. Use postcat to confirm you are removing the right thing first.

  • postsuper -d ABCD1234EF — Delete one message by its exact queue ID. This is the safest, most common deletion.
  • postsuper -d ALL deferred — Delete every message in the deferred queue only.
  • postsuper -d ALL active — Delete every message in the active queue only.
  • postsuper -d ALL hold — Empty the hold quarantine.
  • postsuper -d ALL — Delete every message in every queue. This wipes all mail Postfix is holding. Treat it as a last resort.

Deleting by sender, recipient, or pattern

postsuper -d only accepts queue IDs or the keyword ALL; it has no built-in filter by address. To delete, say, every message from one spammy sender, combine postqueue -p with a small awk pipeline that extracts matching queue IDs and feeds them to postsuper:

  • mailq | awk '/^[A-F0-9]/ \u0026\u0026 $7 == "spammer@bad.example" { print $1 }' | tr -d '*!' | postsuper -d - \u2014 The trailing - tells postsuper to read queue IDs from standard input, one per line.

This same input-from-stdin trick (postsuper -d -, postsuper -h -, postsuper -r -) is the standard way to script bulk operations on a precisely selected set of messages.

Command Quick Reference

GoalCommand
List the queuemailq or postqueue -p
Queue as JSONpostqueue -j
View one messagepostcat -q ID
Flush whole queuepostqueue -f / postfix flush
Flush one domainpostqueue -s example.com
Flush one messagepostqueue -i ID
Hold all mailpostsuper -h ALL
Release all heldpostsuper -H ALL
Requeue allpostsuper -r ALL
Delete one messagepostsuper -d ID
Delete a whole queuepostsuper -d ALL deferred
Delete everythingpostsuper -d ALL

Common Pitfalls and Cautions

  • Run as root. Queue files are owned by the Postfix system accounts. postsuper in particular must be run by the superuser; otherwise it cannot read or modify the spool.
  • Mass deletion is irreversible. postsuper -d ALL destroys mail silently \u2014 no bounce, no copy, no confirmation prompt. Always list and verify with postqueue -p first, and prefer deleting by specific queue ID.
  • Case matters. Lowercase -h holds; uppercase -H releases. Lowercase -d deletes. A single wrong character can do the opposite of what you intend.
  • Don't flush a dead destination repeatedly. Hammering postqueue -f against a server that is genuinely offline wastes resources and can look like abuse. Fix the root cause first, then flush.
  • Requeuing changes IDs and resets age. Any queue ID you recorded becomes stale after postsuper -r, and the reset age can extend how long a message lingers before hitting maximal_queue_lifetime.
  • Never hand-edit spool files. Do not move, copy, or open queue files with a text editor. Use the official tools \u2014 direct edits can corrupt the queue.
  • The hold queue never expires. Mail you place on hold stays forever until you act on it. Don't forget about quarantined messages.

Verifying Your Changes

Always confirm the result of any queue operation rather than assuming it worked.

  • Re-run postqueue -p (or mailq) and check the summary line for the new request/byte totals.
  • After a flush, watch the log to see delivery attempts: tail -f /var/log/mail.log (Debian/Ubuntu) or /var/log/maillog (RHEL/CentOS/Fedora). On systemd hosts use journalctl -u postfix -f.
  • After holding, look for the ! marker beside affected queue IDs in postqueue -p.
  • After deleting by ID, confirm the ID no longer appears in the listing.
  • For a healthy server, the deferred queue should trend toward empty; a persistently growing deferred count signals an ongoing delivery problem worth investigating with qshape deferred.

Key Takeaways

  • Flush with postqueue -f (alias postfix flush) to force immediate redelivery; use postqueue -s domain for a gentler per-site flush.
  • Inspect before you act using postqueue -p / mailq to list and postcat -q ID to read individual messages.
  • Hold (-h) and release (-H) let you quarantine mail safely; the hold queue is operator-driven and never expires on its own.
  • Delete carefully with postsuper -d \u2014 prefer a specific queue ID; postsuper -d ALL erases all mail permanently with no bounce.
  • Always run as root and verify afterward by re-listing the queue and tailing the mail log.

Frequently Asked Questions

What is the difference between postqueue and postsuper?

postqueue is the everyday tool for listing the queue and triggering delivery (flushing), and it works by communicating with the queue manager. postsuper is the superuser maintenance tool that physically deletes, holds, releases, and requeues queue files. As a rule: reading and flushing use postqueue; structural changes use postsuper.

How do I delete all deferred mail without touching anything else?

Run postsuper -d ALL deferred as root. The optional queue name after ALL scopes the action to a single queue, so active and incoming mail remain untouched. Verify with postqueue -p afterward.

Why won't my deferred mail deliver even after I flush it?

Flushing only schedules a fresh attempt \u2014 it does not fix the underlying cause. If the recipient's server is still down, DNS is wrong, or your IP is blocklisted, the messages simply defer again. Read the error in parentheses in postqueue -p, check /var/log/maillog, and resolve that problem first.

Is mailq the same as postqueue -p?

Yes. On a Postfix system the classic mailq command is provided as a compatibility wrapper that maps directly to postqueue -p, so the two produce identical output.

If this guide helped you tame your mail server, subscribe to @explorenystream on YouTube for more practical Linux and sysadmin walkthroughs.