Commit Graph
1039 Commits
Author SHA1 Message Date
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 Caiandncai 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
Mike Hillyer 77832e81a6 Typo 2024-12-12 13:59:35 -05:00
Wez Furlong c13dde9ecb message: introduce intrusive MessageList type, replace Fifo internals
I've been recently troubleshooting a couple of systems with high memory
usage, and in one of them there were very large amounts of
memory being allocated to ready queues.  That could be partially
mitigated by reducing `max_ready` to a more reasonable and small value,
but it is difficult to compute the right balance between large-enough
for high throughput and small-enough to keep memory usage reasonable.

This commit switches away from crossbeam's ArrayQueue, which
pre-allocates sufficient space to hold exactly `max_ready` messages for
each instantiated ready queue, and to a newly introduced MessageList,
which is an intrusive doubly-linked list.

The intrusive list, in exchange for some small additional overhead
per-Message, requires no auxilliary additional memory allocations to
track the membership of that Message in some other list.

That means that `max_ready` is no longer a pre-allocated minimum amount
of additional storage, and changes the memory overhead from
`O(number-of-queues * max_ready)` to `O(number-of-ready-messages)`,
which is typically a lot smaller.  This is independent of the individual
messages metadata and bodies that are nominally associated with being in
a ready queue.
2024-12-10 14:29:41 -07:00
Wez Furlong 8689d4daf0 docs: document new TSA Bounce actions
closes: https://github.com/KumoCorp/kumomta/issues/272
2024-12-09 07:27:14 -07:00
Wez Furlong 6da455d42b kumod: process TSA Bounce rules and apply as bounces
Accepts scheduled queue bounce events from the event subscription,
and translates them into local admin bounce records.

refs: https://github.com/KumoCorp/kumomta/issues/272
2024-12-09 07:15:45 -07:00
Wez Furlong 80c61ec3df tsa: add plumbing to support new Bounce action
Full docs will be written up once the kumod side is done.

This commit:

* Adds a table to record bounces
* bounces can be scoped to scheduled queues (not ready queues) keyed
  either by:
   * domain
   * domain + tenant
   * domain + tenant + optional campaign

Rather than define one websocket endpoint per event type, define
a new endpoint that can support more than just suspensions.

The existing suspension endpoint taps into the same source of
events, but filters it down to just suspension data for
backwards compatibility.

The integration tests for kumod+tsa that validate suspensions
continue to operate correctly with this change, proving that
this works.

In the next commit, the client side will be adjusted to be aware
of the bounces on the new endpoint in a way that will tolerate
version splay during deployment.

One thing I noticed while implementing this is that we were not
reporting the list of scheduled q suspensions in the initial
websocket (re)connection.  This would impact newly restarted
kumod instances the most, but they would eventually right
themselves because the node that missed the data would likely
pass traffic that would trigger the rule anew, or they wouldn't
and it wouldn't matter anyway.

refs: https://github.com/KumoCorp/kumomta/issues/272
2024-12-09 06:17:31 -07:00
Wez Furlong c92cff2a60 maildir: support template expansion of maildir_path
closes: https://github.com/KumoCorp/kumomta/issues/109
2024-12-08 10:15:53 -07:00
Wez Furlong 1a83f72b6d maildir: expose dir_mode and file_mode to protocol config
You can now specify the dir and file modes in your maildir
protocol configuration.

refs: https://github.com/KumoCorp/kumomta/issues/109
2024-12-08 09:41:55 -07:00
Mike Hillyer 3a3ba78969 Typo. 2024-12-05 15:22:03 -05:00
Mike Hillyer 415b1736ed Add a note about throttles and webhooks. 2024-12-05 14:45:52 -05:00
Wez Furlong 2dca79ad9b dns-resolver: add metrics around MailExchanger::resolve 2024-12-04 09:19:22 -07:00
Wez Furlong 20ad646514 smtp_server: move listener domain cache to be scoped per connection
This fixes an issue where the cache being scoped globally could allow
the same IP/domain combination to appear to be satisfied by an earlier
authenticated session with the same IP/domain combination, for a period
of 60 seconds (the default TTL that we used for that cache).

This commit moves the cache to be smaller and more focused in scope;
now each session remembers the last few domains (bounded, to avoid
a trivial DoS by a malicious client) made on it.

closes: https://github.com/KumoCorp/kumomta/issues/320
2024-12-04 08:23:46 -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 e5127cb24b queue: route most ready-queue-insertion errors via requeue_message event
Previously, we would only trigger the requeue_message event in
situations where we were actively working on talking to the destination.
That left issues such as persistently NXDOMAIN destinations as being
unable to be caught and handled by the requeue_message event, which is
an issue for sites that want to fail out messages from the queue that
have bogus domains before they reach max_age.

This commit replaces all but one of the force_into_delayed calls with
requeue_message, and makes the call out to the event unconditional
(rather than dependent upon whether we were incrementing retries or
not).

