- support for multiple OUs under the base (as found in /etc/mail/update-mailboxes.oulist) lv-doktor
authorheiko
Tue, 06 May 2008 12:26:07 +0000
branchlv-doktor
changeset 10 c00369d0867f
parent 9 1972df4a58c0
child 11 7446e196dc31
- support for multiple OUs under the base (as found in /etc/mail/update-mailboxes.oulist)
update-mailboxes
--- a/update-mailboxes	Fri Apr 18 08:48:10 2008 +0000
+++ b/update-mailboxes	Tue May 06 12:26:07 2008 +0000
@@ -12,58 +12,66 @@
 use Pod::Usage;
 use if $ENV{DEBUG} => "Smart::Comments";
 
-my $ME       = basename $0;
-my $PRIVATE  = "$ENV{HOME}/private/accounts";
-my $LDAPCONF = "/etc/ldap/ldap.conf";
-my $SERVER   = "localhost";
+my $ME        = basename $0;
+my $PRIVATE   = "$ENV{HOME}/private/accounts";
+my $LDAPCONF  = "/etc/ldap/ldap.conf";
+my $SERVER    = "localhost";
 my $BLACKLIST = "/etc/mail/update-mailboxes.blacklist";
+my $OULIST    = "/etc/mail/update-mailboxes.oulist";
 
-my $opt_delete  = 0;
-my $opt_protocol= undef;
-my $opt_help    = 0;
-my $opt_man     = 0;
-my $opt_verbose = -t STDOUT;
-
+my $opt_delete   = 0;
+my $opt_protocol = undef;
+my $opt_help     = 0;
+my $opt_man      = 0;
+my $opt_verbose  = -t STDOUT;
+my $opt_dry	     = 0;
 
 sub get_credentials($$);
 
-my ($USER, $PASS) = get_credentials($PRIVATE => "cyrusadmin");
-my ($LDAPADMIN, $LDAPPASS) = get_credentials($PRIVATE => "ldapadmin");
+my ( $USER,      $PASS )     = get_credentials( $PRIVATE => "cyrusadmin" );
+my ( $LDAPADMIN, $LDAPPASS ) = get_credentials( $PRIVATE => "ldapadmin" );
 
