Commit Graph

1074 Commits

Author SHA1 Message Date
Wez Furlong 4ed60d30a1 docs: update for release 2025-01-29 17:05:37 -07:00
Wez Furlong 833f82a818 egress_source: fix potentially stale rr state when config changes
Previously, we would compare only the names of the pools when
updating the round robin source selection state.

That meant that if you change the composition of a pool by changing
either the number of the definition of its constituent sources,
that change may not take effect until the corresponding queues
had aged out.

This commit resolves this by comparing both the name and the
composition of the pool when deciding to rebuild the source
selection state.
2025-01-29 12:38:38 -07:00
Wez Furlong 8042f7b07a config: invalid pooled lua context when epoch changes
I noticed while testing the throttle serialization commit
that precedes this one that my directly-in-the-lua-file config
changes weren't being picked up when the config epoch changed.

This commit revises the pooling logic to also check the epoch
in addition to the age of the pooled entries.
2025-01-29 11:24:36 -07:00
Wez Furlong 04a1777727 docs: changelog for #329 2025-01-29 10:28:54 -07:00
Wez Furlong ea8f2be678 docs: add weird period example to throttle docs 2025-01-29 09:45:04 -07:00
Wez Furlong 87e0939f43 throttle: expose max_burst throttle spec
This was always present, it just wasn't something we provided a syntax
to specify.

max_burst allows you to control how quickly your throttle budget will
be consumed over the throttle time period.

The default max_burst is equal to the limit you specify, allowing
the full budget to be instantaneously consumed.

refs: https://github.com/KumoCorp/kumomta/issues/326
2025-01-29 09:22:57 -07:00
Wez Furlong e3b3bfefb3 docs: changelog for #328 2025-01-28 10:35:58 -07:00
Wez Furlong d224feb62f tracing: enable server-side processing of terse flag
Cutting down on the data being transmitted can reduce the number
of lag events.

Increase the channel buffer size as well while we're in here.
2025-01-28 10:35:19 -07:00
Wez Furlong 399c8505ae avoid potential cache thrashing issue with remember_broken_tls
A customer reported a really long log record like:

```
KumoMTA internal: failed to connect to any candidate hosts: TLS
handshake failed: tls handshake eof, will re-connect in the clear
because opportunistic_tls_reconnect_on_failed_handshake=true, TLS
handshake failed: tls handshake eof ...
```

the site in question had just a single address in its connection plan.

I don't see how we could loop like this unless the cache that is
used to indicate that TLS is broken is being thrashed and the value
that we write to it in response to this event triggering is
never actually sticking in the cache.

This commit introduces a per-session variable to flag that TLS
is broken for this particular site, so that we don't have to rely
on the cached value when we're about to loop and retry.
2025-01-24 19:34:11 -07:00
Wez Furlong f9d8ceee9d inspect-sched-q: add now time to the response
This is useful when sanity checking the due times vs. the current time
2025-01-24 15:28: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 54e809dc93 smtp_dispatcher: fix incorrect reuse of closed connection
In the smtp client we internally map IO and timeout errors into
a NotConnected state and break its internal socket, prevent it
from trying to talk to a broken session.

In the dispatcher layer that sits above it, when we consider
whether we need to open a connection, we look only to see if
we have a connection open or not.

If that connection is in a broken state we would keep trying to
use it, because we didn't consider that it might have such
an internal broken state.

This commit fixes up that logic so that we realize that it is
broken, and allow us to move to the next host in the connection
plan.
2025-01-24 13:43:49 -07:00
Wez Furlong b29cea10f4 rfc5321 client: fix rset regression 2025-01-24 13:43:49 -07:00
Mike Hillyer c606ac8244 Update changelog title for consistency. 2025-01-24 11:50:14 -05:00
Wez Furlong 6841841283 first run at an inspect-sched-q command
This can return a sample (or all) of the messages as well as
some additional queue metadata for a named scheduled queue.

refs: #231
2025-01-23 17:10:41 -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 b8752b23b1 docs: mention LMTP support
refs: #267
2025-01-20 08:32:48 -07:00
Wez Furlong cf6f3540e7 Add new Delay log record type
The purpose of this record is to log additional context about why
a message might end up in the scheduled queue when it hasn't
logged a TransientFailure.

There are a few situations around handling throttles and limits
where we might put a message back into the scheduled queue, without also
logging a TransientFailure record. It's possible that we should
reconsider some of those, but for the moment, there is an observability
hole that needs to be filled.

What this commit does is introduce an `InsertContext` which can hold one
or more `InsertReason`s about why a message is being inserted into the
scheduled queue.

There are 3 primary reasons for insertion:

