#!/usr/bin/perl
#
# sendmal2qmail.pl ver. 2.0 - creates users with their maildirs from an old sendmail structure ( /var/spool/mail/user, /etc/passwd, /etc/shadow, /home/user/... )
#  by Phil2k@gmail.com
#


$mailbox2maildir="/usr/local/sbin/mailbox2maildir.pl < #MAILBOX#";
$uid=getpwnam("vpopmail");
$gid=getgrnam("vpopmail");
$maildir_name=".maildir";

$vpopmail="/var/vpopmail";
$vuserinfo="$vpopmail/bin/vuserinfo";
$vadduser="$vpopmail/bin/vadduser";
$vmoduser="$vpopmail/bin/vmoduser";
$min_uid=500;
$max_uid=65533;

#####
$passwd="";
$shadow="";

if ($#ARGV<2) {
  print "Syntax: $0 <domain> <sendmail_mail_spool_path> <sendmail_users_passwd_file> [<sendmail_users_shadow_file>] [<min_uid>] [<max_uid>]\n";
  exit(1);
  }

$cwd=qx!pwd!;
chomp($cwd);

$domain=$ARGV[0];

$mailbox_path=$ARGV[1];
$mailbox_path=~s/\/+$//;  
#print "$mailbox_path\n";

$passwd=$ARGV[2];
if ($#ARGV>2) {
  $arg=$ARGV[3];
  if ((int($arg) eq $arg) && (($#ARGV==3) || (int($ARGV[4]) eq $ARGV[4]))) {
    $shadow=undef;
    $min_uid=$arg;
    } else {
    $shadow=$arg;
    }
  }
if ($#ARGV>3) {
  $arg=$ARGV[4];
  if (!defined($shadow)) {
    $max_uid=$arg;
    } else {
    $min_uid=$arg;
    }
  }
if ($#ARGV>4) {
  $arg=$ARGV[5];
  if (defined($shadow)) {
 
    $max_uid=$arg;
    }
  }
if (!defined($shadow)) { $shadow=""; }

if ($passwd=~/\//) {
  $sm_root1=&dirname(&dirname($passwd));
  }
if ($shadow=~/\//) {
  $sm_root2=&dirname(&dirname($shadow));
  } else {
  $sm_root2=$sm_root1;
  }
if ($mailbox_path=~/\//) {
  $sm_root3=&dirname(&dirname(&dirname($mailbox_path)));
  }
if (($sm_root1 eq "") || ($sm_root1 ne $sm_root2)) {
  print "Plese enter old(sendmail) root path where ( please ENTER for $sm_root3 ): ";
  $sm_root=<STDIN>;
  chomp($sm_root);
  if ($sm_root=~/^\s*$/) { $sm_root=$sm_root3; }
  } else {
  $sm_root=$sm_root1;
  }

print "Get users lists ... ";
%users=();
open FILE, $passwd or die "Cannot open file $passwd: $!\n";
while($line=<FILE>) {
  ($user, $pass, $uuid, $ugid, $gecos, $homedir, $shell)=split(/:/, $line);
  next if (($uuid<$min_uid) || ($uuid>$max_uid));
  $users{$user}=[ ($pass, $gecos, $homedir) ];
  }
close FILE;

if (defined($shadow) && length($shadow)) {
  open FILE, $shadow or die "Cannot open file $shadow: $!\n";
  while($line=<FILE>) {
    ($user, $pass, $tmp)=split(/:/, $line);
    if (exists($users{$user}) && ($users{$user}->[0] eq "x")) {
      $users{$user}->[0]=$pass;
      }
    }
  close FILE;
  }
print "done (".scalar(keys %users)." users).\n";

# get mailboxes names
%mailbox=();
opendir DIR, $mailbox_path;
while($file=readdir(DIR)) {
  #next if (($file=~/^\.{1,2}$/) || (!-f $mailbox_path."/".file));
  next if ($file=~/^\.{1,2}$/);
  $mailbox{$file}=$mailbox_path."/".$file;
  #print $mailbox{$file}."\n";
  }
closedir DIR;

#exit(0);
##

foreach $user (keys %users) {
  ($pass, $gecos, $sm_homedir)=@{$users{$user}};
  if ($gecos eq "") { $gecos=$user; }
  $email=$user.'@'.$domain;
  
  # Get qmail homedir
  $res=qx!$vuserinfo -d $email 2>&1!;
  if ($res=~/no such user/) {
    print "Adding $email ... ";
    $cmd="$vadduser -c '$gecos' -e '$pass' $email";
    system($cmd);
    print "done.\n";
    $res=qx!$vuserinfo -d $email 2>&1!;
    if ($res=~/no such user/) {
      print STDERR "Cannot add $email !";
      exit(1);
      }
    }
  chomp($res);
  $homedir=$res; # qmail
  
  $maildir="$homedir/$maildir_name";
  if (!-d $maildir) {
    &make_maildir($maildir, 0);
    }
  
  # look for messages in mailbox:
  if (exists($mailbox{$user})) {
    &mailbox2maildir($mailbox{$user}, $maildir);
    }
  
  # look for other folders
  $sm_folderlist_file=$sm_root.$sm_homedir."/.mailboxlist";
  print "look for $sm_folderlist_file\n";
  @folders=();
  if (-e $sm_folderlist_file) {
    open FILE, $sm_folderlist_file;
    while($line=<FILE>) {
      chomp($line);
      $folder=$line;
      if (-e $sm_root.$sm_homedir."/".$folder) {
        &make_maildir($maildir."/.".$folder, 1);
        &mailbox2maildir($sm_root.$sm_homedir."/".$folder, $maildir."/.".$folder);
        }
      push @folders, $folder;
      }
    close FILE;
    }
  if ($#folders>-1) {
    print "Found subfolders ( ".join(',', @folders)." ) !\n";
    }
  push @folders, "INBOX";
  open FILE, ">$maildir/subscriptions";
  foreach $folder (@folders) {
    print FILE "$folder\n";
    }
  close FILE;
  
  system("chown -R $uid:$gid $maildir");
  }

sub make_maildir {
  my ($dir, $subfolder)=@_;
  my @dirs=("new", "cur", "tmp");
  my $d;
  local *FILE;
  
  mkdir $dir, 0700;
  chown $uid, $gid, $dir;
  foreach $d (@dirs) {
    mkdir $dir."/".$d, 0700;
    chown $uid, $gid, $dir."/".$d;
    }
  if ($subfolder) {
    open FILE, ">$dir/maildirfolder";
    close FILE;
    chown $uid, $gid, $dir."/maildirfolder";
    }
  }

sub mailbox2maildir {
  my ($mailboxpath, $maildirpath)=@_;
  my $cmd=$mailbox2maildir;
  $cmd=~s/#MAILBOX#/$mailboxpath/g;
  print "moving $mailboxpath => $maildirpath ... ";
  #print "($cmd) ";
  chdir($maildirpath);
  $res=qx!$cmd|grep ^Writing|wc -l!;
  chomp($res);
  chdir($cwd);
  print "done ($res messages).\n";
  }

sub dirname {
  my $path=$_[0];
  $path=~s/[^\/]+$//;
  $path=~s/\/$//;
  return $path;
  }