Creating your own schemas in FDS Ldap for use in postfix (or anything else for that matter) :P

What I needed for mailman like functioning while making postfix work with ldap was an attribute that stores content of type DN (Distinguished Name) i.e. a node address, or holding a data type that stores nothing but data of type that can hold address of the data type itself.

In openldap, I used a schemas called evolutionPerson and evolutionPersonList (available with my fedora openldap distribution by moving evolutionperson.schema in /usr/share/evolution-data-server-1.12/ to /etc/opanldap/schemas/). evolutionPerson is very similar to inetOrgPerson class, which stores basically everything that could ever be used to describe a person. The reason I chose evolutionPerson over inetOrgPerson was the availablity of the evolutionPersonList class. Its attributes are : mail, contact and listnName, where both mail and contact can contain more than one values. mail and listName attribute type is text, and contact attribute type is DN. contact’s were used to create groups, and mail’s were used to forward the email to a third party server. Here is a screenshot of the same in action :

OpenLdap

The contact attribute worked like charm. If any contact attribute turns out to be another evolutionPersonList, it repeats the whole process again for it, collecting new mails from it, and if it turns out to be evolutionPerson, it takes its mail attribute. The whole process repeats itself, taking care that infinite loops do not get created. In the end, what we get a list of mail ids to which the mail has to be sent.

Now, I haven’t yet figured out how to add evolutionperson.schema to schema. So, what did I do for delta?? I simply created my own schema. For a user, I already had whatever I needed in inetOrgPerson. All I need was some sort of an inetOrgPersonList. So, here are the steps :

  • I am assuming you have already setup fedora directory server through the wonderful install scripts provided. (/usr/sbin/setup-ds-admin.pl and then /usr/sbin/setup-ds.pl)
  • Open Fedora Directory Server admin console : /usr/bin/fedora-idm-console

Me, showing off my workspace

  • Under the server groups entry in the default view tree, select your directory server and open it, using the DN and password you provided earlier during the directory server setup.
  • Under the to configuration tab, select schema. Select Attributes in the right hand pane.
  • Create a new attribute by clicking on the new attribute button at the bottom of the right pane.

DNS Console Attributes

  • I needed two new attributes for my purpose :

    1. contact : of type DN, multi valued.
    2. listName : of type String, single valued.
    3. The third multivalued attribute I needed, mail, already exists.
  • Now, under the Object Classes pane, create any number of Objects you nees, using the attributes you just now created, or the preexisting ones.

DNS Console Objectclass

  • The one created was inetorgpersonlist having Required Attributes listName and objectClass, and Allowed Attributes contact and mail.
    That’s it!!

Mail with postfix and ldap

Yes, it’s possible. I did it for the pragyan.org server.

The setup we used was :

  • /var/mail/virtual/%u: the inboxes of different users,
  • /var/mail/virtual/PragyanMail/%u/%f: the different folders in mailboxes of different users.

It’s much easily setup than one thinks initially.

HOW?? Here’s how:

But, as with anything else, basics first

  • SMTP server : Simple Mail Transfer Protocol : The server which sends and receives mails. Postfix (or smtp).

  • IMAP server : Internet Message Access Protocol : The service which interacts with the SMTP server to access mail and send mail. Dovecot

  • These come preinstalled in most linux distributions.

Apart from these, other tricks that can be used by people to confuse simple minded, bread earning people like us are :

But again, not so fast. As with anything in linux, when you set off to configure something, you end up knowing much more than you bargained for. ;)

Aliases

Aliases are mappings between one source name and one or many destination name (in mail).

Aliases can be found out from flat files in the form of mapping, from sql queries or from ldap (man ldap_table). The source itself can be in the destination.

Link to alias files is given in /etc/postfix/main.cf at line
alias_maps = hash:/etc/aliases, ldap:/etc/postfix/ldap-aliases.cf

Type /usr/sbin/postmap -q core@pragyan.org ldap:/etc/postfix/ldap-aliases.cf to see its effects.

local_transport

The local_transport parameter corresponds to the mail delivery agent used.

  1. The default with postfix is local. The problem with local is that is requires local users and hence, a posixAccount schema to be an objectClass of every mail account. Rejected. Btw local also has to ability of mail forwarding to a user. i.e. if mailbox of user user1 is user1@gmail.com (user forwarding), then local will also forward to user1@gmail.com. By default, it assumes the uid of the user it is delivering mail to while delvering mail.

  2. Next is virtual. This is the one used. Virtual accepts users who are system users. But virtual (for security purposes) does not forward to hosts other than the localhost. So how do we forward to external hosts? virtual forwards in case the mails are aliases. So we simply put the gmail address as the entry of one of the aliases of the mail. If virtual MDA is used then whose uid does it use? (because the uid of the user himself doesn’t exist on the system). Another parameter value has to be used :

    1
    2
    3
    virtual_minimum_uid = 100 (security feature)
    virtual_uid_maps = static:700
    virtual_gid_maps = static:700
  3. Other mail delivery agents : procmail doesn’t understand LDAP, and maildrop has too much overhead.

