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.
Table of Contents
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 pine, 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 perl or 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.
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: billg@microsoft.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: dancingmonkeyboy@microsoft.com telephoneNumber: +1 425 882 8080 postalAddress: One Microsoft Way $ Redmond, WA 98052-6399
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 cf/README
file:
dn: sendmailMTAKey=sendmail-list, dc=sendmail, dc=org objectClass: sendmailMTA objectClass: sendmailMTAAlias objectClass: sendmailMTAAliasObject sendmailMTAAliasGrouping: aliases sendmailMTAHost: etrn.sendmail.org sendmailMTAKey: sendmail-list sendmailMTAAliasValue: ca@example.org sendmailMTAAliasValue: eric sendmailMTAAliasValue: gshapiro@example.com
In this example, the sendmail-list alias would get expanded to ca@example.org, eric, and gshapiro@example.com.
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: billg@microsoft.com sendmailMTAAliasValue: dancingmonkeyboy@microsoft.com
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.
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.
The steps to accomplish this were relatively straightforward, once I waded through a mound of Google searches and sendmail
READMEs.
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.schema with two OID entries:
# Paul Heinlein's LDAP schemata # # Note: I, ahem, borrowed part of the Sendmail Private Enterprise # Number namespace for these OIDs. # attributetype ( 1.3.6.1.4.1.6152.945.2.1 NAME 'mailingListName' SUP name ) objectclass ( 1.3.6.1.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 include directives 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
objectClass: mailingListPerson
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:
mailingListName: microsoft-execs
Rebuild your sendmail.cf file. I’ll admit it, I’d rather use the m4 macros than do this by hand -- so I’m only going to show you the two additional
lines I added to my sendmail.mc file:
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 sendmail.cf and restart sendmail.
That should do it. You ought to be able to send mail to microsoft-execs@your.host.name and have it delivered to Messrs. Gates and Ballmer. (Bug reports would likely be appreciated :-)
Comments and suggestions about this document are appreciated and can be addressed to the author at <heinlein@madboa.com>.
This article is licensed under a Creative Commons License.