User Migration


Migration from one mail system to another is often painful. It can result in a user having to look in two different places to find mail, or in the worst case mail disappearing.

Copying the contents of one mail system to another often seems like a good idea, that way if anything goes wrong at least the old mail is still available. Ideally you know exactly what you are going to do at the start, you move everything across, and then you kill the old mail system (or at least make it not visible from mail clients). That way users are not confused by having two sets of identical folders.

In reality you may have to learn on the job. After user data has been migrated to Zimbra, users can access their mail via the web client without any additional setup until their mail client has been configured to access the Zimbra server.

Migrating Mail

Bulk Creating the Accounts

The first step in migrating users is to create the accounts, this is a topic of its own at Bulk Create

Migrating from an existing IMAP server (Recommended Method)

Currently, the recommended method for migrating users to Zimbra from an existing IMAP server is with the imapsync tool written by Gilles Lamiral. The following guide to imapsync was originally posted to the forums by GertThiel:

Before you can use imapsync you must have both the source IMAP message store and ZCS up running and accessible to user accounts via IMAP. You can check that using an email client before starting the migration. You will need the login names (i.e. email addresses) and passwords for the users to be migrated. In addition, imapsync will not be able to authenticate to the Zimbra server until you enable clear text login for the IMAP service. You can set that option under the IMAP tab of the Global Settings or individual Server settings in the Zimbra Admin Console UI. There are also a few Perl module dependances, including; Digest::MD5, IO::Socket::SSL,Term::ReadKey, Digest:HMAC libmail:imapclient. You can install these with your favorite package manager, from RPM's or with cpan. Finally, consider that imapsync will be a heavy load on your CPU and memory; the system running the migration will be less responsive.

For this example my existing IMAP server is running on server.gtds.lan and I set up Zimbra on a new machine named zimbra.gtds.lan.

   imapsync --nosyncacls --subscribe --syncinternaldates \
   --host1 server.gtds.lan --user1 yourAccount --password1 yourPassword \
   --host2 zimbra.gtds.lan --user2 yourZimbraAccount --password2 yourZimbraPassword

Of course the complete command belongs on one line (signified by the backslashes: \).

A slightly more secure method is to write each password into a separate file, and then use the --passfile{1|2} options intead of the --password{1|2} options:

   imapsync --nosyncacls --subscribe --syncinternaldates \
   --host1 server.gtds.lan --user1 yourAccount --passfile1 yourPasswordFile \
   --host2 zimbra.gtds.lan --user2 yourZimbraAccount --passfile2 yourZimbraPasswordFile

If your old IMAP server doesen't support NAMESPACE you have to also add appropriate options for example on iMail 6.0 --sep1 . --prefix1 INBOX. are required.

You may interrupt imapsync at any time with CTRL-C. Simply restart the same command again to resume the migration. You can also run it more than once to sync changes for a staged migration.

I used imapsync to migrate from a Cyrus IMAPd to Zimbra. The ReadMe lists a number of other IMAP servers compatible with imapsync.

Here is a script to download and build imapsync and all of the required packages.

#!/bin/bash
#
#CopyLeft 2006 Steve Fink
#stevef-at-ublug.org
#
#This script will get all of
#the necessary packages to
#build imapsync 1.182 except OpenSSL
#OpenSSL & it's development libraries are
#required and OpenSSL is usually installed
#already so check and get the matching libraries
#
#you have to run this script as root
#or under sudo so it can do all the installs
#
#I don't recommend doing the extended tests
#they mostly fail anyway but imapsync still works


