84 Commits

Author SHA1 Message Date
Wez Furlong 332595ee2a queue.lua: add typing to setup methods
We had an issue where a typo resulted in a relatively inscrutable
error at runtime:

```lua
local queue_helper =  queue_module:setup ('/opt/kumomta/etc/policy/queues.toml')
```

produced this:

```
problem initializing: call validate_config callback: runtime error: /opt/kumomta/share/policy-extras/queue.lua:602: bad argument #1 to 'for iterator' (table expected, got nil)
stack traceback:
        [C]: in function 'next'
        /opt/kumomta/share/policy-extras/queue.lua:602: in function </opt/kumomta/share/policy-extras/queue.lua:551>
Error: Initialization raised an error: call validate_config callback: runtime error: /opt/kumomta/share/policy-extras/queue.lua:602: bad argument #1 to 'for iterator' (table expected, got nil)
stack traceback:
        [C]: in function 'next'
        /opt/kumomta/share/policy-extras/queue.lua:602: in function </opt/kumomta/share/policy-extras/queue.lua:551>
```

with the changes in this commit we'll present this issue like this,
during server startup, which points a little more clearly at the setup
call and the file names parameter, and suggests more strongly that it
should be a list of strings (or config objects):

```
    runtime error: [string "./simple_policy.lua"]:52: assets/policy-extras/queue.lua:463 QueueHelperSetup: invalid value for field 'file_names'
    assets/policy-extras/queue.lua:463 Expected value of type 'list<variant<string,QueueHelperConfig>>' but got type 'string' '/opt/kumomta/etc/policy/queues.toml'
    stack traceback:
        [C]: in function 'error'
        assets/policy-extras/typing.lua:78: in method 'raise'
        assets/policy-extras/typing.lua:249: in metamethod 'newindex'
        assets/policy-extras/typing.lua:258: in function <assets/policy-extras/typing.lua:253>
        (...tail calls...)
        assets/policy-extras/queue.lua:463: in function 'policy-extras.queue.setup_with_options'
        (...tail calls...)
        [string "./simple_policy.lua"]:52: in main chunk
```

this change actually surfaced a minor issue in the ndr.lua file that is
part of an integration test, as well as in my adhoc simple_policy file.
2026-03-04 09:23:08 +00: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
Pankaj Rathi 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
Mike Hillyer 58e9770206 We miss you Mister Rogers. 2025-07-18 12:11:14 -04:00
Wez Furlong 3e9bc5a946 smtp_server: introduce new peer matching option to start_esmtp_listener
This allows crafting peer-address-specific values for a listener.
2025-03-22 10:35:42 -07:00
Wez Furlong 3d22151d14 add SingletonTimerWheelV2 strategy option
This uses our new leaner timeq data structure; that has lower
memory overhead and is a bit more efficient at ticking.

It is not the default at this time, but ideally will become
the default in the future once it has been proven out.
2025-02-06 13:38:06 -07:00
Wez Furlong dbcc831b82 simple_policy: tweak my test config for more throughput 2024-12-10 14:49:12 -07:00
Wez Furlong 65b51b2ec5 simple_policy: adjust for networking changes 2024-10-21 07:57:32 -07:00
Wez Furlong fbd794782a bounce classifier: reload classifier when config epoch changes
This change plugs the bounce classification layer into the config
epoch layer, so that when a change in the configuration is detected,
we reload the classifier using the previously established parameters
and then arrange for the classifier threads to wake up and update
their local classifiers from that updated state.

refs: https://github.com/KumoCorp/kumomta/issues/298
2024-10-09 08:18:00 -07:00
Wez Furlong 64fac57d09 formalize provider information for queues, add to logs
The recent changes to enable shaping based on a pattern-matched provider
are nice, but it is important to be able to observe their effects.

So far this has been awkward because the provider concept was purely a
function of the logic in the shaping.lua file and nothing else.

This commit introduces the concept of a `provider_name` field in
both the EgressPathConfig and QueueConfig structs.

The idea is that the `get_egress_path_config` and `get_queue_config`
events are free to populate this field as makes sense to them, so that
the core is then aware of which provider is associated with those
queues.

Once we have that data, we're then able to log it as a field in the
JsonLogRecord.

That is what this commit does. There are some interesting points to note
about the implementation here:

1. shaping.lua will implicitly assign provider_name if it matches
   any providers.

2. It is technically possible for a shaping.toml to define multiple
   providers that match a given domain. In that circumstance, the
   last matching provider is the winner when it comes to assigning
   the provider_name field.

