Context: I use Stalwart at home locally to self-host my personal mails. There are no other users. I have multiple domains, and use catcha-all to have an e-mail for every single service ([email protected], etc)
Previously all my domains were added as an aliases with @domain1.com, @domain2.com. This allowed me two things:
Use it as a Catch-All for incoming mails, and mails were directly send to this mailbox, which means Mail Headers To: and Delivered-To were identical.
Catch All are now defined at domain level, not user level anymore. I can configure domain1.com to send all mails to [email protected] (for all domains the same recipient). This changes the Mail Headers. To: [email protected] & Delivered-To: [email protected]. Unsure, if this is noteworthy, or have any practically impacts.
I cannot send from any domain anymore. I get the following error message in Thunderbird:
Sending of the message failed.
An error occurred while sending mail. The mail server responded: You are not allowed to send from this address.. Please verify that your email address is correct in your account settings and try again.
Any way to restore the old behavior. I think #1 doesn’t need to be restored, but I definitely want to send from any mail from my own domains.
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 “You are not allowed to send from this address” error is caused by the mustMatchSender setting in the MTA AUTH Stage. Here’s the full picture:
Issue #2 (can’t send from arbitrary addresses) is the key one to fix. The mustMatchSender field on the MtaStageAuth singleton defaults to true, meaning the authenticated user’s email addresses must match the From: address being used. Since your secondary domain addresses (e.g. [email protected]) aren’t registered as email aliases on your account, the check fails.
You have two ways to fix this:
Option A (recommended for your use case): Add all your domain addresses as email aliases on your account. In the WebUI, go to your user account and add @domain1.com, @domain2.com, etc. as alias addresses. This is the cleanest approach and keeps the security check intact.
Option B: Disable mustMatchSender. If you want to send from truly any address without registering aliases, you can set mustMatchSender to false. In the WebUI, go to Settings › MTA › Session › AUTH Stage and set the mustMatchSender expression to {"else": "false"}. You can also do it via the CLI:
Note: Option B allows your authenticated account to use any From: address, which is fine for a personal single-user setup but would be a security risk on a multi-user server.
Issue #1 (Delivered-To header) is cosmetic for your setup. The catch-all now operates at the domain level via catchAllAddress on each Domain object, routing unknown recipients to your main mailbox. This is by design and shouldn’t cause practical problems.
This feels for me also little bit unsecure. if i set mustMatchSender to false, sounds like any authentificated user can send from any mail-address (not just a selected account).
The behavior changed in 0.16: aliases are now specific addresses rather than whole-domain wildcards, so adding @domain as an alias no longer lets you send as any address in it. With mustMatchSender on (the default), the sender has to be the account’s own address or one of its aliases.
If you only send from a handful of addresses, the clean fix is to add each as an alias on the account and leave mustMatchSender on. If you genuinely need open-ended “send as anything on my domain,” you can set mustMatchSender to false, but as wrenix notes that lets any authenticated user send from any address. Alternatively you could create a custom expression that uses lookup stores to verify who is allowed to send from that domain.
What’s the problem adding whole-domain wildcards as an alias for incoming and outcoming? It worked so awesome in 0.15, and was my favorite feature in Stalwart… and now I cannot use it anymore.
It’s not just a couple of ‘aliases’ for me. I use one mail per service, f.ex. [email protected]. I got hundreds of these, and when I need to write an mail (support ticket), I also send from one of these. Adding an alias each time is not really a solution for me. I had to do this in Exchange, and it was annyoing.
This is a 0.16 change, aliases are now specific addresses rather than whole-domain wildcards, so adding @domain as an alias no longer grants send-as-anything. The send rejection you see is mustMatchSender (on by default): an authenticated account may only use its own address or an alias, otherwise 501 5.5.4. Setting mustMatchSender to false restores open sending, but then any authenticated user can send as any address, which is the security concern others raised.
Incoming catch-all still works, but it’s now domain-level via catchAllAddress, which is why Delivered-To changes to the catch-all mailbox. For sending from many per-service addresses on your own domain there’s no single-account feature in 0.16 today; the options are mustMatchSender=false, per-address aliases, or a custom mustMatchSender expression backed by a lookup store.
@wrenix, unfortunately this is no longer supported in 0.16. I’ll have to repeat it once again: Aliases are now specific addresses rather than whole-domain wildcards, so adding @yourdomain no longer lets you send as any address under it. The rejection is mustMatchSender (on by default), which limits an authenticated account to its own address plus its registered aliases.
For your case there are three options. Add each address as an alias and keep mustMatchSender on (cleanest, but impractical with hundreds of addresses).
Set mustMatchSender to false, which restores open sending; on a single-user instance like yours that’s fine, but be aware that on a multi-user server it lets any authenticated user send as any address. Or, to keep it scoped, use a custom mustMatchSender expression backed by your own domains, for example dropping the per-address check only when the sender domain is one of yours and the session is authenticated:
There’s no single-account “send as anything on my own domain” toggle in 0.16 beyond that. Docs for the field are at stalw.art/docs/ref/object/mta-stage-auth.
warning: type Mailbox aborted: connection error: authentication rejected: server returned 401: {“type”:“about:blank”,“status”:401,“title”:“Unauthorized”,“detail”:“You have to authenticate first.”}
export: AddressBook …
warning: type AddressBook aborted: connection error: authentication rejected: server returned 401: {“type”:“about:blank”,“status”:401,“title”:“Unauthorized”,“detail”:“You have to authenticate first.”}
export: Calendar …
warning: type Calendar aborted: connection error: authentication rejected: server returned 401: {“type”:“about:blank”,“status”:401,“title”:“Unauthorized”,“detail”:“You have to authenticate first.”}
export: Identity …
warning: type Identity aborted: connection error: authentication rejected: server returned 401: {“type”:“about:blank”,“status”:401,“title”:“Unauthorized”,“detail”:“You have to authenticate first.”}
export: SieveScript …
warning: type SieveScript aborted: connection error: authentication rejected: server returned 401: {“type”:“about:blank”,“status”:401,“title”:“Unauthorized”,“detail”:“You have to authenticate first.”}
export: ParticipantIdentity …
warning: type ParticipantIdentity aborted: connection error: authentication rejected: server returned 401: {“type”:“about:blank”,“status”:401,“title”:“Unauthorized”,“detail”:“You have to authenticate first.”}
export: Email …
warning: type Email aborted: connection error: authentication rejected: server returned 401: {“type”:“about:blank”,“status”:401,“title”:“Unauthorized”,“detail”:“You have to authenticate first.”}
export: ContactCard …
warning: type ContactCard aborted: connection error: authentication rejected: server returned 401: {“type”:“about:blank”,“status”:401,“title”:“Unauthorized”,“detail”:“You have to authenticate first.”}
export: CalendarEvent …
warning: type CalendarEvent aborted: connection error: authentication rejected: server returned 401: {“type”:“about:blank”,“status”:401,“title”:“Unauthorized”,“detail”:“You have to authenticate first.”}
@stalwart I’m not quite sure I understand the difference between options 2 and 3. You say on a multi-user server option 2 lets any authenticated user send as any address, which makes sense.
For option 3, is_local_domain checks if the sender domain is one of those that belong to the server, but doesn’t that allow any domain that belongs to the server? (is_local_domain: “Returns true when the domain is registered in the server’s directory.”)
What we ultimately need is a function to check if user has a catch-all registered on the sender_domain, or maybe if they have any alias registered on that domain (though less secure).