Commit Graph
1324 Commits
Author SHA1 Message Date
Wez Furlong 47aac10ea6 data-loader: allow callback/event based loading of secrets
This allows a (more or less) arbitrary lua function to be used to load
data.

The primary advantage of this is that the size of the resulting
KeySource struct is smaller than it would be to hold the actual data
inline.  It also enables the surrounding code to be slightly better
factored.
2025-10-24 13:41:27 +01:00
Mike Hillyer ab2e7ad662 Add reference to AL 2/2023 and remove CentOS 7 reference. 2025-10-23 12:35:08 -06:00
Mike Hillyer a8230ae8dd Update install doc in Userguide to specify Rocky 8/9. 2025-10-23 12:31:25 -06:00
Wez Furlong 6f31d5514c new Time and TimeDelta objects for lua
Motivated by https://github.com/KumoCorp/kumomta/pull/403,
this commit introduces reasonably full featured Time and TimeDelta
types built atop the chrono crate.

closes: https://github.com/KumoCorp/kumomta/pull/403
2025-10-22 17:26:35 +01:00
Dario MaiocchiandWez Furlong 847cc21e9b implement aes-cbc block with examples
Add CBC and ecb Block mode aes encryption/decryption.

To facilitate testing this better, and just to be nicer overall, adjust
data-loader's KeySource::key_data variant to support loading raw binary
bytes.

Co-authored-by: Wez Furlong <wez@wezfurlong.org>

Closes: https://github.com/KumoCorp/kumomta/pull/395
2025-10-22 11:55:16 +01:00
Wez Furlong ac22d6848d docs: format 2025-10-21 21:26:32 +01:00
Wez Furlong 6fc0d782ff spf: populate smtp.mailfrom in Auth-Results, add check_msg func
Add a convenience function that is intended to be used around the
time that you might be building up the overall set of
Authentication-Results.

Populate missing smtp.mailfrom in SPF authentication result.
2025-10-21 21:25:21 +01:00
Mike Hillyer 10ab901174 Update index for new integration page. 2025-10-18 12:07:00 -04:00
Wez Furlong 0a117e9407 fix incorrectly treating 552 as TransientFailure
We should do this ONLY when the response is to a RCPT TO command,
otherwise it is a permanent failure.

refs: https://github.com/KumoCorp/kumomta/issues/431
2025-10-16 16:03:12 +01:00
Mike Hillyer 87bc5d0c7b Typo fix. 2025-10-16 09:56:29 -04:00
Mike Hillyer 0334af7780 Add link. 2025-10-16 09:51:38 -04:00
Mike Hillyer 60a8cf7135 Add EmailElement to Integrations section of UserGuide. 2025-10-16 09:51:38 -04:00
Wez Furlong 8ba93b5454 add smtp_server_rejections counter to metrics
This is incremented each time we log a Rejection record from the smtp
server.

The service label identifies the listener address, and there is a
special `total` that is incremented as a rollup across all listeners.

```
 # HELP smtp_server_rejections number of Rejection records logged by the smtp server
 # TYPE smtp_server_rejections counter
 smtp_server_rejections{service="127.0.0.1:2025"} 1
 smtp_server_rejections{service="total"} 1
```

closes: https://github.com/KumoCorp/kumomta/issues/429
2025-10-15 06:59:56 +01:00
Wez Furlong 7eeb755f30 mailparsing: fix quoting issue with Mailbox display name
Let's base our quoting decisions based on whether the string is fully
atext compatible, and once quoting, on whether the character requires
quoting within the quoted string.

refs: https://github.com/KumoCorp/kumomta/issues/428
2025-10-14 14:59:04 +01:00
Wez Furlong 43e45e12c0 smtp_server: fix max_line_length issue
Partially reverts aac842439f and fixes the
underlying issue that led me to throw that together: the issue was that
the check_line_lengths function needed to add 2 to the index otherwise
iterations after the first would over-estimate the length of the
currently found line by 2, because the prior index included the CRLF
that it found in the input.

While poking at this, I found that there was a fairly harmless edge case
around non-DATA line handling: we used a 1024 stack buffer to read the
command in, and would accept anything that fit into that as valid, even
though the limit is set to a slightly smaller value.
2025-10-14 08:15:52 +01:00
Wez Furlong aac842439f smtp_server: increase line_length_hard_limit default to 1000
We were including the CRLF in the measurement that we were making,
while the default value was the value from the spec excluding the CRLF.
Let's increase the default value to 1000 to make things match up.
2025-10-13 09:53:03 +01:00
Wez Furlong adfdcef1f8 spf: improve test coverage, couple of fixes
* Add exp= test based on an example in the rfc
 * Discovered that we were a bit too strict and didn't allow spaces
   as shown in that example
 * Add integration test for the ehlo_domain string quoting issue
   resolved in 236afa417f
 * lua spf check: Assume ehlo_domain = domain when sender is none
