Migrating a single user from MBX or MBOX mailbox format to Maildir++

Environment

  • Postfix with procmail as MDA
  • MBX IMAPd: UW-IMAP
  • Maildir IMAPd: Dovecot (used via ssh and pre-authentication only)
  • Mails arrive by default in /var/mail/%u and UW-IMAP moves them to /var/imap/%1u/%u/INBOX on INBOX selection.
  • mbox_snarf plugin for Dovecot can't snarf to Maildir mailboxes -> no option for us
  • We use the Maildir++ Extension for subfolders as used by Dovecot and Courier. This means the Maildir subfolder "xyz" is named ".xyz" on the filesystem.

Order

Below are several steps described in detail. Some of them have to be done several times, so here's the right order:

  • Create a Maildir backup folder.
  • Close all MUA usually accessing the account.
  • Convert all mailboxes not receiving mails by the MDA/MTA.
  • Make procmail defer all incoming mails.
  • Fire up the MUA (or issue a01 select INBOX and a02 logout in /etc/rimapd) once to move the mails received since closing the MUA get moved from /var/mail/%u to /var/imap/%1u/%u by UW-IMAPd.
  • Convert all incoming mailboxes.
  • Move the INBOX to the new place.
  • Adapt the procmail delivery rules from dmail/tmail to deliver directly to the appropriate Maildir.
  • Remove the deferring procmail rules inserted above.

Create a Maildir backup folder

Create a Maildir folder in which backups of Mails deferred during the migration will be saved. Example is for the user "abe", you will need to adjust the path appropriately.

maildirmake /var/imap/a/abe/.MigrationBackup

maildirmake is a tool provided by e.g. Dovecot or Courier.

If everything goes fine, this folder can be removed after the migration since the MTA will try to deliver the mails again until we remove the block described below.

Make procmail defer all incoming mails

For minimized risk, all mails which the MDA attempted to deliver get deferred and saved to the backup mailbox created in the previous step.

Add the following lines between the variable and the rules section of your .procmailrc, i.e. very close to the top so that it matches all incoming mails amd all others rules are not evaluated. A log file helps diagnosting potientally occuring errors.

LOGFILE=/home/abe/procmail-migration.log
EXITCODE=75
:0
/var/imap/a/abe/.MigrationBackup/

As soon as the '.procmailrc' has been saved, the migration has begun.

Convert all existing mailboxes

Shell script which converts all MBX boxes given as parameter. They should all reside in the current directory. (still the braindump version)

 #!/bin/sh

set -e
mkdir -pv CONVERTED_MAILBOXES;
for mbx in "$@" ; do
    type=`file "./$mbx" | awk '{print $2}'`
    if [ "$type" != "MBX" ]; then
        echo "$mbx is no MBX mailbox"
        exit 1;
    fi

    if [ -d "./.$mbx" ]; then
        echo ".$mbx already exists"
        exit 2;
    fi
    mv -vi "./$mbx" "./$mbx.mbx"
    echo "Converting $mbx.mbx to mbox format at $mbx.mbox"
    mbxcat "./$mbx.mbx" > "./$mbx.mbox"
    echo "Creating Maildir at .$mbx"
    maildirmake "./.$mbx"
    echo "Converting mbox to Maildir"
    mb2md -s `pwd`"/$mbx.mbox" -d `pwd`"/.$mbx"
    mv -vi "./$mbx.mbox" "./$mbx.mbx" CONVERTED_MAILBOXES/
done

:!: mb2md needs absolute paths, otherwise, even with "./" or "../" prepended, paths will be relative to the home directory of the executing user!

:?: License of the mbxcat program is currently unclear. We will publish a link or download as soon as this has been checked and is suitable for redistribution. Contact us if you need information about it earlier.

This will also convert the "INBOX". So we have to move it manually to the right place:

mv -vi .INBOX/* ./
rmdir -v .INBOX

Finally we need to add all those mails received into /var/mail/%u while doing the migration:

mb2md -s /var/mail/abe -d /var/imap/a/abe/

(I hope they will show up there since I had cases where mails added with a second call of mb2md made the newly added mails invisible in the MUA, but existent on disk. I will see. -- Axel)

Change all rules using dmail or tmail

Change all occurrences of e.g.

| dmail +mailfolder
| dmail =mailfolder
| tmail +mailfolder
| tmail =mailfolder

to

/var/imap/a/abe/.mailfolder/

:!: It is essential that the trailing slash is present in the folder name, otherwise procmail will not recognize it as Maildir folder.

Note that we change the action from piping to a command to directly delivering to a Maildir mailbox. (dmail was needed before because procmail can't deliver to MBX mailboxes.)