Tracer not working as expected

Issue Description

I want to forward all stalwart messages to journald and then rsyslog. But it seems as if the appropriate tracer is not forwarding the same amount of information to journald than it does to the log file

Expected Behavior

Data in the /var/log/stalwart/stalwart.log.2026-10-13 file:

2026-10-13T22:20:27Z INFO SMTP MAIL FROM command (smtp.mail-from) listenerId = “smtp”, localPort = 25, remoteIp = 93.88.225.60, remotePort = 53731, from = “[email protected]”
2026-10-13T22:20:27Z INFO SMTP RCPT TO command (smtp.rcpt-to) listenerId = “smtp”, localPort = 25, remoteIp = 93.88.225.60, remotePort = 53731, to = “[email protected]”
2026-10-13T22:20:28Z INFO DKIM verification failed (smtp.dkim-fail) listenerId = “smtp”, localPort = 25, remoteIp = 93.88.225.60, remotePort = 53731, strict = false, result = , elapsed = 0ms
2026-10-13T22:20:28Z INFO DMARC check failed (smtp.dmarc-fail) listenerId = “smtp”, localPort = 25, remoteIp = 93.88.225.60, remotePort = 53731, strict = false, domain = “museo-hotel.my”, policy
= “none”, result = No DMARC record (dmarc.none), elapsed = 856ms
2026-10-13T22:20:48Z INFO Queued message for delivery (queue.message-queued) listenerId = “smtp”, localPort = 25, remoteIp = 93.88.225.60, remotePort = 53731, queueId = 334810377495846404, from = “yb
[email protected]”, to = [“[email protected]”], size = 135828, nextRetry = 2026-10-13T22:20:45Z, nextDsn = 2026-10-14T22:20:45Z, expires = 2026-10-16T22:20:45Z
2026-10-13T22:22:14Z INFO Task scheduled for future execution (task-manager.task-scheduled) due = 2026-10-13T22:27:13Z, id = “calculateMetrics”
2026-10-13T22:22:14Z INFO Metrics collected (telemetry.metrics-collected) elapsed = 2ms
2026-10-13T22:22:32Z INFO Invalid EHLO command (smtp.invalid-ehlo) listenerId = “smtp”, localPort = 25, remoteIp = 45.115.26.149, remotePort = 58921, domain = “harrryyyy”
2026-10-13T22:27:14Z INFO Task scheduled for future execution (task-manager.task-scheduled) due = 2026-10-13T22:32:13Z, id = “calculateMetrics”
2026-10-13T22:27:14Z INFO Metrics collected (telemetry.metrics-collected) elapsed = 2ms
2026-10-13T22:32:14Z INFO Task scheduled for future execution (task-manager.task-scheduled) due = 2026-10-13T22:37:13Z, id = “calculateMetrics”
2026-10-13T22:32:14Z INFO Metrics collected (telemetry.metrics-collected) elapsed = 2ms
2026-10-13T22:33:42Z INFO SMTP EHLO command (smtp.ehlo) listenerId = “Printer”, localPort = 587, remoteIp = 66.132.195.53, remotePort = 36122, domain = “www.censys.io”
2026-10-13T22:33:44Z INFO TLS handshake (tls.handshake) listenerId = “Printer”, localPort = 587, remoteIp = 66.132.195.53, remotePort = 36122, listenerId = “Printer”, version = “TLSv1_3”, details
= “TLS13_AES_256_GCM_SHA384”
2026-10-13T22:37:14Z INFO Task scheduled for future execution (task-manager.task-scheduled) due = 2026-10-13T22:42:13Z, id = “calculateMetrics”
2026-10-13T22:37:14Z INFO Metrics collected (telemetry.metrics-collected) elapsed = 2ms

Expected to same the same data in the journald

Actual Behavior

Output of journalctl -u stalwart (note: the timestamps are different but the same data types are in journald the whole day)

Okt 14 00:29:34 mail stalwart[2490]: SMTP QUIT command
Okt 14 00:29:34 mail stalwart[2490]: SMTP connection ended
Okt 14 00:30:34 mail stalwart[2490]: SMTP connection started
Okt 14 00:30:34 mail stalwart[2490]: SMTP QUIT command
Okt 14 00:30:34 mail stalwart[2490]: SMTP connection ended
Okt 14 00:31:34 mail stalwart[2490]: SMTP connection started
Okt 14 00:31:34 mail stalwart[2490]: SMTP QUIT command
Okt 14 00:31:34 mail stalwart[2490]: SMTP connection ended
Okt 14 00:32:14 mail stalwart[2490]: Task scheduled for future execution
Okt 14 00:32:14 mail stalwart[2490]: Metrics collected

Reproduction Steps

  1. Configure Tracer to log file with standard parameters
  2. Configure a second tracer to journald with standard parameters

Relevant Log Output

