Commit Graph
59 Commits
Author SHA1 Message Date
Wez Furlong d9851e3e02 update dev -> 2026.09.22-a276d4a8
Update docs for new stable tag

```
./assets/find-since-dev.sh 2026.09.22-a276d4a8
./docs/build.sh
```
2026-09-23 15:26:24 +01:00
Wez Furlong 41be60dfce Evaluate MTA-STS during MX resolution to fix aliasing issue
refs: https://github.com/KumoCorp/kumomta/issues/484

Briefly, the issue is that if some random domain that shares MX records
with another (eg: someone is using google apps or icloud for their
vanity domain) publishes a broken MTA-STS policy that requires eg:
cloudflare MX hosts then because we roll up by site name, that broken
MTA-STS policy bleeds into all the other domains that share those MX
records.

The resolution is simple, but is technically a breaking change.

Moving the policy resolution to happen during site_name resolution
allows us to resolve both per-domain things at the same and have the
MTA-STS policy amend the effective set of MX hosts.  The output of that
is then used for site_name aggregation/rollup.

The consequence of this is quite nice: an MTA-STS policy that is more
restrictive than the full set of MX hosts now prevents delivering to
any of the excluded hosts, and a totally broken policy that prevents all
of its MX hosts is now completely undeliverable and will produce
transient failures.

The downside is that for users that had previously disabled mta-sts in
their default shaping block, they will need to change a different config
option to continue to prevent MTA-STS from being consulted.  One example
of this that I recall is that one user's network posture prevented
MTA-STS from making HTTPS requests to fetch the policy.  Another user
just wanted to cut out the additional DNS traffic.  Those use cases
require altering the new kumo.dns.set_mta_sts_enabled enabled to false
during `init`.
2026-07-27 08:02:37 +01:00
Wez Furlong dfb17abd0d dane: engage for secure CNAME into unsigned zone
Per RFC 7672 section 2.2.2, an MX host that is a securely published
CNAME remains DANE-eligible at its original name even when the alias
target lands in an unsigned zone: it is the secure TLSA RRset, not the
address records, that authenticates the peer. When the address chain is
insecure but MX selection was secure, an explicit CNAME query isolates
the alias's own DNSSEC status; a secure alias engages DANE, an
indeterminate status defers for downgrade resistance.

refs: https://github.com/KumoCorp/kumomta/pull/545#discussion_r3472353021
2026-07-06 11:46:51 +01:00
Wez Furlong 4fc3cbca92 add treat_mx_list_as_secure to SmtpProtocol
This allows you to explicit indicate that an mx_list should
be treated as DNSSEC secure.

We cannot simply assume that lua code setting mx_list be treated
as secure, because the lua code may be simply passing through
the result of some other DNS lookup--we need an explicit way
to thread through the overall secure flag in order for the
secure property to be correctly upheld.
2026-07-06 11:46:51 +01:00
Wez Furlong e13734d186 address review feedback on https://github.com/KumoCorp/kumomta/pull/545
Address most of the easy points from the review, others will land
separately.
2026-07-06 11:46:51 +01:00
Wez Furlong 3b61117145 dns: add RFC 5011 managed trust anchor option for unbound
trust_anchor_file now accepts `{ managed = "<path>" }` for an RFC 5011
auto-maintained anchor file (unbound only; hickory errors). Unbound seeds
the file from the bundled root anchors when the file is absent.
2026-07-06 11:46:51 +01:00
Wez Furlong 1874dc09f7 enable DNSSEC when using hickory, allows enable_dane w/o unbound
When we first built out DANE, the hickory implementation was
all or nothing when DNSSEC validation was enabled, making it unsuitable
for use in an MTA.

Since that time hickory has matured; this commit wires up the
DNSSEC signals and that enables its use with DANE.

We do still require openssl for establishing the connection when
DANE is enabled; that's a different constraint.
2026-07-06 11:46:50 +01:00
Wez Furlong 7331cb4ec7 new allow_smtp_auth_plain_without_valid_certificate option
This is technically a breaking change, but in a good way.
We will no longer send SMTP AUTH PLAIN creds when we didn't
validate the peer certificate.  This is what you want in
all production deployments.  The new option facilitates
test setups or other unusual configurations where the certs
cannot be verified but you have contrived to trust the
remote system through some other means.
2026-07-06 11:46:50 +01:00
Wez Furlong a4c4b40fbe add dane_result_count metric
This surfaces aggregate dane results
2026-07-06 11:46:50 +01:00
Wez Furlong d920ffb5c4 fix: DANE downgrade resistance
We weren't checking the DNSSEC status for A/AAAA when considering
DANE, and were overly permissive in a couple of related cases.

This diff ended up fairly large because the bulk of it is to
facilitate testing.

