Skip to content
Coritan Docs

Move every mailbox from a cPanel host

Bring a whole cPanel account's email at once, each mailbox with a new password and all of its mail, its forwarders and its catch-all.

View as Markdown

A migration moves a whole cPanel account's email to a Mail Hosting service in one go. We read the account's email accounts over cPanel's own API, make a mailbox here for each one with a new password, turn its forwarders into aliases, and copy every message from each old mailbox, folder by folder, with its read and flagged state and its original date.

The copying runs on our side, so it carries on after you close the page, however much mail there is. To bring mail into one mailbox at a time instead, see Move existing mail into a mailbox.

  • A Mail Hosting service with room for the mailboxes: a migration makes one mailbox for each email account, and gives each a quota that holds what the old one holds.
  • The domain of the email accounts on the service, and proved to be yours. See Add a domain to Mail Hosting. A migration leaves out the accounts of a domain that is not ready, and says so.
  • The cPanel account's username, and an API token for it. In cPanel, open Security, then Manage API Tokens, and create one. The cPanel password works too, unless the account uses two-factor authentication.
  • A way to read each old mailbox. cPanel does not let anyone read a mailbox without its password, so either give each old mailbox's current password, or let us set a new password on the old mailboxes you leave blank.

Warning

When we set a new password on an old mailbox, phones and computers that still sign in to the old server stop receiving its mail there. Move them to the new mailbox, with its new password, once the migration has started.

  1. In the dashboard, go to Email, open the Mail Hosting service, then the Mailboxes tab.
  2. Select Move from cPanel….
  3. In cPanel host, enter where you sign in to cPanel, such as example.com, or your host's server name. In Username, enter the cPanel username.
  4. Under Sign in with, keep API token and paste the token in API token, or choose Password and enter the cPanel password.
  5. Select Find mailboxes. We list every email account with how much it holds and what it becomes here: New mailbox, Already here, or Cannot move with the reason under it.
  6. Check the mailboxes to move. For each new one, set Quota (GB); we fill in a size that holds what the old mailbox holds.
  7. For each old mailbox whose password you know, enter it in Current password: we read it without changing anything on the old server. Leave the others blank, and keep Set a new password on old mailboxes left blank checked so we can read them too.
  8. Turn on Also bring Trash or Also bring Spam to copy those folders. Turn forwarders into aliases and Make the catch-all are on, and appear when there is something for them to do. The dialog lists the aliases we make and what does not move.
  9. Select Start the migration. When we are about to set new passwords on the old server, we ask first: select Set new passwords and start.
  10. Save the new passwords. Each new mailbox signs in with its address and the password shown, and we show them only this once. Use Copy all or Download CSV, then select Done.

We check everything before anything changes: the plan's room, the old server's IMAP, and each password you gave. When a check fails, the dialog says why and nothing is made.

On the cPanel account Here
Each email account A mailbox with the same address and a new password, or the mailbox already here with that address
Its mail, in every folder The same folders. Inbox, Sent, Drafts and Archive go into the mailbox's own, and Trash and Spam too when you ask for them
A forwarder to mailboxes that move An alias to those mailboxes
A domain's default address, when it is one of the mailboxes The domain's catch-all

What does not move is listed with the reason, so you can set it up by hand:

  • A forwarder to an address outside the service, such as a Gmail address. Forwarding there needs that address to confirm it, so set it up for a mailbox in webmail, under Settings, Forwarding.
  • A forwarder on an address that is also a mailbox, a forwarder to a program or a file, and autoresponders.
  • An account whose sign-in is suspended on the old server: its mailbox is made here, without its mail.

The Moving mail in card above the mailboxes shows each migration: how many mailboxes are done and how many messages came across. Select Show mailboxes to see each one with its import's status, its counts and any note. Pause and Resume steer one mailbox's import.

An import never stops because there is a lot of mail. When our mail server takes in mail more slowly for a while, the import waits and goes on by itself, and its row says when, as Goes on at and a time.

Mail keeps reaching the old server until your domain's MX records point here. Once they do:

  1. Select Sync again, then Sync again in the question. A second pass brings what arrived since, and copies nothing twice.
  2. When the last pass is done, select Finish…, then Finish migration. We forget the old mailboxes' passwords, and you cannot sync it again.

We keep those passwords until you finish the migration, or for 30 days.

… refused that username and token
cPanel did not accept the sign-in. Check the username and the token. An account with two-factor authentication needs an API token rather than the password.
… did not show a certificate valid for its name on port 2083
Enter the server's own host name instead of your domain. Your host's welcome email, or cPanel's Server Information page, gives it.
We could not reach the old server's mail over IMAP (TLS, port 993): …
The old server does not offer IMAP over TLS on any of the names we tried. Ask your host for the IMAP server name, and enter it as the cPanel host.
The old server refused some of the passwords given; nothing was changed
The answer lists each mailbox whose password did not work. Correct those passwords, or leave them blank and let us set new ones.
The plan has room for … more mailboxes, and the migration makes …
Choose fewer mailboxes, or change the plan first.

All the paths below sit under /client/mail/{service_id}/migrations. A relay has no mailboxes: the same paths under /client/smtp-relay/{service_id}/migrations answer 404.

First see what a migration would do. Nothing changes on either side:

Shell
curl -X POST https://api.coritan.com/api/v1/client/mail/4812/migrations/cpanel/discover \
  -H "Authorization: Bearer $CORITAN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"host": "example.com", "username": "example", "token": "CPANEL_API_TOKEN"}'

host is the cPanel host, as you sign in to it: example.com, example.com:2083, or the server's name. Send password instead of token for an account without two-factor authentication. The answer lists each email account under mailboxes, with its used_bytes, the quota we suggest (suggested_quota_bytes) and its state:

