How To Migrate From Microsoft Exchange to Kopano

March 11, 2019

Written by
Category: blog

At Kopano we frequently receive questions about the easiest way to migrate from one system to Kopano. Therefore, we decided to write a series of blog posts about Kopano migrations, starting with the most common one: Exchange to Kopano. Do you want to migrate from Microsoft Exchange to Kopano? Check out this blog post to learn how to do this in a quick and easy way.

Well begun is half done

Prepare your Kopano environment

First and foremost, you need a working Kopano environment. This means you need a Kopano server with existing users who can log in and send emails. If you don’t have a Kopano server yet, you can check out this page which explains how to install one.

Prepare your Microsoft Exchange environment

On the Exchange side, there is not much to prepare, except for one thing. You need to create a central place to store your data and this place has to be an NFS share.

Allocate sufficient time for the migration

Importing and exporting data takes time. How much? It depends. On system load, bandwidth, mailbox size, number of users to migrate, email size, network speed, etc. But count on a few hours for small projects to a few days for large projects. If possible, try migrating the mailboxes after office hours so that you do not have to interfere in the daily work of people.

Make sure no one is emailing anymore

Probably an open door, but before you start, make sure nobody in the company uses Exchange to send emails on the day(s) of migration. If they do, these emails won’t be migrated and be gone forever.

There is no such thing as a 100% success rate

A 100% success is exceptional, if not impossible. So please accept the fact that probably not all, but more like 95% of your data will make it to the other side.

Prepared everything you could prepare? Then you’re ready to export your Exchange mailboxes.

Export your Microsoft Exchange mailbox

There are three ways to export data from Exchange

  • Create PST from Outlook
  • Use the New-MailboxExportRequest command
  • Use the ECP/EAC to create backups

Personally, I would recommend using the New-MailboxExportRequest command because it is the quickest way to get the job done. Creating PSTs from Outlook means that you have to manually create a PST file for each user, so that is probably not something that will cheer you up. Using the ECP/EAC to make backups is a bit faster, but in my opinion not ideal either. Still, to keep the options open, I will explain how to migrate from Microsoft Exchange to Kopano using the ‘New-MailboxExportRequest’ and ECP/EAC way.

For both New-MailboxExportRequest and the ECP way, you need the Mailbox Import Export role, which isn’t assigned to any role groups by default. To assign the role to a role group that you belong to, see Add a role to a role group.

Export Exchange Mailbox using New-MailboxExportRequest

The command to export the mailbox to PST is (make sure the file path is a network share):

New-MailboxExportRequest -Mailbox "Username" -FilePath \\SERVER\PST\username.pst

To export all mailboxes, use the PowerShell ‘script’ below. Change SERVERNAME AND PST for the desired file path.

$mbxs = Get-Mailbox
foreach ($mbx in $mbxs) {
    New-MailboxExportRequest -Mailbox "$($mbx.Name)" -FilePath \\SERVERNAME\PST\$($mbx.Alias).pst
}

The output should like this:

Running Get-MailboxExportRequest will give you the status of the exports:

Export Exchange Mailbox using ECP/EAC

In the Exchange admin centre, select recipients, Mailboxes, Administrator and click on the three dots at the right sight of the toolbar

1. Select the ‘Export to a PST file option: Microsoft Exchange to Kopano III
2. Choose if you want to export mailbox or archiver:Microsoft Exchange to Kopano IV
3. Enter the NFS share:
4. Choose if you want to receive a notification: Microsoft Exchange to Kopano VI

Using SCANPST

Run SCANPST a few time for the PST file to make sure all corrupted items are fixed or removed.

We will use the 365 version of Outlook. As of outlook 2016 you are able to use it on the commandline. The location of SCANPST is different for each Outlook version, in our setup (Office 365) it was located in c:\Program Files (x86)\Microsoft Office\root\Office16

SCANPST.EXE -rescan 3 -silent -force -log path\to\log\file\ --file path\to\pst

This example script can be used to automate it:

SET PSTLOCATION=C:\Users\kopano\Desktop\psts
SET SCANPSTLOCATION=C:\Program Files (x86)\Microsoft Office\root\Office16

