Postfix with LDAP backend
Contents
Although there is a lot of documentation regarding Postfix and OpenLDAP I could not find a complete example.
A good starting point when looking for the integration is the LDAP_README of postfix which gives at least some basic information.
In this post I’ll show how I managed to combine Postfix with OpenLDAP.
I had the following requirements for my setups:
- Host multiple Domains
- Each user can have one or more addresses, not limited to a single Domain
- Each user does only have one Login and Mailbox.
- Support for Catchall
Basics
I assume, that you are using a Postfix with LDAP support (e.g. the default Debian one) and a simple LDAP schema like this:
Structure:
- Users: ou=Users,dc=foobar
- Groups: ou=Groups,dc=foobar
- Domains: ou=Domains,dc=foobar
User-Attributes:
Attribute | Usage | Cardinality |
---|---|---|
cn | Login | 1 |
maildrop | Main Mailbox | 1 |
mailacceptinggeneralid | Mail Alias | * |
To simplify the post, I’ll replace some values with variables:
Variable | Example |
---|---|
{{ ldap_bind_dn }} | cn=postfix,ou=Applications,dc=foobar |
{{ ldap_bind_pw }} | foobar123 |
{{ ldap_host }} | ldaps://ldap.foobar:636 |
{{ ldap_base }} | dc=foobar |
{{ ldap_user_base }} | ou=Users,dc=foobar |
{{ ldap_domains_base }} | ou=Domains,dc=foobar |
Setup Postfix
First of all we have to tell Postfix, how logins, aliases, domains and recipients are handled.
For each of those mapping we have to create file in /etc/postfix/ldap
.
Logins
The smtpd_sender_login_maps
configurations performs a lookup from an incoming email-recipient to a username. Postfix first performs a full lookup on user@domain
, then user
and then @domain
. The later one is also used for catchalls where the mailacceptinggeneralid
is set to e.g. @foobar.com
/etc/postfix/ldap/virtual_senders.cf
bind = yes
bind_dn = {{ ldap_bind_dn }}
bind_pw = {{ ldap_bind_pw }}
server_host = {{ ldap_host }}
search_base = {{ ldap_user_base }}
query_filter = (&(objectclass=inetOrgPerson)(mailacceptinggeneralid=%s))
result_attribute = cn
Domains
The virtual_mailbox_domains
configurations performs a lookup, if the postfix is responsible for the given domain.
/etc/postfix/ldap/virtual_domains.cf
bind = yes
bind_dn = {{ ldap_bind_dn }}
bind_pw = {{ ldap_bind_pw }}
server_host = {{ ldap_host }}
search_base = {{ ldap_domains_base }}
query_filter = (&(ObjectClass=dNSDomain)(dc=%s))
result_attribute = dc
Recipients
As we only want to accept mail, where we know the recipients (and are responsible for them), the virtual_mailbox_maps
configuration is used.
/etc/postfix/ldap/virtual_recipients.cf
bind = yes
bind_dn = {{ ldap_bind_dn }}
bind_pw = {{ ldap_bind_pw }}
server_host = {{ ldap_host }}
search_base = {{ ldap_user_base }}
query_filter = (&(objectclass=postfixUser)(mailacceptinggeneralid=%s))
result_format =%s/
result_attribute = cn
Aliases
Last but not least the virtual_alias_maps
setting is used to find the target mailbox (configured in maildrop
).
/etc/postfix/ldap/virtual_aliases.cf
bind = yes
bind_dn = {{ ldap_bind_dn }}
bind_pw = {{ ldap_bind_pw }}
server_host = {{ ldap_host }}
search_base = {{ ldap_user_base }}
query_filter = (&(objectclass=inetOrgPerson)(mailacceptinggeneralid=%s))
result_attribute = maildrop
Main.cf
The final part is to modify the main.cf of Postfix to use the configured files.
##
## Virtual config
##
virtual_alias_maps = proxy:ldap:/etc/postfix/ldap/virtual_aliases.cf
virtual_mailbox_domains = proxy:ldap:/etc/postfix/ldap/virtual_domains.cf
virtual_mailbox_maps = proxy:ldap:/etc/postfix/ldap/virtual_recipients.cf
smtpd_sender_login_maps = proxy:ldap:/etc/postfix/ldap/virtual_senders.cf
local_recipient_maps = $virtual_mailbox_maps
virtual_mailbox_limit = 52428800
virtual_mailbox_base = /var/vmail
virtual_minimum_uid = 5000
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_transport = lmtp:unix:private/dovecot-lmtp
mailbox_transport = lmtp:unix:private/dovecot-lmtp
Comments