# HG changeset patch # User Matthias Förste foerste@schlittermann.de # Date 1322132251 -3600 # Node ID a0ed03bc2e1d8d8f26b3074a0550d61f53103d2f # Parent cc9a80eb647c348b054bb8e765e38c555691fe62 ma acc --add should work diff -r cc9a80eb647c -r a0ed03bc2e1d Common.pm --- a/Common.pm Wed Nov 23 13:05:59 2011 +0100 +++ b/Common.pm Thu Nov 24 11:57:31 2011 +0100 @@ -28,9 +28,12 @@ # * account * default_domain => { ARGS => "=s", DEFAULT => "" }, imap_server => { ARGS => "=s", DEFAULT => "localhost" }, + imap_port => { ARGS => "=s", DEFAULT => "143" }, imap_admin => { ARGS => "=s", DEFAULT => $ENV{USER} }, imap_password =>{ ARGS => "=s" }, - imap_quota => { ARGS => "=i", DEFAULT => 300, ALIAS => "quota" }, + imap_quota => { ARGS => "=i", DEFAULT => 300 * 1024 * 1024, ALIAS => "quota" }, + # dovecots mail_location (%1, %u & %d supported) + imap_mail_location => { ARGS => "=s", DEFAULT => '/var/vmail/users/%d/%1/%u' }, mbox => { ARGS => "!", DEFAULT => 1 }, password => { ARGS => "=s" }, @@ -63,6 +66,7 @@ ldap_at_address => { ARGS => "=s", DEFAULT => "XXXmailAddress" }, ldap_at_group => { ARGS => "=s", DEFAULT => "XXXmailGroup" }, + ldap_at_quota => { ARGS => "=s", DEFAULT => "XXXmailQuota" }, ldap_at_forwardingaddress => { ARGS => "=s", DEFAULT => "XXXmailForwardingAddress" }, ldap_at_primaryaddress => diff -r cc9a80eb647c -r a0ed03bc2e1d account.pm --- a/account.pm Wed Nov 23 13:05:59 2011 +0100 +++ b/account.pm Thu Nov 24 11:57:31 2011 +0100 @@ -8,14 +8,14 @@ use Net::LDAP; use Net::LDAP::Constant qw(LDAP_ALREADY_EXISTS LDAP_NO_SUCH_OBJECT LDAP_TYPE_OR_VALUE_EXISTS); use Net::LDAP::Entry; -use Cyrus::IMAP::Admin; +use Mail::IMAPTalk; use Text::Wrap; use password; my $Cf; my ($ldap, $ubase, $abase); -my ($imap); +my ($imap, $imap_password); END { $imap and $imap = undef; }; @@ -33,6 +33,7 @@ sub AT_ADDRESS(); sub AT_GROUP(); sub AT_FORWARDINGADDRESS(); +sub AT_QUOTA(); sub import(@) { $Cf = shift; @@ -45,6 +46,7 @@ import constant AT_ADDRESS => $Cf->ldap_at_address; import constant AT_GROUP => $Cf->ldap_at_group; import constant AT_FORWARDINGADDRESS => $Cf->ldap_at_forwardingaddress; + import constant AT_QUOTA => $Cf->ldap_at_quota; $ubase = OU_ACCOUNTS . "," . $Cf->ldap_base; $abase = OU_ALIASES . "," . $Cf->ldap_base; @@ -57,11 +59,9 @@ password => $Cf->ldap_password || $ENV{LDAP_PASS} || password::ask("LDAP (". $Cf->ldap_bind_dn .") password: ")); die $r->error, "\n" if $r->code; - $imap = new Cyrus::IMAP::Admin or die $@; - $imap->authenticate(-server => $Cf->imap_server, -user => $Cf->imap_admin, - -password => $Cf->imap_password || $ENV{IMAP_PASS} || password::ask("IMAP (". $Cf->imap_admin .") password: ")) - or die $@; - + $imap = Mail::IMAPTalk->new(Server => $Cf->imap_server, Port => $Cf->imap_port) + or die "Can't connect to IMAP Server '", $Cf->imap_server, "', Port '", $Cf->imap_port, "': ", $@; + $imap_password = $Cf->imap_password || $ENV{IMAP_PASS} || password::ask("IMAP (". $Cf->imap_admin .") password: "); if ($Cf->list) { _list() } elsif ($Cf->add) { _add() } @@ -88,12 +88,19 @@ my $mailAddress = [$user, split /,/, $Cf->other || ""]; # ditto $user =~ s/!$//; # jetzt können wir ! nicht mehr brauchn - my $mbox = "user/$user"; my $cn = $Cf->fullname || $user; my $sn = (reverse split " ", $cn)[0]; my $mailGroup = [split /,/, $Cf->group || ""]; my $mailForwardingAddress = [split /,/, $Cf->forward || ""]; my $pw = _mkpw($Cf->password || "{pwgen}"); + # assuming usernames of the form localpart@domain + $user =~ /@(.+)$/; + my $escapes; + die "Invalid username '$user'" unless $escapes->{'%u'} = $user + and $escapes->{'%1'} = substr $user, 0, 1 + and $escapes->{'%d'} = $1; + my $mbox = $Cf->imap_mail_location; + $mbox =~ s/$_/$escapes->{$_}/ for keys %{$escapes}; if ($mailPrimaryAddress !~ /@/) { $mailPrimaryAddress .= "@" . $Cf->default_domain; @@ -139,9 +146,10 @@ $e->add((AT_ADDRESS) => $mailAddress); $e->add((AT_PRIMARYADDRESS) => $mailPrimaryAddress); - $e->add(userPassword => $pw); + $e->add(userPassword => "{plain}$pw"); $e->add((AT_GROUP) => $mailGroup) if @$mailGroup; $e->add((AT_FORWARDINGADDRESS) => $mailForwardingAddress) if @$mailForwardingAddress; + $e->add((AT_QUOTA) => $Cf->imap_quota); # $e->add(iusRestrictedMail => $Cf->internal) if $Cf->internal ne ":"; @@ -152,22 +160,24 @@ $r = $e->update($ldap); die $r->error if $r->code; - verbose("ok"); + verbose('ok'); verbose(" Password: $pw") if not $Cf->password or $Cf->password eq "{pwgen}"; } if($Cf->mbox) { verbose("\n\t$mbox..."); - if ($imap->list($mbox)) { verbose("exists") } + if (-d $mbox) { verbose('exists') } else { - $imap->create($mbox) and verbose("ok") or die $@; - $imap->setacl($mbox, $Cf->imap_admin => "lrswipcda") or die $@; - $imap->setquota($mbox, STORAGE => 1024 * $Cf->imap_quota) or die $@; + + $imap->login($user, $pw) or die $@; + # 'list' seems to trigger acl file (and thus the maildir) creation with dovecot + $imap->list('', '*') or die $@; + verbose('ok'); } + } - verbose("\n"); } @@ -187,7 +197,6 @@ my $user = $e->get_value("uid"); my $dn = $e->dn; - my $mbox = "user/$user"; my $modified = 0; verbose "$user:"; @@ -296,8 +305,8 @@ # FIXME: Wenn keine Mailbox existiert, gibt es hier ein Problem if (defined $Cf->imap_quota) { - $imap->setquota($mbox, STORAGE => $Cf->imap_quota * 1024) - or die $@; +# $imap->setquota($mbox, STORAGE => $Cf->imap_quota * 1024) +# or die $@; } verbose "ok\n"; @@ -322,7 +331,6 @@ foreach (@ARGV) { my $user = $_; my $dn = "uid=$user,$ubase"; - my $mbox = "user/$user"; verbose("$user:\n"); @@ -352,9 +360,11 @@ verbose("\n"); if ($Cf->mbox) { - verbose("\tdeleting mbox $mbox..."); - $imap->delete($mbox) and verbose("ok") - or verbose($imap->error); + verbose("\tdeleting mbox for $user..."); + my $m = user_dovecot( 'LOGIN' )->{'home'}; + if (not (defined $m and $m)) { verbose("can't determine mbox location - not deleting it"); } + elsif (not unlink $m) { verbose("Can't unlink $m: $!"); } + else { verbose('ok'); } } verbose("\n"); @@ -384,7 +394,6 @@ my $ml = join(", ", $e->get_value(AT_ADDRESS)) || ""; # ?? my $mg = join(", ", $e->get_value(AT_GROUP)) || ""; # ?? my $forw = join (", ", $e->get_value(AT_FORWARDINGADDRESS)) || ""; - my $mbox = "user/$uid"; print "$uid: $cn <$mr>"; @@ -392,13 +401,15 @@ #print " INTERNAL"; #} + $imap->login("$uid*" . $Cf->imap_admin, $imap_password ) or die $@; + MBOX: { - if (!$imap->list($mbox)) { + if (!$imap->list()) { print ", no mbox"; last MBOX; } print ", mbox"; - my %q = $imap->listquota($mbox); + my %q = $imap->listquota(); my ($used, $max) = map { int($_ / 1024) } @{$q{STORAGE}}; if (!$max) { diff -r cc9a80eb647c -r a0ed03bc2e1d ma --- a/ma Wed Nov 23 13:05:59 2011 +0100 +++ b/ma Thu Nov 24 11:57:31 2011 +0100 @@ -52,7 +52,6 @@ use warnings; use IO::File; -use Cyrus::IMAP::Admin; use AppConfig qw(:expand); use File::Basename; use FindBin; diff -r cc9a80eb647c -r a0ed03bc2e1d ma.conf.ex --- a/ma.conf.ex Wed Nov 23 13:05:59 2011 +0100 +++ b/ma.conf.ex Thu Nov 24 11:57:31 2011 +0100 @@ -18,7 +18,10 @@ at_forwardingaddress = XXXMailForwardingAddress at_primaryaddress = XXXMailPrimaryAddress at_group = XXXMailGroup +at_quota = XXXMailQuotaBytes [imap] admin = cyrus password = SECRET +server = localhost +port = 143