mkdir imapsync
cd imapsync
#
wget http://search.cpan.org/CPAN/authors/id/D/DC/DCONWAY/Parse-RecDescent-1.94.tar.gz
tar xvfpz Parse-RecDescent-1.94.tar.gz
rm Parse-RecDescent-1.94.tar.gz
cd Parse-RecDescent-1.94/
perl Makefile.PL
make
make install
#
cd ..
wget http://search.cpan.org/CPAN/authors/id/G/GA/GAAS/Digest-MD5-2.33.tar.gz
tar xvfpz Digest-MD5-2.33.tar.gz
rm Digest-MD5-2.33.tar.gz
cd Digest-MD5-2.33/
perl Makefile.PL
make
make install
#
cd ..
wget http://search.cpan.org/CPAN/authors/id/J/JS/JSTOWE/TermReadKey-2.30.tar.gz
tar xvfpz TermReadKey-2.30.tar.gz
rm TermReadKey-2.30.tar.gz
cd TermReadKey-2.30/
perl Makefile.PL
make
make install
#
cd ..
wget http://search.cpan.org/CPAN/authors/id/A/AS/ASPA/IO-Socket-SSL-0.81.tar.gz
tar xvfpz IO-Socket-SSL-0.81.tar.gz
rm IO-Socket-SSL-0.81.tar.gz
cd IO-Socket-SSL-0.81/
perl Makefile.PL
make
make install
#
cd ..
wget http://search.cpan.org/CPAN/authors/id/F/FL/FLORA/Net_SSLeay.pm-1.30.tar.gz
tar xvfpz Net_SSLeay.pm-1.30.tar.gz
rm Net_SSLeay.pm-1.30.tar.gz
cd Net_SSLeay.pm-1.30/
./Makefile.PL -t
make install
#
cd ..
wget http://search.cpan.org/CPAN/authors/id/D/DJ/DJKERNEN/Mail-IMAPClient-2.2.9.tar.gz
tar xvfpz Mail-IMAPClient-2.2.9.tar.gz
rm Mail-IMAPClient-2.2.9.tar.gz
cd Mail-IMAPClient-2.2.9/
perl Makefile.PL
make
make test
make install
#
cd ..
wget http://www.linux-france.org/prj/imapsync/dist/imapsync-1.182.tgz
tar xvfpz imapsync-1.182.tgz
rm imapsync-1.182.tgz
cd imapsync-1.182/
perl -c imapsync
make install
#
cd ..
cd ..
rm -Rf imapsync/

Save this script as buildimapsync, chmod 755 buildimapsync, sudo buildimapsync

Note: see [Talk:User_Migration discussion] if you're having problems with the imapsync source.


SSL

You can also do SSL version of imapsync, by calling the "imapsync-ssl" and providing "--ssl1" and/or "--ssl2" for each of the accounts you wish to migrate.

Batch Proccessing

You can automate multiple users by using this script.

    #!/bin/bash
    
    logfile="sinklog.txt"
    
    host1=123.123.123.123
    #host1 is Source
    
    host2=321.321.321.321
    #host2 is Dest
    
    domain=xyz.com
    #domain is where email account is
    #everything after @ symbol
    
    ###### Do not modify past here
    #######################################
    
    date=`date +%X_-_%x`
    
    echo "" >> $logfile
    echo "------------------------------------" >> $logfile
    echo "IMAPSync started..  $date" >> $logfile
    echo "" >> $logfile
    
    { while IFS=';' read  u1 p1; do 
            user=$u1"@"$domain    
    	     echo "Syncing User $user"
            date=`date +%X_-_%x`
            echo "Start Syncing User $u1"
            echo "Starting $u1 $date" >> $logfile
    imapsync --nosyncacls --syncinternaldates --host1 $host1 --user1 "$user" --password1 \ 
    "$p1"--host2 $host2 --user2 "$user" --password2 "$p1"
            date=`date +%X_-_%x`
            echo "User $user done"
            echo "Finished $user $date" >> $logfile
            echo "" >> $logfile
    
            done ; } < userlist.txt
    
    date=`date +%X_-_%x`
    
    echo "" >> $logfile
    echo "IMAPSync Finished..  $date" >> $logfile
    echo "------------------------------------" >> $logfile

Now create a CSV file with the user names and passwords in the following format.

    user;password
    user2;password2


