How to manage mailman list membership using LDAP or Active Directory

Run this perl script on your mailman server once an hour using cron. Replace MY_LDAP_SERVER etc. with your own configuration. Also, depending on your LDAP implementation you may need to use group or groupOfNames instead of posixGroup.

For each list you wish to manage, create an LDAP/AD group with the email attribute set to the full address of the mailing list. The script scans all groups under the BASE_DN for any with an email address ending in @MY.LIST.SERVER. It overwrites each list’s membership with that of the corresponding LDAP group (if such a group exists, otherwise it does nothing). Make sure there is only one group for each mailing list! Multiple domain names are not supported, but could be with only a little hacking.

#!/usr/bin/perl -w

use Net::LDAP;

# Connect to LDAP proxy and authenticate
$ldap = Net::LDAP->new('ldaps://MY_LDAP_SERVER') || die "Can't connect to server\n";
$mesg = $ldap->bind(
  password => 'MY_PASSWORD'
) || die "Connected to server, but couldn't bind\n";
# search for interesting AD groups
$mesg = $ldap->search(                 
  base   => "MY_BASE_DN",
  filter => "(&(objectClass=posixGroup))"
die "Search returned no interesting security groups\n" unless $mesg;
foreach $group ($mesg->entries) {
  $list_email = $group->get_value("mail");
  # For groups with emails of the form "*@MY.LIST.SERVER"                            
  # Try to chop off the name of our list server. If we fail, it wasn't meant to be.
  if($list_email && $list_email=~s/\@MY\.LIST\.SERVER$//) {
    # get the membership list   
    @member_list = $group->get_value("uniqueMember");
    die "Security group for list $list_email looks empty - PANIC!\n" unless @member_list;
    # make a list of emails to pass to mailman
    $member_emails = "";
    foreach $member_dn (@member_list) {
      $mesg2 = $ldap->search(
        base  => $member_dn,
        filter => "(&(cn=*))",
        scope => "base"
      die "Couldn't locate entry $member_dn - PANIC!\n" unless $mesg2;
      $member = $mesg2->entry(0);
      $member_emails .= $member->get_value("cn") . " get_value("mail") . ">\n";
    # now update the mailman list membership
    # be verbose!
    print "\nchanging $list_email\n";
    open( PIPE, "|/var/mailman/bin/sync_members -w=yes -g=yes -a=yes -f - $list_email" )
      || die "Couldn't fork process! $!\n";
    print PIPE $member_emails;
    close PIPE;

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s