Knowledge base

allow-empty-x-virtual-mta

<source>

Whether an empty X-Virtual-MTA header value is acceptable
in the configuration this is a lineallow-empty-x-virtual-mta falseinside the block <source>
An empty header — an error or “choose yourself”

The default is false. A header with an empty value — x-virtual-mta: and nothing after it — is treated as an invalid stream choice and so falls under the general rule: the message is rejected unless the “fallback stream plus lifted rejection” pair is configured.

With the value yes an empty header is accepted, and the message leaves via the default stream — the one assigned to the source by the default-virtual-mta directive.

The main trap is not noticing where the empty header comes from. It is almost always set by a submission template that substitutes the stream name from a variable, and the variable turned out empty. So the rejection here signals a real error on the sender’s side, and enabling tolerance means hiding that error: messages will go out, but not from the address that was intended.
What the Hub does. It does not write it — it keeps the default. The Hub sets the header itself, and an empty value would mean an error in the warm-up plan that is better learned from a rejection. The line would be useful for a third-party platform that sets the header unconditionally and cannot omit it.
Recommended values

What to set. The decision depends on whose submission it is:

Value When What you pay
no (default) the submission is ours, we set the header nothing: an empty value is an error, and it is visible
yes a third-party platform always sends the header an empty value stops being noticeable

If you enable it, make sure default-virtual-mta is set sensibly for this source: it is the one that will receive such messages.

The false default and the fact that an empty header sends the message to the default stream come from the manual. The “whose submission” analysis is ours.
Example configuration
# a third-party platform always sets the header, sometimes empty
<source 10.0.0.0/24>
    process-x-virtual-mta yes
    allow-empty-x-virtual-mta yes    default-virtual-mta mta-hub-pool
</source>
The three lines work together: the first allows the header, the second accepts an empty value, the third says where such a message will go. Without the third, tolerance is pointless — you cannot accept a message and not know which stream to send it with.
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▶

Enabling tolerance instead of fixing the sender

our experience

What it costsAn empty header almost always means an empty variable in the submission template. Tolerance turns a visible error into an invisible one: messages leave via the default stream, that is, not the one that was intended.
How to spot itThe rejections stopped, but the distribution of messages across addresses does not match the expected one.
How to do it rightFirst find out why the header is empty. Enable tolerance where the sender really cannot be changed.

Enabling it without setting a default stream

§ 3.3.7.67

What it costsThe message is accepted and leaves via the default stream — which the source may not have at all. The setup is done halfway.
How to spot itMessages with an empty header behave unpredictably: some go out, some do not, with no visible dependence on the sender.
How to do it rightSet default-virtual-mta for the same source. Tolerance and the default are one setting of two lines.
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
allow-empty-x-virtual-mta <boolean>
Values
yes | no | true | false
Default
false § 3.3.7.67
Applying
reload, no restart needed
Queue
will not touch what is already queued
Where to write it
<source>
How many times
once in the block
Everything here comes from the manual, with the section.
Inheritance
The directive lives in <source> and merges by the source rule: a narrower block overrides a wider one. It is worth enabling it pointwise, in the block of the subnet the empty-intolerant platform submits from — otherwise your own error gets hidden too.
How to check on the node
The line is visible only in the configuration; it has no counter of its own:
grep -n -B5 allow-empty-x-virtual-mta /etc/pmta/config
If the line is absent, the no default applies. An indirect sign that it is needed is submission rejections for a platform that always sets the header: in its logs this looks like rejected messages without a clear reason.
In the Hub
Cost of a mistake
reversible: harms only while it is set
Scenarios
Connect a sending platform