Postfix (cluster) Queue Manager
Go to file
2024-01-09 11:27:55 +01:00
.flake8 initial public commit 2023-01-12 10:09:18 +01:00
.gitignore add .mypy_cache to .gitignore 2023-01-12 10:24:06 +01:00
check-lints.sh initial public commit 2023-01-12 10:09:18 +01:00
LICENSE initial public commit 2023-01-12 10:09:18 +01:00
pqm add "forward-to" command to forward mails in the queue and their verbose state as attachment to given recipients 2024-01-09 11:27:55 +01:00
pqm.example.yaml add "forward-to" command to forward mails in the queue and their verbose state as attachment to given recipients 2024-01-09 11:27:55 +01:00
README.md initial public commit 2023-01-12 10:09:18 +01:00

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.