Commit Graph
1385 Commits
Author SHA1 Message Date
Wez Furlong 5b20731ea4 docs: restore proper version for template_dialect
This was accidentally lost in 75debad675
2026-01-07 07:48:20 +00:00
Wez Furlong 3ed4bb8083 Improve context in jinja template error messages
For this invalid jinja field: `{{ First Name }}` we'd report:

```
syntax error: unexpected identifier, expected end of variable block (in 0:1)
```

which is not very helpful.

With this commit we now report:

```
failed parsing field 'content.text_body' as template: syntax error: unexpected identifier, expected end of variable block (in template '0' line 1: 'Hello {{ First Name }},')
```

which is much more informative!

We include a length-limited fragment of the extracted source line in the
message to help track down the issue.  It is length limited because the
templates can potentially be very large.

The string truncation requires a function that was stabilized in rust
1.91, so this commit bumps the minimum version required.
2026-01-07 07:46:28 +00:00
Wez Furlong 885c4914ca docs: update openapi spec for amp_html 2026-01-07 07:46:27 +00:00
Mike Hillyer 75debad675 Updating headings in Inject API doc so that sidebar menu populates correctly. 2026-01-06 12:23:49 -05:00
Wez Furlong 0a112417c0 Add support for AMP in the message builder and injection APIs 2025-12-19 06:37:27 +00:00
Wez Furlong 55537a9ca9 docs: fixup anchor for requestaws_sign_v4params 2025-12-18 20:48:50 +00:00
Wez Furlong 6845a80c6b docs: changelog for #458 2025-12-18 14:17:56 +00:00
Aditya GantiandAditya Ganti af59493e00 Add aws_sign_v4 helper on kumo.http.Request (#458)
* Add aws_sign_v4 helper to kumo.http.Request and cross-link docs

Co-authored-by: Aditya Ganti <adityaganti@mac.mynetworksettings.com>
2025-12-18 07:14:36 -07:00
Wez Furlong 07ab3d44a3 inject+xfer: cut over to AuthInfo from AuthKind
Replace the older type with the newer one.

Serialize a copy of auth_info when handling deferred generation,
so that we have a lossless representation of that state when
we eventually process the request.  That doesn't change really
anything today, but will enable more granular ACL checks in
the future.

Pass the auth_info through to the http_message_generated and
xfer_message_received events to enable more granular access
control policies to be scripted.
2025-12-18 10:19:09 +00:00
Wez Furlong 5926112956 acct: add kumo.aaa.configure_acct_log
This function sets up the accounting log which records authentication
and authorization events to a local log file.

Add some test assertions that we're not seeing any failed authn/authz
in a number of integration tests.

Add explicit check for failed a request to kcli's streaming metrics
parser, which previously would ignore the request status.
2025-12-18 08:22:31 +00:00
Wez Furlong 3e85297fca authn: allow returning AuthInfo from smtp/http auth event callbacks
This commit allows the policy to return a richer representation of
the authentication information, which can include multiple identities
and group membership information.
2025-12-18 06:30:06 +00:00
Wez Furlong 4055c50522 authz: introduce an ACL facility
This commit is a step towards some general improvements around
our handling of authentication and authorization.

This commit is focused primarily on authorization, but there are
some adjustments to how we track authentication as part of enabling
that.

We now have a separate AuthInfo type that holds the overall
authentication information/context associated with an inbound
SMTP or HTTP session.

It is populated with the peer_address as a fact rather than a statement
of trust.

If authentication via the appropriate lua auth callback is successful,
then the AuthInfo has additional identities added.

There are some types and events for loading access control lists and
matching their rules against an AuthInfo.

There is now a system default ACL that is equivalent to the prior
hard-coded access policy that was encoded into each HTTP endpoint.

This change makes it possible to replace the ACL with a
user-defined ACL.

Later will be some work on authentication to allow more options
for HTTP auth.
2025-12-18 06:30:06 +00:00
Wez Furlong d68a4eca30 fix: log errors raised during should_enqueue_log_record
Previously, errors raised there would be silently discarded.
This commit logs them to the diagnostic log.
2025-12-18 06:23:43 +00:00
Wez Furlong fead711c80 mailparsing: improve charset detection/conformance fixing
We found an interesting issue where a MIME part was labelled as `text/`
with no explicit charset (and was thus implicitly "us-ascii", according
to the specs).  The content was actually UTF-8 encoded farsi text.

Since encoding_rs treats us-ascii as being an alias for windows-1252,
that part was re-encoded as bogus data, rather than being recognized as
UTF-8.

This commit improves the outcome in this situation:

1. Remove encoding_rs.  Replace its Charset type with the Encoding type
   that I added to the charset-normalizer crate in
   https://github.com/nickspring/charset-normalizer-rs/pull/45
   which allows us to actually differentiate between 7-bit ascii
   and latin-1.
2. Improve the handling of body part extraction; there were a couple
   of cases where we didn't consider the charset for text parts(!)
   and now we do, with some additional smarts for when the charset
   fails to decode.
3. Improve the conformance checking.  We do the majority of this
   during parsing, but we don't check for deeper issues such as
   the charset not matching the transfer-decoded payload because
   that is too costly to do for the majoriy of parses.  This commit
   introduces a deep conformance check that does validate that we
   can extract the part, flagging any failures as
   NEEDS_TRANSFER_ENCODING.
4. The charset detection options are threaded through the conformance
   checks and into the logic that extracts the parts during a rebuild,
   so that we can fix up those parts during rebuild.

The bulk of the conformance checking/fixing has been moved into the
mailparsing crate from the message crate, which makes the above a bit
easier and centralizes that logic better--fewer places to look to figure
things out.
2025-12-17 10:31:59 +00:00
Wez Furlong 6119250ebf templates: enable recursive lookup for Handlebars 2025-12-17 06:31:14 +00:00
Wez Furlong 716f880d41 spf: fix a potential panic if spf record contains U+200B
Adopting the get() method to handle the case where a string index is not
valid allows trapping and dealing appropriately with this abberant
input.
2025-12-16 13:53:27 +00:00
Wez Furlong b551d6b4c7 docs: update for release 2025.12.02-67ee9e96 2025-12-02 11:11:05 +00:00
Wez Furlong 67ee9e96ea docs: mail_auth: dmarc is implemented and available 2025-12-02 10:54:29 +00:00
Wez Furlong c379a931a1 docs: fix typo 2025-11-27 17:18:11 +00:00
Wez Furlong f0c2b490f4 metrics: fix prefix not being applied to metrics with multiple labels
we were producing output like this when `prefix=kumomta_`:

```
 # HELP kumomta_total_readyq_runs total number of times a readyq maintainer was run
 # TYPE kumomta_total_readyq_runs counter
 kumomta_total_readyq_runs 17
 # HELP kumomta_connection_count number of active connections
 # TYPE kumomta_connection_count gauge
 connection_count{service="smtp_client"} 0
 connection_count{service="esmtp_listener"} 0
 connection_count{service="lua"} 0
```

Those `connection_count` lines should be `kumomta_connection_count`.
2025-11-27 05:00:13 +00:00
Wez Furlong 3c4553ad7b docs: add logo 2025-11-26 16:46:25 +00:00
Wez Furlong c5266e260e docs: changelog for #457 2025-11-25 13:17:46 +00:00
Wez Furlong 38a15fe891 docs: format aws_sign_v4
refs: https://github.com/KumoCorp/kumomta/pull/457
2025-11-25 13:16:20 +00:00
Aditya GantiandAditya Ganti b96dd0843f Add AWS SigV4 signature module (#457)
* Add AWS SigV4 signature module

 - Implements complete AWS Signature Version 4 algorithm
 - Supports all AWS services (S3, SNS, SQS, Kinesis Firehose, etc.)
 - Includes SHA256 hashing and HMAC-SHA256 signing
 - Secure key management via KeySource (files, Vault, inline)
 - Session token support for temporary credentials
 - Comprehensive documentation and examples
 - 5 unit tests and 5 integration tests (all passing)

 Exposes kumo.aws.sign_v4() function to Lua for signing AWS API
 requests. This enables KumoMTA to integrate with AWS services for
 streaming logs to Kinesis Firehose, storing data in S3, sending
 notifications via SNS, and more.

 Tested with:
 - S3 GET/PUT requests
 - SNS POST requests
 - SQS with query parameters
 - Kinesis Firehose PutRecord

updating README.md file

Co-authored-by: Aditya Ganti <adityaganti@mac.mynetworksettings.com>
2025-11-25 06:14:48 -07:00
Mike Hillyer 7186aa380d Add reference to community contributed Mautic Webhook Callback. 2025-11-24 16:02:02 -05: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 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
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 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
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 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
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 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