Difference between revisions of "Maildir to zmmailbox with bash"

Line 1: Line 1:
Place this script in your /home directory (/home NOT /home/USER/ !!!) and run. Script will import all emails from "cur" and "new" directories from /home/*/Maildir/ (and all subdirectories) into /Import IMAP folder.
+
== What's new ==
  
<pre>
+
I decided to rewrite Jarosław's script to fix a few bugs I stumbled upon while migrating my bare-Postfix server to Zimbra, namely:
#!/bin/bash
+
 
 +
* all folders were merged into the main folder due to a bug in the script (hint: '=' instead of '==').
 +
* folders with spaces in their name were not imported and caused an error
 +
* import messages from accounts across multiple domains, if needed
 +
* made the code readable
 +
* no need for two loops
 +
 
 +
 
 +
== How to use ==
 +
 
 +
The script expects to find the mailboxes in the current path! The structure of maildirs must be as follows:
 +
 
 +
domain/username/{cur|new|tmp}
 +
domain/username/subfolder1/{cur|new|tmp}
 +
domain/username/subfolder2/{cur|new|tmp}
 +
...
  
#
+
After the script has run, every zimbra user will have a subfolder in his mailbox called 'old-mbox' (feel free to change the name at the beginning of the script).
# Maildir to Zimbra import
+
The hierarchy of subfolders is maintained under old-mbox.
#
 
# Created by Jarosław Czarniak on 26-10-2008
 
#
 
  
clear
+
== The code ==
chown -R zimbra:zimbra *
 
  
domain="jarsat.pl" # change to your domain!
+
<pre>
IMPORT="/Import"
+
#!/bin/bash
  
 +
# Postfix virtual transport -> Zimbra mailbox migration
 +
# written by NERvOus (http://www.nervous.it)
  
for user in `ls -d1 */|sed s/\\\///`
+
# base folder where msgs will be imported
do
+
BFOLDER="old-mbox"
    echo
+
ZMMBOX="/opt/zimbra/bin/zmmailbox"
    echo "User $user"
+
BDIR=$(pwd)
    echo
 
    echo "createFolder $IMPORT" > /tmp/tmp.txt
 
    /opt/zimbra/bin/zmmailbox -z -m $user@$domain < /tmp/tmp.txt
 
  
    #
+
echo You must run $0 from inside /var/mail/virtual directory
    # CUR
+
echo $0 expects to find the mailboxes in the current path!
    #
+
echo The structure of maildirs must be as follows:
    for sciezka in `find $user -maxdepth 10 -type d -name cur`
+
echo
    do
+
echo "domain/username/{cur|new|tmp}"
    echo
+
echo "domain/username/subfolder1/{cur|new|tmp}"
    echo "Directory $sciezka"
+
echo "domain/username/subfolder2/{cur|new|tmp}"
    echo
+
echo ...
 +
echo  
 +
echo All folders will be stored in a subfolder called $BFOLDER
 +
echo The hierarchy of subfolders will be maintained under $BFOLDER.
 +
echo
 +
echo Press Enter to start, CTRL+C to abort.
 +
read
  
    nazwa=`echo $sciezka|cut -f3 -d"/"|sed s/\\\.//`
+
# handle folders with a space inside, they are more common than you may
    if [ "$nazwa" = "cur" ]
+
# think
        then
+
IFS='
            echo "addMessage ${IMPORT} $PWD/$user/Maildir/cur" > /tmp/tmp.txt
+
'
            /opt/zimbra/bin/zmmailbox -z -m $user@$domain < /tmp/tmp.txt
 
        else
 
            echo "createFolder ${IMPORT}/$nazwa" > /tmp/tmp.txt
 
            /opt/zimbra/bin/zmmailbox -z -m $user@$domain < /tmp/tmp.txt
 
            echo "addMessage ${IMPORT}/$nazwa ${PWD}/${sciezka}" > /tmp/tmp.txt
 
            /opt/zimbra/bin/zmmailbox -z -m $user@$domain < /tmp/tmp.txt
 
    fi
 
    done
 
  
    #
+
for p in $(find . -type d -name cur); do
    # NEW
+
        DOMAIN=`echo $p | cut -d'/' -f2`
    #
+
        UNAME=`echo $p | cut -d'/' -f3`
    for sciezka in `find $user -maxdepth 10 -type d -name new`
+
        DIRNAME=`echo $p | cut -d'/' -f4`
    do
+
        # this may fail, if folder already exists. Who cares. Ignore the
    echo
+
        # error.
    echo "Directory $sciezka"
+
        echo createFolder /$BFOLDER | $ZMMBOX -z -m $UNAME@$DOMAIN
    echo
+
        if [ "$DIRNAME" == "cur" ]; then
    nazwa=`echo $sciezka|cut -f3 -d"/"|sed s/\\\.//`
+
                echo Importing INBOX folder for $UNAME@$DOMAIN from $BDIR/$DOMAIN/$UNAME/ 1>&2
    if [ "$nazwa" = "new" ]
+
                # we are importing the top level folder
        then
+
                echo addMessage /$BFOLDER $BDIR/$DOMAIN/$UNAME/cur | $ZMMBOX -z -m $UNAME@$DOMAIN
            echo "addMessage ${IMPORT} $PWD/$user/Maildir/new" > /tmp/tmp.txt