refs: https://github.com/KumoCorp/kumomta/issues/543
refs: https://github.com/KumoCorp/kumomta/pull/517
2026-07-06 11:46:49 +01:00
Wez Furlong 423abc4704 add per-dispatcher state tracking and watchdog
The ready queue maintainer now tracks for each dispatcher whether it
is making progress.  If it exceeds dispatcher_progress_watchdog_timeout
then the task will be aborted and any message(s) it held onto will
be returned to the scheduled queue.  This will free up the connection
slot and allow another connection to be attempted, potentially
making further progress.

refs: https://github.com/KumoCorp/kumomta/issues/539
2026-06-23 09:56:45 +01:00
Wez Furlong 37236c40b1 docs: update for the 2026.04.09-ea3b2a9b release 2026-04-29 08:07:13 +01:00
Wez Furlong 654f9b88f5 new: ip_lookup_strategy option in make_egress_path
This provides control over IPv4 and IPv6 lookups based on the source
and/or destination.
2026-03-04 16:33:32 +00:00
Wez Furlong 4eef49df3c docs: remove suspended option from docs
This was removed from the product over a year ago in
16fb1ae316
2026-03-04 15:14:50 +00:00
Wez Furlong 93e8e7dd01 docs: update since('dev') macros for stable release 2026-03-04 08:03:21 +00:00
Mike Hillyer c4c161543f Typo. 2026-03-03 13:53:31 -05:00
Wez Furlong 7d521fd493 docs: clarify enable_mta_sts 2026-03-03 17:19:25 +00:00
Wez Furlong 4f636a0fae skip_hosts: downgrade to a transient failure
This is a conceptually breaking change, but shouldn't be harmful
in practice.

Recently, Microsoft hosted domains have had a number of incidences where
the DNS stopped returning IPv4 addresses, which lead to systems that
employ skip_hosts to disable their IPv6 addresses (presumably due to
difficulties in warmup and reputation) to trigger the terminal case
where we would sweep the ready queue away as a permanent routing
failure.

