.flake8 | ||
.gitignore | ||
check-lints.sh | ||
LICENSE | ||
pqm | ||
pqm.example.yaml | ||
README.md |
Postfix (cluster) queue manager
CLI tool to manage postfix queues (optionally across multiple hosts through ssh).
It uses trio for asynchronous operations (i.e. parallel handling of many nodes in a cluster).
It also has proper readline support with history of commands.
Workflow
Start with health
to get a feeling for the queue state.
Show the list of deferred mails with list
, or show all mails from a certain user (maybe health
showed a suspicious user) with list from bob@example.com
.
Note that list
(contrary to list-verbose
) only shows the last (remaining) recipient of a mail (and how many targets are remaining).
Build up filters to match only certain mails - e.g. start with select from MAILER-DAEMON
to search for bounces, and then limit those to no-reply targets with select to ~reply
. Use list
or list-verbose
to see which mails remain, and what the problem is.
Use show mailid
to show headers of suspicious emails, or show -hb mailid
to show the body too if really necessary.
Use hold
to hold all currently selected mails (e.g. spam/...), and then delete them later with delete
. Or use delete mailid
to delete specific mails directly.
Use expire
to return mails to the sender (because you think the error from list-verbose
is permanent, even if postfix doesn't know it yet).
delete
and expire
operations prompt for confirmation after showing affected mails.
List of commands
There is an interactive help command.
# help
clear Clear all filters
clear <arg> Clear filter with given index (zero based; first filter is at index 0)
current Show current filters
delete Delete selected mails from the hold queue
delete <arg> Delete mails with given IDs from the queues
delete-all Delete selected mails from all queues
exit Exit pqm (or press Ctrl-D on empty prompt)
expire Expire mails and flush them (return error to sender).
expire <arg> Expire mails (return error to sender) with given IDs and flush them.
expire-noflush Expire mails (return error to sender on next delivery attempt).
expire-noflush <arg> Expire mails (return error to sender on next delivery attempt) with given IDs.
expire-release Expire mails and flush them (return error to sender); release if mails are on hold.
expire-release <arg> Expire mails (return error to sender) with given IDs and flush them; release if mails are on hold.
flush Flush (deferred) selected mails in the queue: attempt to deliver them
flush <arg> Flush (deferred) mails with given IDs: attempt to deliver them
flush-all Flush the queue: attempt to deliver all queued mail.
health Show generic stats for queues and overly active address
help Show all available commands
help <arg> Show detailed help for a command
hold Put selected mails on hold
hold <arg> Put mails with given IDs on hold
list [<arg>] List all mails (single line per mail); if no filter is configured hide active and hold queue
list-all [<arg>] List all mails (including active + hold queue, single line per mail)
list-verbose [<arg>] List all mails (verbose output); if no filter is configured hide active and hold queue
list-verbose-all [<arg>] List all mails (including active + hold queue, verbose output)
pop Remove last filter
release Release mail that was put "on hold".
release <arg> Release mails with given IDs that were put "on hold".
requeue Requeue mail (move to "maildrop"; get reprocessed)
requeue <arg> Requeue mail with given IDs (move to "maildrop"; get reprocessed)
select <arg> Add filter for mails that other commands work on
show <arg> usage: show [-b] [-e] [-h] ID [ID ...]
Available filter expressions are show in the help for select
:
# help select
>>>> select <args>
Add filter for mails that other commands work on
Filter syntax:
- `from bob@example.com`, `from alice@example.com,bob@example.com,@example.net`, `from "alice@example.com" "bob@example.com"`
Multiple address can be given to match any of them; either unquoted and comma separated, or quoted and whitespace
separated. In the unquoted case the (comma separated) pattern must not include any whitespace.
An address starting with `@` only checks the domain name and ignores the local part.
- `from ~regex.*@example.(com|net)`, `from ~"regex.*@example.(com|net)" "other@example.com`
To use regular expressions either put `~` in front of an unquoted pattern (need to repeat for each regex in a
comma separated pattern list) or before the quotes of a quoted pattern.
- `to ...` and `address ...` (matching both to and from) work the same as `from ...`
- `queue hold,deferred`
Comma separated list of queues a mail must be in. For single queue names `queue` can be omitted, e.g. `hold`.
- `$expr1 and $expr2`
- `$expr1 or $expr2` (`a and b or c` is parsed as `a and (b or c)`)
- `($expr)`
- `not $expr`
The select expressions use the data provided by postqueue -j
- which is why it doesn't support filtering by subject/other headers.
Installation
Dependencies:
On Debian: apt install python3-trio python3-pyparsing python3-yaml
Put the pqm script into your path and make it executable.
Configuration
Configuration is optional; by default it tries to use ~/.config/pqm.yaml
and /etc/pqm.yaml
(picking the first one that exists).
Also see pqm.example.yaml
in this repository.
Source (hosts load load mails from)
By default it will use the local queue; it probably needs to run as root for that.
Use remote-sources
in the config to use remote hosts instead ("cluster" mode). Each remote source has a unique alias that is used in the pqm
output (by default the first DNS label in the hostname).
pqm
uses ssh -oBatchMode=yes root@remotesource ...
to execute postfix tools on the remote nodes; this means you'll probably want a public-key based authentication to the postfix nodes, and the server keys must already be trusted.
You'll also want to make sure the ssh login is fast; UseDNS no
(should be the default) on the server and ed25519 keys should help with that.
Queue IDs
Each mail in the postfix queues has an ID; when using the local source pqm
will use this ID directly. With remote sources it will prepend alias/
to the ID.