Postfix dovecot disable lmtp

dovecotpostfixsmtp

I have 3 servers. 1 MX server with postfix and 2 dovecot servers. MX server receive emails and then serve them through LMTP to specific dovecot server. All mailboxes from same domain are on same server.

Is there any way to temporary disable LMTP and deffer messages for specific domain? For example in case of migrating domains between dovecot servers.

On postfix I use transport_maps

transport_maps = mysql:/etc/postfix/sql/transport.cf

With this query

 query = SELECT concat('lmtp:',servers.address, ':24') FROM servers
         JOIN domains ON (domains.server_id=servers.ID)
         WHERE domains.name LIKE SUBSTRING_INDEX("%s", "@", -1)
         LIMIT 1;

Dovecot is listening for lmtp on port 24, user_query in dovecot is

user_query = SELECT 1
        FROM domains
        JOIN mailboxes ON (domains.ID=mailboxes.domain_id)
        WHERE
            domains.name LIKE '%d'
            AND mailboxes.name LIKE '%n'
            AND domains.server_id='X'
        LIMIT 1;

I checked dovecot user_query man page, but there is nothing what can help me (http://wiki2.dovecot.org/UserDatabase and http://wiki2.dovecot.org/UserDatabase/ExtraFields)

I have tried to add condition to user_query "AND domains.enable_lmtp = 1", but then postfix server successfully passed email to dovecot server and dovecot server returned to sender error "User doesn't exists".

Next I tried to add same condition to server query on postfix server. Query returned nothing (nowhere to transport), email was deleted and in log said

postfix/virtual[724]: fatal: bad string length 0 < 1: virtual_mailbox_base =
postfix/master[32263]: warning: process /usr/libexec/postfix/virtual pid 724 exit status 1
postfix postfix/master[32263]: warning: /usr/libexec/postfix/virtual: bad command startup -- throttling

I hoped that postfix would put messages into deferred queue, but it didn't. Messages were deleted. Same think happened when I changed transport server to non exist address.

So am I doing something wrong? Is there any way to solve my problem?

My postconf -n

alias_database = hash:/etc/aliases
alias_maps = hash:/etc/aliases
config_directory = /etc/postfix
content_filter = smtp-amavis:[127.0.0.1]:10024
mydestination = $myhostname, localhost.$mydomain, localhost
smtpd_client_restrictions = permit_mynetworks, reject_unknown_client_hostname, reject_unknown_reverse_client_hostname
smtpd_helo_restrictions = permit_mynetworks, reject_invalid_hostname, reject_non_fqdn_hostname,
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, reject_unknown_recipient_domain, reject_non_fqdn_recipient, check_policy_service unix:/var/spool/postfix/postgrey/socket, check_policy_service unix:private/recipient_restrictions
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination
smtpd_sender_restrictions = permit_mynetworks, reject_non_fqdn_sender, reject_unknown_sender_domain
smtpd_tls_cert_file = /etc/postfix/smtpd.cert
smtpd_tls_key_file = /etc/postfix/smtpd.key
smtpd_tls_loglevel = 0
smtpd_tls_received_header = yes
smtpd_use_tls = yes
transport_maps = mysql:/etc/postfix/sql/transport.cf
unknown_local_recipient_reject_code = 550
virtual_mailbox_domains = mysql:/etc/postfix/sql/mailbox_domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/sql/mailbox_maps.cf

Best Answer

This problem can be tackled either by postfix or dovecot.

  1. In dovecot, you should set the LMTP service to reply with temporary reject 4XX (for your "special" domain) when postfix send email.
  2. In postfix, you need to configure postfix so it must defer the email if the recipient domain match your "special" domain.

Option 1 isn't possible because -unlike postfix- dovecot can't be configured to issue the tempfail error to particular domain. See the discussion on [Dovecot] Configuration of LMTP Reject Code.

For option 2, you need to transport the "special" domain to non-working address, for example you can deliver it to closed port in your LMTP server. For that, you need second transport_maps with query like this

#/etc/postfix/sql/transport-defer.cf

query = SELECT concat('lmtp:',servers.address, ':2424') FROM servers
        JOIN domains ON (domains.server_id=servers.ID)
        WHERE domains.name LIKE SUBSTRING_INDEX("%s", "@", -1)
        AND domains.enable_lmtp != 1
        LIMIT 1;

In above query, I use port 2424 as closed port to keep postfix defer the message.

Then put it next to mysql:/etc/postfix/sql/transport.cf

#main.cf
transport_maps = mysql:/etc/postfix/sql/transport.cf mysql:/etc/postfix/sql/transport-defer.cf

PS: Because you have no mailbox in postfix server then it would be preferable to use relay_domains and relay_recipient_maps to replace virtual_mailbox_domains and virtual_mailbox_maps. See relay domain class documentation.