Output of journalctl -u stalwart.service -f with TRACER as LOGGING LEVEL intermixed with the log file output
Okt 14 00:50:17 mail stalwart[2490]: Raw SMTP output sent
Okt 14 00:50:17 mail stalwart[2490]: Raw SMTP input received
Okt 14 00:50:17 mail stalwart[2490]: SMTP EHLO command
2026-10-13T22:50:18Z INFO SPF EHLO check failed (smtp.spf-ehlo-fail) listenerId = “smtp”, localPort = 25, remoteIp = 136.90.19.168, remotePort = 58708, domain = “jolliman.co.uk”, result = SPF soft fail (spf.soft-fail), elapsed = 972ms
2026-10-13T22:50:18Z INFO IPREV check passed (smtp.iprev-pass) listenerId = “smtp”, localPort = 25, remoteIp = 136.90.19.168, remotePort = 58708, domain = “jolliman.co.uk”, result = IPREV check passed (iprev.pass) { details = [“168.19.90.136.bc.googleusercontent.com.”] }, elapsed = 172ms
Okt 14 00:50:18 mail stalwart[2490]: SPF EHLO check failed
Okt 14 00:50:18 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:18 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:18 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:18 mail stalwart[2490]: Raw SMTP output sent
Okt 14 00:50:18 mail stalwart[2490]: Raw SMTP input received
Okt 14 00:50:18 mail stalwart[2490]: IPREV check passed
Okt 14 00:50:18 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:18 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:18 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:18 mail stalwart[2490]: Expression evaluation result
2026-10-13T22:50:18Z INFO SPF From check failed (smtp.spf-from-fail) listenerId = “smtp”, localPort = 25, remoteIp = 136.90.19.168, remotePort = 58708, domain = “jolliman.co.uk”, from = “[email protected]”, result = SPF soft fail (spf.soft-fail), elapsed = 0ms
2026-10-13T22:50:18Z INFO SMTP MAIL FROM command (smtp.mail-from) listenerId = “smtp”, localPort = 25, remoteIp = 136.90.19.168, remotePort = 58708, from = “[email protected]”
Okt 14 00:50:18 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:18 mail stalwart[2490]: SPF From check failed
Okt 14 00:50:18 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:18 mail stalwart[2490]: SMTP MAIL FROM command
Okt 14 00:50:18 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:18 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:18 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:18 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:18 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:18 mail stalwart[2490]: Raw SMTP output sent
Okt 14 00:50:19 mail stalwart[2490]: Raw SMTP input received
Okt 14 00:50:19 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:19 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:19 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:19 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:19 mail stalwart[2490]: Cache hit
Okt 14 00:50:19 mail stalwart[2490]: Cache hit
Okt 14 00:50:19 mail stalwart[2490]: Cache hit
Okt 14 00:50:19 mail stalwart[2490]: Cache hit
Okt 14 00:50:19 mail stalwart[2490]: Expression evaluation result
2026-10-13T22:50:19Z INFO RCPT TO greylisted (smtp.rcpt-to-greylisted) listenerId = “smtp”, localPort = 25, remoteIp = 136.90.19.168, remotePort = 58708, to = “[email protected]”
Okt 14 00:50:19 mail stalwart[2490]: Write batch operation
Okt 14 00:50:19 mail stalwart[2490]: Write batch operation
Okt 14 00:50:19 mail stalwart[2490]: RCPT TO greylisted
Okt 14 00:50:19 mail stalwart[2490]: Raw SMTP output sent
Okt 14 00:50:19 mail stalwart[2490]: Raw SMTP input received
Okt 14 00:50:19 mail stalwart[2490]: SMTP QUIT command
Okt 14 00:50:19 mail stalwart[2490]: Raw SMTP output sent
Okt 14 00:50:19 mail stalwart[2490]: SMTP connection ended
Okt 14 00:50:33 mail stalwart[2490]: SMTP connection started
Okt 14 00:50:33 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:34 mail stalwart[2490]: Write batch operation
Okt 14 00:50:34 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:34 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:34 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:34 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:34 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:34 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:34 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:34 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:34 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:34 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:34 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:34 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:34 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:34 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:34 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:34 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:34 mail stalwart[2490]: Expression evaluation result
Okt 14 00:50:34 mail stalwart[2490]: Raw SMTP output sent
Okt 14 00:50:34 mail stalwart[2490]: Raw SMTP input received
Okt 14 00:50:34 mail stalwart[2490]: SMTP QUIT command
Okt 14 00:50:34 mail stalwart[2490]: Raw SMTP output sent
Okt 14 00:50:34 mail stalwart[2490]: SMTP connection ended

Stalwart Version

v0.16.x

Installation Method

Binary (Linux)

Database Backend

MySQL

Blob Storage

S3-compatible

Search Engine

MySQL

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.

on

This is a level/filter mismatch between your two tracers, not a bug in journald forwarding. Each tracer (log file, journald, etc.) has its own independent level setting, and your journald tracer appears to be configured at a verbose level (e.g. trace or debug), which also emits internal diagnostic events like “Raw SMTP output sent”, “Expression evaluation result”, and “Cache hit” that are not shown in the file tracer because that one is set to info.

To get the journald tracer to match the file tracer’s output, set its level to info (and make sure it isn’t overridden to a lower level per-event). You can also use events + eventsPolicy on the tracer to include/exclude specific event types if you want finer control than a single global level.

If after setting level: info on the journald tracer you still see mismatched output (e.g. missing SMTP MAIL FROM/RCPT TO/DKIM/DMARC events that appear in the log file), check whether an eventsPolicy: exclude list or a per-event EventTracingLevel override is filtering those specific event types out for that tracer only.

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

Sorry, but I looked at those two points already.

Both tracers had the exact SAME configuration (except, of course the target) and still the data in journald is much less than in the log file

Nothing is missing, it’s stored differently. The journal tracer writes the event description as the journal MESSAGE and each detail (listener, remote IP, from, to and so on) as a separate structured field, and journalctl’s default view only prints MESSAGE. Try:

journalctl -u stalwart -o verbose

and you’ll see fields like REMOTEIP and LISTENERID next to each entry.

rsyslog’s imjournal also forwards just MESSAGE unless your template pulls in the extra fields ($!REMOTEIP, or $!all-json for all of them). If you want syslog lines that look like the log file, it’s easier to use the console tracer with ANSI colours and multiline off, let systemd capture its output, and disable the journal tracer so you don’t get every event twice.

The “Expression evaluation result” and “Raw SMTP” lines in your second excerpt are trace-level events, so the journal tracer is set to trace. Set it to info or debug to get rid of them.