Group expansion

Excellent notes are available in /usr/share/doc/postfix-2.4.3/README_FILES/LDAP_README.

Any “map” parameter value, like alias_maps, can be either given a flat mapping file name, or a .cf file, with tells it what to do to get the mapping, in this format : protocol:filename. Eg.

virtual_mailbox_maps = ldap:/etc/postfix/accountsmap.cf

Mail boxes

mbox is a format for storing mails. It is the default format used in postfix and dovecot. This is a line from dovecot conf :
mail_location = mbox:/var/spool/mail/virtual/PragyanMail/%u:INBOX=/var/spool/mail/virtual/%u

The first part (mbox:/var/spool/mail/virtual/PragyanMail/%u:INBOX=/var/spool/mail/virtual/%u) refers to the user’s mail folder, which contains all his mail folders (Trash, drafts, sent mail.. ) (the user’s mail folders are files in mbox format)

The second part (mbox:/var/spool/mail/virtual/PragyanMail/%u:INBOX=/var/spool/mail/virtual/%u) refers to the one specific user folder (i.e. server file) which postfix writes to, that is his INBOX. (All other folders are written to and handled by the IMAP client - dovecot.) Other variables which could have been used for specifying this are : %u - username, %n - user part in user@domain, same as %u if there’s no domain, %d - domain part in user@domain, %h - home directory etc.

A virtual user can specify his mail folder to be anywhere. So, the following is a security config for postfix INBOX files :

virtual_mailbox_base = /var/spool/mail/virtual

Also chmod g+s /usr/bin/procmail for it to be able to create mail directories

Maps specified in postfix

Maps are specified in /etc/postfix/main.cf. Important maps to be specified are :

  1. User aliases virtual_alias_maps - mapping between group@domain.org and user1@pragyan.org, user2@pragyan.org, …
  2. User mailboxes virtual_mailbox_maps - mapping between mailaddress (user1@pragyan.org) and mailbox location (/var/spool/mail/virtual/user1). A confirmation that the mail address corresponds to a real virtual user. For mail to be delivered, this entry needs to be there, which contains the mailbox address. This is but only a one to one mapping. (Ignores all following values)
    local_recipient_maps = $virtual_mailbox_maps
    This line is required whenever the local_transport is changed to something else. (in this case to virtual)

Schemas (The Real Working):

  • Ldap Entry evolutionPersonList


    contact (multiple) : links to others ldap entries : uid=sahil,ou=P... , uid=cyber, ou=.. , ...
    mail (multiple) : mails : sahilahuja@gmail.com, core@pragyan.org, ...
    listName (single) : list name : coding

  • main.cf entry : virtual_alias_maps = ldap:/etc/postfix/ldap-aliases.cf. Contents of ldap-aliases.cf :

    1
    2
    3
    4
    5
    6
    7
    8
    server_host = 10.0.0.126
    search_base = ou=Groups,ou=Pragyan,dc=delta,dc=nitt.edu
    query_filter = (&(objectClass=*)(listName=%u))
    result_attribute = mail
    special_result_attribute = contact
    bind = yes
    bind_dn = cn=dovecot,ou=Pragyan,dc=delta,dc=nitt.edu
    bind_pw = ******
    • The field matched is listName.
    • The query runs recursively runs on field “contact”.
    • All mails of form alias@pragyan.org again go through the same process.
  • Ldap entry evolutionPerson . Important thing in it is the mapping between uid and mail. It’s a proof to postfix the user is a real virtual user.

  • main.cf entry virtual_mailbox_maps = ldap:/etc/postfix/accountsmap.cf. Contents of accountsmap.cf :

    1
    2
    3
    4
    5
    6
    7
    server_host = 10.0.0.126
    search_base = ou=People,ou=Pragyan,dc=delta,dc=nitt.edu
    query_filter = (&(objectClass=*)(mail=%s))
    result_attribute = uid
    bind = yes
    bind_dn = cn=dovecot,ou=Pragyan,dc=delta,dc=nitt.edu
    [gallery]bind_pw = ******
  • The final main.cf entry that fits it all : virtual_mailbox_base = /var/spool/mail/virtual . A file with the name that is a result of the previous query (uid), gets created in this directory as the inbox of the user.
    Workflow is mailid → getaliases → Use alias result to get mail ids → deliver. That is, first alaises get processed, then accountsmap.

Here are the files I used finally :

  • Postfix : main.cf, accountsmap.cf, ldap-alias.conf
  • Dovecot : dovecot.conf, dovecot-ldap.conf
  • Here is a compilation of the final content of these files.

Here is the link of the guide I used as my own reference.