Public
Snippet $167 authored by irul

Migrasi email Google Workspace ke Domainesia Mailspace

migrasi-email.md

Migrasi email Google Workspace ke Domainesia Mailspace

Strategi migrasi untuk migrasi Google Workspace → Mailspace pakai imapsync tanpa login per user.

🔥 Service Account + Domain-Wide Delegation + IMAP OAuth2 🔥 1x setup admin → ratusan akun 🔥 No browser, no app password

Service Account (Google Cloud)
        ↓  JWT OAuth2
Domain-Wide Delegation (Admin approve)
        ↓  impersonate
user1@domain.com
user2@domain.com
user3@domain.com
        ↓
IMAP Gmail  →  IMAP Mailspace

1️⃣ GOOGLE CLOUD — SERVICE ACCOUNT

A. Buat Project

Google Cloud Console → New Project Nama bebas (mis: imap-migration)


B. Enable API

Enable:

  • Gmail API

👉 Ini WAJIB, walaupun kita akses via IMAP


C. Buat Service Account

IAM & Admin → Service Accounts → Create

  • Name: imap-migration-sa
  • Role: No role needed
  • Enable:

    • Domain-wide delegation

👉 Simpan:

  • Client ID (penting)
  • Email SA

D. Buat Key (JSON)

Create Key → JSON Unduh → simpan sebagai:

service_account.json

2️⃣ GOOGLE ADMIN CONSOLE — DOMAIN-WIDE DELEGATION

Login sebagai Super Admin

Security → API Controls

  • Domain-Wide Delegation → ENABLE

Add New

  • Client ID: (dari Service Account)
  • Scope:
  https://mail.google.com/

👉 Artinya: Service Account boleh impersonate SEMUA user Gmail


3️⃣ EMAIL MIGRATION TOOL — imapsync

Installation reference: https://imapsync.lamiral.info/#install

cd /tmp/
wget https://imapsync.lamiral.info/dist2/imapsync.deb
sudo apt install ./imapsync.deb

4️⃣ SCRIPT PYTHON — ACCESS TOKEN (IMPERSONATION)

sudo apt update
sudo apt install python3-pip jq -y
pip3 install google-auth

📄 get_token.py

#!/usr/bin/env python3

import sys
from google.oauth2 import service_account
import google.auth.transport.requests

SERVICE_ACCOUNT_FILE = "service_account.json"
SCOPES = ['https://mail.google.com/']

USER = sys.argv[1]

creds = service_account.Credentials.from_service_account_file(
    SERVICE_ACCOUNT_FILE,
    scopes=SCOPES
)

delegated_creds = creds.with_subject(USER)

request = google.auth.transport.requests.Request()
delegated_creds.refresh(request)

print(delegated_creds.token)
chmod +x get_token.py

️ Ini inti solusi ️ Tidak ada browser ️ Tidak ada login user


5️⃣ FILE AKUN MIGRASI

📄 accounts.csv

#gmail_user,mailspace_user,mailspace_password
user1@domainlama.com,user1@domainbaru.com,password1
user2@domainlama.com,user2@domainbaru.com,password2

6️⃣ BASH SCRIPT MIGRASI MASSAL

📄 migrate-imap-sa.sh

#!/bin/bash

SRC_HOST="imap.gmail.com"
DST_HOST="mail.domainesia.com" # sesuaikan

SLEEP_SEC=60 # 1 menit

LOG_DIR="./logs"
mkdir -p "$LOG_DIR"

while IFS=',' read -r SRC_USER DST_USER DST_PASS
do
    [[ "$SRC_USER" =~ ^#.*$ ]] && continue
    [[ -z "$SRC_USER" ]] && continue

    echo "======================================"
    echo "Migrating $SRC_USER$DST_USER"
    echo "======================================"

    while true; do
        echo "=== $(date) : requesting fresh token ==="

        TOKEN=$(./get_token.py "$SRC_USER")

        if [ -z "$TOKEN" ]; then
            echo "[ERROR] Token failed for $SRC_USER"
            sleep 30
            continue
        fi

        echo "=== $(date) : starting imapsync ==="

        imapsync \
          --host1 "$SRC_HOST" \
          --user1 "$SRC_USER" \
          --oauthaccesstoken1 "$TOKEN" \
          --host2 "$DST_HOST" \
          --user2 "$DST_USER" \
          --password2 "$DST_PASS" \
          --ssl1 \
          --ssl2 \
          --compress1 \
          --compress2 \
          --automap \
          --exclude '^Mailspring(/.*)?$' \
          --exclude '^\[Gmail\]/All Mail$' \
          --exclude '^\[Gmail\]/Important$' \
          --exclude '^\[Gmail\]/Starred$' \
          --exclude '^\[Gmail\]/Drafts$' \
          --exclude '^\[Gmail\]/Spam$' \
          --exclude '^\[Gmail\]/Bin$' \
          --syncinternaldates \
          --skipcrossduplicates \
          --subscribe \
          --nofoldersizes \
          --skipsize \
          --errorsmax 0 \
          --reconnectretry1 10 \
          --reconnectretry2 10 \
          --maxbytespersecond 500000 \
          --timeout 60 \
          --logdir "$LOG_DIR"

          # --exclude '^\[Gmail\]/Sent Mail$' \

        RC=$?

        if [ "$RC" -eq 0 ]; then
            echo "=== $(date) : migration finished successfully ==="
            break
        fi

        echo "=== $(date) : imapsync exited with $RC, retry in ${SLEEP_SEC}s ==="
        sleep "$SLEEP_SEC"
    done

done < accounts.csv

chmod +x migrate-imap-sa.sh

7️⃣ JALANKAN

./migrate-imap-sa.sh

️ Tidak ada login ️ Tidak ada prompt ️ Bisa ratusan user


8️⃣ BEST PRACTICE MIGRASI

Jalankan 2x:
  1. Sebelum MX pindah
  2. Sesudah MX pindah (final sync)

9️⃣ ERROR UMUM & SOLUSI

Error Penyebab
unauthorized_client Domain-wide delegation belum
invalid_grant Scope salah
AUTHENTICATIONFAILED Bukan Super Admin
quota Speed terlalu tinggi