state Meaning
new A mailbox is made for it
exists The mailbox with that address is already here, and its mail goes into it
domain_missing, domain_unproved Its domain is not on the service, or not proved to be yours
disabled The mailbox here is turned off
taken The address is in use on Coritan as an alias or on another service

forwarders, catch_all and autoresponders say what becomes of the rest, each with a note when it does not move. room says whether the plan has space for the new mailboxes (fits).

Then start it:

Shell
curl -X POST https://api.coritan.com/api/v1/client/mail/4812/migrations/cpanel \
  -H "Authorization: Bearer $CORITAN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"host": "example.com", "username": "example", "token": "CPANEL_API_TOKEN", "reset_passwords": true,
       "mailboxes": [{"address": "info@example.com"}, {"address": "alex@example.com", "password": "alex-old-password"}]}'

The body takes the sign-in above and:

mailboxes
The old mailboxes to move, each {"address"} with an optional password (its current one, which changes nothing on the old server), quota_bytes (at least 100 MB) and import (false makes the mailbox without its mail). Leave the list out to move every mailbox that can.
reset_passwords
false by default. With true, we set a new password on each old mailbox that has no password here, to read its mail. Without it, such a mailbox is made here without its mail.
forwarders, catch_all
true by default: make the aliases and the catch-all.
trash, spam
false by default: whether to copy the old Trash and Spam folders.

Nothing changes until every check passes. The answer is 201 with the migration, and passwords holds each new mailbox's address and password, once:

JSON
{
  "id": 41,
  "status": "active",
  "source": {"host": "example.com", "port": 2083, "username": "example", "imap_host": "mail.example.com", "trash": false, "spam": false},
  "keeps_passwords": true,
  "keep_until": "2026-11-07T10:20:00+00:00",
  "mailboxes": [
    {"address": "info@example.com", "used_bytes": 2147483648, "account_id": 5121, "created": true, "read": "reset", "note": null,
     "import": {"id": 77, "status": "queued", "imported": 0, "duplicates": 0, "skipped": 0, "failed": 0, "next_try_at": null}}
  ],
  "made": [{"kind": "alias", "address": "hello@example.com", "targets": ["info@example.com"]}],
  "not_moved": [{"kind": "forwarder", "address": "boss@example.com", "reason": "Forwarding to someone@gmail.com needs that address to confirm it; set it up for a mailbox in webmail, under Settings, Forwarding"}],
  "totals": {"imported": 0, "duplicates": 0, "skipped": 0, "failed": 0, "done": 0, "importing": 1, "paused": 0, "stopped": 0},
  "passwords": [{"address": "info@example.com", "password": "…"}]
}

Each mailbox's read says how its mail is read: given (the password you gave), reset (a password we set on the old server) or none (not read; note says why). Its import is the import as Move existing mail into a mailbox describes it, and you steer it with that page's pause, resume and cancel.

The other operations:

Operation Answer
GET .../migrations {"items": [...], "max_mailboxes": 100, "keep_days": 30}: the last 20 migrations, newest first
GET .../migrations/{migration_id} The migration, without passwords
POST .../migrations/{migration_id}/sync The migration: a paused import goes on, one under way is left alone, any other starts again
POST .../migrations/{migration_id}/finish The migration, finished, its kept passwords forgotten

A refused request answers with a detail object that holds a code and a message:

Status code When
422 cpanel_incomplete The host, the username, or both the token and the password are missing, or the port is not 2083 or 443
422 cpanel_refused, cpanel_unreachable, cpanel_error, cpanel_empty cPanel refused the sign-in, did not answer, said something went wrong, or holds no email accounts
422 migration_invalid A mailbox chosen cannot move; errors names each one and why. Nothing was changed
422 plan_full, plan_storage The plan has too few mailboxes or too little storage left. Nothing was changed
422 imap_unreachable, source_refused The old server's IMAP did not answer, or refused a password given; errors names each mailbox. Nothing was changed
404 not_mail_hosting The service is not Mail Hosting
409 service_inactive The service is not active
409 migration_finished A sync of a migration whose passwords are forgotten

A migration_id that is not the service's answers 404 Migration not found. A service may look at cPanel accounts 30 times an hour and start or sync migrations 10 times a day; past that the answer is 429.

API operations on this page

MethodPathWhat it does
GET/api/v1/client/mail/{service_id}/migrationsList the service's migrations
POST/api/v1/client/mail/{service_id}/migrations/cpanelMove a cPanel account's mail here
POST/api/v1/client/mail/{service_id}/migrations/cpanel/discoverFind what a cPanel account holds and what moving it here would do
GET/api/v1/client/mail/{service_id}/migrations/{migration_id}Get one migration and how far each of its mailboxes has got
POST/api/v1/client/mail/{service_id}/migrations/{migration_id}/finishFinish a migration and forget the old mailboxes' passwords
POST/api/v1/client/mail/{service_id}/migrations/{migration_id}/syncBring in what reached the old mailboxes since the migration started
GET/api/v1/client/smtp-relay/{service_id}/migrationsList the service's migrations
POST/api/v1/client/smtp-relay/{service_id}/migrations/cpanelMove a cPanel account's mail here
POST/api/v1/client/smtp-relay/{service_id}/migrations/cpanel/discoverFind what a cPanel account holds and what moving it here would do
GET/api/v1/client/smtp-relay/{service_id}/migrations/{migration_id}Get one migration and how far each of its mailboxes has got
POST/api/v1/client/smtp-relay/{service_id}/migrations/{migration_id}/finishFinish a migration and forget the old mailboxes' passwords
POST/api/v1/client/smtp-relay/{service_id}/migrations/{migration_id}/syncBring in what reached the old mailboxes since the migration started