Knowledge base

Reports the engine does not understand by itself

non-standard report handling
When a receiver writes a report in its own way

Large mailbox providers send reports in standard formats, and the engine parses them by itself. Some do not: the message arrives as human text, with the needed information buried in prose.

The mechanism is simple: your own regular expression with named groups. The group name is the accounting field name, and what is extracted goes into the record next to what the engine found itself. The manual’s example is taken from a real complaint service message: from the line Email from 1.2.3.4 the sending address is extracted.

Patterns live in <email-patterns>, nested in the processor. Each processor has its own set, and it can hold several files — one per format.

🔴 Until there is a pattern, the report does not exist for analytics. It gets into neither complaint records nor bounce records — it is just a misunderstood message whose fate is decided by deliver-unmatched-email. That is, the complaint rate for such a receiver will be understated, and there will be nothing to explain it with.

The main trap is not noticing that a receiver has dropped out. No complaints looks like good news. What needs checking is not “are there complaints” but “are there complaints from every large receiver we send volume to.”
What the Hub does. It does not use it: we have no custom patterns.

🔎 A sign that it is time: messages to fbl@fbl.<domain> from some receiver are arriving, but there are no complaint records for it in accounting. The panel will then show a zero spam rate for it — that is, the most favorable picture exactly where there is simply no data.

Recommended values

The mechanism has no values of its own — it is enabled by two lines in the patterns block:

What Line
the pattern itself body-pattern-file, repeatable
which of them matched log-match-info

The group names in the expression must match accounting field names — otherwise there is nowhere to put what is extracted.

The pattern mechanism, the example message and the list of extracted fields come from the manual (§ 13.10). The remark that no complaints looks like good news is ours.
Example configuration
# the pattern is taken from a real message from the receiver
<feedback-loop-processor>
    <email-patterns>
        body-pattern-file /etc/pmta/report-pattern.txt        log-match-info true
    </email-patterns>
</feedback-loop-processor>
The file holds a regular expression like Email from (?<dlvSourceIp>[0-9\.]+). The group name equals the accounting field name, and the extracted value will go there.
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 ends1 mistake▶

Taking the absence of complaints for the absence of problems

our experience

What it costsA receiver whose reports the engine does not understand gives a zero complaint rate. It looks like the best result in the fleet, but it means there is no data.
How to spot itA large receiver with high volume has a complaint rate of exactly zero.
How to do it rightCheck whether messages from it arrive at the processor’s address, and write a pattern if necessary.
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 has no inheritance: patterns live inside a block nested in a processor and apply only to it. The bounce processor and the complaint processor have independent sets.
How to check on the node
Check it in the log, with the match line enabled:
grep -i "pattern" /var/log/pmta/log | tail -20
The line matched body-pattern defined in file:… names the pattern that fired. Empty while messages are arriving means none matched and the message went to the unrecognized ones.
In the Hub
Cost of a mistake
safe: a wrong value breaks nothing
Scenarios
Bounce classification