* Received - the message was just received/injected
* Enumerated - the message was discovered in spool enumeration
* DueTimeWasReached - the message is now due for delivery and is being
  popped off the scheduled queue

The additional reasons can be added to the context to provide more
color about what happened.

When a message is added to the scheduled queue, the accumulation
in the InsertContext is examined, and if the context doesn't
indicate that the message was Enumerated and it wasn't also
already logged as a TransientFailure, a `Delay` record is
logged.

The `Delay` record includes in its `response.content` the ordered set of
InsertReasons as well as the delay duration and due time.

Logging Delay records might place undesirable pressure on the
logging storage, so you may wish to disable it via:

```lua
kumo.configure_local_logs {
  per_record = {
    Delay = {
      -- Suppress Delay records
      enable = false
    }
  }
}
```

or similar.
2025-01-17 13:21:47 -07:00
Wez Furlong 9770d333b5 egress_source: allow empty egress pools
We said that this worked, and while it does in the code,
we wouldn't allow you to deserialize an empty list of sources.
2025-01-16 11:46:05 -07:00
Wez Furlong 12895496be tsa: fix automation rules with multiple SetConfig actions
Only the first would take effect because the rule_hash we
computed included all of the actions, so each individual
action would appear to be a duplicate of the first.

This commit ensures that we vary the hash per-action
to avoid this, and augments the integration test
to explicitly verify the result.
2025-01-15 14:41:50 -07:00
Wez Furlong ed93a0e592 rfc3464: transfer-decode delivery-status parts
This fixes an issue where such a part was encoded in base64
and failed to parse.
2025-01-13 09:48:49 -07:00
Wez Furlong c1575bba6d docs: mention that timer:done() returns seconds
I didn't include this in the recent code change that added the
return value.
2025-01-11 06:52:10 -07:00
Wez Furlong 9e823dc352 add kumo.time lua module, with new timer object
The timer object can track latencies in lua code and is helpful for
ad-hoc, explicit "profiling" in your policy script: the latencies are
exported via a prometheus histogram.
2025-01-09 15:36:30 -07:00
Wez Furlong ebd9a0002e fix: egress pool change wouldn't take effect until age out
I noticed this while reading through the code; we were not updating the
round robin state which we maintain based on the configured egress pool
if the config updates and changes the pool.

We resolve this here by using an arcswap to keep a read-only reference
to the state; since has some async portions it is important to allow it
to continue its management of interior mutability so that it doesn't
acquire a mutex while awaiting on async state.
2025-01-09 12:02:47 -07:00
Wez Furlong 49eb0a634c smtp_server_ehlo: pass in and allow returning a list of extensions
This is helpful in situations where you need to do things that
are not strictly supported but might just happen to squeak by
if support is claimed for them.
2025-01-09 11:03:11 -07:00
Wez Furlong 4375958da2 docs: tag available_parallelism with threadpool 2025-01-08 16:00:17 -07:00
Wez Furlong cd2fea5d99 docs: fix typo on configure_unbound_resolver page 2025-01-08 15:55:04 -07:00
Wez Furlong 1b82b54bc8 docs: tag set_logging_threads too 2025-01-08 15:54:05 -07:00
Wez Furlong 2dc9b2b319 docs: setup tags to find threadpool related options 2025-01-08 15:52:06 -07:00
Wez Furlong d436c08858 docs: add kumo.dkim.set_signing_threads
This was added in the last release, but the docs were overlooked.
2025-01-08 15:32:08 -07:00
Wez Furlong 58a4b9921a docs: format recent kafka changes 2025-01-08 15:31:38 -07:00
Wez Furlong dc5b06d072 docs: mention maintain connection limit behavior change 2025-01-07 06:53:44 -07:00
Wez Furlong 1b4058944d docs: changelog for #324 2025-01-07 06:51:10 -07:00
Wez Furlong 7390f3111a mailparsing: fix qp_encode with UTF-8 subsequences containing 0x20
With a specific farsi input string, there are one or more codepoints
that encode with 0x20 as part of their subsequence.  The qp_encode
function would confuse those with a space and produce the wrong
output.

This commit fixes that by having the encoder iterate by codepoint
rather than by byte, and then emit the appropriate byte sequences
from there.
2025-01-06 11:02:26 -07:00
Wez Furlong 313a084c29 mailparsing: fix construction of Mailbox name containing @
We need to ensure that we quote the name portion of a mailbox
if it contains an @-sign in order for the resulting mailbox to
be valid.

