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
C. Buat Service Account
IAM & Admin → Service Accounts → Create
- Name:
imap-migration-sa - Role: No role needed
-
Enable:
-
✅ Domain-wide delegation
-
- 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/
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
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
8️⃣ BEST PRACTICE MIGRASI
Jalankan 2x:
- Sebelum MX pindah
- 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 |