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]