ma acc --add should work foerste
authorMatthias Förste foerste@schlittermann.de
Thu, 24 Nov 2011 11:57:31 +0100
branchfoerste
changeset 41 a0ed03bc2e1d
parent 40 cc9a80eb647c
child 42 b90dc89e8c66
ma acc --add should work
Common.pm
account.pm
ma
ma.conf.ex
--- 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 => 
--- 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) {
--- 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;
--- 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