3. In order to populate the provider_name in the queue.lua helper,
   we need to be able to call out to the get_egress_path_config
   event handlers, so a new kumo.invoke_get_egress_path_config
   has been added to support that.

4. kumo.invoke_get_egress_path_config isn't 100% done: there are
   a couple of fields (openssl related) that don't have a defined
   serializer, so we're simply omitting them.  The function is
   "done enough" for the purposes of retrieving the provider_name

refs: https://github.com/KumoCorp/kumomta/issues/276
2024-09-12 20:51:00 -07:00
Wez Furlong a7f5326c15 fix code formatting 2024-09-11 11:00:24 -07:00
Wez Furlong a412757513 Add smart-sink example docker compose
Adds an example docker compose file that can be used to quickly
stand up an SMTP sink service that is useful when load testing
an SMTP server.

The sink has configurable and "realistic" bounce response rates,
so that you can excercise queue growth scenarios.
2024-09-10 08:00:06 -07:00
Wez Furlong 4fa23e9a7d http injector: add deferred generation
There's big explanation about this in the included docs change.

The TL;DR is: we can now optionally queue the request and generate it
asynchronously wrt. the incoming injection request.

There's also a throttle that can be used to constrain this, because
the asynchronous submission disconnects the injection request from
any kind of back pressure that we'd otherwise have to indicate to
the injector that there might be load related issues.
2024-09-06 10:12:33 -07:00
Wez Furlong a89e9455ec simple_policy: tone down the number of queues
I don't need to have millions by default any more :)
2024-09-02 10:42:40 -07:00
Wez Furlong baefa4651f ready_queue: add epoch and refresh_interval options to path config
This commit changes the config refresh strategy for ready queues
to be similar to that of scheduled queues; there is now a per-queue
refresh_interval possible, as well as the ability to select Epoch
based refreshes.

Shaping will use Epoch when TSA is not in use; a future commit
will enable Epoch for TSA.
2024-09-02 10:42:14 -07:00
Wez Furlong 179e075d9e simple_policy: make http and smtp injection do the same processing 2024-08-15 10:09:18 -07:00
Wez Furlong 9a9443be71 logs: add source_address field to SMTP client logs
Previously we would log the pool and source name, but it is
desirable to also log the underlying socket address information,
so here we go!

refs: #40
2024-07-12 08:39:15 -07:00
Wez Furlong b003e49c9c rfc5321: split out banner_timeout from connect_timeout
The motivation for this is:

My test environment is not permitted to reach outbound port 25.
If I run an ad-hoc test without setting up an explicit sink,
I end up with messages that try to reach the public internet.
Since they are blocked at a firewall, each of the MX hosts in
the connection plan is subject to a 60s wait before trying the next
thing.

In addition, this can cause the shutdown to take longer while
we wait for the in-flight delivery attempts to complete.

Making a separate configuration option allows the local administrator
to decide how to split the time waiting for a connection from
the time waiting for the banner.

refs: https://github.com/KumoCorp/kumomta/issues/196
2024-07-12 07:54:43 -07:00
Wez Furlong a00e8d0f0a NEW: add tracing to smtp client, kcli trace-smtp-client
It is now possible to trace outbound SMTP sessions, filtering
by a variety of properties.

Details are in `kcli trace-smtp-client --help` and also in
the docs at /reference/kcli/trace-smtp-client.md

refs: #87
2024-07-11 08:56:25 -07:00
Wez Furlong 11bbd07f3f listener_domains: add typing and validation
refs: #211
2024-06-28 09:43:38 -07:00
Wez Furlong b9dccf1cc3 add policy-extras.typing lua module
The primary purpose here is to allow defining typed records
for use in our helpers.

The dkim_sign module has been updated to make use of this
to ensure that the correct shape of data has been loaded.
2024-06-26 16:38:22 -07:00
Wez Furlong 39818c1e36 Add validation for dkim_sign helper
refs: https://github.com/KumoCorp/kumomta/issues/211
2024-06-25 12:08:37 -07:00
Wez Furlong 3139be2cfd Add new kumod --validate flag
The purpose is to provide a deeper, offline validation pass
of the policy configuration, prior to deploying and making it
live.

The system behavior changes when in `--validate` mode:

* Listeners, spool and spawned tasks will be silently skipped;
  the parameters will be validated but the primary functions
  of those things will be skipped silently.
* After triggering the `init` event, an additional new `validate_config`
  event (which can be registered multiple times) will be triggered
  to allow lua modules to perform extended validation.
