Issue Description
Mail sent to a MailingList object’s address is accepted at RCPT TO time (DKIM/SPF/DMARC all pass, message queued successfully), but the subsequent local delivery attempt fails with 550 5.5.0 Mailbox not found, even though the MailingList object is correctly configured, enabled, and independently verified via stalwart-cli. Domain object (isEnabled: true, directoryId: null → internal directory) and MailingList object (domainId matching the domain, recipients populated) were both re-checked via the Management API after the failure and are consistent. A full container restart did not change the behaviour, ruling out a stale directory/lookup cache.
Expected Behavior
Mail addressed to a valid, enabled MailingList should be expanded to its recipients and delivered/relayed accordingly - consistent with the fact that the SMTP listener accepts RCPT TO for that address in the first place.
Actual Behavior
Local delivery permanently fails with 550 5.5.0 Mailbox not found, regardless of whether the message originates internally (JMAP-composed) or externally (real SMTP delivery from an external sender) - both fail identically. The rejecting RCPT check happens against hostname = “localhost”, i.e. an internal loopback delivery step distinct from the SMTP listener that originally accepted the message.
Reproduction Steps
- Create a Domain object, e.g. shared.example.^com, with catchAllAddress set to the mailing list’s address.
- Create a MailingList object: name = family, domainId = , with one external recipient address.
- Send an email addressed to the mailing list’s address (tested both via internal JMAP compose and real external SMTP delivery).
- RCPT TO is accepted, DKIM/SPF/DMARC checks pass, message is queued.
- The local-queue delivery attempt fails immediately with 550 5.5.0 Mailbox not found against hostname = “localhost”.
- Restarting the Stalwart container does not change the outcome.
Relevant Log Output
INFO SMTP RCPT TO command (smtp.rcpt-to) … to = “[email protected].^com”
INFO DKIM verification passed (smtp.dkim-pass) … domain = “sender-domain.example”
INFO ARC verification passed (smtp.arc-pass) …
INFO DMARC check passed (smtp.dmarc-pass) … domain = “sender-domain.example”, policy = “none”
INFO Queued message for delivery (queue.message-queued) queueId = …, from = “[email protected]”, to = [“[email protected]”]
INFO Delivery attempt started (delivery.attempt-start) …, queueName = “local”, to = [“[email protected].^com”]
INFO New delivery attempt for domain (delivery.domain-delivery-start) …, queueName = “local”, domain = “shared.example.^com”
INFO DSN permanent failure notification (delivery.dsn-perm-fail) …, to = “[email protected].^com”, hostname = “localhost”, details = “Unexpected response for RCPT TO:<[email protected].^com>: Code: 550, Enhanced code: 5.5.0, Message: Mailbox not found.”
Object dumps via stalwart-cli get … --json:
Domain (id: h):
{
“name”: “shared.example.^com”,
“isEnabled”: true,
“memberTenantId”: null,
“directoryId”: null,
“catchAllAddress”: “[email protected].^com”,
“subAddressing”: {“@type”: “Enabled”},
“allowRelaying”: false,
“id”: “h”
}
MailingList (id: b):
{
“name”: “family”,
“domainId”: “h”,
“aliases”: {},
“memberTenantId”: null,
“recipients”: {“someone@external-provider.^com”: true},
“emailAddress”: “[email protected].^com”,
“id”: “b”
}
Stalwart Version
v0.16.x
Installation Method
Docker
Database Backend
RocksDB
Blob Storage
RocksDB
Search Engine
Meilisearch
Directory Backend
Internal
Additional Context
The affected domain is a secondary/shared domain on a multi-domain Stalwart instance that also serves several other domains correctly via the same internal directory.
No LDAP/SQL/OIDC external directory is involved for this domain.
Per the “Preparing for Stalwart v0.16: Breaking Changes” discussion, MailingList objects were split out of the principal model into a standalone top-level object type in v0.16. This may be relevant: it’s possible the local/loopback delivery resolution path was not fully updated to look up the new standalone MailingList table, while SMTP-listener-side RCPT validation was.
Possibly related to the “Catchall ignored for local bounces” report (same permanent-failure reason string Mailbox not found. in the local delivery status path), though the reproduction trigger there is different (VERP bounce addresses vs. direct delivery to a MailingList address here).
Happy to provide full unredacted logs or further stalwart-cli describe/get output on request.
The two URI-limit for new users sucks, I had to redact everythin ending .com in this post.
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