Here is a second batch script that will allow different usernames on the Source and Destination servers. Name this file imapsyncbatch then chmod to 755 execute with ./imapsyncbatch can be used with the --dry option for a dry run.

        #!/bin/bash
        ##Modified by Steve Fink stevef-at-ublug.org
	##This IMAPSync Batch Script is used when you have different
	##usernames on the Source and Destination servers
	##(kinda what IMAPSync was intended for)
	##the format for the user-list.csv file is
	##sourceusername,sourcepassword,destinationusername,destinationpassword 
	
	## Get the info
		while [ -z $infile ]; do
			echo "What is the path to the input file?"
			read infile
		done
		while [ -z $host1 ]; do
			echo "What is the Source Host? (mail1.domain.com)"
			read host1
		done
		while [ -z $host2 ]; do
			echo "What is the Destination Host? (mail2.domain.com)"
			read host2
		done
		while [ -z $domain ]; do
			echo "What is the Domain? (domain.com)"
			read domain
		done
		while [ -z $logfile ]; do
			echo "Where would you like the log? (synclog.txt)"
			read logfile
		done

		if [ ! -f $infile ]
        	then
                	{
				echo "The input file does not exist!"
				echo ""
				echo "What is the path to the input file?"
				read infile
			}
		fi
		
		INPUTFILE=$infile
		
		clear
		echo ""
		echo ""
		echo "IMAPSync is about to begin using:"
		echo "Input File $INPUTFILE"
		echo "Source Host $host1"
		echo "Destination Host $host2"
		echo "Domain $domain"
		echo "Log File $logfile"
		echo ""
		echo ""
		echo "Is this information correct?"
                echo "Press Enter to continue or"
		echo "Hit CTRL+C to start over"
		read wait

	## Begin IMAPSync
		date=`date +%X_-_%x`
		echo "IMAPSync Logfile started @ $logfile"
		echo "" >> $logfile
		echo "------------------------------------" >> $logfile
    		echo "IMAPSync started..  $date" >> $logfile
    		echo "" >> $logfile

	#Get rid of the commas
		tr "," " " <$INPUTFILE | while read u1 p1 u2 p2
			do

        			user=$u1"@"$domain
           			user2=$u2"@"$domain
             			echo "Syncing User $user to $user2"
            			date=`date +%X_-_%x`
            			echo "Start Syncing User $user to $user2"
            			echo "Starting $u1 $date" >> $logfile
    				imapsync $1 --nosyncacls --syncinternaldates \
				--exclude "#KnownSpam" --exclude "#FalsePositives" \
				--exclude "Trash" --exclude "Deleted Items" \
				--exclude "Deleted Messages" --exclude "Deleted" \
				--exclude "Sent" --exclude "Sent Items" \
				--exclude "Sent Messages" \
				--host1 $host1 --user1 "$user" --password1 "$p1" \
				--host2 $host2 --user2 "$user2" --password2 "$p2"
            			date=`date +%X_-_%x`
            			echo "User $user to $user2 done"
            			echo "Finished $user to $user2 $date" >> $logfile
            			echo "" >> $logfile

            		done

    		date=`date +%X_-_%x`

    		echo "" >> $logfile
    		echo "IMAPSync Finished..  $date" >> $logfile
    		echo "------------------------------------" >> $logfile

The format for the .csv file for this script is: sourceusername,sourcepassword,destinationusername,destinationpassword

Migrating from POP3

pop2imap is a tool used to get a pop inbox and syncronise it to an IMAP folder. You can get it from [1]

It is very similar to imapsync above.

   pop2imap  \
   --host1 some.pop.com.au --user1 yourAccount --passfile1 yourPasswordFile \
   --host2 zimbra.imap.com.au --user2 yourZimbraAccount --passfile2 yourZimbraPasswordFile \
   --folder MyOldPOPMail

Will copy the INBOX on your pop account to MyOldPOPMail folder.

There are some problems with pop2imap though.

  • It will not create the folder, you must have that manually created
  • It does not support SLL, however this is easy to do with "stunnel" - providing the SSL tunnel to the server
  • It downloads all of the messages first to get headers, although some pop servers do this well, many do not and this is a very time consuming operation. Modifications to the script are simple to skip this step and force a copy of the mail (technically no longer a sync, but a straight copy).

Also check this out... http://www.athensfbc.com/imap_tools/ it has batch mode with lists built in for all activities...POP3-IMAP, IMAP-IMAP...

Migrating from Dovecot

See User_Migration_From_Dovecot_With_External_LDAP

Migrating from iMail

The first step is to export the users information including the password. I used this utility for CommuniGate Pro which creates a fixed length file. I then coverted it to a Tab-Delimited file with this utility so that I could use the Bulk Create process. After you create your Domains and provision the accounts, turn on IMAP4 for iMail and use the IMAP migration process.

Migrating from Exchange

