Commit Graph
3410 Commits
Author SHA1 Message Date
Wez Furlong 3c75f92d76 ci: re-enable sccache default features
At some point turning off most features used to make things work in our
environments, but looking at things today, I think it basically makes
it do nothing useful any more.

Turning things off just made the image build a hair faster and the
image a hair lighter.

So let's just turn it back on
2025-11-22 21:26:53 +00:00
Wez Furlong 08a72bb9b1 CI: implement dependency cooldown for github actions
See: https://blog.yossarian.net/2025/11/21/We-should-all-be-using-dependency-cooldowns
2025-11-21 21:04:09 +00:00
Wez Furlong 2d557f68bf kcli: expose smtp_server_rejections counter 2025-11-20 15:39:36 +00:00
Wez Furlong 245221ae29 docs: clarify Time and TimeDelta
It wasn't clear that these pages were describing a class rather than a
literal object.

Add some more usage examples.
2025-11-20 15:26:42 +00:00
Wez Furlong 3d7802db37 docs: changelog for keysource event callback 2025-11-20 15:12:35 +00:00
Wez Furlong 65fde5c03b docs: fixup whitespace in changelog 2025-11-20 15:09:16 +00:00
crxandWez Furlong 39fbf150a9 traffic-gen header in changelog (#455)
* Changelog update

Co-authored-by: Wez Furlong <wez@wezfurlong.org>
2025-11-20 08:08:15 -07:00
Wez Furlong 027e3e9f75 docs: wrap examples in normalize_smtp_response.md 2025-11-20 14:54:26 +00:00
Wez Furlong 7b240db3e1 docs: fix copypasta in smtp_server_rewrite_response page
It said smtp_CLIENT instead of server
2025-11-20 14:53:03 +00:00
Wez Furlong 2023aba6af docs: mention template dialect in injection and eval_template APIs 2025-11-20 14:50:15 +00:00
Wez Furlong 3781ff7d95 docs: format 2025-11-19 07:57:37 +00:00
Wez Furlong 984e4a3156 CI: try out automatic mirroring to codeberg 2025-11-18 22:14:40 +00:00
Wez Furlong a28508ea07 rfc5321: improve error message formatting
In reviewing some live logs, I could see that some timeout errors
were including the debug repr of the SMTP command, which is too verbose
to be useful in the error log line, so let's tidy that up a bit
here to make it easier to understand.
2025-11-18 16:55:57 +00:00
Wez Furlong 6f53931fde add kumo.invoke_get_egress_(pool|source)
These functions are similar to the existing
invoke_get_egress_path_config and invoke_get_queue_config functions;
they return the configuration information that is defined by your
overall policy in the same way that the system does.

The intent is for more advanced policies that need that info to
decide how to configure other parts of the policy.

Docs are included, and I fleshed out the missing docs for the two
pre-existing functions.
2025-11-14 07:04:58 +00:00
Wez Furlong 4c89acae96 docs and changelog for require_proxy_protocol #440 2025-11-13 15:27:39 +00:00
4e767ff96f Add support for proxy protocol (#440)
Add support for proxy_protocol for start_esmtp_listener

Co-authored-by: Solvik Blum <solvik@solvik.fr>
Co-authored-by: Wez Furlong <wez@wezfurlong.org>
Co-authored-by: ncai <ncai@chapsvision.com>
2025-11-13 07:54:36 -07:00
Wez Furlong f2f792e74f kumo.digest: add various HMAC_SHAXXX functions 2025-11-13 12:06:32 +00:00
Wez Furlong fdd2276dfb mod-digest: switch from ring::digest to aws-lc-rs::digest
Switch away from ring to aws-lc-rs which API compatible and has support
for more digest algorithms.

Add support for all of the current algorithms.
2025-11-13 11:10:13 +00:00
Wez Furlong 26a0c86c49 Expose version number to lua via kumo.version
I'm surprised that we didn't already do this!
It allows phrasing the policy to accommodate different versions
of kumo.
2025-11-13 06:30:35 +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 9e0b019155 response normalizer: allow seeing into parentheticals
For a sequence like `[BASE64 IP: IPADDR]` we were not previously
able to see the base64 or IP address inside the square brackets.

This commit adds a pre-processing step to strip out parentheticals
surrounded by spaces (or the end of the string) so that our existing
tokenization can take effect.

I spent a few hours today trying a few different matching strategies,
rewriting this crate 3 different ways to try to simplify the logic and
lean more heavily on the regex or fancy_regex crate so that we can avoid
special cases.  While they all worked, they all were over an order of
magnitude worse in terms of throughput and performance.

The strategy here is to perform a very cheap SIMD-assisted test to see
if we need to pre-process the string so that we can avoid the overhead
of the additional string allocation and full processing step.

The result is that the performance before and after this change is very
close to neutral when the response contains no brackets, but 33% slower
(and 50% throughput) when brackets are present.  That's still 180MiB/s
on my threadripper which is still decent for this application.

While grubbing around in here today, I noticed that a couple of regexeps
had typos: `(:?` when they should have been `(?:`, and I annotated more
sub-expressions to be non-capturing as well.
2025-11-12 15:40:28 +00:00
Wez Furlong 1795fa6f56 message: ensure all data-loading methods are async and load data
This commit tidies up a bit of an API wart that stems from
the initial implementation where we couldn't guarantee that
the message crate would know how to get a spool handle to
implicitly load data when needed.

This has resulted in a couple of issues over time where we try to
operate on the message data and it just hasn't been loaded, leading to
transient errors being raised in the best case, but in a possible worst
case, a silent error condition.

During the rebind_message event, if the message is not loaded,
msg:get_data() could return the placeholder empty data value.  If the
rebind_message event is trying to mutate the message then the best case
is that an error is raised, a medium-bad case is that operations like
`msg:append_header` will fail to find the header block and thus fail,
and the worst case is that mutation operations that blinding prepend
data (perhaps msg:prepend_header) could end up assigning a bogus
truncated message.  While we don't generally recommend this sort of
action, this is potentially a very gnarly consequence of trying things
out.

Let's just head all of these sorts of issues off by making the accessors
async and have them internally load the data as required.
2025-11-11 10:28:51 +00:00
Wez Furlong 4917ee6245 prohibited_hosts: add v4 and v6 any address
Saw an MX record that expands to 0.0.0.0 in the wild.

As well as being nonsense, that causes a mail loop, so we should add it
to prohibited_hosts.

I noticed that we also did not document its default value, so the
doc update here shows the before and after for this.
2025-11-10 15:09:11 +00:00
Wez Furlong 7703b9fcf2 docs: migrate userguide amqp example to basic_publish
Since we have deprecated the `build_client` approach, we should
be showing how to use the preferred function!
2025-11-10 11:58:46 +00:00
dependabot[bot] 64f65a634f build(deps): bump actions/upload-artifact from 4 to 5
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-10 11:58:19 +00:00
dependabot[bot] fd4fd99ab2 build(deps): bump actions/download-artifact from 5 to 6
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-10 11:57:51 +00:00
Wez Furlong c06b0bc0c0 docs: changelog for normalize_smtp_response 2025-11-09 08:13:39 +00:00
Wez Furlong d4028f9931 Add smtp response text normalizer 2025-11-09 08:09:51 +00:00
Wez Furlong ad8a858136 templates: add Handlebars dialect
This is fairly barebones: there are very few helpers at this time.

refs: https://github.com/KumoCorp/kumomta/issues/446
2025-11-09 07:53:20 +00:00
Wez Furlong e106c3d496 template: add Static engine
This engine does no templating; the source text is output exactly
as it was entered into the template engine.

Expose template_dialect to the http injection API and add a test
to show that selecting the Static dialect doesn't perform any
template expansion.

refs: https://github.com/KumoCorp/kumomta/issues/446
2025-11-09 07:53:19 +00:00
Wez Furlong 9ea28f9c2f template: add optional dialect argument to kumo.string.eval_template
refs: https://github.com/KumoCorp/kumomta/issues/446
2025-11-09 07:53:19 +00:00
Wez Furlong 5d78d5b2b5 templates: prepare to support multiple dialects of templates
This is primarily a refactoring of kumo-template to conceptually
support the idea of having multiple dialects, even though it
only defines a single dialect.

It prepares the types/interface for that purpose.

It also pulls in the handlebars crate, but doesn't use anything
from it yet; that'll be in a follow up commit.

refs: https://github.com/KumoCorp/kumomta/issues/446
2025-11-09 07:53:19 +00:00
Wez Furlong d5181f179f smtp_dispatcher: remove stray debug 2025-11-07 13:35:21 +00:00
Wez Furlong 7ac9a5eac0 smtp_dispatcher: handle pathologic all-452 case
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.
2025-11-07 08:13:36 +00:00
Sophia Turner 96bdbef106 add a dmarc lua test, fix API 2025-11-07 08:08:29 +00:00
Wez Furlong 94628f06ab smtp_dispatcher: fix interpretation of 452 for single-recip messages
The multi-recipient send logic introduced a regression in `main` that
could cause messages like "452 4.1.1 mailbox full" to be considered
immediately retryable always, because we thought it meant "too many
recipients" in this batch.

This commit fixes up the immediate retry logic to only apply when we
have a batch size > 1, and we try to be a bit more discerning with the
enhanced status code when it is present.

This issue isn't being mentioned in the changelog as a breaking change,
as the breakage is vs. an earlier `dev` build and not a prior stable
release.
2025-11-06 07:58:27 +00:00
Wez Furlong b5f2c46f08 docs: add breaking change note about RCPT TO 552 status
in 18e55a6e91 I noticed that we should be
handling 552 as a transient failure, but I neglected to mention this
change in the changelog because it seemed obscure and "couldn't" hurt
anyone.

I overlooked that we have client response rewriting and of course this
change did impact one of our sponsors that rewrites certain transient
452 responses to 552 responses.

So, let's add a note explaining this to see if we can prevent others
from hitting it in the future.
2025-11-04 17:11:34 +00:00
Wez Furlong 4e8e616dad logging: load meta before retrieving the recipient_list
We had a sponsor report an issue where we'd log an error during
processing a log hook. It transpired that the recipient list we were
attempting to log was `["metadata is not loaded"]`, which doesn't parse
as a valid EnvelopeAddress (see prior commit:
52e2f95e9f)

This commit fixes up the recipient_list logic in the logging function to
avoid taking the error message as the recipient list, and moves the
metadata loading to happen just before we try to read the recipient
list.

This should work around the issue, but a consequence is that we might
be holding on to the metadata for that message in RAM for longer than
we should; will need to do some thinking about managing the resident
status in this situation better.
2025-11-04 07:26:43 +00:00
Wez Furlong 52e2f95e9f address.rs: add more context to invalid addresses when parsing fails 2025-11-03 21:35:39 +00:00
610b441e67 Allow temp/perm errors in dmarc (#441)
allow temp/perm errors in dmarc

Co-authored-by: Sophia Turner <sophiajt@users.noreply.github.com>
Co-authored-by: Wez Furlong <wez@wezfurlong.org>
2025-11-03 01:36:41 -07:00
Wez Furlong 4c6d7ca8ea add policy-extras.mail_auth module
This aggregates the various authentication-results producing auth checks
into a more convenient function.

Part of this change improves some plumbing in the dkim checking (we no
longer raise an error for a missing From, but instead indicate a failed
dkim result), and we now support passing down a resolver name to the
various checking functions, to facilitate testing and other more
advanced use cases.

refs: https://github.com/KumoCorp/kumomta/issues/16
refs: https://github.com/KumoCorp/kumomta/issues/84
2025-11-02 11:56:57 +00:00
Wez Furlong 49cdee1ec5 lruttl: expose pre-defined cache info to the docs
This commit adds some plumbing to allow us to collect metadata
about the caches and spit it out into a json file that we can
then use in the docs to show the predefined caches, capacities
and brief comments about their purpose.

We put that info on the set_lruttl_cache_capacity doc page.
2025-11-01 07:40:40 +00:00
Wez Furlong c085e368b2 dkim_(key|signer)_cache: enable thundering herd protection
Use the managed accessor for thundering herd protection.

May help with a situation as discussed in
https://github.com/KumoCorp/kumomta/pull/438
2025-10-31 18:04:17 +00:00
Wez Furlong e7f4806f1b dkim: add integration test assertions for signing cache
refs: https://github.com/KumoCorp/kumomta/pull/438
2025-10-31 17:27:05 +00:00
Wez Furlong 5ad7df0203 arc: expose arc_seal and arc_verify methods to lua
refs: https://github.com/KumoCorp/kumomta/issues/16
2025-10-31 12:16:32 +00:00
Wez Furlong 1da468ea9a arc: we can now produce an arc seal
refs: https://github.com/KumoCorp/kumomta/issues/16
2025-10-31 12:16:32 +00:00
Wez Furlong 4bd42ae57f arc: we can now validate an arc chain
refs: https://github.com/KumoCorp/kumomta/issues/16
2025-10-31 12:16:32 +00:00
Wez Furlong 823ee09db9 dkim: refactor and improve some of the test logic
refs: https://github.com/KumoCorp/kumomta/issues/16
2025-10-31 12:16:31 +00:00
Wez Furlong ee4266cd19 WIP: building out ARC processing
This is not fully baked yet, but I want to checkpoint.

refs: https://github.com/KumoCorp/kumomta/issues/16
2025-10-31 12:16:31 +00:00
Wez Furlong 93210b8346 dkim: add ARCSealHeader type
refs: https://github.com/KumoCorp/kumomta/issues/16
2025-10-31 12:16:31 +00:00