I have a domain with few hundred email addresses. We are migrating our hosting to multiple ISPConfig servers. My problem is if someone sends email to email@domain.example and if the email does not exists on the first server how can I tell the postfix not to reply with

550 5.1.1 ecipient address rejected: User unknown in virtual mailbox table (in reply to RCPT TO command)

But to forward the mail to the MX second server, where the email exists.

I have tried to extend my postfix main.cf config like this:

transport_maps = hash:/var/lib/mailman/data/transport-mailman, proxy:mysql:/etc/postfix/mysql-virtual_transports.cf, hash:/etc/postfix/transport

/etc/postfix/transport looks like this:

relay: [IPv4 address of the server]

But it did not work.

My config is:

address_verify_virtual_transport = $virtual_transport
propagate_unmatched_extensions = canonical, virtual
proxy_read_maps = $local_recipient_maps $mydestination $virtual_alias_maps $virtual_alias_domains $sender_bcc_maps $virtual_mailbox_maps $virtual_mailbox_domains $relay_recipient_maps $relay_domains $canonical_maps $sender_canonical_maps $recipient_canonical_maps $relocated_maps $transport_maps $mynetworks $smtpd_sender_login_maps
relay_domains = mysql:/etc/postfix/mysql-virtual_relaydomains.cf
relay_recipient_maps = mysql:/etc/postfix/mysql-virtual_relayrecipientmaps.cf
sender_bcc_maps = proxy:mysql:/etc/postfix/mysql-virtual_outgoing_bcc.cf
smtpd_client_restrictions = check_client_access mysql:/etc/postfix/mysql-virtual_client.cf
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, reject_rbl_client zen.spamhaus.org, check_recipient_access mysql:/etc/postfix/mysql-virtual_recipient.cf, check_recipient_access mysql:/etc/postfix/mysql-virtual_policy_greylist.cf
smtpd_sender_login_maps = proxy:mysql:/etc/postfix/mysql-virtual_sender_login_maps.cf
smtpd_sender_restrictions = check_sender_access regexp:/etc/postfix/tag_as_originating.re , permit_mynetworks, permit_sasl_authenticated, check_sender_access mysql:/etc/postfix/mysql-virtual_sender.cf, check_sender_access regexp:/etc/postfix/tag_as_foreign.re
transport_maps = hash:/var/lib/mailman/data/transport-mailman, hash:/etc/postfix/transport, proxy:mysql:/etc/postfix/mysql-virtual_transports.cf
unknown_virtual_alias_reject_code = 550
unknown_virtual_mailbox_reject_code = 550
virtual_alias_address_length_limit = 1000
virtual_alias_domains =
virtual_alias_expansion_limit = 1000
virtual_alias_maps = hash:/var/lib/mailman/data/virtual-mailman, proxy:mysql:/etc/postfix/mysql-virtual_forwardings.cf, proxy:mysql:/etc/postfix/mysql-virtual_email2email.cf
virtual_alias_recursion_limit = 1000
virtual_delivery_slot_cost = $default_delivery_slot_cost
virtual_delivery_slot_discount = $default_delivery_slot_discount
virtual_delivery_slot_loan = $default_delivery_slot_loan
virtual_delivery_status_filter = $default_delivery_status_filter
virtual_destination_concurrency_failed_cohort_limit = $default_destination_concurrency_failed_cohort_limit
virtual_destination_concurrency_limit = $default_destination_concurrency_limit
virtual_destination_concurrency_negative_feedback = $default_destination_concurrency_negative_feedback
virtual_destination_concurrency_positive_feedback = $default_destination_concurrency_positive_feedback
virtual_destination_rate_delay = $default_destination_rate_delay
virtual_destination_recipient_limit = $default_destination_recipient_limit
virtual_extra_recipient_limit = $default_extra_recipient_limit
virtual_gid_maps = mysql:/etc/postfix/mysql-virtual_gids.cf
virtual_initial_destination_concurrency = $initial_destination_concurrency
virtual_mailbox_base = /var/vmail
virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual_domains.cf
virtual_mailbox_limit = 51200000
virtual_mailbox_lock = fcntl, dotlock
virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailboxes.cf
virtual_minimum_delivery_slots = $default_minimum_delivery_slots
virtual_minimum_uid = 100
virtual_recipient_limit = $default_recipient_limit
virtual_recipient_refill_delay = $default_recipient_refill_delay
virtual_recipient_refill_limit = $default_recipient_refill_limit
virtual_transport = dovecot
virtual_transport_rate_delay = $default_transport_rate_delay
virtual_uid_maps = mysql:/etc/postfix/mysql-virtual_uids.cf