* A module can either raise an error via `error` to immediately report
  a problem, or instead call a new, preferred, `kumo.validation_failed()`
  function to flag validation as failed but allow additional validation
  to be performed and summarized all together.
* Once the `validate_config` event returns, the process will terminate
  with either exit code 0 for a successful validation, or non-zero
  to indicate that something failed.

Validation errors are reported in a human readable form.

This commit adds validate_config event handlers for the following
helper modules:

* `shaping` - any warnings reported by the underlying rust code
  will be reported here and cause validation to fail. This is
  functionally equivalent to using the `validate-shaping` binary,
  except that it will automatically be passed the set of shaping
  files defined by your `init.lua`

  If the `sources` helper is also configured, the list of sources
  referenced by the shaping config will be cross-checked against
  the sources data to confirm that all possible sources are defined.

* `sources` - each listed source and pool will be validated by
  calling `kumo.make_egress_source` or `kumo.make_egress_pool`
  respectively.

  Pool membership will be validated to confirm that every
  listed pool is defined in the sources data.

* `queues` - each domain and tenant that references an egress_pool
  will be cross-checked with the `sources` helper, if the sources
  helper has been configured.

It is now an error to attempt to setup any of the above helpers
more than once.

refs: https://github.com/KumoCorp/kumomta/issues/211
2024-06-25 11:05:04 -07:00
Wez Furlong 403f80ac26 simple_policy/sink: use temporary file for acct db
These files are used by me (wez!) while hacking things together locally
as a non-privileged user (myself).  They should not contribute to the
overall message accounting database.  Let's give each instantiation a
separate temporary path.
2024-03-28 07:14:35 -07:00
Wez Furlong 15b1fab110 checkpoint some local testing/hacking in my test configs 2024-03-27 16:33:17 -07:00
Wez Furlong 7ff5c4115e dkim helper: give a clearer error message when From: header is missing
Previously, we'd just generate an attempt to index `nil` error
message, and the result would be a 421 technical difficulties.

Promote this to a 522 with an explanation about the missing
From header.
2023-12-13 10:21:37 -07:00
Wez Furlong a03fcb2bf1 docs: fix sqlite auth example 2023-11-10 07:01:58 -07:00
Wez Furlong 929d51deba events: plumbing for registering multiple handlers
Previously, we'd restrict `kumo.on` to allowing just a single
instance of an event to be registered. The purpose of this was
to help surface logical errors where copypasta would result in
a bogus configuration.

With multiple helper lua modules now wanting to take responsibility
for some portion of the event handling, it is becoming more complex
to stitch things together.

It is desirable to allow multiple handlers for certain events,
so that a module can handle just its area of responsibility
without worry other modules about it.

This commit introduces a CallbackSignature type that allows
defining the function signature for event callbacks.

The signature can be pre-created and registered ahead of setting
up any lua contexts, which allows declaring whether an event
can have multiple callbacks registered.

The `get_queue_config` event handler has been set to allow multiple
callbacks.
2023-11-02 18:11:17 -07:00
Wez Furlong 4c36489681 First pass at accounting db
This keeps track of the volume of receptions and deliveries over time.
2023-10-12 20:43:58 -04:00
Wez Furlong 3b10d637f9 docs: show how to use dkim verification
refs: https://github.com/KumoCorp/kumomta/issues/82
2023-09-14 13:03:41 -07:00
Wez Furlong 06bb8d0492 add msg:add_authentication_results
This method will prepend an Authentication-Results header
to the message with the specified set of results and
local server name.

We need a more convenient way to default the server name;
ideally we'd pick this up from the listener, but that is currently
awkward in the policy.

refs: https://github.com/KumoCorp/kumomta/issues/82
2023-09-14 13:03:41 -07:00
Wez Furlong e4bb5d674d add msg:dkim_verify()
This method returns an array of AuthenticationResult reflecting
the verification status.

refs: https://github.com/KumoCorp/kumomta/issues/82
2023-09-14 13:03:41 -07:00
Wez Furlong 0b21193b8a add msg:check_fix_conformance()
This is for check and/or fixing message conformance issues.
2023-08-29 16:18:59 -07:00
Wez Furlong a6a711e72f simple_policy: remove rollup from testing policy 2023-08-11 12:36:54 -07:00
Wez Furlong 67b71a8b83 policy-extras: add rollup.lua
This is a prototype of a means for dealing with rolling up microsoft's
domains so that shaping can be applied holistically over both eg:
hotmail.com and outlook.com.

Those domains don't work with our default automatic MX based rollup
because they don't return the same MX hostnames.

