Email

Migrate Google Workspace email with imapsync (OAuth2 service account)

Reviewed on 11 min read migracion de correo imapsync google workspace

When a client wants to move a domain's email hosted on Google Workspace to our servers, they can use imapsync. Google no longer lets third-party applications connect over IMAP with the account's normal password. You need to use OAuth 2.0 or, for a one-off migration of a few accounts where the policy allows it, an app password.

In this guide we explain the two valid ways of authenticating the Google Workspace source and, specifically, how to set up a service account with domain-wide delegation. The same credential can authenticate the authorised mailboxes without touching each user, although imapsync has to synchronise them one by one.

Why the normal password no longer works

Google has phased out access for "less secure apps" (basic auth):

  • 15 June 2024: the less secure apps setting is removed from the Admin console. Administrators can no longer turn it on (existing connections kept working for a while).
  • 14 March 2025: Google began turning off third-party app access with the normal password on Workspace accounts.
  • 1 May 2025: the announced transition for these apps ended.

So do not set up imapsync with the normal password. OAuth2 delegation is the right option for many accounts; an app password is a per-user exception that requires 2-Step Verification and that the administrator has not restricted it.

The two options

Service account (XOAUTH2) App passwords
Best for Migrating a whole domain Migrating one or a few accounts
Need to touch each user No Yes (turn on 2-Step Verification + generate a code)
What you need 1 JSON file (the admin creates it once) A 16-character code per account
Access required Workspace admin + Google Cloud Access to each account

If you are only migrating one or two accounts, app passwords (described in Move Gmail accounts to Hostsuar) are the quickest. For a whole domain, carry on with the service account.

Set up the service account (done by the Workspace administrator)

These steps are carried out only once by a super administrator of the Google Workspace domain. At the end you get a JSON file containing a private key. Delegation can allow impersonating domain users for the granted scopes: a list of mailboxes written in a script does not technically limit that power.

1. Create or select a project in Google Cloud

Go to console.cloud.google.com with the administrator account and create a new project (for example migracion-correo) or select an existing one.

2. Review the Google Cloud project

IMAP XOAUTH2 authentication uses the mail scope authorised in the domain delegation. Enabling the Gmail API does not replace that authorisation and is not a requirement imapsync documents for its JSON flow. You can enable it if other tools in the project will use the API, but do not grant the service account extra IAM roles for this migration.

3. Create the service account and its JSON key

Go to APIs & Services → Credentials → Create credentials → Service account and give it a name. The wizard will then offer two steps marked (optional): "Permissions / Grant this service account access to project" (select a role) and "Principals with access". Leave both empty and continue: this service account does not need any IAM role on the project, because access to the mailboxes is granted in step 4 (domain-wide delegation), not here. Click Done to create it.

Then, inside the service account, go to the Keys → Add key → Create new key tab and choose the JSON format (do not use P12).

A file with this structure will be downloaded, which you will rename to secret.xoauth2.json:

{
  "type": "service_account",
  "project_id": "...",
  "private_key_id": "...",
  "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
  "client_email": "xxx@proyecto.iam.gserviceaccount.com",
  "client_id": "1234567890...",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://accounts.google.com/o/oauth2/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "..."
}

Note down the client_id value from the JSON (a long number): you will need it in the next step. It is the service account's OAuth2 identifier, and it is exactly what goes in the Client ID field of the domain-wide delegation (step 4).

4. Authorise domain-wide delegation

This step takes place in the Google Workspace Admin console (admin.google.com), which is a different site from the Google Cloud Console where you created the service account.

The quickest way is to go straight to the delegation URL (signed in as super administrator):

https://admin.google.com/ac/owl/domainwidedelegation

Or navigate: Menu (☰) → Security → Access and data control → API controls → "Manage Domain Wide Delegation". Once there, click Add new and:

  • In Client ID, paste the client_id from the previous step.
  • In OAuth scopes, enter this scope:
https://mail.google.com/

Very important: https://mail.google.com/ is the scope imapsync's JSON flow requests for IMAP access. Authorise only that scope. gmail.readonly does not allow IMAP sign-in. Google documents gmail.imap_admin as an alternative for clients that explicitly request that scope; adding it in the console does not make imapsync request it, nor does it guarantee that hidden labels will appear.

Click Authorize to save.

5. Check that IMAP is enabled

In the Admin console, go to Apps → Google Workspace → Gmail → End User Access and make sure IMAP access is turned on. The mail client policy for the organisational unit concerned must allow any mail client; restricting it to specific OAuth client IDs can block the service account even if the delegation exists.

With that, the Google side is ready. The secret.xoauth2.json file contains a private key and must be treated as a credential that can impersonate the authorised mailboxes.

Test and run imapsync

This flow requires a version of imapsync that supports JSON service accounts and their XOAUTH2 dependencies. It does not work in the graphical migration interface based on username and password. First run an authentication test for one account:

imapsync \
  --host1 imap.gmail.com --ssl1 --sslargs1 SSL_verify_mode=1 --user1 usuario@tudominio.com \
  --password1 /ruta/privada/secret.xoauth2.json --authmech1 XOAUTH2 \
  --host2 SERVIDOR_IMAP_DESTINO --ssl2 --sslargs2 SSL_verify_mode=1 --user2 usuario@tudominio.com \
  --passfile2 "$HOME/.imapsync-destino" --justlogin

Remove --justlogin only once both authentications work. Delegation saves you creating a key per user, but imapsync still runs one synchronisation per mailbox. Test one account first, check labels and counts, and then process the rest in a controlled way. Gmail limits IMAP downloads to 2,500 MB per user per day according to the published limit, which Google may change; when you reach the limit, stop that account and wait before resuming it. For SERVIDOR_IMAP_DESTINO, use the hostname with a valid certificate shown in cPanel's Connect Devices.

Handing over and safely withdrawing the key

  • Transfer the JSON through a one-time encrypted exchange, with an expiry and access limited to the person who will run the migration. Do not paste it into the text of a ticket or send it by email.
  • On the migration machine, store it outside public directories, owned by a single user and with 0600 permissions: chmod 600 secret.xoauth2.json. Do not copy it to repositories, shared backups or command logs.
  • Limit the delegation to the length of the migration. Once you have finished and verified the mailboxes, remove the domain-wide delegation authorisation, revoke and delete the service account key in Google Cloud and delete every local copy of the JSON.
  • If the key was sent through the wrong channel or may have been exposed, revoke it before continuing and generate a new one; deleting only the file does not invalidate a key that has already been copied.

Decide who can run the migration

Authorise this procedure only for the agreed mailboxes and operation. The https://mail.google.com/ scope is not read-only: running imapsync without deletion options does not reduce the permissions anyone who obtains the key would have.

The IMAP policy restricted to OAuth client IDs does not support this delegation flow, according to Google. Do not loosen the policy for the whole organisation for convenience: the administrator should weigh up the unit affected, the duration and restoring the controls, or choose another authorised method.

Before processing the whole set, test one account and keep an inventory of source, destination, skipped folders, errors and last synchronisation. When you wrap up, as well as withdrawing the key and the delegation, check that any temporary policies are back to their intended state.

You may also find useful

Something wrong or out of date? Tell us and we will review it.