Knowledge base

PMTA knowledge base›Block <domain>›Directive§ 3.3.10.111.1

command

<domain>

Which program to run for messages of this queue
in the configuration this is a linecommandinside the block <domain>
The handler’s command line

It works for a pipe queue (type) and is mandatory for it. It sets the command line the node uses to run the handler program; the message is fed to its standard input. The program is run for each new recipient.

Substitutions with message properties are expanded in the line: $envid — the envelope identifier, $user — the recipient name before the at sign (and if it contains +, the part to the left of it), $domain — its domain, $from and $to — the envelope addresses, $isodate, $ctime, $rfctime, $timet — the time in four forms, $bodytype — the message body type.

The backslash is doubled. It also serves to escape spaces, quotes and the dollar sign, so a Windows-style path is written with double backslashes — or with ordinary forward slashes, which the engine also accepts.

The main trap is a substitution without quotes. A recipient address may contain a space, and then $user will split into several command-line arguments. The handler will get a fragment instead of the address and process the wrong message. The manual advises wrapping substitutions in double quotes — the advice is worth reading as a requirement.
What the Hub does. It does not write it: it creates no pipe queues, and its bounce parsing is its own and lives in the Hub. The PowerMTA distribution includes two ready-made programs — appendtofile and newfile — in case a handler on the node is needed for a simple task after all.
Recommended values

Put every substitution in double quotes. It is the only protection against a space in an address.

The program must start quickly. It is run for every recipient; half a second of startup at a thousand messages a minute is already load on the node, not on the mail.

Write the path as absolute. The node runs the program outside your environment, and a relative path does not work the way it does in the shell.

The requirements about an absolute path and fast startup are ours. From the manual here come the line being mandatory for the pipe type, the full list of substitutions, doubling the backslash and the advice to put substitutions in quotes.
Example configuration
# a bounce handler: the envelope identifier and the recipient name
<domain bounces.example.com>
    type pipe
    command "/opt/bounce/parse --envid \"$envid\" \"$user\""</domain>
The quotes inside the line are escaped: the line itself is also in quotes, and without escaping it would break off at the first of them.
yellow — — directive names, blue — blocks. They are highlighted the same way in the text of the card.
▲

Common mistakes and problems

what people get wrong and how it ends3 mistakes▶

Writing substitutions without quotes

§ 3.3.10.111.1

What it costsAn address with a space splits into several arguments. The handler gets a fragment and processes the wrong message — silently, without an error.
How to spot itOccasionally the handler fires for an address other than the one in the envelope.
How to do it rightPut every substitution in double quotes, escaping them inside the line.

Setting a relative path to the program

our experience

What it costsThe node runs the program outside your environment. A path that works in the shell is not found here, and messages get stuck.
How to spot itThe queue grows, zero deliveries, and a launch error in the log.
How to do it rightWrite an absolute path and check execute permission for the user the service runs as.

Using a heavy handler for a stream

§ 11.21

What it costsThe program is run for every recipient. A handler that starts an interpreter or a database connection eats the node on launches alone when there is a stream.
How to spot itNode load grows along with the pipe queue.
How to do it rightEither make the handler lightweight or switch to the http-delivery type — there is one process there, and it lives permanently.
Compatibility
PowerMTA 6.0
described in the manual of this version · platform: any
The vendor does not state the first version for every directive — there is no note here. The name also appears in the 5.0 edition of the manual.
Reference data
Syntax
command <string>
Values
the full command line for running the program, in quotes; the substitutions $envid, $user, $domain, $from, $to, $isodate, $ctime, $rfctime, $timet, $bodytype are allowed
Applying
reload, no restart needed
Queue
will not touch what is already queued
Where to write it
<domain>
How many times
once in the block
Everything here comes from the manual, with the section.
Inheritance
The value merges across <domain> blocks from general to specific: the best-matching block wins, not the last one in the file. In a queue of another type the line is ignored — the manual says this about the whole pipe section. It is picked up by pmta reload; handler processes already running will finish with the old line.
How to check on the node
The effective line is printed by the queue settings command; whether the handler works is visible from whether messages leave the queue:
pmta show settings bounces.example.com/vmta1 | grep -E '^type|^command'
pmta show queues | grep -i bounces.example.com
A growing queue with the line set almost always means the program is not starting: a wrong path or no execute permission. The Hub does not create pipe queues.
In the Hub
Cost of a mistake
dangerous: effects outlast a rollback
Scenarios
Connect a sending platform