2025-10-13 08:22:36 +01:00
Wez Furlong 6197367312 docs: add splitting step to event sequence diagram 2025-10-11 07:13:06 +01:00
Wez Furlong 7311510ff6 docs: recip needs to be an array in this example 2025-10-11 07:09:11 +01:00
Wez Furlong a81493a17e docs: remove extraneous quotes 2025-10-11 07:07:54 +01:00
Wez Furlong b73d81b0fc dns: utilities and plumbing for querying DNSBLs
This commit does some plumbing work to allow defining alternative
resolvers with different names that can be used to query different
upstream DNS servers.

This is most useful when implement DNSBLs where you might have a custom
DNS server configured with one or more RBL zones that is reserved purely
for RBL lookups.

The plumbing introduces a more regular syntax for defining one of the
various implementations of the Resolver trait, as well as a new
Aggregate resolver impl that can query across multiple Resolvers until a
query is satisfied.

This allows some interesting and powerful configurations, such as
loading a static zone file into memory to query it directly, and/or
blending that together with querying either the system or some other
upstream DNS server as a fallback.

The various lookup functions (except for MX!) have been updated to
accept an optional alternate resolver name, so that they work together
with the above.

A new rbl_lookup function is also provided as a convenience for querying
the most common form of RBLS.

ptr_host and reverse_ip are two string utility functions that are likely
not going to be widely used, but are very convenient to have when you
do have a usecase that requires it!

closes: https://github.com/KumoCorp/kumomta/issues/269
2025-10-10 18:45:52 +01:00
Wez Furlong 67061e3a24 spf: fixup handling of NoRecordsFound during exists: check
Similar to the general purpose resolve function, we should map
NoRecordsFound to empty list(s) of results in the specialized
ip, mx and ptr lookup functions, otherwise we can cause rule
evaluation to terminate too soon.
2025-10-09 08:47:09 +01:00
Wez Furlong 5b914a597a deprecating the lapin-based amqp client
This never worked as well as the other amqp option that we support,
and upgrading it to the current version is a bit of a chore.

I'd rather just drop this dep and keep things more trim.

