Removes the deref to str as this is now a fallible operation that
can panic.
Process the fanout of this change, which is dealing with more
possibility that things might be binary in more places.
There are some transitional APIs introduced as deprecated so that I'm
nagged to remove them already: I want to get the bulk of the code aware
of the possibility of binary sorted before I tackle adjusting the
message parser for that, so that that particular commit is more
self-contained.
If you have two scheduled queues with the same mx_list and then one of
those domains is updated to use a different mx_list, depending on the
ordering of the updates and subsequent traffic, the changed domain may
continue to have traffic route through the old mx_list.
The reason for this is that protocol configuration for that egress path
comes from the scheduled queue configuration, and there is no explicit
dependency between the two pieces of configuration.
This commit resolves this by adding a sanity check that the protocol
information is consistent with the ready queue instance. If it is no
longer consistent we'll remove the association between the rq name and
the instance, then wind down any associated dispatchers.
This reduces the boilerplate around declaring metrics
(counters, histograms, gauges) in their various forms,
and more or less standardizes them, making the syntax
more regular regardless of how the metrics are actually
stored.
We move the help out to doc comments, making it easier
to write a multi-line exposition on a given metric (in
the future; we're not doing that yet).
linkme is used to form a registry that can be used to
eagerly collect metadata from the various metrics. This
will be used to drive some automated documentation
extraction for the various metrics in a future commit.
When using an explicit mx_list, rather than consuming the DNS-provided
MX records, we were populating the connection plan LIFO with the mx_list
which is specified as a FIFO.
The result was that we would connect to the addresses in the reverse of
the intended order.
Most users only populate a single entry for mx_list, if they use this at
all, so it has flown under the radar. This issue was introduced
together with the mx_list feature in bcd2946c53.
This commit corrects that issue so that the behavior conforms to the
intended and documented ordering, and tweaks the tests to accommodate
it; the test changes required were:
1. disconnect_in_data was actually sensitive to the order, and encoded
the reverse ordering in its expectations. :-/
It now correctly encodes the correct order, which should allow
detection of regression in the future.
2. disconnect_terminate_ok is sensitive to extraneous TransientFailures.
It was implicitly dependent on the ordering of the mx_list in the
sense that it relied on the FIFO list returning as [127.0.0.1, ::1],
which resulted in trying ::1 first (because that list is consumed as
LIFO), failing due to ::1 not actually being bound in the test
environment, and proceeding to test with 127.0.0.1 being the last
working address.
With the ordering fixed that test started to fail because the second
host in the correct connection plan was ::1 and that was not
reachable, triggering a TransientFailure against the expectations
of the test.
The goal of the test was to verify the behavior in the
exhausted-connection-plan case, rather than the
unreachable-final-mx-case, so the resolution here is to add v6
addresses to the skip_hosts config. Will that come back to haunt us?
Time will tell.
This commit implements a kumomta-specific message transfer
protocol that is intended to be used to migrate messages
from one kumomta node to another.
The transfer is carried out using an HTTP POST request
to the destination node's http listener.
The request includes the full message metadata and body,
in a compressed form.
An xfer request can be made via `kcli xfer` (and thus also via an HTTP API
endpoint). It works similarly to a rebind operation; you specify the
criteria to be used to match scheduled queues, along with the target
node for the xfer, and kumomta will find matching queues, drain out the
messages, make an adjustment to the metadata to capture current
scheduling information, and then place the messages into an xfer queue.
The xfer queue has hard-coded scheduling queue configuration of its own,
with the base retry interval set to 10 seconds, which should be suitably
aggressive for the intended use case.
You may apply shaping to affect the number of concurrent requests in a
similar way to how TSA shaping is configured.
On the receiving side, the incoming xfer sanity check to prohibit
trying to xfer to itself.
The spool id of the Message is not suitable to be reused verbatim on
another node (spool ids include the local mac address and creation
timestamp information, as well as a random component), so the receiving
side will derive an id that should be suitable for use on that node.
The originating node id and spool id will be preserved in metadata to
aid in tracing.
It is possible for an xfer request to target an existing xfer queue, so
that you can correct/update the target in various circumstances. In that
situation the messages will be "simply" moved from the source queue to
the destination queue.
It is possible to cancel an xfer request via `kcli xfer-cancel` (and
thus also via an HTTP API endpoint). You specify the target queue,
which must be an xfer queue, and it will have its messages drained and
the metadata changes that were applied when the xfer was initiated will
be reversed, allowing the messages to then be reinserted into their
originating queue.
refs: https://github.com/KumoCorp/kumomta/issues/311
This makes a first pass over relaying a batch, with a test
to prove that it worked.
The logic in the smtp client likely needs to be enhanced
to handle hitting recipient-per-transaction limits; tests
for various scenarios need to be added in follow-on commits.
This commit adds some plumbing to facilitate generation of RFC 3464
non-delivery reports and some corresponding glue to enable calling
it from lua.
Examples in the docs that are also added.
This commit:
* Adds auto-discovery of both module style and crate style tests
* Runs each test via its own instance of `kumod`, so that one test
cannot pollute the state of another
* Runs all lua tests concurrently
This enables configuring mTLS support in the listener.
Adjust TLS client tests to use this on the sink side and verify
that mTLS works for both inbound and outbound SMTP.
refs: #100
refs: #391
This commit extracts the TLS version, cipher and subject name from
the TLS state and captures it:
* In the trace headers
* In the connection metadata
* In the Reception log record
In order to capture the info in trace headers, this commit will
now change the reception protocol to ESMTPS (for SSL) or ESMTPSA (for
authenticated SSL), and emit the version and cipher information as
a comment like: `with ESMTPS (TLSv1_3:TLS13_AES_256_GCM_SHA384)`.
closes: #100
This is to help humans grok a diagnostic log file a bit better.
This isn't a supported product surface and isn't deployed with
kumomta. It is intended primarily as a log debugging aid.
While doing a torture test with a very large combination of
the number of domains, campaigns and tenants (effectively
unbounded in any meaningful time period), using the smart sink
to generate bounces and suspensions, I found that the overhead
of tracking the set of bounces and suspensions by scheduled
queue was too high: each bounce lookup was O(number-of-bounces),
and when you can have 100k admin bounces configured, that is
not good for the miss case, which, despite the volume of admin
bounce records, is still the dominant case.
This commit introduces a helper map/multi-index type that
maintains indices for the common tuples:
* (domain, campaign, tenant),
* (domain, tenant)
* (domain)
* other
then uses an appropriate index based on the current context.
That reduces the the lookup cost to effectively constant time (3 x O(1)
lookups), unless there are admin bounces registered in the "other"
bucket, in which case there is an additional O(number-of-other) lookups.
The primary purpose of this is so that I can do this:
```
ROCKSDB_LIB_DIR=/usr/lib/x86_64-linux-gnu
```
on my ubuntu system and cut down on rocksdb related build times.
Adds an example docker compose file that can be used to quickly
stand up an SMTP sink service that is useful when load testing
an SMTP server.
The sink has configurable and "realistic" bounce response rates,
so that you can excercise queue growth scenarios.
This isn't shipped in the packages at this time.
It's a utility for post-mortem or offline analysis
of kumomta spools.
This version assumes rocksdb, but could be tweaked to work
with a plain filesystem spool.
We could add functions in the future to migrate from one format
to another, or perform other sorts of maintenance/admin operations.
This is conceptually similar in purpose to running `openssl s_client`
to figure out the capabilities of a remote mx and its TLS
implementation.
This commit also adds a currently-deliberately-undocumented
tls_prefer_openssl option to the egress path config that forces
the selection of an openssl based client connector.
I want to try this out a bit before fleshing it out into a
larger product feature and its additional configuration.
RUST_LOG=trace ./tls-probe example.com:25
I regret optimizing the structure for toml when this module was
created, as it makes it difficult to define a regular schema.
This commit introduces typed records for the queue helper
data structure, and, unfortunately, a parsing layer to adapt
between the toml data and the well-defined types.
It also adjusts how lua tests are run; previously we'd co-opt the main
flow of parsing by looking at an env var, but since the modules can now
potentially require each other (especially the typing module) we need to
de-couple from that, otherwise what happens is that we'd only ever run
the typing module tests and exit. So we now have a script that imports
all the modules and runs their respective `:test()` methods.
refs: #211
The primary purpose here is to allow defining typed records
for use in our helpers.
The dkim_sign module has been updated to make use of this
to ensure that the correct shape of data has been loaded.
We skip logging the 421 we generate while shutting down because
it feels a bit redundant; you'll see the server shutting down
in the journal anyway.
refs: https://github.com/KumoCorp/kumomta/issues/88
This commit refactors listener_domains.lua to facilitate unit testing
and adds a couple of basic test cases.
The functional change here is that we were missing an explicit
fallback step in the case where no listener or domain matches
the provided values directly; we need to explicitly add a check
against the `*` listener AND `*` domain for the final step.
Previously, we would only look at the `*` listener for the final
step.
closes: #128
The intent is to limit the overall rate at which a tenant
is able to send messages out from the server. It is NOT related
to the rate at which messages can be injected to ths server.
This is allowed in two locations:
* Directly in the tenant block
* In a new campaigns table located under a tenant
```toml
[tenant.'mytenant']
egress_pool = 'tpool'
overall_max_message_rate = "100/s"
[tenant.'mytenant'.campaigns.'mycampaign']
overall_max_message_rate = "50/s"
```
The tenant level throttle is checked first, and if it permits
the message, then the campaign specific throttle is checked.
refs: https://github.com/KumoCorp/kumomta/issues/143
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.
I definitely forgot to do this on the very first change after
adding them, so I want to make it less likely in the future.
This causes the specs to get updated in the docs if they have
changed (other than the version field) since the last time they
were updated.
We check this during test and doc building. That should be
sufficient to catch this during my dev loop.
refs: https://github.com/KumoCorp/kumomta/issues/96
use the drone cli to check that the starlark is well-formed,
and to try to run a build.
Useful for sanity checking a pending CI commit.
Slim down the deps very slight on ubuntu systems.
This has our first end-to-end integration test that validates
smtp -> source mta -> sink mta -> maildir
and confirms that the message has the right bits inside it.
The end to end test will get refactored into more easily usable
pieces in follow-up commit(s).