Knowledge base

The sender names the stream for each message

critical

VirtualMTA selection at submission
The stream is named by whoever submits the message

The method is small, but its consequences are big. A stream can be chosen in three places: in the configuration — by a rule or a source default; in a pool — by round-robin distribution; and here — when the submitting program names the stream directly for this message.

This is the most direct and the most invisible of the three. The node configuration keeps no trace of the fact that a message left through a particular stream because the sender said so. Reading the configuration, you cannot tell how traffic is distributed.

For warm-up this is the only suitable mechanism. A plan that must send exactly so many messages through exactly this address at exactly this time cannot hand the decision to a pool: a pool distributes round-robin, not according to a plan.

Available both over SMTP and through the API. Over SMTP — with the X-Virtual-MTA header, through the API — with a method call. The only difference between them is granularity during merging: the header applies to the whole job.

The main trap. Nothing checks that the node carried out the choice. The sender named a stream, the message was accepted — and that is it; whether the name matched a configured stream shows only in accounting, after the fact. A typo in the name turns into a rejection at submission or, with a fallback configured, into silent sending from the wrong address.
What the Hub does. This is exactly how warm-up works: the scheduler puts a header with the name of the right stream on every message. The Hub writes the header permission itself — process-x-virtual-mta yes in the submission sources. What is missing so far is reconciliation: nobody compares which stream a message actually left through with the one the plan assigned. The data for reconciliation exists: the vmta field is written to accounting for every message.
Recommended values

The mechanism has no values of its own: the value is the name of a stream or pool, and the sender sets it. On the node side, only the permission (process-x-virtual-mta) and the behavior with an unknown name (reject-invalid-virtual-mta and invalid-virtual-mta-fallback) are configured.

From the manual here are that the choice is made per message and that the name can be a pool name. The point about reconciliation with the plan is our observation.
Example configuration
# the message names the stream itself — the way the warm-up scheduler does it
x-virtual-mta: shop-example-com
From: Shop <news@shop.example.com>
To: recipient@example.net
Subject: Warm-up check

Message body.
The node strips the header before delivery; the recipient does not see it. For the line to work, the source the message was submitted from must have process-x-virtual-mta yes — without it the header not only fails to select the stream but also travels to the recipient as is.
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 ends2 mistakes▶

Sending the header to a source that does not process it

§ 3.3.7.52

What it costsThe trouble is twofold: the selection does not work — the message leaves by default — and the header itself stays in the message and reaches the recipient, showing them the internal stream names.
How to spot itThe delivered message shows X-Virtual-MTA, while accounting has a completely different stream name.
How to do it rightSet process-x-virtual-mta yes on the source submission comes from. Not “somewhere,” but precisely on the matching <source> block.

Batching warm-up with merging

§ 9.4

What it costsWith merging, the header applies to the whole job, not to a recipient: the engine usually takes the first value it encounters. A plan built on “each recipient gets its own address” collapses into one address for the whole batch.
How to spot itDaily volumes by address drift away from the plan: one address has too much, the others have nothing.
How to do it rightSubmit warm-up messages one at a time, without merging. Speed is not needed here, and precision is the whole point.
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.
Inheritance
The mechanism never has inheritance: the choice is made anew for every message. What is inherited is the permission for it — process-x-virtual-mta is written in <source> and merges by the source rule, where a narrower block overrides a wider one.
How to check on the node
Comparing what was assigned with what was sent is possible only through accounting — the node does not comment on its decision:
pmtaacctfind --output csv[vmta,header:x-virtual-mta,rcpt] /var/log/pmta/acct-*.csv
The vmta field is the stream the message left through. If it differs from what the plan assigned, the cause is one of two: the header was not processed for this source, or a merge variable in the content overrode it.
In the Hub
Cost of a mistake
reversible: harms only while it is set
Scenarios
Sending address rotation · Address warm-up · Sending through proxies
Priority
critical