Custom Sub-Adressing no longer seems to work after upgrade to 0.16

Issue Description

custom SubAdressing no longer seems to work after upgrade to 0.16

Expected Behavior

username.alias@domain should be delivered to the existing account username@domain

Actual Behavior

5.5.0, Message: Mailbox not found.

Reproduction Steps

  1. Configure stalwart Domanin → Email → Sub-Addressing → Enable custom sub addressing
  2. tried two regex options
    2a. if is matches(‘^([^.]+).([^.]+)@(.+)$’, rcpt) , then is $1 + ‘@’ + $3 , and else is false. this worked in stalwart before 0.16
    2b. if is matches(‘^([^.]+)\.([^.]+)$’, rcpt) , then is $1 , and else is rcpt.
  3. both option is not working in 0.16. getting “5.5.0, Message: Mailbox not found.” error.

Stalwart Version

v0.16.x

Installation Method

Binary (Linux)

Database Backend

RocksDB

Blob Storage

RocksDB

Search Engine

Internal

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

Let me look into how sub-addressing and its configuration work in the current version.

The issue is clear from the current documentation. The customRule expression works differently in the current version than you may have expected from before: the expression receives only the local part (without the domain), and must return only the local part. The domain is preserved separately by the server.

Here’s the key behavior change to be aware of:

  • The variable rcpt in customRule contains only the local part (e.g., username.alias), NOT the full email address.
  • The expression must return only the local part of the resolved address (e.g., username).

So your regex option 2b was actually correct in shape, but you need to capture the right group. According to the current docs example, to strip a prefix so that [email protected] delivers to [email protected], the expression should be:

{
  "subAddressing": {
    "@type": "Custom",
    "customRule": {
      "match": [{"if": "matches('^([^.]+)\\.([^.]+)$', rcpt)", "then": "$2"}],
      "else": "rcpt"
    }
  }
}

Note that $2 is used (capturing the second group, the username after the dot), not $1. Your option 2b was using $1, which would have returned the alias prefix instead of the actual username - causing “Mailbox not found.”

Your option 2a was also wrong for current versions because it used the full rcpt@domain format and tried to reconstruct the full address, but customRule only operates on and returns the local part.

To summarize the fix: use "then": "$2" (not $1) with the regex '^([^.]+)\\.([^.]+)$' so that alias.username resolves to username.

See the full documentation here: Subaddressing - Inbound RCPT

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

my emails are in the format username.alias@domain and i want it to be delivered to username@domain. so i believe $1 is correct only as per my use case. but still getting mailbox not found error.

if “matches(‘^([^.@]+).[^@]+’, rcpt)”
then “$1”
else “rcpt”
this config resolves the issue