Building Sendmail Mailing Lists in LDAP
If you already keep e-mail addresses in an LDAP database, it’s possible to tweak things a bit so that sendmail can lookup mailing list addresses in it.
First published on April 21, 2002
Last updated on June 4, 2004
At home, I’ve slowly been migrating all address-book data to an LDAP directory running on my Linux box. It’s not a huge directory (a couple hundred entries), but it’s comprehensive enough that I rely on it fairly heavily.
In particular, I use it for e-mail address lookups from within
while my wife does the same from within Eudora on her Windows box.
I’ve thought for some time that it’d be just too cool to be able to
build mailing lists using live LDAP data. It’d be fairly easy to build a
sendmail aliases file, or even a pine
.addressbook, using a
shell script – but that seemed like a needless extra step.
For some time, sendmail has supported using LDAP for maps, aliases, and classes, so I finally decided it was time to learn how to implement at least the aliases stuff on my home system.
Now that I’ve got it working successfully, I thought I’d pass along how I did it, just so you don’t have to repeat all the doc-wading and mistake-making that I did.
My LDAP directory
I have just two main subtrees in my LDAP directory, people and hosts:
+ dc=heinlein, dc=net | + ou=people | | | + cn=Bill Gates | | | + cn=Steve Ballmer | | | + ... | + ou=hosts | + ...
From the beginning of my LDAP explorations, I’ve tried to use standard schemata instead of home-brewed ones, a habit that proved handy when it came time to transition from OpenLDAP 1.x to the stricter 2.x. The “people” subtree of my home directory is based on the inetOrgPerson object class, e.g.,
dn: cn=Bill Gates, ou=people, dc=heinlein, dc=net objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson ou: people cn: Bill Gates cn: William Gates, III cn: Borg Boy givenName: William sn: Gates mail: email@example.com telephoneNumber: +1 425 882 8080 postalAddress: One Microsoft Way $ Redmond, WA 98052-6399 dn: cn=Steven Ballmer, ou=people, dc=heinlein, dc=net objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson ou: people cn: Steven Ballmer cn: Steve Ballmer cn: Fred Astaire NOT givenName: Steven sn: Ballmer mail: firstname.lastname@example.org telephoneNumber: +1 425 882 8080 postalAddress: One Microsoft Way $ Redmond, WA 98052-6399
The sendmail.schema shortfall
Sendmail includes a
.schema file that defines some object classes and
attribute types that could be used to build LDAP-based alias maps.
Here’s the example from the current
dn: sendmailMTAKey=sendmail-list, dc=sendmail, dc=org objectClass: sendmailMTA objectClass: sendmailMTAAlias objectClass: sendmailMTAAliasObject sendmailMTAAliasGrouping: aliases sendmailMTAHost: etrn.sendmail.org sendmailMTAKey: sendmail-list sendmailMTAAliasValue: email@example.com sendmailMTAAliasValue: eric sendmailMTAAliasValue: firstname.lastname@example.org
In this example, the sendmail-list alias would get expanded to email@example.com, eric, and firstname.lastname@example.org.
This would work well if you maintained mailing lists that were largely unrelated to any other data in your LDAP directory.
For me, however, the sendmail schemata are problematic because I don’t want to have to edit the same e-mail address in two places. Let’s say that I built a microsoft-execs list and included
sendmailMTAAliasValue: email@example.com sendmailMTAAliasValue: firstname.lastname@example.org
If Bill were to change his e-mail address, I’d have to touch it in two places: my original people record and the microsoft-execs alias record.
In some instances, this might be a good thing. Someone might want to receive different alias mailings at different e-mail addresses. In that case, the sendmail way of doing things is much more flexible than what I wanted.
A different goal
My goal was to be able to build mailing lists from LDAP records I already have on hand in such a way that changing the original people record would automatically update all the aliases associated with that person. So, for instance, if I had my parents’ record associated with a bunch of aliases (all-friends, all-family, nuclear-family); then when they finally ditched AOL (fat chance!), I’d only have to update the one record for all the aliases to be accurate.
Getting it done
The steps to accomplish this were relatively straightforward, once I
waded through a mound of Google searches and sendmail
Oh, I probably ought to note that I did all this on an x86 box running Red Hat 7.1 and the standard sendmail and openldap packages. I didn’t have to rebuild anything (though I’ve hand-built both sendmail and OpenLDAP in other contexts).
Make sure your sendmail is compiled with LDAP support. Run the following command:
sendmail -d0.1 -bv postmaster
You should see “LDAPMAP” in the “Compiled with:” section. If you don’t, you’ll have to rebuild sendmail, an operation outside the scope of this document.
Make sure your ldap server is running properly (as if you’d read this far if it weren’t…).
The tricky part: add/use the appropriate object classes and attribute types to add a mailing list entry to your people records.
I’ll tell you what I did – and you’re of course welcome to copy it – but your solution may be somewhat different than mine.
I created a file called
/etc/openldap/schema/heinlein.schemawith two OID entries:
# Paul Heinlein's LDAP schemata # # Note: I, ahem, borrowed part of the Sendmail Private Enterprise # Number namespace for these OIDs. # attributetype ( 18.104.22.168.4.1.6152.945.2.1 NAME 'mailingListName' SUP name ) objectclass ( 22.214.171.124.4.1.6152.945.1.1 NAME 'mailingListPerson' SUP inetOrgPerson STRUCTURAL MAY mailingListName ) # # eof #
The objectclass mailingListPerson builds on the inetOrgPerson class and adds just one attribute: mailingListName. I tried to be as unintrusive as possible when it comes to adding new LDAP definitions.
Add the new schemata to your slapd.conf file. If you’re running OpenLDAP 2.x, you’ll find a bunch of
includedirectives toward the top of the configuration file. Just add another line with the path to the new .schema file you created.
Restart slapd to let the new schemata take effect.
Alter your person records. For each person entry, I added
Then I added a mailingListName attribute for each alias. To make Bill and Steve part of the microsoft-execs alias, you’d add the following attribute to each of their entries:
sendmail.cffile. I’ll admit it, I’d rather use the
m4macros than do this by hand – so I’m only going to show you the two additional lines I added to my
define(`ALIAS_FILE', `/etc/aliases,ldap: -v mail -k (mailingListName=%0)')dnl define(`confLDAP_DEFAULT_SPEC', `-h localhost -b dc=heinlein,dc=net')dnl
The second line tells sendmail to use the LDAP server running on localhost and to make all searches with the base dn of
dc=heinlein,dc=net. (Note: you can specify multiple hosts behind the -h switch; if the first server times out, sendmail will check the second one, and so on.)
The first line tells sendmail to look for aliases first in the traditional /etc/aliases dbm file. If it’s not there, then use LDAP: search for all records that include a mailingListName entry for the alias in question (%0 gets expanded, obviously). In each of the returned records, find the recipient’s e-mail address in the attribute called “mail.”
Once you’ve edited the .mc file, then rebuild
That should do it. You ought to be able to send mail to email@example.com and have it delivered to Messrs. Gates and Ballmer. (Bug reports would likely be appreciated :-)