Since none of our sponsors are using the lapin implementation, let's
mark it as deprecated and we can take it out after we cut the next
stable release.
2025-10-08 11:17:55 +01:00
Wez Furlong 8fc11713d8 deps: update axum and utoipa ecosystem crates
A "casualty" of this is that the client-ip crate, which we were using
for its InsecureClientIp type for informational purposes, has retired
the InsecureClientIp type because it wasn't trustworthy overall
(https://github.com/imbolc/axum-client-ip/issues/32).

What we do for the time being is configure that crate to use the direct
peer IP.  There isn't a way to automagically select the "best"
information available without building in some kind of middleware, and
we probably should make that configurable in order to be fully
trustworthy.

So for now, we're punting on that until someone shows up with some
requirements and sponsorship and we'll make it happen then.
2025-10-08 10:24:57 +01:00
Wez Furlong 5c98511c06 add new kumo.file_type module
This is useful for example when processing attachments as part of a
content scanning policy.
2025-10-07 12:12:46 +01: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 de6e3bd0de allow admin bounce and suspend to specify exact queue name 2025-10-07 08:43:16 +01:00
Wez Furlong 5b5145aec8 openapi: manually poke the version number
These changes have been amended and rebased over the past few
weeks, so the version numbers for the json file no longer
correlate to real commits or dates.
2025-10-07 08:36:41 +01:00
Wez Furlong 407d2bc332 docs: update for multi-recipient changes 2025-10-07 08:35:59 +01:00
Wez Furlong 794113f0b0 smtp_dispatcher: add max_recipients_per_batch
This sets a client side shaping control to manage the maximum number of
RCPT TO commands issued in a single transaction.
2025-10-07 07:53:15 +01:00
Wez Furlong f968935315 add smtp_server_split_transaction event
This provides full control over how an incoming smtp transaction
will be split into batches.
2025-10-07 07:53:15 +01:00
Wez Furlong b157e2f617 add smtp_server_data event for per-txn message validation
Great for doing content scanning and recipient list modification!
2025-10-07 07:53:13 +01:00
Wez Furlong db5ebb88a7 message: expose recipient list to lua api
message:recipient() may now return an array style table
holding the recipient list, if there is more than a single
recipient on the message.

Since this can be somewhat ambiguous/frustrating to work with,
there is now also a message:recipient_list() that will always
return an array style table, even if it holds just a single
element.

The included helpers have been updated to use `message:recipient_list`.

message:set_recipient() will now optionally accept an array
style table holding the recipient list to be set.
2025-10-07 07:52:58 +01:00
Wez Furlong 18e55a6e91 smtp: handle "too many recipients" status more appropriately
This commit adds a test for exceeding the number of recipients
allowed in a transaction and fleshes out our handling of that
status so that we will immediately try the remaining recipients
of the batch, without delaying the message by eg: 20 minutes
in the default retry parameters.

As part of this, I noticed that we were returning the wrong
smtp status code in our server implementation, so this
commit fixes that up.
2025-10-07 07:52:58 +01:00
Wez Furlong 9079a9e569 WIP: more multi-recipient type changes
This commit updates the type signatures of some key structures
to allow for the possibility of a Message having multiple recipients:

 * Message (continuing from previous commit)
 * JsonLogRecord
 * MessageInformation

Some logic has been updated to account for multiple recipients,
but critically, nothing in the core will generate them, and none
of the queue management or delivery infrastructure is aware
of recipients beyond the first.
2025-10-07 07:52:57 +01:00
Wez Furlong 206dc7c7fa optionally detect legacy 8-bit during check-fix 2025-10-07 07:50:46 +01:00
Wez Furlong 981de67f1c docs: update for 2025.10.06-5ec871ab release 2025-10-07 07:38:10 +01:00
Wez Furlong 307d0b3093 docs: changelog for #423
closes: https://github.com/KumoCorp/kumomta/issues/423
2025-10-06 19:41:53 +01:00
Wez Furlong 4ba41290a6 docs: format and fixup whitespace 2025-10-06 07:02:18 +01:00
Wez Furlong dba45cfa28 logging: allow * to match meta names
This uses the same scheme as allowed for matching header names
in logging.
2025-10-06 07:02:18 +01:00
Tom Mairs 873f9e524d Update sample code 2025-10-03 20:27:23 +01:00
Wez Furlong 5228f794bb xclient: capture original via/from address in context
I can see someone wanting to know the raw physical connection
info at some point, regardless of the adjusted xclient values,
or in the future, the proxy protocol adjusted values.
2025-10-03 20:03:14 +01:00
ncai ce743133b0 fix typo in doc 2025-09-30 07:35:32 +01:00
Wez Furlong d9d3d14e3e enable XCLIENT support
Hooks up the parsed XCLIENT command to the smtp server.
We support just the address changing attributes; we don't
do anything special with the NAME attribute, and I'd like
to think a lot more about authentication before allowing
messing with the LOGIN attribute.

After applying changes to the metadata in the connection,
take care to re-evaluate the listener parameters and
dynamic parameters so that `via` and `peer` blocks can
match the new configuration.
2025-09-26 09:36:15 +01:00
Wez Furlong 90dd172f6c wrap up 8BITMIME and SMTPUTF8 support
Finishes up support for these extensions by adding a send-time
check and error for the case where we have 8 bit content and
the appropriate extension is not advertised by the next hop.

A shaping option is provided to bypass this, both to facilitate
testing and as a way to bypass it for situations where the
operator knows best.

closes: https://github.com/KumoCorp/kumomta/issues/327
2025-09-25 12:37:11 +01:00
Wez Furlong 33e1883d79 add kumo.apply_supplemental_trace_header
This allows manual and conditional control over whether and how this
header is added to a message.
2025-09-25 09:02:41 +01:00
Wez Furlong 6fdffa53e3 expose hostname and received_via for http injections
To facilitate this we need to feed the `AppState` down through
the Router more generally, and expand it to grab a copy of the
http listener parameters.

closes: https://github.com/KumoCorp/kumomta/issues/417
2025-09-25 08:37:06 +01:00
Wez Furlong eb54cc74d9 proxy-server: raise NOFILE soft limit to match hard limit
This makes the startup behavior consistent with kumod and tsa-daemon,
which can help with "Too many open files" errors in systems without
any explicit tunings for the proxy server.

It is still a good idea to explicitly tune that value up, and it is
something we should put into a systemd unit when we get around to
shipping one of those for the proxy server (#188)
2025-09-18 15:54:18 +01:00
Wez Furlong 220edf24b4 fix doc link 2025-09-18 15:27:05 +01:00
Wez Furlong b615646e84 mod-encode: be more relaxed about excess baseXX padding
The implementation of these encodings in the data-encoding crate is
overly strict when extraneous/excess padding is used, presenting
problems from the perspective of Postel's law especially in the context
of email: there are base64 encoders widely deployed that can produce
extraneous padding that is otherwise harmless but which will raise an
error from this crate.

This commit works around this by manipulating the encoding context
to remove the padding requirement, as well as the padding, and
decodes the input without padding.
2025-09-18 15:22:04 +01:00