+
                echo addMessage /$BFOLDER $BDIR/$DOMAIN/$UNAME/new | $ZMMBOX -z -m $UNAME@$DOMAIN
            /opt/zimbra/bin/zmmailbox -z -m $user@$domain < /tmp/tmp.txt
 
 
         else
 
         else
            echo "createFolder ${IMPORT}/$nazwa" > /tmp/tmp.txt
+
                DIRNAME=$(echo $DIRNAME | sed -e 's/\/cur$//')
            /opt/zimbra/bin/zmmailbox -z -m $user@$domain < /tmp/tmp.txt
+
                echo Importing folder $DIRNAME for $UNAME@$DOMAIN from $BDIR/$DOMAIN/$UNAME/$DIRNAME 1>&2
            echo "addMessage ${IMPORT}/$nazwa ${PWD}/${sciezka}" > /tmp/tmp.txt
+
                echo createFolder \'/$BFOLDER/$DIRNAME\' | $ZMMBOX -z -m $UNAME@$DOMAIN
            /opt/zimbra/bin/zmmailbox -z -m $user@$domain < /tmp/tmp.txt
+
                echo addMessage \'/$BFOLDER/$DIRNAME\' \'$BDIR/$DOMAIN/$UNAME/$DIRNAME/cur\' | $ZMMBOX -z -m $UNAME@$DOMAIN
    fi
+
                echo addMessage \'/$BFOLDER/$DIRNAME\' \'$BDIR/$DOMAIN/$UNAME/$DIRNAME/new\' | $ZMMBOX -z -m $UNAME@$DOMAIN
    done
+
        fi
 
done
 
done
 +
 +
 
</pre>
 
</pre>
 +
 +
  
 
[[Category:Migration]]
 
[[Category:Migration]]

Revision as of 17:53, 20 December 2009

What's new

I decided to rewrite Jarosław's script to fix a few bugs I stumbled upon while migrating my bare-Postfix server to Zimbra, namely:

  • all folders were merged into the main folder due to a bug in the script (hint: '=' instead of '==').
  • folders with spaces in their name were not imported and caused an error
  • import messages from accounts across multiple domains, if needed
  • made the code readable
  • no need for two loops


How to use

The script expects to find the mailboxes in the current path! The structure of maildirs must be as follows:

domain/username/{cur|new|tmp} domain/username/subfolder1/{cur|new|tmp} domain/username/subfolder2/{cur|new|tmp} ...

After the script has run, every zimbra user will have a subfolder in his mailbox called 'old-mbox' (feel free to change the name at the beginning of the script). The hierarchy of subfolders is maintained under old-mbox.

The code

#!/bin/bash

# Postfix virtual transport -> Zimbra mailbox migration
# written by NERvOus (http://www.nervous.it)

# base folder where msgs will be imported
BFOLDER="old-mbox"
ZMMBOX="/opt/zimbra/bin/zmmailbox"
BDIR=$(pwd)

echo You must run $0 from inside /var/mail/virtual directory
echo $0 expects to find the mailboxes in the current path!
echo The structure of maildirs must be as follows:
echo 
echo "domain/username/{cur|new|tmp}"
echo "domain/username/subfolder1/{cur|new|tmp}"
echo "domain/username/subfolder2/{cur|new|tmp}"
echo ...
echo 
echo All folders will be stored in a subfolder called $BFOLDER
echo The hierarchy of subfolders will be maintained under $BFOLDER.
echo 
echo Press Enter to start, CTRL+C to abort.
read

# handle folders with a space inside, they are more common than you may
# think
IFS='
'

for p in $(find . -type d -name cur); do
        DOMAIN=`echo $p | cut -d'/' -f2`
        UNAME=`echo $p | cut -d'/' -f3`
        DIRNAME=`echo $p | cut -d'/' -f4`
        # this may fail, if folder already exists. Who cares. Ignore the
        # error.
        echo createFolder /$BFOLDER | $ZMMBOX -z -m $UNAME@$DOMAIN
        if [ "$DIRNAME" == "cur" ]; then
                echo Importing INBOX folder for $UNAME@$DOMAIN from $BDIR/$DOMAIN/$UNAME/ 1>&2
                # we are importing the top level folder
                echo addMessage /$BFOLDER $BDIR/$DOMAIN/$UNAME/cur | $ZMMBOX -z -m $UNAME@$DOMAIN
                echo addMessage /$BFOLDER $BDIR/$DOMAIN/$UNAME/new | $ZMMBOX -z -m $UNAME@$DOMAIN
        else
                DIRNAME=$(echo $DIRNAME | sed -e 's/\/cur$//')
                echo Importing folder $DIRNAME for $UNAME@$DOMAIN from $BDIR/$DOMAIN/$UNAME/$DIRNAME 1>&2
                echo createFolder \'/$BFOLDER/$DIRNAME\' | $ZMMBOX -z -m $UNAME@$DOMAIN
                echo addMessage \'/$BFOLDER/$DIRNAME\' \'$BDIR/$DOMAIN/$UNAME/$DIRNAME/cur\' | $ZMMBOX -z -m $UNAME@$DOMAIN
                echo addMessage \'/$BFOLDER/$DIRNAME\' \'$BDIR/$DOMAIN/$UNAME/$DIRNAME/new\' | $ZMMBOX -z -m $UNAME@$DOMAIN
        fi
done


Jump to: navigation, search