Checking this in to make it easier for others to test/evaluate.
In the future, we may find a way to integrate this with our main
shaping helpers.
2023-08-10 11:48:07 -07:00
Wez Furlong 3fd76dd45a introduce routing_domain concept
Augments our queue name format to be
`campaign:tenant@domain!routing_domain`.

The routing_domain is optional.  If the routing_domain is not set, its
effective value is that of the recipient domain.

You can `msg:set_meta('routing_domain', 'bar.com')` to set the
routing_domain for a message, so if the original recipient was
`user@foo.com`, that would cause the computed queue name for it to be
`foo.com!bar.com`.

The routing_domain is used when deciding on the ready_queue name
and destination MXs, so continuing our example, instead of resolving
`foo.com` MX records we'd resolve `bar.com` and deliver to that site.

The `get_egress_path_config` event `domain` parameter is redefined to be
the effective `routing_domain`.

The `get_queue_config` event `domain` parameter is the regular recipient
domain. The `routing_domain` is not currently made available to
`get_queue_config`. If/when we expose it, it will likely be via a
queue name object instead of adding an additional parameter. That would
be a breaking change.

The consequence of not exposing this parameter is that per-message
routing scenarios for the same domain (but different routing domains)
cannot vary the scheduled queue parmeters (eg: retry intervals). Even
though they would have separate scheduled queue instances, those
instances would have the same scheduled queue parameters.  If you need
to be able to do that, then explicitly setting the domain portion of the
queue name would be a way to do that: `msg:set_meta('queue',
'foo.com-via-bar.com!bar.com')`.  `get_queue_config` would then be
called with `domain='foo.com-via-bar.com'` and your policy could then
respond accordingly.
2023-08-10 08:43:20 -07:00
Wez Furlong 8b2584f0f3 simple_policy.lua: tweak data timeouts 2023-06-22 13:25:35 -07:00
Wez Furlong 45c5d011d1 simple_policy.lua: s/max_connections/connection_limit/
use the correct name for this field
2023-06-16 08:47:33 -07:00
Wez Furlong b7c557c31a define_egress_(pool|source) -> make_egress_(pool|source)
Switch the configuration plumbing for pools and sources to be pull-based
rather than push based.

In other words, rather than defining them in the `init` event,
you now need to supply them to the new `get_egress_pool` and
`get_egress_source` events.

Data is cached by default for 1 minute. This allows for new sources
to come into being on-demand, and for data to age out and change
over time, without requiring that the server be restarted.

This commit updates the reference section, but there is some content
in the user guide that refers to the old style of configuration that
will need to be updated.

refs: https://github.com/KumoCorp/kumomta/issues/13
2023-05-30 14:08:07 -07:00
Wez Furlong 278bc81aa0 move shaping -> policy-extras/shaping, and deploy with package
The assets/policy-extras dir is now deployed to
`/opt/kumomta/share/policy-extras` and added to the require path,
so you can do:

```lua
local shaping = require 'policy-extras.shaping'
```

to pull it into your policy.
2023-04-26 14:51:52 -07:00
Wez Furlong b3f3f877df add functions for working with address headers 2023-03-14 18:53:47 -07:00
Wez Furlong 269e0702b4 add SMTP AUTH PLAIN support
Verified via:

```
swaks ... --auth plain --tls --auth-user scott --auth-password tiger
```
2023-03-11 16:23:49 -07:00
Wez Furlong 92a5509af5 update simple_policy for changes to the dkim vault parameters 2023-03-07 14:52:36 -07:00
Wez Furlong 7054fb31c9 switch to using human time for the queue related time intervals 2023-03-06 19:33:05 -07:00
Wez Furlong 00c253a9dd add maildir support
This is to facilitate end-to-end testing to validate that the
right bits come out at the end.
2023-03-06 19:05:49 -07:00
Wez Furlong 30e64c577f tweak simple policy to show sqlite usage for auth 2023-03-06 12:35:25 -07:00
Wez Furlong 0ca585bd5a Optionally use redis for throttles 2023-03-05 10:39:56 -07:00
Wez Furlong 52f7ab6150 add prohibited_hosts and skip_hosts for outbound resolving
While in that part of the code, handle null MX destination domains
(such as `example.com) more nicely.
2023-03-04 10:09:17 -07:00
Wez Furlong 7d76b3d9d7 add support for retrieving signing keys from hashicorp vault 2023-03-03 10:32:16 -07:00
Wez Furlong 35d90a72ab undo changes to simple_policy.lua
I'm not sure if these were intended to be committed, but
back them out so that they don't collide with my testing!
2023-03-01 16:23:45 -07:00