package MailDumper;

use Fcntl qw/O_RDONLY O_BINARY/;
use File::Basename;
use Imapd2Md;
use Logging;

use constant MAILBOX_MBX => 1;
use constant MAILBOX_MBOX => 2;
use constant MAILBOX_MAGIC_LENGTH => 5;

sub convertMail {
  my ($domainRoot, $userName, $tmpDir) = @_;
  Logging::debug("Converting mail of user '$userName' stored in '$domainRoot'");

  $convertedMailDir = $tmpDir . '/Maildir';
  if (! -d $convertedMailDir) {
    mkdir($convertedMailDir, 0700) or die "Can't create temporary mail directory '$convertedMailDir': $!";
  }

  # mb2md.pl was initially taken from http://batleth.sapienti-sat.org/projects/mb2md/mb2md-3.20.pl.gz
  my $mb2mdPath = dirname(__FILE__) . '/shared_legacy/mb2md.pl';

  # inbox messages stored in mailbox format in var/spool/mail
  my $inboxFile = $domainRoot . "/var/spool/mail/" . $userName;
  if (-f $inboxFile) {
    Logging::debug("Converting inbox content stored in '$inboxFile'");
    `/usr/bin/perl $mb2mdPath -s $inboxFile -d $convertedMailDir`;
  }

  # all other messages (except inbox) are stored in IMAP format in user's home directory
  my $mailHome = $domainRoot . "/home/" . $userName;
  my @mail;
  my $mailBoxList = $mailHome . "/.mailboxlist";
  if (-f $mailBoxList) {
    open MAILBOXLIST, "<$mailBoxList";
    binmode MAILBOXLIST;
    while (<MAILBOXLIST>) {
      chomp;
      if (-f "$mailHome/$_") {
        push @mail, $_;
      }
    }
  }
  if (@mail) {
    foreach my $mailFolder(@mail) {
      Logging::debug("Converting '$mailFolder' content");
      my $sourceMailbox = File::Spec->catfile($mailHome, $mailFolder);
      my $destPath = $mailFolder;
      $destPath =~ s/^mail//g;
      $destPath =~ s/^\///g;
      $destPath =~ s/\./_/g;
      $destPath =~ s/\//\./g;
      $destPath = ".$destPath";

      my $mailboxType = getMailboxType($sourceMailbox);
      if (defined($mailboxType) and $mailboxType == MAILBOX_MBX) {
        my $conversionResult = Imapd2Md::convertit( $sourceMailbox, "$convertedMailDir/$destPath" );
        if ($conversionResult) {
          Logging::info("Failed to convert '$mailFolder' content stored in '$sourceMailbox': '$conversionResult'");
        }
      } elsif (defined($mailboxType) and $mailboxType == MAILBOX_MBOX) {
        `/usr/bin/perl $mb2mdPath -s '$sourceMailbox' -d $convertedMailDir/$destPath`;
      } else {
        Logging::debug("Unknown type of '$mailFolder' content stored in '$sourceMailbox', it will be skipped");
      }
      system("touch", "$convertedMailDir/$destPath/maildirfolder") if -e "$convertedMailDir/$destPath";
    }
  }
}

sub getMailboxType($) {
  my ($mailboxFilename) = @_;
  sysopen(MAILBOX, $mailboxFilename, O_RDONLY | O_BINARY) or return undef;
  my $magic = '';
  my $bytesRead = read(MAILBOX, $magic, MAILBOX_MAGIC_LENGTH);
  close(MAILBOX);

  if( $bytesRead != MAILBOX_MAGIC_LENGTH ) {
    return undef;
  }

  if ($magic eq 'From ') {
    return MAILBOX_MBOX;
  } elsif ($magic eq '*mbx*') {
    return MAILBOX_MBX;
  } else {
    return undef;
  }
}

1;