-my ($LDAPBASE, $LDAPSERVER);
+my ( $LDAPBASE, $LDAPSERVER );
 {
-    open(my $in, $LDAPCONF);
+    open( my $in, $LDAPCONF );
     $_ = join "", <$in>;
     ($LDAPBASE)   = /^\s*BASE\s+(.*?)\s*$/ms;
     ($LDAPSERVER) = /^\s*URI\s+(.*?)\s*$/ms;
-    $LDAPBASE = "ou=proconcept,$LDAPBASE";
+}
+
+my @OU;
+{
+    open( my $in, $OULIST );
+    @OU = grep /^(?!#)\S+/, map { /(\S+)/; $1 } <$in>;
 }
 
 my %BLACK;
-if (open(my $in, $BLACKLIST)) {
-	while (<$in>) { chomp;
-		s/#.*//;
-		s/^\s*(.*)\s*$/$1/;
-		next if not $_;
-		$BLACK{$_} = 1;
-	}
+if ( open( my $in, $BLACKLIST ) ) {
+    while (<$in>) {
+        chomp;
+        s/#.*//;
+        s/^\s*(.*)\s*$/$1/;
+        next if not $_;
+        $BLACK{$_} = 1;
+    }
 }
 
 MAIN: {
     Getopt::Long::Configure("bundling");
     GetOptions(
-	"p|protocol=s" => \$opt_protocol,
-        "d|delete"   => \$opt_delete,
-        "v|verbose!" => \$opt_verbose,
-        "man"        => \$opt_man,
-        "help"       => \$opt_help,
+        "p|protocol=s" => \$opt_protocol,
+        "d|delete"     => \$opt_delete,
+        "v|verbose!"   => \$opt_verbose,
+		"n|dry!"       => \$opt_dry,
+        "man"          => \$opt_man,
+        "help"         => \$opt_help,
     ) or pod2usage();
 
-    pod2usage(-exitval => 0, -verbose => 3) if $opt_man;
-    pod2usage(-exitval => 0, -verbose => 1) if $opt_help;
+    pod2usage( -exitval => 0, -verbose => 3 ) if $opt_man;
+    pod2usage( -exitval => 0, -verbose => 1 ) if $opt_help;
 
     $opt_verbose and $| = 1
-      or open(STDOUT, ">/dev/null");
+      or open( STDOUT, ">/dev/null" );
 
     # IMAP anzapfen
     my $imap = new Mail::IMAPClient(
@@ -74,94 +82,112 @@
 
     my %folder = map { $_, 1 } grep !m{/.*/}, $imap->folders();
 
-    # LDAP anzapfen
-    my $ldap = new Net::LDAP($LDAPSERVER, onerror => "die");
-    $ldap->bind($LDAPADMIN, password => $LDAPPASS);
-    my $msg = $ldap->search(
-        base   => $LDAPBASE,
-        filter => "(&(samAccountName=*))",
-        attrs  => ["samAccountName"],
-    );
-    die "$ME: keine LDAP-Einträge gefunden\n" if $msg->count == 0;
+    # LDAP anzapfen und erstmal die Einträge sammeln (ist notwendig,
+    # weil wir jetzt mehrere Gruppen haben und der ADS leider nicht
+    # (ou:dn:=*) versteht
+
+    my @entries;
+    {
+        my $ldap = new Net::LDAP( $LDAPSERVER, onerror => "die" );
+        $ldap->bind( $LDAPADMIN, password => $LDAPPASS );
+        foreach my $ou (@OU) {
+            my $msg = $ldap->search(
+                base   => "$ou,$LDAPBASE",
+                filter => "(&(samAccountName=*))",
+                attrs  => ["samAccountName"],
+            );
+            push @entries, $msg->entries;
+        }
+
+    }
+    die "$ME: keine LDAP-Einträge gefunden\n" if not @entries;
 
     my %mbox;
-    while (my $e = $msg->pop_entry) {
+    foreach my $e (@entries) {
+
+        my $mbox = $e->get_value("samAccountName");
 
-    	my $mbox = $e->get_value("samAccountName");
-	
-	if ($BLACK{$mbox}) {
-		print "$mbox blacklisted\n";
-		next;
-	}
+        if ( $BLACK{$mbox} ) {
+            print "$mbox blacklisted\n";
+            next;
+        }
 
         my $folder = "user/$mbox";
 
         print "$folder: ";
-	if ($imap->exists($folder)) {
-		print "exists\n";
-		$mbox{$mbox} = $folder;
-		next;
-	}
+
+        if ( $imap->exists($folder) ) {
+            print "exists\n";
+            $mbox{$mbox} = $folder;
+            next;
+        }
+
+		if ($opt_dry) {
+			$mbox{$mbox} = $folder;
+			print " doing nothing (dry run)\n";
+			next;
+		}
 
         print "creating ";
-	if (!$imap->create($folder)) {
-          	warn "$folder: $@\n";
-		next;
-	}
+        if ( !$imap->create($folder) ) {
+            warn "$folder: $@\n";
+            next;
+        }
 
-	$mbox{$mbox} = $folder;
+        $mbox{$mbox} = $folder;
         print "acl ";
 
-        if (!$imap->setacl($folder, $USER, "lrswipcda")) {
-          warn "$folder: $@\n";
-          next;
-	}
+        if ( !$imap->setacl( $folder, $USER, "lrswipcda" ) ) {
+            warn "$folder: $@\n";
+            next;
+        }
 
         print "ok\n";
     }
 
-	delete @folder{values %mbox};
+    delete @folder{ values %mbox };
 
     # now check if there are still folders we didn't touch;
-    delete @folder{map { "user/$_" } keys %mbox};
+    delete @folder{ map { "user/$_" } keys %mbox };
 
-    if (keys %folder) {
-        print scalar(keys %folder)
+    if ( keys %folder ) {
+        print scalar( keys %folder )
           . " unused mailboxe(s):\n" . "\t"
-          . join("\n\t", keys %folder) . "\n";
+          . join( "\n\t", keys %folder ) . "\n";
 
-        if ($opt_delete) {
+        if ($opt_delete && $opt_dry == 0) {
             print "deleting unused mailboxes\n";
-            foreach (keys %folder) {
+            foreach ( keys %folder ) {
                 print "$_ ";
                 $imap->delete($_) and print "ok\n"
                   or warn "$_: ($@)\n";
             }
         }
-	else {
-	    %mbox = (%mbox, %folder);
-	}
+        else {
+            %mbox = ( %mbox, %folder );
+        }
 
     }
 
     if ($opt_protocol) {
-    	open(my $o, ">$opt_protocol") or die "Can't open >$opt_protocol: $!\n";
-	print $o join "\n",
-		"# Liste der Mailboxen (nur zur Info)",
-		"# updater: $0 " . '($Id$)', 
-		sort(keys %mbox),
-		"";
+        open( my $o, ">$opt_protocol" )
+          or die "Can't open >$opt_protocol: $!\n";
+        print $o join "\n", "# Liste der Mailboxen (nur zur Info)",
+          "# updater: $0 "
+          . '($Id$)',
+          sort( keys %mbox ), "";
     }
 
     exit 0;
 }
 
 sub get_credentials($$) {
-	my ($file, $pattern) = @_;
-	open(my $fh, $file) or die "Can't open $file: $!\n";
-	my (undef, $u, $p) = (split /\s*:\s*/, (grep /^$pattern\s*:/, <$fh>)[0]);
-	chomp($u, $p);
-	return($u, $p);
+    my ( $file, $pattern ) = @_;
+    open( my $fh, $file ) or die "Can't open $file: $!\n";
+    my ( undef, $u, $p ) =
+      ( split /\s*:\s*/, ( grep /^$pattern\s*:/, <$fh> )[0] );
+    chomp( $u, $p );
+    return ( $u, $p );
 }
 
 __END__