In the context of a transient failure to route ipv4 the permanent
disposition was surprising and unwanted so it feels better to make
the effect of this situation more closely map to how we handle the
case where no MX records are returned.
2026-02-04 13:12:14 +00:00
Wez Furlong b551d6b4c7 docs: update for release 2025.12.02-67ee9e96 2025-12-02 11:11:05 +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 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 981de67f1c docs: update for 2025.10.06-5ec871ab release 2025-10-07 07:38:10 +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
Pankaj RathiandWez Furlong eae61a90fe Add support for custom key names in HashiCorp Vault secrets (#399)
* Add support for custom key names in HashiCorp Vault secrets

Co-authored-by: Wez Furlong <wez@wezfurlong.org>
2025-07-25 06:02:21 +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
kayozaki 76add2ced5 Adding support for presenting Client cert as part of make_egress_path (#391) 2025-07-24 13:00:27 +01:00
Wez Furlong d9a2392ccb allow setting destination smtp port via mx_list 2025-07-21 12:30:29 +01:00
Mike Hillyer 58e9770206 We miss you Mister Rogers. 2025-07-18 12:11:14 -04:00
Wez Furlong 42bf5c5e61 docs: adjust reference to improve search terms
We've been hoping that mkdocs-material will ship the much anticipated
search enhancements for some time, but it's time to recognize that
we need to do something to improve the search results with how
things work right now.

This is a big commit that changes the titles of the various pages
from the code-annotated synopsis to just the name of the function.

This makes it much easier now to match things like `kumo.reject`
directly, but `reject` remains awkward to find.

I think this is the best that we can do at this time.

A few functions have been annotated with the `status: deprecated` to
show as deprecated in the toc/nav (shows with a little trash can next
to the name).
2025-05-16 14:02:19 -07:00
Wez Furlong b0c6b1cf6a smtp_dispatcher: retry more aggressively in transport-error-ish scenarios
Some sites are non-conforming in their behavior when they have a policy
that issues a transient failure and then snips the connection without
explicitly issuing a 421.

This can cause "splash damage" where a message is transiently failed
and the connection snipped "disgracefully" and a subsequent message
that is due to go out on that same established connection encounters
a transport error when the RSET part of the pipeline is sent.

This commit provides methods on the ClientError and Response types
to help reason about whether the response might be specifically
about the message being delivered, vs. more of a transport error.

The gist of this check is that timeouts and transport level stuff
where there is no protocol level response are not considered to
be due to the message.  Protocol level responses prior to MAIL FROM
are similarly considered to be more like transport errors.

The functional change in this commit is:

* If we get a transport-ish error and we have more candidate hosts
  available in the connection plan, then after logging a
  TransientFailure for the error we just encountered, we'll push
  back the message to be tried again on the next connection that
  we open in the current session.

* For timeout errors specifically, this behavior is gated behind
  a try_next_host_on_timeout boolean option.
2025-05-08 10:41:06 -07:00
Wez Furlong c3dff7e2c8 docs: update for latest release 2025-05-06 18:24:15 -07:00
Wez Furlong 18e510ebe2 ready_queue: introduce dispatcher_wakeup_strategy and maintainer_wakeup_strategy
These allow optionally reducing how aggressively the dispatcher and
maintainers will be awoken when message(s) are submitted to the ready
queue.

The default behavior remains the same; the new thing here is the
ability to make it more relaxed, which should reduce some CPU
overheads for very busy systems with many queues.

Making things more relaxed does introduce a possibility for higher
outbound latency in some edge cases with low or bursty traffic.
2025-04-16 15:19:27 -07:00
Wez Furlong 3b14587192 fix delayed shutdown for non-smtp delivery handlers
Occasionally we'll have someone report that systemd timed out
and sigkill'd their kumo on shutdown.

One possible scenario for this is a lua delivery handler that
is taking too long, presumably because the other end of it
(eg: webhook or other custom endpoint) is not responding in
a timely fashion.

The way that we handle shutdown is that we compute a maximum
theoretical timeout value by summing up all of the smtp client
timeout values.  Some of those can be several minutes in
duration because the are using default values derived from
a very conservative set of values suggested by the SMTP
RFCs from the '70s.

Those obviously should not apply to a custom delivery handler,
but also, in the context of an established SMTP session, we
should not add in the connection-establishment-specific values
when we're just waiting for a per-message send.

This commit addresses this situation on two fronts:

* Introduce a new system_shutdown_timeout value that allows the
  user to conveniently express their desired timeout value
  in a single option.  This is *not* set by default!
* The default value for system_shutdown_timeout is computed by
  summing the per-message-delivery smtp timeout options, which
  is a much more reasonable, and more importantly, shorter than
  our 300s TimeoutStopSec value in kumomta.service
2025-04-02 14:21:31 -07:00
Wez Furlong 337b4e33a8 docs: update for stable 2025.03.19-1d3f1f67 release 2025-03-20 07:28:32 -07:00
Wez Furlong 6d17a0a453 docs: mention mta-sts and dane on the enable_tls page 2025-03-17 08:52:10 -07:00
Wez Furlong 9286394e72 docs: fixup list bullets for source_selection_rate 2025-03-11 09:54:14 -07:00
Wez Furlong 6ef73a096e docs for source_selection_rate 2025-03-11 09:46:58 -07:00
Wez Furlong 3805afdcc1 docs: fixup list presentation for (low|no)_memory_reduction_policy 2025-02-21 14:32:36 -07:00
Wez Furlong a1fb96dfc0 add (low|no)_memory_reduction_policy options
These provide more control over the memory vs spool IO tradeoff
when memory is short.
2025-02-21 10:48:14 -07:00
Wez Furlong 4ed60d30a1 docs: update for release 2025-01-29 17:05:37 -07:00
Wez Furlong e474516b01 add reconnect_strategy option
This controls what we do in an smtp session when we experience a
disconnect during message sending; do we give up on the session,
continue with the connection plan, or try to connect to the same
host again and continue sending any additional messages there?
2025-01-24 13:43:49 -07:00
Wez Furlong 01c52eef03 docs: update for 2025.01.23-7273d2bc release 2025-01-23 13:49:35 -07:00
Wez Furlong bb66d06169 docs: add opportunistic_tls_reconnect_on_failed_handshake to changelog 2025-01-23 07:32:08 -07:00
Wez Furlong c215ed9c2f rfc5321: add enable_rset and enable_pipelining options
These control whether we'll use RSET and/or PIPELINING when
sending via SMTP.
2025-01-23 07:20:00 -07:00
Wez Furlong 44c0c029e4 throttle: introduce LimitSpec and force_local mode
This brings parity with ThrottleSpec in allowing for explicitly
local limits, even when redis sharing is enabled.
2025-01-06 06:53:12 -07:00
Wez Furlong 8be4ad82a1 add basic outbound LMTP support
This enables LMTP over TCP by setting `use_lmtp = true` in the
egress path configuration.

refs: https://github.com/KumoCorp/kumomta/issues/267
2024-12-17 06:48:52 -07:00
Wez Furlong 05295e415a add opportunistic_tls_reconnect_on_failed_handshake option
When used together with an Opportunistic TLS mode, if the handshake
or subsequent EHLO fails, we will re-connect to the current host
and disable TLS.

This is implemented as a recursive solution, which I'm not totally
keen on, but the recursion is limited to a single level so it's
not so bad.
2024-12-16 15:20:13 -07:00
Wez Furlong 38fd692e94 docs: show how to skip IPv6
I was halfway through adding special purpose options for this,
but I realized that skip_hosts already exists for this function
and is much more flexible.

Add an example to the docs to show how it can be done.
The same technique can be used to skip using IPv4 if that is
desired (despite being impractical with the current state
of SMTP on ipv6), but using `0.0.0.0/0` as an entry in the
skip_hosts list.

closes: https://github.com/KumoCorp/kumomta/issues/317
2024-12-04 07:33:50 -07:00
Wez Furlong cf911c4067 docs: update dev -> 2024.11.08-d383b033 2024-11-12 12:25:53 -07:00
Wez Furlong d3e399cfda docs: describe the configuration monitoring and epoch system 2024-11-08 07:14:03 -07:00