postconf |grep smtpd_recipient

smtpd_recipient_limit = 1000
smtpd_recipient_overshoot_limit = 1000
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, reject_rbl_client zen.spamhaus.org, check_recipient_access mysql:/etc/postfix/mysql-virtual_recipient.cf, check_recipient_access mysql:/etc/postfix/mysql-virtual_policy_greylist.cf
  • Look for settings related to "Postfix As A Backup MX" or "Configuring Postfix as primary or backup MX host for a remote site". – Ingvar J Oct 16 '18 at 12:10
  • backup MX servers don't work that way, a sendign SMTP server will only contact lower priority (higher numbered) MXs if the lowest number/highest priority isn't available (off line, firewall blocking access to it, etc) – ivanivan Oct 16 '18 at 14:05
  • BackupMX if I am right works as spare servers which collect the emails while the main server is offline and if it comes back to life the backupMX push the emails to that, so the main server serving all the email addresses. In my case two equal servers would serve the users and half of the email addresses (like [a-k]@domain.tld would be on the first server and [l-z]@domain.tld would be on the second server – Arany Péter Oct 17 '18 at 6:58

The transport_map is the way to go for figuring out how to deliver, but it kicks in AFTER the " smtpd_reject_unlisted_recipient" or smtpd_recipient_restrictions = reject_unlisted_recipient, ...

So you need to add validation for recipients in the OTHER mailserver as well, not just users in the current server.

You have in smtpd_recipient_restrictions = .... check_recipient_access mysql:/etc/postfix/mysql-virtual_recipient.cf,... it must also find a list of valid users in the other mailserver my some means. Either with a SQL lookup directly to the other mailserver, or by exporting a list to a map file (with cron regularly) so that it will not fail if the other mailserver is down. In my case I use ldap to find valid users, and creates a local file with a list of all valid recipients mail adresses. You could possibly also use the same method for creating a transport map + some scripting to add the smtp:[i.p.address.othermailserver] after each mail address

You can start postfix in debug mode (-D )and/or with verbose logging ( -vvv) to see how it evaluates the rejects.

See also http://www.postfix.org/postconf.5.html#smtpd_reject_unlisted_recipient

| improve this answer | |
  • Thanks, I could make it work thanks to you. I created the mailbox users and set up a transport like: email address smtp:[another.postfix.server] I extended the main.cf: transport_maps = hash:/var/lib/mailman/data/transport-mailman, hash:/etc/postfix/transport, proxy:mysql:/etc/postfix/mysql-virtual_transports.cf And like this everything looks fine, the mails are not stored on both server but just on the right. Thanks again! – Arany Péter Oct 17 '18 at 12:30

How do You validate the mail address today for an incoming mail, Local linux users or Ldap/SQl/xyz? Can You share

  • sudo postconf |grep virtual

  • sudo postconf |grep recipient

| improve this answer | |
  • I pasted my config above – Arany Péter Oct 17 '18 at 9:13
  • Now I am trying a workaround with the transport_map, I am trying to add the email addresses exists on the other server to get forwarded there: my transport file looks like this: arape3@domain.hu smtp:[mail.domain.hu] db file has been generated with postmap command, the transport_maps has been extended in the main.cf: transport_maps = hash:/var/lib/mailman/data/transport-mailman, hash:/etc/postfix/transport, proxy:mysql:/etc/postfix/mysql-virtual_transports.cf But does not want to do its job. – Arany Péter Oct 17 '18 at 9:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.