# IMAP-to-IMAP Mailbox Migration — SiteGround → MXroute

Migrated Jul 8, 2026: garrison@iamgmb.com (324 msgs) and greyson@iamgmb.com (74 msgs).

## SiteGround IMAP Discovery

- Host: c1113726.sgvps.net:993
- SiteGround uses `.` as folder separator (not `/`)
- Folders listed as `INBOX.Trash`, `INBOX.Sent Messages`, etc.
- IMAP LIST response format: `(flags) "." "INBOX.Trash"`
- Parsing: `decoded.rsplit('"', 2)[-2]` to extract the folder name
- The same SiteGround IP serves as the SMTP relay for all hosted domains

## Folder Mapping (SiteGround → MXroute)

| SiteGround | MXroute |
|-----------|---------|
| `INBOX` | `INBOX` |
| `INBOX.Sent Messages` + `INBOX.Sent` | `Sent` |
| `INBOX.Trash` + `INBOX.Deleted Messages` | `Trash` |
| `INBOX.spam` + `INBOX.Junk` | `Junk` |
| `INBOX.Drafts` | `Drafts` |
| `INBOX.Archive` | `Archive` |

## Count Per Folder (garrison@)

| Folder | Count |
|--------|-------|
| INBOX | 170 |
| INBOX.Trash | 118 |
| INBOX.Deleted Messages | 30 |
| INBOX.Sent Messages | 5 |
| INBOX.Sent | 1 |

## Migration Script Pattern

```python
old = imaplib.IMAP4_SSL(old_host, 993)
old.login(email, old_pw)
new = imaplib.IMAP4_SSL(new_host, 993)
new.login(email, new_pw)

# Select folder with quoting for spaces
old.select('"INBOX"')
uids = old.search(None, "ALL")[1][0].split()

for uid in uids:
    r = old.fetch(uid, "(RFC822)")
    if r[0] == "OK" and isinstance(r[1][0], tuple):
        new.append("INBOX", None, None, r[1][0][1])
```

## Pitfalls
- SiteGround server can timeout on batches >170 msgs
- MXroute folders must be created BEFORE appending
- No IMAP deduplication on APPEND — multiple runs create duplicates
- UIDs differ between servers; append doesn't preserve old UIDs
- Test with a small batch first to catch timeout issues
- Verify ALL folders and message counts after migration
