#!@l_prefix@/bin/perl ## ## dbmail-folders -- DBMail Folders Creation Utility ## Copyright (c) 2007-2008 Ralf S. Engelschall ## ## See also: ## http://www.dbmail.org/dokuwiki/doku.php?id=shared-mbox ## http://library.mobrien.com/dbmailadministrator/DBMA_ACLs.htm ## # language requirements require 5.008; use strict; use warnings; # load extensions use Getopt::Long; use DBI; use DBD::Pg; use DBIx::Simple; # command line argument parsing my $opt = { -help => 0, -hostname => ($ENV{"PGHOST"} || "localhost"), -database => ($ENV{"PGDATABASE"} || "dbmail" ), -username => ($ENV{"PGUSER"} || "dbmail" ), -password => ($ENV{"PGPASSWORD"} || "dbmail" ), }; my $p = new Getopt::Long::Parser; $p->configure("bundling"); $p->getoptions( 'h|help' => \$opt->{-help}, 'H|hostname=s' => \$opt->{-hostname}, 'D|database=s' => \$opt->{-database}, 'U|username=s' => \$opt->{-username}, 'P|password=s' => \$opt->{-password}, ) || die "option parsing failed"; undef $p; if ($opt->{-help} or @ARGV < 2) { printf(STDERR "USAGE: dbmail-folders [-h|--help]\n"); printf(STDERR " [-H|--hostname ] [-D|--database ]\n"); printf(STDERR " [-U|--username ] [-P|--password ]\n"); printf(STDERR " [[{ro,rw}:] ...]\n"); printf(STDERR "EXAMPLES:\n"); printf(STDERR "1. # create public folder #Public/ (fully shared)\n"); printf(STDERR " \$ dbmail-folders __public__ anyone\n"); printf(STDERR "2. # create personal shared folder #Users// (fully shared)\n"); printf(STDERR " \$ dbmail-folders anyone\n"); printf(STDERR "3. # create personal shared folder #Users// (fully shared, different access)\n"); printf(STDERR " \$ dbmail-folders ro:anyone rw:\n"); printf(STDERR "4. # create personal shared folder #Users// (partly shared)\n"); printf(STDERR " \$ dbmail-folders ...\n"); printf(STDERR "5. # create personal private folder #Users// (not shared)\n"); printf(STDERR " \$ dbmail-folders \n"); exit($opt->{-help} ? 0 : 1); } my $owner = shift(@ARGV); my $folder = shift(@ARGV); my @users = @ARGV; # connect to DBMail's PostgreSQL-based backend RDBMS my $db = DBIx::Simple->connect( sprintf("dbi:Pg:host=%s;dbname=%s", $opt->{-hostname}, $opt->{-database}), $opt->{-username}, $opt->{-password}, { RaiseError => 1, AutoCommit => 1 } ); die "failed to connect to database" if (not defined($db)); # ensure that the folder owner exists my ($owner_id) = $db->query(q{ SELECT user_idnr FROM dbmail_users WHERE userid = ?; }, $owner)->flat(); if (not defined $owner_id) { printf(STDERR "dbmail-folders:ERROR: folder owner \"%s\" not existing\n", $owner); exit(1); } # check whether folder already exists my ($mailbox_id) = $db->query(q{ SELECT mailbox_idnr FROM dbmail_mailboxes WHERE owner_idnr = ? AND name = ?; }, $owner_id, $folder)->flat(); if (not defined $mailbox_id) { # create it if still not existing $db->query(q{ INSERT INTO dbmail_mailboxes ( owner_idnr, name, seen_flag, answered_flag, deleted_flag, flagged_flag, recent_flag, draft_flag, no_inferiors, no_select, permission ) VALUES ( ?, ?, 1, 1, 1, 1, 1, 1, 0, 0, 2 ); }, $owner_id, $folder) or printf(STDERR "dbmail-folders:ERROR: unable to create folder \"%s/%s\": %s\n", $owner, $folder, $db->error()), exit(1); ($mailbox_id) = $db->query(q{ SELECT mailbox_idnr FROM dbmail_mailboxes WHERE owner_idnr = ? AND name = ?; }, $owner_id, $folder)->flat(); if (not defined $mailbox_id) { printf(STDERR "dbmail-folders:ERROR: unable to determine id of newly created folder\n"); exit(1); } } # optionally grant access to folder for additional users (beside folder owner) $db->query(q{ DELETE FROM dbmail_acl WHERE mailbox_id = ?; }, $mailbox_id); foreach my $user (@ARGV) { my $mode = "rw"; if ($user =~ m/^(r[ow]):(.+)$/) { $mode = $1; $user = $2; } my ($user_id) = $db->query(q{ SELECT user_idnr FROM dbmail_users WHERE userid = ?; }, $user)->flat(); if (not defined $user_id) { printf(STDERR "dbmail-folders:WARNING: user \"%s\" not existing\n", $user); next; } if ($mode eq "rw") { $db->query(q{ INSERT INTO dbmail_acl ( user_id, mailbox_id, lookup_flag, read_flag, seen_flag, write_flag, insert_flag, post_flag, create_flag, delete_flag, administer_flag ) VALUES ( ?, ?, 1, 1, 1, 1, 1, 1, 1, 1, 1 ); }, $user_id, $mailbox_id); } else { $db->query(q{ INSERT INTO dbmail_acl ( user_id, mailbox_id, lookup_flag, read_flag, seen_flag, write_flag, insert_flag, post_flag, create_flag, delete_flag, administer_flag ) VALUES ( ?, ?, 1, 1, 0, 0, 0, 0, 0, 0, 0 ); }, $user_id, $mailbox_id); } } # make sure at least owner is subscribed to folder my ($exists) = $db->query(q{ SELECT 1 FROM dbmail_subscription WHERE user_id = ? AND mailbox_id = ?; }, $owner_id, $mailbox_id)->flat(); if (not (defined $exists and $exists)) { $db->query(q{ INSERT INTO dbmail_subscription ( user_id, mailbox_id ) VALUES ( ?, ? ); }, $owner_id, $mailbox_id); } # disconnect from DBMail's PostgreSQL-based backend RDBMS $db->disconnect(); undef $db; # die gracefully exit(0);