There are a least two ways to migrate the content of the individual MS Exchange user. First, is to use Zimbra Wizard. Second, is to export the content of MS Exchange to .pst file and restore it once Zimbra profile is created for a corresponding Zimbra user.

See forums: Migration from Exchange

Migrating from MBOX files

The MBOX file format is commonly used by many programs, most notably sendmail. The advantage of migrating from MBOX files is that no passwords or special accounts are needed. The following perl script will forward from an MBOX file to the designated address, while preserving attachments:

    #!/usr/bin/perl

    use strict;
    use Email::Folder;
    use Mail::Mailer;
    use MIME::Parser;
    use Net::SMTP;

    my $mbox = $ARGV[0];
    my $email = $ARGV[1];
    my $server = $ARGV[2];

    $server = 'smtp' if(!defined($server));

    die "Usage: $0 mbox dest_address [smtp server]" if(!defined($mbox) || !-f $mbox);
    die "Usage: $0 mbox dest_address [smtp server]" if(!defined($email) || $email !~ m/\@/);

    my $folder = Email::Folder->new($mbox ||
        die "Usage: $0 mbox dest_address [smtp server]
        Forward all mail found in mail file mbox to address.
    ");

    my $count=0;
    my @messages=$folder->messages;
    my $total=@messages;

    foreach (@messages){
        $count++;
        my $parser = new MIME::Parser;
        $parser->output_under("/tmp");
        $parser->decode_headers(0);
        $parser->ignore_errors(1);
        my $entity = $parser->parse_data($_->as_string);
        my $header = $entity->head;
        my $sender = $entity->head->get('From');
        next if $header->get("subject") =~ m/FOLDER INTERNAL/;
        $header->replace('To', $email);
        $header->delete('Received');
        $header->delete('MIME-Version');
        $header->delete('Return-Path');
        $header->delete('User-Agent');
        $header->delete('Message-ID');
        $header->delete('X-Mailer');
        $header->delete('X-Security');
        $header->delete('X-Spam-Checker-Version');
        $entity->head($header);
        $entity->sync_headers;
        print "Message $count / $total\n";
        print "Sending message with subject: " . $entity->head->get("subject");
        print " to $email via $server\n";

        my $smtp = new Net::SMTP($server) or die "No mailserver";
        $smtp->mail($sender) or die "unable to set sender";
        $smtp->to($email) or die "unable to address message";
        $smtp->data() or die "unable to start data send";
        $smtp->datasend($entity->as_string()) or die "Message send failed";
        $smtp->dataend() or die "Message end failed";
        $smtp->quit();
        print "Done\n\n";
    }

Migrating from Lotus Notes/Domino

Migrating Contacts and Calendar

If your mail migration strategy doesn't cover contacts and calendar, you can import via the REST (REpresentational State Transfer) [2] interface. (Currently, contacts and calendar are only imported with the Exchange migration tool, so this applies to most IMAP migrations).

Procedure Overview

The basic procedure is this:

  1. Export calendar or contact data from your existing server into a csv or ics file
  2. Migrate that data file to a host that can access the zimbra server
  3. Use the REST interface to insert the data into Zimbra


REST overview

Today, within the Zimbra Collaboration Suite we have a number of different server-side URLs that our client accesses to download an attachment, export contacts as CSV, export a calendar as an ICS, file etc. We are also adding sharing (what would collaboration be without sharing, after all) of calendars, contacts, etc. Not only within a particular Zimbra community, but between Zimbra communities and the public at large.

In order to facilitate this, we are coming up with a clean, consistent URL interface to all our resources. The best way to describe this is with some examples.

Lets say I want access to my calendar folder from within iCal. The URL would look like:

 http://server/zimbra/user/roland/calendar

The default format on calendar folders is ICS, so no need to specify the format.

Lets say I want to export my contacts folder so I can import them into another account:

 http://server/zimbra/user/roland/contacts

Contact folders have a default type of CSV, so like calendars, no need to specify the format.

How about an RSS feed of unread messages in my inbox:

 http://server/zimbra/user/roland/inbox.rss?query=is:unread

By specifying an extension of ".rss" on the inbox folder, the server will automatically generate an RSS feed on it. Adding the "query" parameter lets me further refine what gets returned. You can also specify "?fmt=rss" instead of using the ".rss" extension if you'd like. You can also use the encoding for double quotes, %22 (For example, inbox.rss?query=%22is:unread%22)

Lets do something a little more interesting. How about a zip file containing all messages in my talks/ajax folder:

 http://server/zimbra/user/roland/talks/ajax.zip

The server zips them all up and returns the zip file.

Another interesting example is say you have created a public calendar that you want to share with everyone. Once you have granted access to the calendar, it is up to the consumer to chose what format they want to view it in:

 http://server/zimbra/user/roland/calendar/talks.ics
 http://server/zimbra/user/roland/calendar/talks.html?view=month
 http://server/zimbra/user/roland/calendar/talks.atom
 http://server/zimbra/user/roland/calendar/talks.xml
 http://server/zimbra/user/roland/calendar/talks.txt

How about accessing another user's calendar/folder? Once they grant you access, you can use the same exact syntax:

 http://server/zimbra/user/janie/holidays.ics

One last interesting example to leave you with. Lets say you have a friend at widgets.com who you know is running Zimbra and who has shared their calendar with you, but you don't know the name of their public Zimbra server. As long as they publish some DNS SRV records for _zimbra._tcp.widgets.com, then you can access it directly from your Zimbra without needing to know his server's address:

 http://server/zimbra/user/friend@widgets.com/calendar

This last format (user@domain.com) is also necessary when accessing resources in a non-default domain on your local Zimbra server.

REST file formats

Format Types

We are supporting a number of different "formats" for returned data. The formats we currently have implemented are:

REST file formats
Format Description
atom For generating an ATOM feed of mail messages and calendar appts.
csv For exporting contacts.
ics For exporting calendar appointments. See RFC 2445.
ifb Calendar free/busy data. See RFC 2445.
native Default formatter used to output messages and attachments in their "native" format. Used by the web client to reference attachments for downloading.
rss For generating an RSS feed of mail messages and calendar appts.
sync Similar to the native formatter, used by sync clients to retrieve raw message data, along with some extra meta-data in the HTTP header (tags, flags, received date).
vcf For exporting vcard files (vcard 3.0)
zip For exporting a set of messages (folder or search result) as a ZIP file.

Time Range Specifications

The time range can be specified in a number of different formats:

  • (milliseconds UTC)
  • MM/DD/YYYY
  • YYYY/MM/DD
  • {relative dates}

relative dates are either in the future (p/+/{not-specified}) or the past (m/-), along with a numeric value, followed by the units.

For units, everything after the first character is ignored (except for the "mi" case):

  • m(onths)
  • mi(nutes)
  • d(ays)
  • w(eeks)
  • h(ours)
  • y(ears)
Examples
1day 1 day from now
+2days 2 days from now
p1day 1 day from now
-2days 2 days ago
+60mi 60 minutes from now
+1week 1 week from now
+6mon 6 months from now
1year 1 year from now

The start/end query parameters apply to the atom, ics, rss, and ifb formatters.

Format Examples

ATOM

 http://server/zimbra/home/schemers/inbox.atom  

Returns an Atom feed for all messages in the inbox. If you only want unread messages as part of the feed, you could include a search query:

 http://server/zimbra/home/schemers/inbox.atom?query="is:unread"

You can also request an Atom feed of a calendar folder as well:

 http://server/zimbra/home/schemers/calendar.atom  

Note that "calendar" is the pathname to the folder called "calendar", it isn't a special-cased pathname. If you had a calendar folder called "talks", then you can access that folder via:

 http://server/zimbra/home/schemers/talks.atom  

When used with a calendar folder, the Atom feed will (by default) generate a feed of all appointments -/+ 7 days from the current time. To specify a different time range, you can use the start/end query parameters:

 http://server/zimbra/home/schemers/calendar.atom?start=0days&end=30days  


CSV

 http://server/zimbra/home/schemers/contacts.csv  

Exports all contacts in the contacts folder. If you want to export only contacts tagged "zimbra", you can specify a query:

 http://server/zimbra/home/schemers/contacts.csv?query="tag:zimbra"  

This will only export contacts that are tagged with "zimbra".

ICS

 http://server/zimbra/home/schemers/calendar.ics  

Will export all appointments in the calendar folder in the ICS format, suitable for import into a calendar client such as Apple's iCal, or Mozilla's Sunbird calendar client.

IFB

 http://server/zimbra/home/schemers/calendar.ifb?start=0d&end=60d  

Will export the free/busy data in the calendar folder for the next 60 days. Note that this is the free/busy data for the calendar folder only. If someone has multiple calendar folders then you'd want to use the following URL instead:

 http://server/zimbra/home/schemers/?fmt=ifb&start=0d&end=60d  

That URL will return free/busy data across all calendars that are configured to be included in free/busy data.

NATIVE

The native formatter is used to request raw RFC 822 messages (for example, to implement "show original") or to down an attachment. For example, lets assume that message id 376 in my inbox is a multipart/mixed MIME message, and part 2 is an image.

The following URL (which is normally generated automatically when you are viewing your mail and click on an attachment), would download that attachment and display it in your browser:

 http://server/zimbra/home/schemers/?id=376&part=2  

Lets say part 3 in that same message is a word doc, you could display that via:

 http://server/zimbra/home/schemers/?id=376&part=3  

Finally, lets say you have the Network edition installed and want to view that same word doc as HTML instead of downloading the word doc and opening it up as an attachment. Adding "view=html" to the end of the URL will convert the word doc to HTML:

 http://server/zimbra/home/schemers/?id=376&part=3&view=html  

An upcoming release will expose this functionality directly in the web UI.

RSS

 http://server/zimbra/home/schemers/inbox.rss  

Returns an RSS feed for all messages in the inbox. All the other examples given for the Atom formatter also apply to the RSS formatter.

One further note on both the Atom and RSS formatters is that the calendar feeds provided by them currently only include the title/notes data. As soon as a more complete server-side I18N infrastructure is in place (we have been focused on the web client) the Atom/RSS feeds for calendars will be much more detailed.

SYNC

The sync formatter is similar to the native formatter, with the only exception being it adds some extra meta-data to the output for sync clients.

VCF

The "vcf" formatter can export your contacts as series of vcards (vCard 3.0), or can be used to export a single contact as a vCard (to be used by the web client in a future version).

To get all your contacts as a series of vCard entries, specify "vcf" as the formatter on the GET url:

 http://server/zimbra/home/schemers/contacts.vcf  

ZIP

The Zip formatter allows you to request a set of messages (currently only mail messages, at some point will probably allow attachments/contacts/appts as well) returned to you as a Zip file.

For example, if you want a copy of all messages in your inbox, you could use the following URL:

 http://server/zimbra/home/schemers/inbox.zip  

If you wanted all messages across all folders that were from Ross, you could use a query that returned only those:

 http://server/zimbra/home/schemers/?fmt=zip&query="from:ross"  

The zip file will consist of a set of RFC822 files, with the name of the file based on the subject of the message.

Importing into Zimbra

We've added the ability to update/create content by POST'ing content to REST urls. GETs continue to remain read only, with no side-effects (as they should be).

For example, you can POST an RFC822 formatted message to your inbox REST url to append messages to the inbox folder. Using the popular curl program, this would look like the following:

 curl -u schemers:password --data-binary @/tmp/rfc822.txt https://server/service/home/schemers/inbox

Note, you currently have to use /service/home for POSTs instead of /zimbra/home, because /zimbra/home issues a redirect, which isn't allowed with POSTs. We'll be fixing that in an upcoming release.

Other items that can be updated this way are calendar appointments (ICS), and contacts (csv and the new vcf (vCard) format):

 curl -u schemers:password --data-binary @/tmp/new.csv http://server/service/home/schemers/contacts?fmt=csv
 curl -u schemers:password --data-binary @/tmp/new.ics http://server/service/home/schemers/calendar?fmt=ics
 curl -u schemers:password --data-binary @/tmp/new.vcf http://server/service/home/schemers/contacts?fmt=vcf

The full user name (user@domain.com) is required when importing to resources on a non-default domain on your local Zimbra server.

The target "contacts" in the above command corresponds to the actual folder name on the Zimbra server, rather than a service. This means that you can import to user-defined folders by specifying the appropriate target name in the command. If you have created a folder named "SharedContacts", for example, the command to import into this folder would be

 curl -u schemers:password --data-binary @/tmp/new.csv http://server/service/home/schemers/sharedcontacts?fmt=csv
Jump to: navigation, search