Commit Graph

50 Commits

Author SHA1 Message Date
Wez Furlong 4b84181479 SharedString: remove deref to str, deal with fanout
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.
2026-03-28 07:20:27 +00:00
Wez Furlong d489f738f3 fix an issue around mx_list and config refreshing
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.
2026-03-02 15:13:01 +00:00
Wez Furlong 942d0463b5 Makefile: force alternate node-id for my sink configs
I'd rather that they didn't fall back to synthesizing the same
node-specific id when I run my non-kumod-user test setups.
2026-02-24 12:19:54 +00:00
Wez Furlong 66e5aa5508 docs: generate a page for each exported metric 2026-02-04 09:10:25 +00:00
Wez Furlong dd41e999c4 introduce declare_metric! macro
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.
2026-02-04 09:10:25 +00:00
Wez Furlong 549e9c611d add per-message xfer functionality
This commit adds a new kumo.xfer module that allows configuring or
cancelling xfer on a per-message basis.
2026-01-28 12:49:06 +00:00
Wez Furlong 1c3b6dc14a smtp_dispatcher: fix reverse order for mx_list
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.
2025-11-13 06:12:38 +00:00
Wez Furlong d4028f9931 Add smtp response text normalizer 2025-11-09 08:09:51 +00:00
Wez Furlong 7f4a929ca2 message transfer (xfer) support
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
2025-10-07 10:58:07 +01:00
Wez Furlong 888928b60f WIP: basic batch relaying and end-to-end test
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.
2025-10-07 07:52:57 +01:00
Wez Furlong 7fffccf410 Add support for generating NDRs
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.
2025-09-09 14:12:52 +01:00
Wez Furlong 1bf9d138ce extended lua mime parsing API
refs: https://github.com/KumoCorp/kumomta/issues/117

Could also make it possible to do eg:
https://github.com/KumoCorp/kumomta/issues/142
without any explicit direct support in the product.
2025-09-09 09:15:58 +01:00
Wez Furlong f85094282f migrate run-lua-test to rust
At least one of our supported platforms doesn't have a new enough
python to run the python version, let's just use rust for this.
2025-08-13 07:09:53 +01:00
Wez Furlong 9f316ed689 ci: improve run-lua-test
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
2025-08-11 13:24:41 +01:00
Wez Furlong 9e62a275c5 add tls_required_client_ca esmtp listener parameter
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
2025-07-24 15:40:49 +01:00
Wez Furlong c8027effb6 smtp_server: collect incoming tls information for logs/meta
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
2025-07-24 13:01:13 +01:00
Wez Furlong c22e98bcd5 add log-filter.py helper script
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.
2025-04-16 14:53:25 -07:00
Wez Furlong 4b7577ebbd even more clippy 2025-04-09 10:26:12 -07:00
Wez Furlong a1f4172f4f more clippy 2025-04-09 10:26:12 -07:00
Wez Furlong d5decd1361 bounce/suspend schedq: improve data structures
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.
2025-03-18 14:05:53 -07:00
Wez Furlong 22d405a23f make: pick up supplemental env vars from an optional .make-env
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.
2024-11-21 07:27:24 -07:00
Wez Furlong a412757513 Add smart-sink example docker compose
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.
2024-09-10 08:00:06 -07:00
Wez Furlong 50681b149c spool-util: add initial version
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.
2024-08-08 07:02:23 -07:00
Wez Furlong 435b6cb476 add tls-probe utility
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
2024-07-19 05:52:36 -07:00
Wez Furlong 007e234d9e Add toml2jsonc utility to convert toml to json with comments
The intended purpose is to use to auto-generate json representations
of example toml data files for the documentation.

refs: https://github.com/KumoCorp/kumomta/issues/212
2024-07-03 11:53:59 -07:00
Wez Furlong f0b91dd652 queue.lua: add typing
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
2024-06-28 08:54:46 -07:00
Wez Furlong af99c0bb75 run-lua-test: factor out of Makefile
This makes the Makefile less verbose/boilerplate-y
2024-06-27 05:51:11 -07:00
Wez Furlong b9dccf1cc3 add policy-extras.typing lua module
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.
2024-06-26 16:38:22 -07:00
Wez Furlong c9b98adc10 ci: cache target dir directly 2024-06-12 12:19:29 -07:00
Wez Furlong c5428dd5c8 ci: add xcp (parallel cp) to builder image 2024-06-12 09:15:22 -07:00
Wez Furlong 3e97cd3106 optimize the fast path for queue insertion
Avoid doing some work in the fast path, and accept that we might do
some redundant extra work in the slow path, in order to make the
fast path faster.
2024-05-01 22:36:26 -07:00
Wez Furlong a230e78ce6 add helper script for analyzing stack traces 2024-04-03 07:54:09 -07:00
Wez Furlong e94506fd96 Add new Rejection log event
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
2024-03-29 16:37:37 -07:00
Wez Furlong 15b1fab110 checkpoint some local testing/hacking in my test configs 2024-03-27 16:33:17 -07:00
Wez Furlong f6f8c55ea4 listener_domains: fix fallback issue
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
2024-03-22 09:48:18 -07:00
Wez Furlong a075e97e8d fixup make test to pick up username even if $USER is unset 2024-03-21 16:23:26 -07:00
Wez Furlong a145100105 fix running new lua unit tests when run as root 2024-03-21 12:19:25 -07:00
Wez Furlong 8ef3af530a add overall_max_message_rate option to queue helper
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
2024-03-21 09:16:40 -07:00
Wez Furlong e6973c2a04 slim down some deps
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.
2023-12-22 10:24:30 -07:00
Wez Furlong 837f9e5c0e automate updating the openapi spec files
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
2023-11-23 09:02:00 -07:00
Wez Furlong 9c0041b051 remove drone bits from makefile 2023-10-04 10:51:51 -07:00
drone f8674c3d63 Add woodpecker CI pipeline 2023-09-30 15:57:48 -07:00
Wez Furlong 620470f5aa ci: add local checker
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.
2023-09-19 09:54:54 -07:00
Wez Furlong 5d882096a9 return array of pipelines 2023-09-16 11:30:50 -07:00
Wez Furlong 257dc4a25a flesh out integration testing some more
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).
2023-03-07 18:42:14 -07:00
Wez Furlong a05724e40c auto-format generate-toc.py too 2023-03-07 07:36:50 -07:00
Wez Furlong 79afc79794 add lua code formatting 2023-02-15 06:51:59 -07:00
Wez Furlong e388a2cc4f refine smtp sink targets 2023-02-14 17:13:32 -07:00
Wez Furlong 5422a5fa76 can now deliver mail 2023-02-14 16:11:24 -07:00
Wez Furlong 3287523d84 Skeleton tokio server for kumod 2023-02-10 16:44:10 -07:00