The only case now that doesn't cause requeue_message to fire is when the
ready queue is full. The rationale is that that is a transient local
resource issue (rather than some external factor to which we need to
react), and that is likely to be a hot event when it triggers, so we
don't want to add CPU pressure with calling out to the requeue event for
them.

refs: https://github.com/KumoCorp/kumomta/issues/319
2024-12-03 13:01:42 -07:00
Wez Furlong 4a0a4d6a1e queue.rs: fix occasional accidental delay
The timerwheel achieves its cheap insertion and removal by
bucketing events with a slight loss in precision.

It is possible for messages to be popped because they are due "now", but
the precise now value for any given message might still be a small
number (tens) of milliseconds in the future.

Separately from this, there is logic that checks to see if the various
throttling related events have delayed any messages and will reinsert
those messages into the scheduled queue.

That logic can be falsely triggered by the slight imprecision and
cause a message to miss its true scheduling window.  I've observed
this case manifest in the retry_schedule test case.

This commit deals with this case by ensuring that we wait until all
of the due messages are really due; in practice this is either 0ns
or ~20ms.
2024-12-03 12:54:24 -07:00
Wez Furlong 1da8c390da validate-shaping: ensure that we have at least one file to validate 2024-11-27 18:30:56 -07:00
Wez Furlong a2f8a1007b remove stale comment 2024-11-22 09:42:10 -07:00
Wez Furlong 17fafff1c8 adopt more compact representation of ResolvedAddress in logs/diagnostics
Previously we'd use the Debug impl of ResolvedAddress, which rendered
like `ResolvedAddress { name: "some.host.", addr: "10.0.0.1" }`, which
is a bit heavyweight when it shows up in a log where we're indicating
that none of the hosts could be connected.

This commit adds a Display impl that renders that same struct in a
more compact form: `some.host./10.0.0.1`.
2024-11-22 08:54:12 -07:00
Wez Furlong b1484c405e queue: check for expiration even if we're not incrementing retries
This should help to age out messages in pathological cases where
the bulk of the messages are not actually being attempted, but
rather being requeued due to excessive connection failures or
other bulk queue operations.
2024-11-20 16:17:56 -07:00
Wez Furlong e85f2c245a update unbound, fixup DNS port number propagation
closes: https://github.com/KumoCorp/kumomta/issues/314
2024-11-19 10:57:49 -07:00
Wez Furlong 6c8a1882e5 docs: changelog for #316
closes: #316
2024-11-19 08:16:16 -07:00
Wez Furlong 70583302ee add session_id to LogRecord and thread through
refs: https://github.com/KumoCorp/kumomta/issues/316
2024-11-19 08:12:13 -07:00
Wez Furlong f75e0edc0f ignore remember_broken_tls when tls policy is required
This makes it easier to set a default for remember_broken_tls
without it causing issues for sites that have a transient blip
with TLS, when TLS is set to required for those sites.
2024-11-15 15:10:14 -07:00
Mike Hillyer 25bace1f30 Update custom.html
Bye Bot
2024-11-13 13:15:31 -05:00
Mike Hillyer 6ea55a8709 Add pattern matching rollups to the changelog. 2024-11-13 10:42:48 -05:00
Wez Furlong 971612a7d2 docs: add section about memory management 2024-11-12 13:30:10 -07:00
Wez Furlong e06a4a9049 docs: rotate changelog for 2024.11.08-d383b033 2024-11-12 12:28:40 -07:00
Wez Furlong cf911c4067 docs: update dev -> 2024.11.08-d383b033 2024-11-12 12:25:53 -07:00
Wez Furlong d383b033cf docs: add a refman section for template syntax 2024-11-08 10:37:08 -07:00
Mike Hillyer 00ccd5d69c Update the add_authentication_results page to show SPF as well as DKIM. 2024-11-08 11:11:28 -05:00
Wez Furlong d3e399cfda docs: describe the configuration monitoring and epoch system 2024-11-08 07:14:03 -07:00
Wez Furlong d33aa15c40 docs: add note about the null queue not actually being a queue 2024-11-08 05:32:37 -07:00
Wez Furlong f74f0a7556 add ehlo_domain to the set of predefined connection metadata values 2024-11-08 05:27:02 -07:00
Wez Furlong ea53531bc6 rocks: purge memtables when memory is low, export metrics
Export the memory statistics for each spool database to prometheus for
charting and tracking.

Allow the hosting application to request a cache purge and set up a
monitor task to do that when memory usage is too high.  That step will
print the memory that it reclaimed when it kicks in.
2024-11-07 16:29:11 -07:00
Mike Hillyer 6f154f6f3c Add information on trace-smtp-client to the kcli page of the User Guide. 2024-11-07 16:29:16 -05:00
Wez Furlong d12bda6ee6 docs: changelog for SPF
closes: #83
2024-11-07 08:27:13 -07:00