for %%f in ("%PSTLOCATION%\*.pst") do (
    "%SCANPSTLOCATION%\SCANPST.EXE"  -rescan 3 -silent -force -log "%PSTLOCATION%\"  -file %%f
)

Import PST Kopano

As we already have a NFS share where the PST are stored, we just mount that NFS share.

mkdir ~/pst
mount -t cifs  //SERVER/PST ~/pst -o username=administrator,password=password

Before importing the pst files we need to create a mapping file for the exchange LegacyDN names.

–create-ex-mapping is a new option in kopano-migration-pst 8.7.0

kopano-migration-pst --create-ex-mapping exchange.json  *.pst

To Import a PST, use:

kopano-migration-pst /mnt/administrator.pst  -u administrator

kopano-migration-pst is not able to automatically import all PST in one directory, therefore, you need to use this script to loop over the item (this script is using the alias name of the exchange user as username in Kopano):

#!/bin/bash
FILES=/pst/*
for file in $FILES
do
    if [[ ${file##*.} == 'pst' ]]; then
        kopano-migration-pst  -u $(basename "$file".pst)   --ex-mapping exchange.json ${file}
    fi
done

Export Rules

With the latest Kopano-rules(included in Core 8.7) it is possible to import Exchange rules. Kopano-rules can also be downloaded from https://stash.kopano.io/projects/KSC/repos/core-tools/browse/kopano-rules

On the Exchange server execute the following:

Get-Mailbox; $mbox | Foreach { Get-InboxRule -Mailbox $_.DistinguishedName } | ConvertTo-Json > c:\path\to\json

Example json:

{
    "Description":  {

                    },
    "Enabled":  true,
    "Identity":  {
                     "MailboxOwnerId":  {
                                            "IsDeleted":  false,
                                            "Rdn":  "CN=Administrator",
                                            "Parent":  "winkopano.lan/Users",
                                            "Depth":  3,
                                            "DistinguishedName":  "CN=Administrator,CN=Users,DC=winkopano,DC=lan",
                                            "IsRelativeDn":  false,
                                            "DomainId":  "winkopano.lan",
                                            "PartitionGuid":  "59ce2f71-eaa2-4ddf-a4fa-f25069d0b324",
                                            "ObjectGuid":  "c67f2b59-3174-4a03-9035-f4332e92dc3e",
                                            "Name":  "Administrator"
                                        }
                 },
    "InError":  false,
    "Name":  "Exchange rule",
    "Priority":  1,
    "RuleIdentity":  2666130979403333633,
    "SupportedByTask":  true,
    "BodyContainsWords":  [

                          ],
    "ExceptIfBodyContainsWords":  [

                                  ],
    "FlaggedForAction":  null,
    "ExceptIfFlaggedForAction":  null,
    "FromAddressContainsWords":  [

                                 ],
    "ExceptIfFromAddressContainsWords":  [

                                         ],
    "From":  null,
    "ExceptIfFrom":  null,
    "HasAttachment":  false,
    "ExceptIfHasAttachment":  false,
    "HasClassification":  null,
    "ExceptIfHasClassification":  null,
    "HeaderContainsWords":  [

                            ],
    "ExceptIfHeaderContainsWords":  [

                                    ],
    "FromSubscription":  null,
    "ExceptIfFromSubscription":  null,
    "MessageTypeMatches":  null,
    "ExceptIfMessageTypeMatches":  null,
    "MyNameInCcBox":  false,
    "ExceptIfMyNameInCcBox":  false,
    "MyNameInToBox":  false,
    "ExceptIfMyNameInToBox":  false,
    "MyNameInToOrCcBox":  false,
    "ExceptIfMyNameInToOrCcBox":  false,
    "MyNameNotInToBox":  false,
    "ExceptIfMyNameNotInToBox":  false,
    "ReceivedAfterDate":  null,
    "ExceptIfReceivedAfterDate":  null,
    "ReceivedBeforeDate":  null,
    "ExceptIfReceivedBeforeDate":  null,
    "RecipientAddressContainsWords":  [

                                      ],
    "ExceptIfRecipientAddressContainsWords":  [

                                              ],
    "SentOnlyToMe":  false,
    "ExceptIfSentOnlyToMe":  false,
    "SentTo":  null,
    "ExceptIfSentTo":  null,
    "SubjectContainsWords":  [
                                 "Migration"
                             ],
    "ExceptIfSubjectContainsWords":  [

                                     ],
    "SubjectOrBodyContainsWords":  [

                                   ],
    "ExceptIfSubjectOrBodyContainsWords":  [

                                           ],
    "WithImportance":  null,
    "ExceptIfWithImportance":  null,
    "WithinSizeRangeMaximum":  null,
    "ExceptIfWithinSizeRangeMaximum":  null,
    "WithinSizeRangeMinimum":  null,
    "ExceptIfWithinSizeRangeMinimum":  null,
    "WithSensitivity":  null,
    "ExceptIfWithSensitivity":  null,
    "ApplyCategory":  [

                      ],
    "CopyToFolder":  null,
    "DeleteMessage":  true,
    "ForwardAsAttachmentTo":  null,
    "ForwardTo":  null,
    "MarkAsRead":  false,
    "MarkImportance":  null,
    "MoveToFolder":  null,
    "RedirectTo":  null,
    "SendTextMessageNotificationTo":  [

                                      ],
    "StopProcessingRules":  true,
    "MailboxOwnerId":  {
                           "IsDeleted":  false,
                           "Rdn":  {
                                       "Prefix":  "CN",
                                       "EscapedName":  "Administrator",
                                       "UnescapedName":  "Administrator"
                                   },
                           "Parent":  {
                                          "IsDeleted":  false,
                                          "Rdn":  "CN=Users",
                                          "Parent":  "winkopano.lan",
                                          "Depth":  2,
                                          "DistinguishedName":  "CN=Users,DC=winkopano,DC=lan",
                                          "IsRelativeDn":  false,
                                          "DomainId":  "winkopano.lan",
                                          "PartitionGuid":  "00000000-0000-0000-0000-000000000000",
                                          "ObjectGuid":  "00000000-0000-0000-0000-000000000000",
                                          "Name":  "Users"
                                      },
                           "Depth":  3,
                           "DistinguishedName":  "CN=Administrator,CN=Users,DC=winkopano,DC=lan",
                           "IsRelativeDn":  false,
                           "DomainId":  {
                                            "IsDeleted":  false,
                                            "Rdn":  "DC=winkopano",
                                            "Parent":  "lan",
                                            "Depth":  1,
                                            "DistinguishedName":  "DC=winkopano,DC=lan",
                                            "IsRelativeDn":  false,
                                            "DomainId":  "winkopano.lan",
                                            "PartitionGuid":  "00000000-0000-0000-0000-000000000000",
                                            "ObjectGuid":  "00000000-0000-0000-0000-000000000000",
                                            "Name":  "winkopano"
                                        },
                           "PartitionGuid":  "59ce2f71-eaa2-4ddf-a4fa-f25069d0b324",
                           "ObjectGuid":  "c67f2b59-3174-4a03-9035-f4332e92dc3e",
                           "Name":  "Administrator"
                       },
    "IsValid":  true,
    "PSComputerName":  "kopanoexchange.winkopano.lan",
    "RunspaceId":  "0aac307d-14b6-474b-a074-e4b0347cd78d",
    "PSShowComputerName":  false,
    "ObjectState":  1
}

Kopano-rule expect that the exchange users are equal to the Kopano users

On the Kopano server execute:

python kopano-rules.py --import-exchange-rules /path/to/json-file

If you got an error like ‘UnicodeDecodeError: ‘utf-8′ codec can’t decode byte 0xff in position 0: invalid start byte’ use dos2unix to remove any windows specific characters

If one of the rules includes a legacyExchangeDN ,use the –ldap-config parameter to convert them to the username.

Create a config.py with the following:

URL = "ldap://x.x.x.x:389"
BINDDN = "example\Administrator"
PASSWORD = "Password"
BASEDN = "DC=example,DC=lan"/code]

Then run:

[code]
python kopano-rules.py --import-exchange-rules/path/to/json-file --ldap-config config.py

If you followed these step closely you should be ready to start using Kopano. Enjoy!