Knowledge base

max-errors-per-connection

<domain>set by the Hub

How many recipient errors break the connection
in the configuration this is a linemax-errors-per-connection unlimitedinside the block <domain>
When it is more polite to hang up

Breaks the connection after the set number of recipient-level errors has accumulated on it — refusals in response to RCPT TO. It is exactly these that count: connection errors and responses to DATA have nothing to do with this counter.

What the receiver sees. A connection with one refusal after another is exactly the pattern by which address harvesting is recognized. Even when there is no harvesting and the issue is an old list, the behavior looks the same, and the receiver’s attitude deteriorates just as fast.

Breaking the connection fixes nothing. The bad addresses do not go anywhere: the engine will open a new connection and continue from the same place. The directive is politeness, not treatment. The treatment is suppression-lists and list cleaning; this only softens how the problem looks from outside.

The default is unlimited. The connection is never broken by the number of errors, however many pile up.

The main trap. A value that is too low turns one problem into another. With max-errors-per-connection 2, a queue with a noticeable share of nonexistent addresses will reopen connections almost for every message — and receivers watch frequent connections more closely than refusals. Instead of “many errors on one connection” you get “a flurry of short connections,” and that is worse.
What the Hub does. It writes 10 — in the recipient policies template, in each of the fifteen blocks: for fourteen major mailbox providers and in the general <domain *>. The reason is given right there in a comment: not to drive the connection to a “too long without the DATA command” error.

Next to it the Hub also writes a neighbor in meaning — max-msg-per-connection with a value based on the selected pace (20 · 50 · 100). So the connection has two bounds: by the number of messages and by the number of errors, and whichever is reached first applies.

List hygiene is handled by the Hub on its own side: hard bounces go to the blocklist, and an address does not reach the engine a second time. The threshold of ten errors is insurance for a list that came from outside.

Recommended values

No lower than ten. The point is to break the connection on a clearly bad list, not on the usual share of invalid addresses. Ten errors in a row are no longer a coincidence; two may well be.

Count from the defect rate. If there are five recipient refusals per hundred messages, then with twenty messages per connection the threshold of ten is usually never reached — and that is right: the directive should fire rarely.

unlimited makes sense where the list is known to be clean: your own validated database with hard bounces going to suppression. Then an extra disconnect only gets in the way.

The order of magnitude and the “no lower than ten” rule are ours. From the manual here come the unlimited default and the fact that recipient-level errors are counted.
Example configuration
# break the connection on a clearly bad list, but not on ordinary defects
<domain hotmail.com>
    max-msg-per-connection 50
    max-errors-per-connection 10</domain>
Two limits on one connection: by messages and by errors. Whichever is reached first applies — on a clean list it is always the first.
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▶

Setting single digits “to be more polite”

our experience

What it costsWith two or three errors per disconnect, a queue with an ordinary defect rate starts reopening connections almost for every message. The receiver sees a flurry of short connections — a picture it reacts to more sharply than to recipient refusals.
How to spot itThe number of connections is comparable to the number of messages, and responses about too-frequent connections appear.
How to do it rightRaise the threshold to ten or more, and deal with a bad list through suppression, not disconnects.

Expecting a disconnect to reduce the number of refusals

§ 3.3.10.1

What it costsThe directive breaks the connection but does not touch the queue: the same addresses will be handed to the next connection and produce the same refusals. The total number of errors will not change — only their distribution across connections.
How to spot itThe share of recipient refusals is the same as before the edit.
How to do it rightRemove nonexistent addresses — suppression-lists and list cleaning. This directive is about how the problem looks, not about the problem itself.
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
max-errors-per-connection <integer>
Values
an integer number of errors or unlimited
Default
unlimited § 3.3.10.1
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. It is picked up by pmta reload, no restart needed; the new value does not affect already open connections.
How to check on the node
There is no separate disconnect counter. An indirect sign is the ratio of connections to messages, plus the recipient errors themselves in accounting:
grep -rn max-errors-per-connection /etc/pmta/
pmtaacctfind --output csv[type,dsnStatus,rcpt] /var/log/pmta/acct-*.csv
If there are many recipient refusals and noticeably more connections to the receiver than messages divided by max-msg-per-connection, disconnects are happening because of this directive. The Hub does not count disconnects separately.
In the Hub
Value
The Hub picks it itself — pace, warm-up stage, metrics
Cost of a mistake
reversible: harms only while it is set
Scenarios
Tune the pace for a provider