quoting here means that the name is enclosed in quotes, but
not that the @-sign is itself quoted with a backslash, so
we have a little hard-coded special case in the string
quoting function for this.
2025-01-06 07:06:53 -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
Nathalie Cai a3c7fe7d00 add send_batch method to kafka mod (#324)
* add send_batch method to kafka mod

* add error messages to returned value and don't log it as error

* add kafka send_batch doc

---------

Co-authored-by: ncai <ncai@chapsvision.com>
2025-01-03 09:57:40 -07:00
Wez Furlong 4909fe8e55 mailparsing: implement own text wrapping function
A user reported that constructing certain UTF-8 From headers
in the HTTP injection API could produce a From header that
could not be parsed by the DKIM helper when subsequently
attempting to sign the message.

The issue was that the textwrap crate will try to fill out
the wrap, preferring to break an existing word rather than
generating a new line to accommodate one when it would
produce a line that was too long.

This commit adds our own text wrapping algorithm that is
more forgiving.
2024-12-31 10:07:02 -07:00
Wez Furlong ff8c0ccff2 Expose ready queue states via api, and in kcli queue-summary
This adds connection limit/throttle states to the readyq rows
in `kcli queue-summary`, alongside where we would show the
suspension state.

This makes it easier to understand when a given egress path
might be hitting connection limits.
2024-12-21 07:44:29 -07:00
Wez Furlong 02fc8458f9 fix connection rate being limit to 1/10min when limit hit
The issue here is:

* If a connection limit was hit (eg: TooManyLeases) then the
  readyq maintainer completes its work for that one wakeup
* readyq maintainer then goes to sleep until either 10 minutes
  have elapsed, or a new message is moved into the ready queue
* If the system either has no new messages being injected to
  that queue, or all of the messages are currently ready,
  then those messages will camp out in the ready queue until
  10 minutes have elapsed before we try to make another connection.

This hampers the rate of egress.

What this commit does is:

* Introduce a QueueState concept where we can indicate a kind of
  "status effect" that applies to a queue. The state has some
  human readable context and a time for when the effect was
  most recently observed.
* Adds a `connection_limited` state to indicate when we've hit a
  connection limit and a `connection_rate_throttled` state when we've
  hit the max_connection_rate.
* The ready queue maintainer will reduce its wakeup interval
  if it observes that connections have been limited, so that
  we can wakeup sooner.

In a separate commit, an API endpoint will be added to expose
these queue states and augment the summary command output.
2024-12-21 06:53:51 -07:00
Mike Hillyer a1c82b3618 Add resolve-shaping-domain to the Userguide and FAQ. 2024-12-20 16:19:32 -05:00
Wez Furlong 39bbc0953e switch to DeferredInjectionRebind for deferred->fully realized
It's confusing to have 2 Delivery records, even if there are other
fields that distinguish between the events.
2024-12-19 10:14:26 -07:00
Wez Furlong cc90c278fa docs: fixup mermaidjs issue
This used to work fine, but recently started to bleed through
some control characters

closes: https://github.com/KumoCorp/kumomta/issues/323
2024-12-18 06:41:45 -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 44eacf1807 providers: add HostName to enable exactly matching MX hostnames 2024-12-16 14:09:01 -07:00
Wez Furlong 48e89105a7 fix provider rule matching with MXSuffix
Given a provider with the following config:

```json
      "match": [
        {
          "MXSuffix": "mta5.am0.yahoodns.net"
        },
        {
          "MXSuffix": "mta6.am0.yahoodns.net"
        },
        {
          "MXSuffix": "mta7.am0.yahoodns.net"
        }
      ]
```

(Note that this configuration is not ideal because someone with
`notreallymta5.am0.yahoodns.net` in their MX records will match
this.  If you were using SMTP auth for such a site, then you risk
leaking your credentials to it! We should consider adding an exact
match option for this case)

we could never match this because the logic had the inner and outer
loops swapped.

For a provider to match, all of the resolved host names must match
at least one of the MXSuffixes defined in the rule.

The flipped logic prevented that from matching.

Most of this commit is adding stuff to help trace this down
and debug it.

In particular, `resolve-queue-config` will tell you what the
effective value of the get-queue-config event is for a given
queue name, and `resolve-shaping-domain` will show you the shaping
configuration for a (bogus) source.
2024-12-16 12:46:31 -07:00
Wez Furlong 5f19f7ce04 add deferred_queue option to the smtp listener
This option should be used with caution, and ideally only
for trusted networks.

The purpose is to absorb the latency of post-DATA processing
and hide it from the trust injector.

It defers processing that would normally happen in smtp_server_message_received
and instead will, at some (ideally) near-future time trigger an
smtp_server_message_deferred_inject event instead.

This will marginally increase your average injection latency but should
clamp your worst case injection latency much lower because the outliers
will not happen inline with the injecting client.
2024-12-16 11:27:40 -07:00