Stalwart 0.16.22 Community: How can I verify inbound SMTP invokes my Rspamd Milter?

Your question

Hello,

I’m running Stalwart 0.16.22 Community Edition and trying to confirm that incoming SMTP messages are passed to Rspamd and then ClamAV.

My saved MtaMilter is configured as follows:

Host: rspamd, port 11332
Enable condition: listener == ‘smtp’
Stage: DATA only
TLS: off
TempFail on Error: on
Protocol version: 6
The smtp listener is on port 25; submissions is on port 465. Rspamd’s Milter worker is listening on port 11332 with milter = true. Direct scans through Rspamd work, and its ClamAV module detects the EICAR test signature. However, inbound SMTP messages are accepted and Rspamd’s scan count does not increase.

I enabled the Console tracer at Trace level and selected the Milter read/write, action, and error events. After sending a new plain-text inbound message, docker logs --since 5m stalwart 2>&1 | tail -n 80 returned no output.

Is Console tracer output expected to appear in Docker logs for this setup? What supported diagnostic can I use in Community Edition to confirm whether the Milter is invoked for an SMTP session, and what should I check if no Milter events appear?

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.

on

Found a directly relevant “live tracing” endpoint/page. Let’s fetch it.

Two separate things are worth checking here, and each explains a plausible root cause.

1. Console tracer output should appear in docker logs.
The Stdout tracer variant writes every log/trace entry to stderr specifically so container runtimes like Docker can capture it. If you got literally zero output at Trace level, the tracer you edited likely isn’t the one actually active, or its enable field is false. Sanity-check by temporarily setting level to trace with no event filter at all (leave events empty) — at that verbosity you should see a flood of unrelated SMTP/queue events. If you still see nothing, the tracer config itself isn’t being applied (wrong instance, not saved, needs the service to pick it up).

2. Watch out for eventsPolicy.
events/eventsPolicy on the Tracer object work as an include/exclude filter, defaulting to exclude. If you added the Milter events to events but left eventsPolicy at its default exclude, you’re telling Stalwart to suppress exactly those events and emit everything else — the opposite of what you want. Set eventsPolicy to include if you only want to see Milter traffic.

3. Which events actually confirm invocation.
milter.read/milter.write are trace-level raw-byte dumps, but the higher-signal events are logged at info/warn regardless of a custom tracer, so a plain level: info console tracer should already show them if the milter is being called:

  • milter.action-accept, milter.action-reject, etc. (info) — the milter responded and Stalwart acted on it.
  • milter.io-error, milter.timeout, milter.disconnected, milter.frame-invalid (warn) — connection/protocol problems talking to Rspamd’s milter worker.

If none of these appear at all for a DATA-stage message, the milter call itself isn’t happening, which points back to the enable expression.

4. Double-check the enable expression’s listener variable.
listener in MtaMilter.enable resolves to the identifier of the NetworkListener object handling the connection, not just “any port 25 traffic.” Confirm that your SMTP listener’s ID is literally smtp (as configured under Network › Listeners) — if it was created with a different name, listener == 'smtp' will always evaluate false and the milter will silently never be invoked, which matches “messages accepted, Rspamd scan count never increases, and no Milter events logged at all.”

Reference: Milter filters and Tracing overview / Console tracer.

This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.

Console tracer output goes to stderr, so docker logs is the right place to look. The tracer is configuration just like the milter, though, and saving it changes nothing until you run Reload server settings or restart, which would explain why nothing showed up at all.

After the reload, set the tracer to info with no event filter for one test and send a message. A milter.action-accept line means the milter ran. No milter lines at all means it isn’t loaded, and the reload result will say why; the likely cause is in Stalwart 0.16.22 accepts SMTP DATA without a Rspamd Milter scan.