Continuing in the same vein as 94628f06ab,
ensure that we have a reasonable outcome when a batch of size > 1
encounters 100% ambiguous 452 responses.
Without special consideration we'd end up in an infinite retry loop for
these, as we'd think that we'd hit the recpient limit on the connection
every time.
This commit introduces a small amount of state into the dispatcher so
that we can remember the set of (spoolid, recipient) from the prior
transaction on the session.
When deciding whether something is eligible for immediate retry
we will gate that choice on the current (spoolid, recipient) being
absent from the prior set of ids. In this way, we bound the immediate
retry for a recipient to one per connection.
To make things a bit more robust when trying to decide whether a 452
means "too many recipients" or not, if we're not sure, we now call out
to the bounce classifier which can be configured to emit a
`TooManyRecipients` classification. If the classifier produces either
that or some non-Uncategorized response, then we have a confident
assessment. Otherwise, we're unsure and will factor that into the
retry strategy.
Previously, the use of BTreeMap for the rules resulted in the overall
rule order being changed in a surprising way; the key order of the map
set the overall order by category and then by the order that the rules
appeared in the file.
This commit uses an OrderMap to preserve the ordering of the keys
in the TOML (or JSON) file so that they match the order in which
they appear in the file, rather than having them become implicit
sorted by key.
Secondly, it removes the use of BTreeMap in the overall classifier
state, so that the all of the patterns are presented in the order
in which they appeared in the sequence of files loaded in the classifier
setup.
A unit test has been added to assert that matching of ambiguous (in this
case, identical) patterns takes its precedence from the order that the
patterns appear in the file.
This helps to remove "false" deps on things like openssl; now that
is linked in only to those components that need it (eg: things that
use unbound for dnssec, or the smtp client for DANE).
This makes the binaries other than kumod (which still has max deps)
a few MB smaller; not a massive win, but nice all the same.
The classifier can load and merge rules from multiple files.
A basic iana enhanced status codes ruleset is provided.
A deployment can define their own to augment that set.
This commit is just the core classifier functionality; it
is not yet connected to kumod.
The classification enum is a bit of an amalgam of categories
defined by other well-known vendors/products and the categories
defined by IANA. Some classifications have no corresponding
rules at the current time.