I was wondering ... does anybody mind if I add this script to the Wiki? I recently created an entry about the non-working 'reconstruct -m' command (http://asg.web.cmu.edu/twiki/bin/view/Cyrus/ReconstructMailboxes), and it'd be nice to offer /some/ recovery option for people who've been bitten by mailboxes.db issues and don't have a backup.
Ideally, of course, everybody would just do good backups that included a plaintext mailboxes.db - but it's been shown by the list traffic that not everybody realises how critical the mailboxes.db is and how hard it is to reconstruct.
Naturally this would need to be prefaced with a warning about the loss of ACL information - a "use as a last resort only" warning.
Hank Beatty wrote:
Many thanks to Scott Adkins and Joe Hrbek for all of their help.
Here are a couple of scripts that I wrote to rebuild the mailboxes.db. The scripts do not take into account default domain, basic or no directory hashing, multiple partitions, and possibly other things, but I figured they might give someone a head start if they run into this problem.
shell script "repairMBoxDB"
#!/bin/sh #stop Cyrus imapd before running this script
#get the directories ls -R /var/spool/imap/* | grep "/" > /bin/scripts/mboxRepair/directories
#run perl repair script (this doesn't actually do any repairing) /bin/scripts/mboxRepair/mboxRepair.pl
#cp the file to Cyrus' home directory and change the ownership cp /bin/scripts/mboxRepair/newMBoxList /home/cyrus/ chown cyrus:mail /home/cyrus/newMBoxList
#save off the current mailboxes.db mv /var/imap/mailboxes.db /var/imap/mailboxes.db.backup
#import the new mailbox list su - cyrus -c "umask 077 ; /usr/cyrus/bin/ctl_mboxlist -u < /home/cyrus/newMBoxList"
#EOF
perl script mboxRepair.pl
#!/usr/bin/perl
&openDirectoriesFile;
&rewriteFormat;
&scriptExit;
sub openDirectoriesFile { my ($lSuccess, $lName);
$lName = "directories";
$lSuccess = open (fhDirectories, "/bin/scripts/mboxRepair/$lName");
if (!$lSuccess) {
print "Didn't open " . $lName . ": $!\n";
&scriptExit ();
}
}
sub scriptExit {
close (fhDirectories);
close (fhNewMBoxList);
exit();
}
sub rewriteFormat {
my ($lSuccess, $lNewLine, $lCount, $lArrayCount, $lSortedCount);
my (@lArray, @lUnsortedArray, @lSortedArray);
$lName = "newMBoxList";
$lSuccess = open (fhNewMBoxList, ">/bin/scripts/mboxRepair/$lName");
if (!$lSuccess) {
print "Didn't open " . $lName . ": $!\n";
&scriptExit ();
}
$lArrayCount = 0;
while(<fhDirectories>){
chomp; # no newline
s/#.*//; # no comments
s/^\s+//; # no leading white
s/\s+$//; # no trailing white
next if ($_ =~ m/\/mail:$/); # no lines ending with
/mail:
s/:$//; # no ending colons
s/^\/var\/spool\/imap\///; # no /var/spool/imap/
next if ($_ !~ m/\//); # get rid of any line that
doesn't
have a /
s/domain\/[A-Z]//; # get rid of domain/A, domain/B,
domain/C, etc.
s/^\///; # no / at the beginning of
a line
next if ($_ !~ m/\//); # get rid of any line that
doesn't
have a /
next if ($_ !~ m/\/user\//); # get rid of any line that
doesn't
have /user
next unless length; # anything left?
@lArray = split ("/", $_);
$lNewLine = sprintf ("%s!%s.%s", $lArray[0], $lArray[2],
$lArray[3]);
$lCount = 4;
while ($lArray[$lCount]) {
$lNewLine = sprintf ("%s.%s", $lNewLine, $lArray[$lCount]);
$lCount++;
}
#now we are going to put it into an array so we can sort it
$lUnsortedArray[$lArrayCount] = $lNewLine;
$lArrayCount++;
}
@lSortedArray = sort { $a cmp $b } @lUnsortedArray;
#now take the sorted array and put it in the proper format and
#write it to a file
while ($lSortedArray[$lSortedCount]) {
@lArray = split (/\./, $lSortedArray[$lSortedCount]);
$lArray[2] =~ s/\^/\./;
my @lDomain = split (/!/, $lSortedArray[$lSortedCount]);
$lNewLine = sprintf ("[EMAIL PROTECTED]",
$lSortedArray[$lSortedCount], $lArray[2], $lDomain[0]);
print fhNewMBoxList "" . $lNewLine . "\n"; # write to a new
file
$lSortedCount++;
}
}