2026.08 / recipient rejection 046
Docker Mailserver “User Unknown in Virtual Mailbox Table”? Fix It
A sender receives a bounce containing 550 5.1.1 Recipient address rejected: User unknown in virtual mailbox table. The domain reaches your Docker Mailserver host, Postfix answers, but it refuses the recipient during the SMTP conversation. That wording is useful: it points to recipient recognition, not a generic outage.
Do not disable recipient checks or turn the domain into a catch-all just to make the error disappear. Postfix rejects unknown recipients at SMTP time so it does not accept mail that cannot be delivered. The safe repair is to prove which address was rejected, determine whether it should be a mailbox or alias, update the configured Docker Mailserver account source, and test the active lookup.
Keep real addresses, server addresses, complete logs, account files, password hashes, and private configuration out of tickets and public posts. The examples below use [email protected].
What the error proves—and what it does not
| Evidence | Meaning |
|---|---|
550 5.1.1 during RCPT TO | The receiving SMTP server rejected that envelope recipient before accepting the message. |
virtual mailbox table | Postfix classified the domain as a virtual mailbox domain and did not find a valid recipient in its effective maps. |
local recipient table | A different address class is involved; inspect mydestination and the mail hostname/domain relationship. |
| A later non-delivery report after acceptance | This is not the same failure; follow the queue ID and final delivery error. |
| One spelling works and another fails | The path is healthy; compare the exact mailbox or alias definition. |
The official Postfix address-class documentation says valid recipients for virtual mailbox domains are listed through virtual_mailbox_maps; invalid recipients are rejected with this exact response. That rejection does not, by itself, prove which Docker Mailserver source is stale or missing.
1. Capture the exact rejected envelope recipient
Read the sender’s complete SMTP response or a narrow private server-log window. Do not rely on the visible To: header: mailing software, aliases, forwarding, and blind-copy delivery can make the SMTP envelope recipient different.
docker compose logs --since 10m mailserver
Use your actual Compose service name. Find the single rejection and record privately:
- the exact address after
to=<...>or in theRCPT TOrejection; - whether the text says
virtual mailbox tableorlocal recipient table; - which hostname received the connection;
- whether the event is current rather than an old bounce being retried.
Common causes at this point are mundane: a typo, an old address retained by a contact form, a removed mailbox, or an alias that was planned but never provisioned.
2. Prove public mail routes to this server
Confirm the recipient domain’s MX records and resolve each target:
dig +short MX example.com
dig +short A mail.example.com
dig +short AAAA mail.example.com
A rejection in your current Docker Mailserver logs already proves that one attempt reached this instance. DNS checks still matter when some senders succeed and others hit a retired host, a stale IPv6 route, or a secondary MX with different account data. Mail records should normally remain DNS-only when using Cloudflare; Cloudflare’s ordinary orange-cloud web proxy is not an SMTP proxy.
3. Decide whether the address should be an account or an alias
Docker Mailserver’s account-management overview distinguishes the two:
- Account: owns a mailbox and login identity, with a password and optional quota.
- Alias: accepts an additional delivery address and routes it to an existing account or another intended target.
If a person needs a separate inbox and IMAP login, create an account. If [email protected] should arrive in [email protected], create an alias. An alias does not become a separate IMAP user. This distinction also prevents unnecessary duplicate mailboxes.
4. List provisioned accounts and aliases through the supported CLI
For Docker Mailserver’s default file provisioner, use the setup commands rather than opening files that contain account hashes:
docker compose exec mailserver setup email list
docker compose exec mailserver setup alias list
Check the exact full address, including its domain. If you use LDAP, the container environment, or another documented provisioner, query that active source instead. Adding an entry to the file provisioner cannot repair an LDAP lookup.
Also check the alias target. An alias that points to a misspelled, removed, or unintended target is not a valid end-to-end repair merely because its left-hand address appears in a list.
5. Add the smallest correct recipient definition
To add a real mailbox with the file provisioner, use an interactive prompt so the password is not placed in shell history:
docker compose exec mailserver \
setup email add [email protected]
To add an alias that delivers to an existing mailbox:
docker compose exec mailserver \
setup alias add [email protected] [email protected]
Use the syntax documented for your pinned Docker Mailserver version. Do not paste passwords into command arguments, publish the generated account file, or create a domain-wide catch-all as a shortcut. Catch-alls attract typo mail and spam, hide address mistakes, and make recipient ownership harder to audit.
6. Query Postfix’s effective maps instead of guessing
First inspect the active parameters:
docker compose exec mailserver \
postconf virtual_mailbox_domains virtual_mailbox_maps virtual_alias_maps mydestination
Keep the output private because it can reveal hosted domains and internal lookup paths. Then use the lookup type and map shown by postconf to query the exact address. A typical map query has this shape:
docker compose exec mailserver \
postmap -q [email protected] <map-from-postconf>
docker compose exec mailserver \
postmap -q [email protected] <alias-map-from-postconf>
Do not copy a map path from an old forum answer. Docker Mailserver versions and provisioners can expose different lookup types. The effective postconf result on the running container is the evidence that matters.
- Account query returns a result: the mailbox map recognizes it.
- Alias query returns its intended target: the alias map recognizes the delivery route.
- Configured source lists it but the active query is empty: regeneration, reload, mount, or source-selection state is inconsistent.
- The domain is in both virtual mailbox domains and
mydestination: fix the address-class conflict using supported persistent configuration.
7. Check persistence before restarting anything
Confirm the configuration volume is the intended persistent host path or named volume and that the change was made through the provisioner your deployment actually uses:
docker compose config
docker compose ps
Review the rendered Compose output locally and redact it before sharing; it may contain domains, paths, and environment details. A recipient added only inside an ephemeral container or to the wrong mounted directory can vanish on recreation. Conversely, blindly restarting may hide which supported setup operation should have updated the running maps.
If your version documents a reload or restart after an account-source change, use that narrow action and immediately re-run the exact map query. Avoid editing generated Postfix files in the container: the next startup can overwrite the change.
8. Handle “local recipient table” as a different branch
If the response says User unknown in local recipient table, inspect the mail hostname and mydestination. Docker Mailserver’s FAQ specifically warns against listing the same domain in both mydestination and virtual_mailbox_domains.
A frequent mistake is using the bare mailbox domain as the server hostname, then unintentionally making Postfix classify addresses under the local domain rules. Keep a stable host identity such as mail.example.com, while example.com remains a hosted mailbox domain. Make persistent changes through Compose environment or documented override files, then compare effective postconf output.
9. Test SMTP recipient acceptance without sending a message
After the map recognizes the recipient, test from a permitted external network over port 25. You can stop after RCPT TO and QUIT; do not send message content:
openssl s_client -quiet -starttls smtp \
-connect mail.example.com:25 \
-servername mail.example.com
EHLO test.example.net
MAIL FROM:<[email protected]>
RCPT TO:<[email protected]>
QUIT
Use domains and addresses you control. A 250-class recipient response proves Postfix now accepts that envelope address; it does not prove final mailbox delivery. If your provider blocks outbound port 25 from the test network, use a controlled message from an external mailbox and correlate it with the server log.
10. Prove final delivery and persistence
- Send one harmless message from an external account to the repaired address.
- Match the SMTP event and queue ID in a short private log window.
- Confirm the message reaches the intended mailbox, not merely that Postfix accepted it.
- If it is an alias, confirm it reaches the exact intended target.
- Restart or recreate only as your normal deployment procedure requires.
- Repeat the account/alias listing and Postfix map query after recreation.
- Send one final controlled message and confirm there is no fresh
550 5.1.1.
This catches two false fixes: an ephemeral account that disappears after deployment, and an alias accepted by SMTP but routed to the wrong destination.
Do not “fix” it by weakening recipient validation
Postfix documentation explains why rejecting unknown recipients during SMTP is desirable: the sender receives an immediate, accurate response, while your server avoids accepting undeliverable mail and generating backscatter later. Emptying recipient maps, accepting every local part, or broadly trusting networks changes the security model instead of repairing the address.
If you genuinely need many role addresses, define explicit aliases and keep their targets reviewed. If you need a temporary migration address, give it an owner and removal date. Recipient validity should be intentional and testable.
Compact diagnosis order
- Capture the exact envelope recipient and full rejection class.
- Confirm MX, A, and AAAA route senders to the intended host.
- Decide whether the address should be a mailbox account or an alias.
- List it through the active Docker Mailserver provisioner.
- Add only the missing account or explicit alias through supported tooling.
- Inspect effective Postfix domain, mailbox, and alias maps.
- Resolve any virtual-versus-local address-class conflict.
- Test
RCPT TO, then prove final mailbox delivery. - Recheck map recognition and delivery after normal recreation.
Authoritative references: Docker Mailserver’s account-management overview, file provisioner documentation, and FAQ; plus Postfix’s official address classes and unknown local recipient documentation. Match commands to the versions and provisioner you actually run.