To migrate mail from cPanel or any other IMAP host to Exchange Online, you create licensed Microsoft 365 mailboxes, build a CSV file listing each mailbox and its IMAP credentials, create an IMAP migration endpoint that points at the old mail server, and run a migration batch from the Exchange admin center or Exchange Online PowerShell. The batch copies mail folders and keeps them in sync once a day until you switch the MX record to Microsoft 365 and delete the batch. Only email moves; contacts, calendars and tasks have to be handled separately.
Who this is for and what you will have
This guide is for administrators moving a small or mid-sized organization off shared web hosting (cPanel, Plesk or a similar control panel) or any other IMAP-only mail service into Exchange Online. By the end you will have:
- Every mailbox's mail folders copied into Exchange Online.
- New mail flowing to Microsoft 365 through an updated MX record.
- The hosting account set so it no longer intercepts mail for your domain.
- A clean stop to synchronization, with nothing lost in the gap.
If you are coming from Google Workspace instead, use the native Gmail migration covered in the Google Workspace to Microsoft 365 migration guide, which also moves calendars and contacts. Once mail is in Exchange Online, the Exchange Online mail flow rules guide covers disclaimers and external sender warnings.
What an IMAP migration does and does not move
| Item | Migrated? | Notes |
|---|---|---|
| Inbox and mail folders | Yes | Newest items first, up to 500,000 items per mailbox |
| Messages over 35 MB | No | Ask users to save large attachments elsewhere first |
| Folders with "/" in the name | No | Rename them before the migration |
| Contacts | No | Export and import separately |
| Calendar items and tasks | No | Export and import separately |
| Folders you exclude | No | Use the filtering options or ExcludeFolders |
Microsoft also notes that the migration service is unaware of messaging records management (MRM) and archive policies. Items that such a policy moves or deletes during the migration are reported as missing, which hides real data loss. Microsoft strongly recommends disabling MRM and archive policies on the target mailboxes until the migration is complete.
Prerequisites
On the Microsoft 365 side
- Add and verify your domain in the Microsoft 365 admin center under Settings > Domains before you create users, so mailboxes get addresses in your domain from the start. Do not change the MX record yet.
- Create every user and assign a licence that includes Exchange Online. IMAP migration copies data into existing mailboxes; it does not create them.
- Get the right permissions. Microsoft's IMAP migration guide points to the "Migration" entry in its recipients permissions article, which lists the Organization Management and Recipient Management role groups.
- Install and connect Exchange Online PowerShell if you want to script the migration:
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -UserPrincipalName admin@contoso.comOn the hosting side
- Find the IMAP server name. In cPanel, go to Email > Email Accounts and select Connect Devices for a mailbox, which opens the Set Up Mail Client page. The Mail Client Manual Settings section lists the incoming server and ports. cPanel recommends its Secure SSL/TLS Settings, with IMAP on port 993; the non-SSL IMAP port is 143. Under the SSL settings, cPanel shows a name in your domain (such as
mail.contoso.com) only if the domain has a valid SSL certificate; otherwise it shows the server's own hostname. Use exactly the incoming server name shown for the SSL settings. On other hosts, find the IMAP server name in the provider's mail client settings. - Check connection limits. Firewalls and mail servers often limit total connections, connections per user and connections per IP address. Microsoft recommends raising these before you migrate. On shared hosting you might not be able to change them, which mainly affects speed and how many mailboxes you can migrate in parallel.
- Lower the MX record TTL to 3,600 seconds (one hour) or less before you start, on every MX record for the domain. When you switch the MX record later, the change spreads faster. Exchange Online only supports MX TTL values below six hours (21,600 seconds).
- Ask users to clean up: delete mail they don't need, rename folders that contain a forward slash, and save very large messages.
Step 1: Build the migration CSV file
The CSV file needs three columns with these exact headers and no spaces:
| Column | Contents |
|---|---|
| EmailAddress | The user's Microsoft 365 mailbox address (the username in Users > Active users) |
| UserName | The sign-in name on the IMAP server |
| Password | The password for that sign-in name |
cPanel mailboxes sign in with the full email address, so when the domain is the same on both sides the first two columns are identical:
EmailAddress,UserName,Password
alex@contoso.com,alex@contoso.com,TempPassw0rd!1
megan@contoso.com,megan@contoso.com,TempPassw0rd!2
info@contoso.com,info@contoso.com,TempPassw0rd!3A single file can list up to 50,000 mailboxes and be up to 10 MB, but you don't have to migrate everyone at once. Split users into batches if you want to test with a few mailboxes first.
Choosing which credentials to use
You have three options, in order of how disruptive they are:
- Mailbox admin credentials. Some IMAP servers let one administrator account open every mailbox. For Dovecot, which supports SASL, the
UserNamevalue isUser_UserName*Admin_UserName(the asterisk is a configurable separator), and the password is the admin account's password. This avoids touching user passwords, but it needs a master account configured on the server. On shared hosting that is the host's decision, so ask them whether it is available. - Known user passwords. If users give you their passwords, nothing changes for them until cutover.
- Reset passwords. Reset each mailbox password in the hosting control panel to a temporary value and record it in the CSV. Users can't reach their old mailbox with their own password afterwards unless you give them the new one.
If you use user passwords, stop users from changing them on the old server until the migration is finished. Microsoft notes that a password change before the mailbox is migrated makes the migration fail, and a change after the initial copy stops new mail from being synchronized.
Treat the CSV file as a secret: it contains working credentials. Delete it when the migration is finished.
Step 2: Create the IMAP migration endpoint
The endpoint stores the connection settings to the old server and controls how many mailboxes are migrated at once.
In the Exchange admin center
- Open the Exchange admin center and go to Migration.
- Select Endpoints, then Add.
- Choose IMAP as the migration type.
- Enter a Migration endpoint name and the IMAP server (for example,
mail.contoso.com). The remaining defaults work for most servers. - Select Create.
In PowerShell
Test the connection first, then create the endpoint with SSL on port 993:
Test-MigrationServerAvailability -IMAP -RemoteServer mail.contoso.com -Port 993 -Security Ssl
New-MigrationEndpoint -IMAP -Name cPanelEndpoint -RemoteServer mail.contoso.com -Port 993 -Security Ssl
Get-MigrationEndpoint cPanelEndpoint | Format-List EndpointType,RemoteServer,Port,Security,Max*Microsoft's guidance is that port 143 is typically used for unencrypted or TLS connections and port 993 for SSL. If the host limits connections, reduce parallelism on the endpoint, for example -MaxConcurrentMigrations 10 -MaxConcurrentIncrementalSyncs 5. Run a small test batch and adjust from there.
Step 3: Create and start the migration batch
In the Exchange admin center
- In Migration, select Add migration batch.
- Enter a batch name without spaces or special characters and choose Migrate to Exchange Online, then Next.
- Select IMAP migration and continue through Prerequisites for IMAP migration.
- On Set a migration endpoint, select the endpoint you created.
- On Add user mailboxes, select Import CSV file and upload your file.
- On Select configuration settings, use Migration filtering options to exclude folders such as trash and junk.
- On Schedule batch migration, choose who receives reports and how the batch starts, then Save and Done.
In PowerShell
$csv = [System.IO.File]::ReadAllBytes("C:\Migration\cpanel-batch1.csv")
New-MigrationBatch -Name cPanelBatch1 `
-SourceEndpoint cPanelEndpoint `
-CSVData $csv `
-ExcludeFolders "Trash","Junk" `
-NotificationEmails admin@contoso.com `
-AutoStartExcludeFolders takes folder names relative to the IMAP root on the source server, isn't case-sensitive and doesn't accept wildcards. Folder names differ between hosts, so check the exact names in a mail client connected to the old server before you exclude anything. Without -AutoStart, start the batch later with Start-MigrationBatch -Identity cPanelBatch1.
Step 4: Monitor and verify
Check the batch and each user:
Get-MigrationBatch -Identity cPanelBatch1 | Format-List Status
Get-MigrationUser -BatchId cPanelBatch1 | Get-MigrationUserStatistics
Get-MigrationUserStatistics -Identity alex@contoso.com -IncludeReport | Format-List Status,Error,Report
Get-MigrationUserStatistics -Identity alex@contoso.com | Format-List SkippedItemCount,SkippedItemsIn the Exchange admin center, select the batch under Migration and use View details in the details pane to open the per-user status report.
After the initial copy, the migration endpoint keeps mailboxes in sync through incremental synchronization, which runs once every 24 hours. That is why the batch stays active through the cutover rather than finishing on its own.
Ask a few users to sign in to Outlook on the web, check that their folders and recent mail are present, set their time zone, and send a test message to another Microsoft 365 user.
Step 5: Cut over mail flow
Switch the MX record
- In the Microsoft 365 admin center, go to Settings > Domains, select the domain, then DNS records > Manage DNS, and keep Exchange and Exchange Online Protection selected.
- Copy the MX value shown on the Add DNS records page. Don't type it from memory; Microsoft 365 generates it for your domain.
- At your DNS host, add the Microsoft 365 MX record with the highest priority available (typically 0), and either remove the old MX records or give them a lower priority (a higher number).
- Add the autodiscover CNAME shown in the same page so Outlook can configure itself.
- Update SPF. If the domain already has an SPF record, don't add a second one; add
include:spf.protection.outlook.comto the existing record so there is a single SPF TXT record. If nothing else sends mail for the domain any more, the record becomesv=spf1 include:spf.protection.outlook.com -all.
Fix cPanel email routing
This step is easy to miss when DNS is hosted somewhere other than the cPanel server. In cPanel, go to Email > Email Routing. Its Automatically Detect Configuration setting reads only the local zone file on the hosting server and does not perform a DNS lookup. If that zone still lists the server itself as the mail exchanger, cPanel keeps treating the domain as local, and any mail generated on the server, such as website contact forms, is delivered to the old local mailboxes instead of Exchange Online.
After the cutover, select Remote Mail Exchanger for the domain and select Change. With that setting, the server no longer accepts mail for the domain and sends all mail for it to the lowest-numbered mail exchanger, which is now Microsoft 365. If your host lets you edit the zone in Zone Editor, update the MX record there as well so automatic detection gives the right answer.
Wait, then remove the batch
It can take up to 72 hours for other mail systems to pick up the new MX record. Leave the batch running for at least 72 hours so that any mail that still arrives at the old server is copied across by the daily synchronization. Before you delete the batch, confirm that:
- All users are working in Exchange Online.
- The batch's last synced time is later than the moment mail started arriving directly in Microsoft 365.
Then remove the batch:
Remove-MigrationBatch -Identity cPanelBatch1
Get-MigrationBatch cPanelBatch1The second command returns the batch with status Removing, or an error saying it can't be found. Once the batch is gone, mail delivered to the old server is no longer copied, so keep the hosting mailboxes until you are certain nothing still points at them, then close them.
Troubleshooting
Test-MigrationServerAvailability fails or the batch can't connect. Confirm the server name, port and security setting against the host's mail client settings. A firewall in front of the IMAP server might need to allow traffic from Microsoft datacenters; Microsoft publishes those addresses in its Exchange Online URLs and IP address ranges list, which you can pass to your host.
A user fails with an authentication error. The password in the CSV is wrong or was changed after you built the file. Fix the CSV entry (or reset the password again) and retry that user.
Users report missing folders. Look for folders with a forward slash in the name, folders you excluded, and folder names that differ from what you expected. Rename and let the next incremental synchronization pick them up.
Some messages didn't arrive. Check SkippedItemCount and SkippedItems. Messages over 35 MB and anything beyond the 500,000-item limit aren't migrated.
The migration is slow or stalls. The usual cause is connection limits on the source. Lower MaxConcurrentMigrations on the endpoint, run batches out of hours, and migrate the largest mailboxes in their own batch.
After cutover, website form mail still lands in the old mailboxes. cPanel email routing is still set to local. Change it to Remote Mail Exchanger as described above.
Mail to some users bounces after cutover. The user doesn't have a licensed Exchange Online mailbox with that address. Add the address to the right mailbox in Microsoft 365.
Don't delete or readdress mailboxes mid-migration. Microsoft warns that changing the SMTP address of, or deleting, a migrated mailbox before the batch is removed causes migration errors.
Checklist
- Domain verified and users created and licensed in Microsoft 365.
- MRM and archive policies off for target mailboxes during the migration.
- IMAP server name and port confirmed; connection limits raised where possible.
- MX TTL lowered to 3,600 seconds or less before starting.
- CSV built with EmailAddress, UserName and Password; stored securely and deleted afterwards.
- Test batch with a few mailboxes, then production batches.
- Users checked their mail in Outlook on the web; contacts and calendars exported separately.
- MX, autodiscover and SPF updated from the values in the Microsoft 365 admin center.
- cPanel email routing set to Remote Mail Exchanger.
- Batch left running at least 72 hours after cutover, then removed.
References
- What you need to know about migrating your IMAP mailboxes to Microsoft 365 or Office 365
- Migrate other types of IMAP mailboxes to Microsoft 365 or Office 365
- Use PowerShell to perform an IMAP migration to Microsoft 365
- Tips for optimizing IMAP migrations in Exchange Online
- New-MigrationBatch
- Get-MigrationUserStatistics
- Connect your domain by adding DNS records
- Connect to Exchange Online PowerShell
- Recipients permissions (Migration entry)
- cPanel: Set Up Mail Client
- cPanel: Email Routing
- cPanel: Email Accounts