mirror of
https://github.com/KumoCorp/kumomta.git
synced 2026-09-05 16:00:57 +00:00
116 lines
3.9 KiB
Markdown
116 lines
3.9 KiB
Markdown
# smtp_server_split_transaction
|
|
|
|
{{since('2025.12.02-67ee9e96')}}
|
|
|
|
```lua
|
|
kumo.on('smtp_server_split_transaction', function(message, conn_meta) end)
|
|
```
|
|
|
|
Called by the ESMTP server to decide whether and how to split the recipient
|
|
list into groups of recipients at the same destination site.
|
|
|
|
SMTP messages can have an envelope that includes multiple recipients. Each
|
|
recipient will receive a copy of the message. If multiple recipients share the
|
|
same mailbox provider then it is advantageous from a bandwidth and efficiency
|
|
perspective to relay that message to that provider as a single message with a
|
|
list of multiple recipients, rather than sending one distinct copy per
|
|
recipient.
|
|
|
|
This event gives you control over how the incoming transaction is split and the
|
|
recipients are grouped together.
|
|
|
|
You do not need to implement this event handler in the vast majority of cases!
|
|
Look at
|
|
[start_esmtp_listener.batch_handling](../kumo/start_esmtp_listener/batch_handling.md)
|
|
for a much simpler way to express the most common choices.
|
|
|
|
You can use [message:recipient_list](../message/recipient_list.md) to retrieve
|
|
the recipient list from the message. That might give you something like:
|
|
|
|
```
|
|
{ 'fred@gmail.com', 'pete@gmail.com', 'joe@hotmail.com' }
|
|
```
|
|
|
|
(but each element is an [EnvelopeAddress](../address/index.md) rather than a string).
|
|
|
|
The return value must be an array of arrays of addresses. For example, if you
|
|
wish to recreate the `batch_handling = "BifurcateAlways"` mode of operation,
|
|
the shape of the result will look like this:
|
|
|
|
```
|
|
{
|
|
{ 'fred@gmail.com' },
|
|
{ 'pete@gmail.com' },
|
|
{ 'joe@hotmail.com' }
|
|
}
|
|
```
|
|
|
|
If you wish to recreate the `batch_handling = "BatchByDomain"` mode of operation,
|
|
it will instead look like this, with all of the gmail addresses in the same
|
|
top level array:
|
|
|
|
```
|
|
{
|
|
{ 'fred@gmail.com', 'pete@gmail.com' },
|
|
{ 'joe@hotmail.com' }
|
|
}
|
|
```
|
|
|
|
Returning `nil` (or not explicitly returning anything) from
|
|
`smtp_server_split_transaction` will cause the `batch_handling` option to be
|
|
consulted to decide how splitting/batching will occur.
|
|
|
|
When a multi-recipient message is routed onwards, the domain of the first
|
|
recipient is used to resolve the MX and decide which host to connect to. In
|
|
the example above, `fred@gmail.com` will be used to resolve routing for the
|
|
first batch, while `joe@hotmail.com` will be used to resolve routing for the
|
|
second batch.
|
|
|
|
!!! warning
|
|
While you can create arbitrary batches with this event handler, if you
|
|
create non-sensical batches you should expect for messages to fail to
|
|
deliver. For example, if you group `user@gmail.com` together with
|
|
`other.user@hotmail.com` then when the message is attempted, gmail (from
|
|
the first recipient) will likely reject the hotmail address because gmail
|
|
is not responsible for and may choose not to relay the hotmail recipient.
|
|
|
|
!!! note
|
|
This event is called even if the recipient list has a single entry
|
|
|
|
It is technically possible to synthesize additional recipients by including
|
|
them in the returned list of batches, but it is recommended that you perform
|
|
recipient list modification in the [smtp_server_data](smtp_server_data.md)
|
|
event rather than this event.
|
|
|
|
## Example: equivalent to batch_handling=BifurcateAlways
|
|
|
|
Every incoming recipient is placed into a separate batch and tracked separately.
|
|
|
|
```lua
|
|
kumo.on('smtp_server_split_transaction', function(message, conn_meta)
|
|
local split = {}
|
|
for _, recip in ipairs(message:recipient_list()) do
|
|
table.insert(split, { recip })
|
|
end
|
|
return split
|
|
end)
|
|
```
|
|
|
|
## Example: equivalent to batch_handling=BatchByDomain
|
|
|
|
Recipients with exactly the same domain portion are grouped together.
|
|
|
|
```lua
|
|
kumo.on('smtp_server_split_transaction', function(message, conn_meta)
|
|
local by_domain = {}
|
|
for _, recip in ipairs(message:recipient_list()) do
|
|
local domain = recip.domain:lower()
|
|
if not by_domain[domain] then
|
|
by_domain[domain] = {}
|
|
end
|
|
table.insert(by_domain[domain], recip)
|
|
end
|
|
return by_domain
|
|
end)
|
|
```
|