Dovecot to Zarafa Migration
From Zarafa wiki
This article is a community contribution and may include unsupported configurations.
I had to import all mails from a remote mailserver running dovecot-imapd. Below you'll find a python-script doing the imports and recreating the folder structure. In order to access the files on the remote mailserver I used sshfs, which can come in quite handy in cases like these.
You're using this script on your own risk - I don't take any responsibility for damaged, lost, destroyed, blown-up data / hardware /cities or any other harmful things or financial loss or whatever someone might think of, which might be directly or indirectly caused by using this code.
Christof Klaus
#!/usr/bin/python
# -*- coding: utf-8 -*-
#################################################
# file: dovecot-to-zarafa.py
# creationdate: 09/30/2010
# author: Christof Klaus
#
# loops through the files / folders of a maildir and calls zarafa-dagent
# with the appropriate params in order to recreate the maildir folder structure in
# zarafa and to import the mails into these folders
#
# furthermore, a conversion of the umlaut-representations that seem to be used in dovecot
# folder storage to latin-1 is being done..
#
# this file has only been tested on a maildir of a dovecot mailserver.
# no guarantee that it works for any other type of imap-server like cyrus, courier or whatever
#
# creates as many threads as maildir/user-combinations are given.
# call with: ./dovecot-to-zarafa.py <path-to-maildir> <zarafausername> [ <path-to-maildir2> <zarafausername2> ...]
#
#################################################
import sys, os
from threading import Thread
class looper(Thread):
def __init__(self, maildir, username):
Thread.__init__(self)
self.maildir = maildir
self.username = username
def dagent_cmd(self, folder, file, read=False):
cmd = '/usr/bin/zarafa-dagent '
if folder:
# do special-char replacements
charmap = {'&-':'&', '&AN8-':'ß', '&AMQ-':'Ä', '&AOQ-':'ä', '&ANY-':'Ö','&APY-':'ö', '&ANw-':'Ü', '&APw-':'ü'}
for k,v in charmap.items(): folder = folder.replace(k,v)
cmd += ' --create -p "." --folder "%s" ' % (folder)
cmd += '-s '
if read: cmd += ' --read '
cmd += ' -f "%s" %s' % (file, self.username)
cmd = unicode(cmd, 'utf-8')
cmd = cmd.encode('latin-1')
os.system(cmd)
def loop_maildir(self, fld, read=True, create_in_folder=):
if os.path.exists(fld) and os.path.isdir(fld):
for sfn in os.listdir(fld):
mp = '%s/%s' % (fld, sfn)
self.dagent_cmd(create_in_folder, mp, read)
def run(self):
for fn in os.listdir(self.maildir): # examine every subfolder, starting with a "."
np = '%s/%s' % (self.maildir, fn)
# a default maildir folder, at least with dovecot
if fn[0] == '.':
if os.path.isdir(np):
print "d2z@%s, importing: %s" % (self.username, fn[1:])
self.loop_maildir('%s/cur' % np, True, fn[1:])
self.loop_maildir('%s/new' % np, False, fn[1:])
self.loop_maildir('%s/tmp' % np, True, fn[1:])
# the "inbox"-folders on toplevel.
elif fn in ['cur','new','tmp']:
print "d2z@%s, importing: inbox/%s" % (self.username, fn)
self.loop_maildir(np, True, )
## MAIN MAIN MAIN
args = sys.argv
bad_args = True
if len(args) >= 3:
args = args[1:]
if divmod(len(args),2)[1] == 0: bad_args = False
if not bad_args:
threads = []
for i in range(0, len(args),2):
maildir = args[i]
username = args[i+1]
if os.path.exists(maildir):
print "starting thread for maildir: %s, username: %s" % (maildir, username)
t = looper(maildir, username)
threads.append(t)
t.start()
else:
print "not starting thread for maildir: %s, username: %s, directory does not exist." % (maildir, username)
if bad_args:
print "insufficient /incorrect number of arguments given.\nusage: dovecot-to-zarafa.py <path-to-maildir> <zarafausername> [ <path-to-maildir2> <zarafausername2> ] ..."
More informations: http://forums.zarafa.com/viewtopic.php?f=10&t=427&view=unread#p24736