Mail delivery configuration with LDAP
Last time I wrote about users’ authentication in LDAP directory to allow them receiving and sending e-mails. Now is time to configure Postfix for mail delivery to appropriate mailboxes.
If you compile Postfix themselves, you need to remember to add support for LDAP. My description is based on Ubuntu, so I only need to install postfix-ldap package:
$ sudo -i # apt-get install postfix-ldap
This will add support for ldap:
maps in Postfix.
Now we go to Postfix configuration:
# cd /etc/postfix # vi main.cf
In main.cf
we need to add something like this (you need to replace example.com with your domain name):
ldap_bind_dn = cn=admin,dc=example,dc=com ldap_bind_pw = secret ldap_search_base = o=hosting,dc=example,dc=com ldap_domain = dc=example,dc=com ldap_server_host = localhost ldap_server_port = 389 ldap_version = 3 # Accounts accounts_server_host = $ldap_server_host accounts_search_base = $ldap_search_base accounts_query_filter = (&(objectClass=mailUser)(mail=%s)) accounts_result_attribute = mailMessageStore accounts_cache = no accounts_bind = yes accounts_bind_dn = $ldap_bind_dn accounts_bind_pw = $ldap_bind_pw accounts_version = $ldap_version accountsmap_server_host = $ldap_server_host accountsmap_search_base = $ldap_search_base accountsmap_query_filter = (&(objectClass=mailUser)(mail=%s)) accountsmap_result_attribute = mail accountsmap_cache = no accountsmap_bind = yes accountsmap_bind_dn = $ldap_bind_dn accountsmap_bind_pw = $ldap_bind_pw accountsmap_version = $ldap_version # aliases aliases_server_host = $ldap_server_host aliases_search_base = $ldap_search_base aliases_query_filter = (&(objectClass=mailAlias)(mail=%s)) aliases_result_attribute = mailForwardingAddress aliases_bind = yes aliases_cache = no aliases_bind_dn = $ldap_bind_dn aliases_bind_pw = $ldap_bind_pw aliases_version = $ldap_version # transports transport_server_host = $ldap_server_host transport_search_base = $ldap_search_base transport_query_filter = (&(objectClass=mailDomain)(domainName=%s)) transport_result_attribute = mtaTransport transport_cache = no transport_bind = yes transport_scope = one transport_bind_dn = $ldap_bind_dn transport_bind_pw = $ldap_bind_pw transport_version = $ldap_version # transport_maps maildrop_destination_concurrency_limit = 2 maildrop_destination_recipient_limit = 1 transport_maps = ldap:transport virtual_alias_maps = ldap:aliases, ldap:accountsmap # virtual accounts for delivery virtual_mailbox_domains = ldap:transport virtual_mailbox_base = /vdhome virtual_mailbox_maps = ldap:accounts virtual_minimum_uid = 501 virtual_uid_maps = static:501 virtual_gid_maps = static:501 local_recipient_maps = $alias_maps $virtual_mailbox_maps
The lines above should be enough for mail delivery. I tried to simplify this, so I do not chceck account status (active/nonactive) etc. There is no need to configure cn=admin to read directory also (security), you should define another user for this purpose, but it will be sufficient for now.
Now we need to restart Postfix and check logs for errors. If Postfix is running, we can leave it and go to mail configuration in LDAP directory. You can use description from Mail system authentication in LDAP, but I will add new domain virtdomain.com, user jsmith and alias postmaster, which will point to jsmith. You can create this in phpLDAPadmin or another utility, or you can import LDIF like this:
dn: domainName=virtdomain.com,o=hosting,dc=example,dc=com domainname: virtdomain.com mtatransport: virtual objectclass: mailDomain objectclass: top dn: uid=jsmith,domainName=virtdomain.com,o=hosting,dc=example,dc=com cn: John Smith givenname: John homedirectory: /vdhome/virtdomain.com/jsmith mail: jsmith@virtdomain.com mailmessagestore: virtdomain.com/jsmith/Maildir/ objectclass: inetOrgPerson objectclass: top objectclass: mailUser sn: Smith uid: jsmith userpassword: {MD5}XD9034sf8w83sfoXXg== dn: mail=postmaster@virtdomain.com,domainName=virtdomain.com,o=hosting,dc=example, dc=com cn: Postmaster mail: postmaster@virtdomain.com mailforwardingaddress: jsmith@virtdomain.com objectclass: mailAlias objectclass: top
If you add this with phpLDAPadmin, then you need to choose inetOrgPerson
as structural objectClass, and then add mailUser
object Class and needed attributes. As RDN you can choose mail
attribute, so you do not need to add uid
then.
Please note homeDirectory
and mailMessageStore
attributes. The last one contains relative path to user’s mailbox. Base directory is added by Postfix, which gets it from virtual_mailbox_base
variable. Dovecot in contrast uses homeDirectory
attribute and stick /Maildir
on the end. This is not good situation, and later I will write how to eliminate it. But it should work for now.
Let’s check if postfix resolves LDAP maps properly:
# postmap -q "virtdomain.com" ldap:transport virtual # postmap -q "postmaster@virtdomain.com" ldap:aliases jsmith@virtdomain.com # postmap -q "jsmith@virtdomain.com" ldap:accounts virtdomain.com/jsmith/Maildir/ # postmap -q "jsmith@virtdomain.com" ldap:accountsmap jsmith@virtdomain.com
You should see something like this above. If you do not have any results or you have connection to LDAP error, then you should check logs and improve configuration.
If everything is fine, you can send message to yourself, and it should be delivered to mailbox. If you see in logs message like this:
status=bounced (mail for example.com loops back to myself)
then there is a problem with transport. Note: you will find many results and solutions for this problem, but many of them suggest that you should your domain (example.com) to mydestination
, this is not good solution! In Postfix documentation, section VIRTUAL_README Vietse wrote:
NEVER list a virtual MAILBOX domain name as a mydestination domain! NEVER list a virtual MAILBOX domain name as a virtual ALIAS domain!
in the other words: if domain is virtual, then should be virtual, Postfix will receive mail for this domain, you need only point him where to deliver.