[pfx] Re: Is virtual_mailbox_maps redundant when virtual_alias_maps already checks mailbox existence
Rajesh Mishra via Postfix-users <[email protected]> Fri, 22 May 2026 14:57:07 +0530
| Newsgroups | gmane.mail.postfix.user |
|---|---|
| Message-ID | <[email protected]> |
Hi, Following up on my earlier question. After digging into the Postfix source and documentation more carefully I believe I have a clearer picture, but I would like to confirm two candidate configurations before changing production. --- What I now understand --- TCP lookup tables (tcp:) send the full recipient address to the daemon exactly once. They do not attempt the multi-form lookups (user+ext@domain, user@domain, @domain) that indexed maps perform. This means my TCP daemon on port 9926 is solely responsible for handling plus-addressing, catchalls, and alias-domain canonicalisation — Postfix will not retry with a stripped or rewritten key. Our daemon already does this: - Step 1: resolves alias domains in-process (no additional DB round-trip) and checks for mailbox existence. - Step 2: checks for explicit aliases and @domain catchalls. So for any recipient in a virtual mailbox domain, by the time smtpd_reject_unlisted_recipient would trigger virtual_mailbox_maps, our daemon has already answered "mailbox does not exist" using the same table and the same conditions. The virtual_mailbox_maps lookup would always return nothing. I also verified that we deliver outbound via SMTP to a relay (virtual_transport = smtp:[relay]:587), not via Postfix virtual(8). This means virtual_mailbox_maps is consulted only during SMTP-time recipient validation, not at delivery time for mailbox path resolution. A no-op replacement should therefore be safe. One thing I want to confirm: setting virtual_mailbox_maps = <empty> while keeping smtpd_reject_unlisted_recipient = yes does NOT give us what we want — it disables the recipient check entirely rather than rejecting unknowns. So an empty map is not the right answer. --- Two candidate designs --- Design A — keep virtual_alias_maps for rewriting, replace virtual_mailbox_maps with a cheap no-op TCP service: virtual_alias_maps = tcp:127.0.0.1:9926 virtual_mailbox_maps = tcp:127.0.0.1:9927 # always returns NOT_FOUND smtpd_reject_unlisted_recipient = yes Port 9926 handles both alias rewriting and implicit mailbox validation. Port 9927 exists only so Postfix has a non-empty virtual_mailbox_maps; it returns NOT_FOUND for every query without touching the database. smtpd_reject_unlisted_recipient does the rejection. Design B — move accept/reject into smtpd_recipient_restrictions, remove virtual_mailbox_maps entirely: smtpd_reject_unlisted_recipient = no smtpd_recipient_restrictions = permit_mynetworks permit_sasl_authenticated reject_unauth_destination check_recipient_access tcp:127.0.0.1:9926 virtual_alias_maps = tcp:127.0.0.1:9927 # alias rewriting only Port 9926 speaks access(5) semantics (OK / REJECT / DUNNO) and handles accept/reject early at SMTP time. Port 9927 handles alias rewriting at cleanup time for messages that were accepted. --- Questions --- 1. For Design A: is there any scenario where Postfix would still consult virtual_mailbox_maps for something other than smtpd_reject_unlisted_recipient validation? For example during cleanup, queue re-injection, or virtual(8) delivery triggered by some other path? 2. Are there any other caveats with either design we should be aware of ? We are leaning toward Design A as it is the smaller change, but we want to make sure port 9927 returning NOT_FOUND for every query is genuinely safe and not just papering over something Postfix legitimately needs. Thanks in advance. Rajesh Mishra On 19/05/26 12:23 pm, Rajesh Mishra wrote: > Hi, > > I want to verify my understanding of the virtual_alias_maps → > virtual_mailbox_maps fallback chain before making a configuration > change, and also explore whether the chain can be simplified further. > > --- > Setup: > > virtual_alias_maps = tcp:127.0.0.1:9926, > proxy:mysql:/etc/postfix/mysql-vam.cf > virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-vmm.cf > smtpd_reject_unlisted_recipient = yes (default) > > Port 9926 is an in-house TCP lookup daemon. For each RCPT TO it runs > two lookups against our database: > > Step 1 — checks whether the mailbox exists for the recipient > address, with domain-alias resolution (if the recipient domain is a > configured alias, it resolves to the canonical domain before > checking). Returns the address if found. For external domains, returns > immediately without proceeding to step 2. > > Step 2 — checks for explicit aliases and catchalls for the recipient > address. > > If both steps return nothing, port 9926 returns NOT_FOUND. Postfix > then tries the MySQL fallback (mysql-vam.cf), which checks the same > alias table as step 2. If that also returns nothing, > smtpd_reject_unlisted_recipient triggers virtual_mailbox_maps. > > The virtual_mailbox_maps MySQL lookup is a direct mailbox existence > check — same table and same status conditions as step 1 above. > > --- > Question 1 — Is virtual_mailbox_maps redundant here? > > Since step 1 already checks mailbox existence with identical > conditions, by the time virtual_mailbox_maps is reached the same > question has already been answered "no" by the same table with the > same filters. If the user existed and matched those conditions, step 1 > would have returned the address, satisfied virtual_alias_maps, and > virtual_mailbox_maps would never have been reached. > > We are therefore considering replacing the MySQL > virtual_mailbox_maps with a TCP lookup on a separate port that > immediately returns NOT_FOUND without hitting the database, on the > basis that this check is always a no-op at that point. > > Is our understanding correct? Are there any Postfix-level scenarios > — such as lookup caching, address normalisation, or anything in how > smtpd_reject_unlisted_recipient interacts with these maps — where > virtual_mailbox_maps could legitimately find a recipient that > virtual_alias_maps step 1 already missed? > > --- > Question 2 — Can virtual_mailbox_maps be skipped entirely? > > Taking this further: is there a way to configure Postfix so that > NOT_FOUND from virtual_alias_maps is treated as a rejection directly, > without consulting virtual_mailbox_maps at all? > > For example, does setting virtual_mailbox_maps = (empty) while > keeping smtpd_reject_unlisted_recipient = yes achieve this? Or does > Postfix require a non-empty virtual_mailbox_maps to be able to reject > unlisted recipients for virtual mailbox domains? > > > Thanks > Rajesh Mishra > _______________________________________________ Postfix-users mailing list -- [email protected] To unsubscribe send an email to [email protected]