# HG changeset patch # User heiko # Date 1210076767 0 # Node ID c00369d0867fc91e045a49e4ad81c18136937253 # Parent 1972df4a58c04e202f3798cf5eea1ca6c3965224 - support for multiple OUs under the base (as found in /etc/mail/update-mailboxes.oulist) diff -r 1972df4a58c0 -r c00369d0867f 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__