Need help configuring a global authenticated outbound relay (smarthost) in Stalwart 0.16.12. I configured the Relay Route and the Outbound Strategy according to my understanding of the official documentation, but outbound SMTP still connects directly to recipient MX servers.
How to configure a global authenticated outbound relay (smarthost) in Stalwart 0.16.12?I am trying to configure a global authenticated outbound relay (smarthost) in Stalwart 0.16.12.
I created a Relay Route with SMTP authentication and configured the Outbound Strategy so that all non-local recipients use that route.
The relay is reachable and TLS connectivity has been verified.
However, when sending to external recipients, Stalwart still connects directly to the recipient MX server instead of using the configured relay.
The Web UI and CLI both show the relay configuration correctly.
Am I missing an additional configuration step, or should the Relay Route be sufficient for this use case?
Expected Behavior
Every outbound message destined for a non-local domain should be sent through the configured authenticated SMTP relay (smtps.aruba.it:465) instead of being delivered directly to the recipient MX server.
Actual Behavior
The configured Relay Route is ignored.
Instead of connecting to the configured relay host (smtps.aruba.it:465), Stalwart opens a direct SMTP connection to the recipient MX server (for example gmail-smtp-in.l.google.com).
Delivery Trace and packet capture both confirm that the configured relay is never used.
Reproduction Steps
Install Stalwart Mail Server 0.16.12 on Debian.
Create a Relay Route pointing to smtps.aruba.it:465 with SMTP authentication enabled.
Configure MtaOutboundStrategy:
IF is_local_domain(rcpt_domain)
local
ELSE
aruba
Send an email to an external recipient (for example Gmail).
Observe the SMTP connection.
Stalwart connects directly to the recipient MX instead of the configured relay.
Stalwart Version
v0.16.x
Installation Method
Binary (Linux)
Database Backend
RocksDB
Blob Storage
RocksDB
Search Engine
PostgreSQL
Directory Backend
Internal
I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.
on
I have searched this support forum (open and closed topics) and confirm this is not a duplicate.
on
I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.
The most common causes of a “Relay Route” being silently ignored are mismatches in how the route expression selects it, so the fix is almost always in the route expression syntax on MtaOutboundStrategy, not in the relay itself.
How it should be wired together
Define your relay as an MtaRoute with @type: "Relay" and a name (for example "aruba"):
On the MtaOutboundStrategy singleton, the route field must be a proper expression object, and string results (both route names and the local check) must be single-quoted inside the JSON string, e.g.:
The pseudo-code you posted (IF ... local ELSE aruba) is not valid — if the then/else values aren’t quoted string literals like 'aruba', the expression will fail to resolve to a route name and Stalwart falls back to its built-in default ('mx'), which is exactly the direct-to-MX behaviour you’re seeing.
The name returned by the route expression ('aruba' in this example) must exactly match the name field of your Relay MtaRoute. If there’s any mismatch (typo, case difference), delivery fails to resolve the named route — check whether your setup actually falls back to mx due to a name mismatch as well.
You can verify what’s actually being evaluated with:
stalwart-cli get MtaOutboundStrategy
stalwart-cli get MtaRoute
and confirm the route name returned by the expression matches one of the returned MtaRoute names.