Knowledge base

The vendor's analytics — and what leaves the node for it

SparkPost Signals
Analytics in exchange for recipient data

A vendor service to which the node continuously hands over accounting data, getting analytics in return: a summary, a bounce report, a sender health score and a spam trap report. Seventeen directives in the chapter configure exactly this — a noticeable part of the advanced features section is devoted to the vendor’s paid service.

How it is enabled. You need an access key created in the service’s account portal with permissions to write events and read the account, and a <signals> block in the configuration. The appearance of the block by itself enables the export — enable-signals allows it by default, and to have the block without the export, you have to say so separately.

What is controlled, what leaves. The switch works at three levels: the whole node, an address pool, an individual sending address. Plus selection by sender domain — but it is taken from the message headers (Sender or From), not from the address settings.

How it leaves. Data accumulates on disk and is deleted after the export. There is a free space threshold (min-free-space), below which the accumulated data starts being discarded irreversibly — the reports will have gaps. The connection is one-way: the node only sends and receives nothing from the service. The firewall must allow access to api.sparkpost.com on port 443.

What can be hidden. privacy-policy hashes the local part of recipient addresses before sending — with a one-way hash. This is the only built-in measure: everything else leaves as is.

Engagement tracking is a separate story. The service wants to know about opens and clicks, and the node can insert a pixel into messages and rewrite links by itself (signals-engagement-tracking).

The main trap is that the block enables the export by the mere fact of appearing. You added <signals> to “look at the settings” — and accounting data started leaving the node. No confirmation or separate permission is required: the switch allows it by default. The second consequence of the same thing: the free space threshold silently discards accumulated data when the service is unavailable — the reports then look reliable but have gaps, and a gap cannot be told apart from a drop in sending by looking at them.
What the Hub does. It does not use it at all — there is no <signals> block in the configuration, and accounting data does not leave the node.

That is by design. The Hub collects the node’s accounting for itself and builds analytics on its own: deliverability by provider, bounces by category, fleet corridors. The vendor’s service would provide a health score and spam traps, which we do not have — but at the cost of recipient addresses leaving our infrastructure and going to a third party.

For a boxed product installed on a client’s own server, this is not a technical problem but a contractual one: their recipients’ data would go to the vendor because of our setting.

Recommended values

There is nothing to set — the block should not exist. If it is ever needed:

What What to watch
enabling itself the block enables the export by its mere appearance
scope node, pool or address — select, do not enable everything
selection by sender taken from the message headers, not from the address settings
address hashing privacy-policy is the only built-in measure
space threshold below it, accumulated data is discarded irreversibly
applying changes the manual advises a restart, not a settings reload

A separate note about the restart. The manual says a reload is sufficient but recommends a restart: otherwise internal processes will not pick up the new settings right away. For a directive that enables data export, “not right away” is a bad property.

The assessment regarding a boxed product is ours. From the manual here come the service’s composition, the three enabling levels, selection by message header, the buffer behavior when the service is unavailable, local part hashing and the advice to restart.
Example configuration
# there is no block — and this is a deliberate decision, not an oversight
# if it appears, the export will start by itself:
<signals>    api-key KEY
    privacy-policy sha1
    min-free-space 2G
</signals>
The example shows the minimum, not a recommendation. The hashing line is not here for looks: without it recipient addresses go to the vendor in full.
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▶

Adding the block “just to look”

§ 11.1

What it costsThe appearance of the block enables the export: the switch allows it by default. Accounting data — with recipient addresses — starts leaving the node from the very first settings reload.
How to spot itThe node has new outgoing connections on port 443 to a third-party address that were not there before.
How to do it rightDo not create the block for exploration. If it is needed for experiments, turn off the export explicitly and enable local part hashing in the same edit.

Selecting mail by address settings instead of by header

§ 11.1.1

What it costsSelection by sender domain looks at the message headers, not at the sending address settings. The expectation “this address is not exported” does not come true: everything that leaves it with a matching header will be exported.
How to spot itThe service’s reports show messages that were not supposed to get there.
How to do it rightLimit the export with the scope switch, and use selection by sender as an addition, remembering where it takes the domain from.

Editing the service's settings with a configuration reload

§ 11.1

What it costsThe manual directly recommends a restart: internal processes will not pick up the new settings right away. An edit that turns off the export does not take effect for a while — and this is about data leaving the node.
How to spot itAfter the edit, the export continues for some time.
How to do it rightRestart the engine after any edit of the service’s settings. Verify by outgoing connections, not by the file.
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 switch is inherited: set at the node level, it applies to all addresses; a pool value overrides the node one, an address value overrides the pool one. The service’s other settings live in the <signals> block at the root of the file and have no scope. The manual advises restarting the engine after editing any of them, not just reloading the settings.
How to check on the node
The first thing worth checking is whether there is no block at all:
grep -n -A6 '^<signals' /etc/pmta/config
ss -tnp | grep ':443'
Empty output from the first command is exactly what means there is no export. The second shows the node’s outgoing connections: connections to api.sparkpost.com on port 443 are a sign that the export is running, even if the block turned up somewhere other than where you looked.
In the Hub
Cost of a mistake
reversible: harms only while it is set
Scenarios
Node security · Collect telemetry