Skill: luigi08001/email-migration-toolkit (version 1.2.0)

--- name: email-migration-toolkit description: "Universal email migration toolkit for any provider to any provider. Use when migrating between Yahoo, Zoho, ProtonMail, iCloud, on-premises Exchange, or any IMAP-capable email service. Covers decision trees, backup/export procedures, IMAP connectivity testing, troubleshooting, and provider-specific configurations. Essential for IT professionals handling diverse email migrations beyond Google/Microsoft ecosystems." --- # Universal Email Migration Toolkit ## Migration Decision Tree Use this matrix to determine the best migration path: | Source | Destination | Method | Complexity | Notes | |--------|-------------|--------|-----------|-------| | Yahoo Mail | Gmail | IMAP → Gmail Import | Easy | Use app passwords | | Yahoo Mail | Outlook | IMAP → Outlook Desktop | Medium | Manual folder setup | | Zoho Mail | Gmail | IMAP → Gmail Import | Easy | Supports IMAP natively | | Zoho Mail | Outlook | Microsoft Migration | Medium | Use Zoho IMAP settings | | ProtonMail | Gmail | Export → Import | Hard | Limited export options | | ProtonMail | Outlook | Manual forwarding | Hard | No bulk export | | iCloud Mail | Gmail | IMAP → Gmail Import | Easy | Requires app password | | iCloud Mail | Outlook | IMAP → Outlook | Medium | Limited folder support | | Any IMAP | Any IMAP | IMAP bridging | Medium | Universal solution | | Exchange On-prem | Cloud | PST export/import | Hard | Requires Exchange admin | ## Universal IMAP Migration Process For most provider-to-provider migrations: ### Step 1: Source Preparation 1. **Enable IMAP** on source account (if not enabled by default) 2. **Create app password** (Gmail, Yahoo, iCloud require this) 3. **Test connectivity** using the IMAP test script 4. **Estimate data size** using the mailbox size script 5. **Document folder structure** for mapping reference ### Step 2: Destination Setup 1. **Create target account** with sufficient storage 2. **Enable IMAP access** (for intermediary tools) 3. **Configure mail client** (Outlook, Thunderbird, or web import) 4. **Set up folder structure** matching source (if needed) 5. **Test inbound mail** to verify account is working ### Step 3: Migration Execution Choose based on destination platform: #### To Gmail (any source with IMAP) 1. Gmail → Settings → Accounts → Import mail and contacts 2. Enter source IMAP details from provider matrix 3. Choose import options (last 30 days vs. all mail) 4. Start import — Gmail handles the rest automatically #### To Outlook/Microsoft 365 1. Outlook Desktop → Add Account → IMAP source 2. Set up both accounts in same Outlook profile 3. Drag and drop folders from source to destination 4. Alternative: Use Microsoft's import tools for bulk #### IMAP-to-IMAP (Universal) 1. Use desktop client (Outlook, Thunderbird, Apple Mail) 2. Configure both accounts as IMAP 3. Copy folders between accounts via client 4. Monitor for errors and retry failed items ### Step 4: Validation 1. **Compare email counts** between source and destination 2. **Test key functionality** (send, receive, search) 3. **Verify contacts and calendar** if migrated 4. **Check folder structure** matches expectations 5. **Validate largest messages** and attachments ## Email Backup and Export Before any migration, create backups: ### Source-Specific Export Methods #### Gmail / Google Workspace - **Method**: Google Takeout (takeout.google.com) - **Format**: MBOX (Thunderbird compatible) - **Includes**: Email, contacts, calendar - **Time**: 2-48 hours depending on mailbox size #### Outlook / Exchange - **Method**: Export to PST file - **Format**: PST (Outlook native) - **Process**: File → Open & Export → Export to File - **Limitation**: Desktop Outlook required #### Yahoo Mail - **Method**: IMAP download via email client - **Format**: Various (depends on client) - **Process**: Configure IMAP, sync all folders locally - **Note**: No bulk export tool from Yahoo #### Zoho Mail - **Method**: IMAP export or Zoho's backup tool - **Format**: MBOX or EML - **Process**: Contact Zoho support for large mailboxes - **Alternative**: IMAP sync to local client #### iCloud Mail - **Method**: IMAP download - **Format**: Various (client dependent) - **Process**: Configure IMAP with app password - **Limitation**: No native export tool #### ProtonMail - **Method**: Individual email export only - **Format**: EML files - **Process**: Select emails individually, export - **Note**: No bulk export due to encryption See `references/backup-export.md` for detailed step-by-step procedures. ## Common Migration Challenges | Challenge | Solution | Prevention | |-----------|----------|------------| | Authentication failures | Use app passwords, check 2FA settings | Test connectivity first | | Size limitations | Split into batches, exclude large attachments | Check provider limits | | Folder mapping issues | Document structure, plan manual creation | Map folders before migration | | Missing emails | Check spam/junk, verify date ranges | Do incremental migration | | Slow transfer speeds | Use multiple connections, off-peak hours | Plan adequate time | | Character encoding | Ensure UTF-8 support in tools | Test with non-ASCII subjects | ## Provider-Specific Considerations ### Yahoo Mail - **IMAP Limitations**: Free accounts have folder limits - **Authentication**: Must use app passwords with 2FA - **Best Practice**: Migrate during off-peak hours (night/weekend) ### Zoho Mail - **IMAP Support**: Full IMAP access on all plans - **Bulk Migration**: Zoho offers migration services for enterprise - **API Access**: Available for custom migration tools ### ProtonMail - **Major Limitation**: No IMAP access due to encryption - **Workaround**: Export to Thunderbird, then migrate from Thunderbird - **Enterprise**: ProtonMail Bridge available for paid plans ### iCloud Mail - **Storage Limits**: 5GB free, consider upgrading temporarily - **IMAP Quirks**: Some folders may not sync properly - **Performance**: Slow IMAP response, plan extra time ### On-Premises Exchange - **Admin Access**: Required for PST export/import - **Network**: Consider bandwidth limitations - **Legacy Versions**: Older Exchange may need PST conversion ## Troubleshooting Workflow When migration fails or stalls: 1. **Check authentication** — Re-enter passwords, regenerate app passwords 2. **Verify IMAP settings** — Double-check server, port, SSL settings 3. **Test connectivity** — Run `scripts/imap-test.py` with exact settings 4. **Check quotas** — Verify destination has enough storage space 5. **Review logs** — Look for specific error messages in client logs 6. **Retry smaller batches** — Split large mailboxes into smaller chunks 7. **Contact support** — Provider-specific issues may need support tickets See `references/troubleshooting.md` for comprehensive error resolution guide. ## Migration Best Practices ### Planning Phase - **Inventory thoroughly** — Document all email accounts, sizes, special requirements - **Test with pilot users** — Never migrate entire organization without testing - **Communicate clearly** — Set expectations with users about timeline and downtime - **Plan rollback** — Always have a way to revert if migration fails ### Execution Phase - **Monitor actively** — Don't start migration and walk away - **Validate incrementally** — Check each user/batch before proceeding - **Keep logs** — Document what worked, what failed, and why - **Stay flexible** — Be prepared to switch methods if primary approach fails ### Post-Migration - **Validate data integrity** — Compare counts, spot-check important emails - **Train users** — New interface, different features, updated mobile setup - **Monitor performance** — Watch for issues in first 48-72 hours - **Plan cleanup** — When to disable old accounts, how long to retain access

path: references/backup-export.md
content: # Email Backup and Export Procedures

## Google Workspace / Gmail

### Method 1: Google Takeout (Recommended)

**Steps:**
1. Go to **takeout.google.com**
2. **Deselect all** → Select only **Mail**
3. Click **Next step**
4. Choose **Export once** and **Send download link via email**
5. Select **MBOX format** (most compatible)
6. Choose archive size (2GB recommended for easier download)
7. Click **Create export**
8. Wait for email notification (can take 2-48 hours)
9. Download archive files

**What's Included:**
- All emails from all folders
- Labels (as folder structure)
- Attachments
- Sent items, drafts, spam

**Format:** MBOX (Thunderbird, Apple Mail compatible)

### Method 2: IMAP Download

**Use when:** Takeout fails or you need selective backup

**Steps:**
1. Enable IMAP in Gmail settings
2. Set up email client (Thunderbird recommended)
3. Configure Gmail account with app password
4. Let client sync all folders
5. Export from client to desired format

## Microsoft 365 / Outlook

### Method 1: PST Export (Desktop Outlook)

**Steps:**
1. Open **Outlook Desktop** (not web version)
2. Go to **File** → **Open & Export** → **Import/Export**
3. Select **Export to a file** → **Next**
4. Choose **Outlook Data File (.pst)** → **Next**
5. Select account or specific folders → **Next**
6. Choose save location and filename → **Finish**
7. Set password (optional but recommended)

**What's Included:**
- All emails, sent items, drafts
- Calendar events
- Contacts
- Rules and settings

**Format:** PST (Outlook native, widely supported)

### Method 2: eDiscovery Export (Admin)

**Use when:** Admin-level bulk export needed

**Steps:**
1. **Microsoft Purview** compliance portal
2. **Content search** → Create new search
3. Select users/mailboxes to export
4. Run search → **Export results**
5. Download using eDiscovery Export Tool

**Requirements:** Compliance admin permissions

## Yahoo Mail

### Method 1: IMAP Download (Only Option)

**Steps:**
1. Enable **IMAP access** in Yahoo Mail settings
2. Generate **app password**: Account Security → App passwords
3. Configure email client with IMAP settings:
   - Server: imap.mail.yahoo.com
   - Port: 993, SSL enabled
   - Use app password (not regular password)
4. Let client download all mail
5. Export from client to desired format

**Limitations:**
- No bulk export tool from Yahoo
- Free accounts have folder limitations
- Large mailboxes may take days to sync

## Zoho Mail

### Method 1: Zoho's Migration Tool

**Steps:**
1. **Zoho Admin Console** → **Migration**
2. Choose **Export** option
3. Select users and date range
4. Choose format (MBOX recommended)
5. Submit request (may take hours/days)
6. Download when ready

**Requirements:** Admin access to Zoho organization

### Method 2: IMAP Download

**Steps:**
1. Use IMAP settings from provider matrix
2. Configure in email client
3. No app password needed for most Zoho accounts
4. Download and export locally

## iCloud Mail

### Method 1: IMAP Download (Only Option)

**Steps:**
1. Generate **app password**: appleid.apple.com → App-Specific Passwords
2. Configure email client with IMAP settings:
   - Server: imap.mail.me.com
   - Port: 993, SSL enabled
   - Use app password
3. Download all folders via client
4. Export from client

**Limitations:**
- No native export tool from Apple
- Some folders may not sync properly
- Slow IMAP performance

## ProtonMail

### Method 1: Individual Export (Web Interface)

**Steps:**
1. Log in to **ProtonMail web interface**
2. Open email to export
3. Click **More** → **Export**
4. Save as EML file
5. Repeat for each important email

**Limitations:**
- No bulk export option
- Very time-consuming for large mailboxes
- Free accounts cannot use Bridge

### Method 2: ProtonMail Bridge (Paid Plans)

**Steps:**
1. Install **ProtonMail Bridge** application
2. Add ProtonMail account to Bridge
3. Configure email client to connect to Bridge
4. Use local IMAP connection to download mail
5. Export from email client

**Requirements:**
- Paid ProtonMail plan
- Desktop Bridge application

## Exchange On-Premises

### Method 1: Exchange Management Shell

**Admin PowerShell:**
```powershell
New-MailboxExportRequest -Mailbox "[REDACTED_SECRET]" -FilePath "\\server\share\user.pst"
Get-MailboxExportRequest | Get-MailboxExportRequestStatistics
```

### Method 2: Outlook PST Export

**Same as Microsoft 365 method** — works for on-premises Exchange

## Thunderbird Universal Backup

**For any IMAP account:**

1. **Install Thunderbird** (free)
2. **Add email account** with IMAP settings
3. **Let sync complete** (may take hours/days)
4. **Profile backup**: Copy entire Thunderbird profile folder
   - Windows: `%APPDATA%\Thunderbird\Profiles\`
   - Mac: `~/Library/Thunderbird/Profiles/`
   - Linux: `~/.thunderbird/`

**Advantages:**
- Works with any IMAP provider
- Preserves folder structure
- Can import to other Thunderbird installations

## Format Conversion Tools

### MBOX to PST
- **MailStore Home** (free for personal use)
- **Stellar MBOX to PST Converter**
- **SysTools MBOX Converter**

### PST to MBOX
- **Aid4Mail** (commercial)
- **PST Converter Pro**
- **MailStore Home**

### EML to MBOX/PST
- **Thunderbird** (import EML files)
- **Windows Live Mail** (can import/export both)

## Backup Best Practices

### Before Migration
1. **Full backup** of source system
2. **Test restore** on sample data
3. **Document folder structure**
4. **Note special configurations** (rules, signatures, etc.)

### During Migration
1. **Incremental backups** of changes
2. **Keep source active** during migration
3. **Monitor backup integrity**

### After Migration
1. **Retain source backups** for 30-90 days
2. **Document successful migration**
3. **Archive backups** for compliance
4. **Test restore procedures**

## Storage Considerations

### File Sizes
- **MBOX files**: Can be very large (GB+)
- **PST files**: 50GB limit (older Outlook versions)
- **Split large files**: Use client options to split

### Compression
- **ZIP archives**: Significant compression for email
- **Encrypted archives**: Recommended for sensitive data
- **Cloud storage**: Ensure encryption in transit/rest

## Recovery Testing

### Verification Steps
1. **Import backup** to test system
2. **Compare email counts** with original
3. **Test search functionality**
4. **Verify attachments** open correctly
5. **Check folder structure** preservation
6. **Test with sample users**

### Common Issues
- **Character encoding** problems with international text
- **Date/time stamps** may change during export/import
- **Folder hierarchy** may flatten in some formats
- **Large attachments** may fail to export/import
- **Encrypted emails** may not decrypt after migration

path: references/imap-settings.md
content: # IMAP Settings by Provider

## Quick Reference Cards

### Gmail
```
IMAP Server: imap.gmail.com
Port: 993 (SSL/TLS)
SMTP Server: smtp.gmail.com  
Port: 465 (SSL) or 587 (STARTTLS)
Authentication: App Password (2FA required)
Special: Labels appear as folders, All Mail contains everything
```

### Microsoft 365/Outlook.com
```
IMAP Server: outlook.office365.com
Port: 993 (SSL/TLS)
SMTP Server: smtp-mail.outlook.com (personal) or smtp.office365.com (business)
Port: 587 (STARTTLS)
Authentication: App Password or OAuth2
Special: Modern auth preferred for business accounts
```

### Yahoo Mail
```
IMAP Server: imap.mail.yahoo.com
Port: 993 (SSL/TLS)
SMTP Server: smtp.mail.yahoo.com
Port: 465 (SSL) or 587 (STARTTLS)
Authentication: App Password required
Special: Free accounts have folder limitations
```

### iCloud Mail
```
IMAP Server: imap.mail.me.com
Port: 993 (SSL/TLS)
SMTP Server: smtp.mail.me.com
Port: 587 (STARTTLS)
Authentication: App Password always required
Special: Generate at appleid.apple.com
```

### Zoho Mail
```
IMAP Server: imap.zoho.com
Port: 993 (SSL/TLS)
SMTP Server: smtp.zoho.com
Port: 465 (SSL) or 587 (STARTTLS)
Authentication: Regular password or app password
Special: Full IMAP support on free and paid plans
```

## Provider-Specific Setup Instructions

### Gmail Setup

**Enable IMAP:**
1. Settings → Forwarding and POP/IMAP
2. Enable IMAP
3. Choose "Auto-Expunge off" for migration

**Generate App Password:**
1. Google Account → Security
2. 2-Step Verification (must be enabled)
3. App passwords → Generate
4. Use generated password (not regular password)

**Client Configuration:**
```
Username: [REDACTED_SECRET]
[REDACTED_SECRET] app password
Security: SSL/TLS
Server Certificate: Accept
```

### Yahoo Mail Setup

**Enable IMAP:**
1. Account Info → Account Security
2. Generate and manage app passwords
3. Create app password for "Mail"

**Client Configuration:**
```
Username: [REDACTED_SECRET]
Password: app password from Yahoo
Security: SSL/TLS
Authentication: Normal password
```

**Troubleshooting:**
- Use full email address as username
- Ensure "Less secure app access" is enabled (legacy)
- Some regions require app passwords even without 2FA

### iCloud Mail Setup

**Generate App Password:**
1. Sign in to appleid.apple.com
2. Sign-In and Security → App-Specific Passwords
3. Generate password for "Mail"
4. Use immediately (passwords shown only once)

**Client Configuration:**
```
Username: [REDACTED_SECRET]
[REDACTED_SECRET] password
IMAP Prefix: INBOX (if required)
Security: SSL/TLS
```

**Common Issues:**
- Must use @icloud.com, not @me.com or @mac.com in client
- Some clients require INBOX prefix
- Slow IMAP response times are normal

### Zoho Mail Setup

**Basic Configuration:**
```
Username: [REDACTED_SECRET] (or [REDACTED_SECRET])
[REDACTED_SECRET] account password
Security: SSL/TLS
Special Folders: Standard IMAP folders
```

**For Enhanced Security:**
1. Zoho Account → Security → App Passwords
2. Generate specific password for email client
3. Use app password instead of regular password

### Microsoft 365 Setup

**Modern Authentication (Preferred):**
- Use OAuth2 if supported by client
- Sign in with regular credentials
- Client handles token refresh automatically

**Basic Authentication (Legacy):**
```
Username: [REDACTED_SECRET]
[REDACTED_SECRET] password or app password
Security: STARTTLS on port 587
Server: outlook.office365.com
```

**App Passwords (if 2FA enabled):**
1. portal.office.com → My Account → Security info
2. Add method → App password
3. Use generated password in email client

## Client-Specific Settings

### Outlook Desktop

**Account Setup Wizard:**
1. File → Add Account → Manual setup
2. Choose IMAP → Enter server details
3. Test account settings before completing
4. Set sync limits if needed (12 months recommended)

**Advanced Settings:**
- Root folder path: Leave blank (usually)
- Use secure authentication: Check if available
- Leave messages on server: Check for migration
- Download shared folders: Uncheck initially

### Thunderbird

**Account Setup:**
1. Account Actions → Add Mail Account
2. Enter name, email, password
3. Manual config if auto-detection fails
4. Set server settings from provider matrix

**Optimization for Migration:**
- Edit → Preferences → Advanced → Config Editor
- Set `mail.server.default.max_cached_connections` to 1
- Set download limit to "Don't download messages larger than X MB"

### Apple Mail

**Account Setup:**
1. Mail → Preferences → Accounts → Add Account
2. Choose "Other Mail Account"
3. Enter email and app password
4. Manual configuration if needed

**Performance Tips:**
- Mailbox → Synchronize All Accounts
- View → Mailbox List → Show All Mailboxes
- For large mailboxes, sync recent messages first

### Mobile Clients (iOS/Android)

**iOS Mail:**
```
Account Type: IMAP
Mail Server: (from provider matrix)
Username: full email address
Password: app password
Use SSL: On
Authentication: Password
Server Port: 993
```

**Gmail App:**
- Can add non-Gmail IMAP accounts
- Go to Settings → Add Account → Other
- Use IMAP settings from matrix

**Outlook Mobile:**
- Supports most IMAP providers
- Add Account → choose provider or "Other"
- Auto-configuration works for major providers

## Advanced Configuration

### Folder Mapping

**Gmail Specifics:**
- All Mail = Archive in other clients
- Sent Mail = Sent Items
- [Gmail]/Spam = Junk/Spam
- [Gmail]/Trash = Deleted Items
- Labels appear as additional folders

**Exchange/Outlook Mapping:**
- Inbox = Inbox
- Sent Items = Sent Mail  
- Deleted Items = Trash
- Junk Email = Spam
- Archive = Archive (if enabled)

### Batch Optimization

**For Migration Tools:**
- Increase connection timeout: 120+ seconds
- Reduce concurrent connections: 1-2 max
- Enable incremental sync
- Set realistic batch sizes (1000 messages max)

**Throttling Settings:**
```
IMAP Commands per minute: 60-120
Concurrent folders: 1-3
Message size limit: 25MB
Retry attempts: 3-5
Backoff multiplier: 2x
```

## Security Considerations

### Authentication Methods Ranked

1. **OAuth2** (most secure) - Token-based, handles 2FA
2. **App passwords** (recommended) - Unique per application
3. **Regular passwords** (least secure) - Main account password

### Network Security

**SSL/TLS Requirements:**
- Always use encrypted connections (993/465/587)
- Verify server certificates
- Avoid plain text IMAP (port 143) in production

**Firewall Considerations:**
- Outbound 993 (IMAP SSL) must be allowed
- Outbound 465/587 (SMTP SSL/STARTTLS) for sending
- Some providers use additional ports for authentication

### Credential Management

**Best Practices:**
- Use app passwords when available
- Rotate passwords after migration
- Document credentials securely
- Revoke unused app passwords
- Monitor for suspicious login attempts

**App Password Naming:**
- Use descriptive names: "Migration Tool - Jan 2024"
- Include date for expiration tracking
- Note purpose and device/application

path: references/provider-matrix.md
content: # Email Provider Matrix — IMAP/SMTP Settings

## Major Email Providers

| Provider | IMAP Server | IMAP Port | SMTP Server | SMTP Port | SSL/TLS | App Password |
|----------|-------------|-----------|-------------|-----------|---------|--------------|
| **Gmail** | imap.gmail.com | 993 | smtp.gmail.com | 465 | SSL | Required |
| **Outlook.com** | outlook.office365.com | 993 | smtp-mail.outlook.com | 587 | STARTTLS | Required |
| **Yahoo Mail** | imap.mail.yahoo.com | 993 | smtp.mail.yahoo.com | 465/587 | SSL | Required |
| **AOL Mail** | imap.aol.com | 993 | smtp.aol.com | 465/587 | SSL | Required |
| **iCloud Mail** | imap.mail.me.com | 993 | smtp.mail.me.com | 587 | STARTTLS | Required |
| **Zoho Mail** | imap.zoho.com | 993 | smtp.zoho.com | 465/587 | SSL | Optional |
| **ProtonMail** | 127.0.0.1* | 1143* | 127.0.0.1* | 1025* | Local | Bridge Only |
| **Fastmail** | imap.fastmail.com | 993 | smtp.fastmail.com | 465/587 | SSL | Optional |
| **Tutanota** | N/A | N/A | N/A | N/A | N/A | No IMAP |

\* ProtonMail requires ProtonMail Bridge application running locally

## Business/Enterprise Providers

| Provider | IMAP Server | IMAP Port | SMTP Server | SMTP Port | SSL/TLS | Notes |
|----------|-------------|-----------|-------------|-----------|---------|-------|
| **Microsoft 365** | outlook.office365.com | 993 | smtp.office365.com | 587 | STARTTLS | OAuth2 preferred |
| **Google Workspace** | imap.gmail.com | 993 | smtp.gmail.com | 465/587 | SSL | OAuth2 preferred |
| **Zoho Workplace** | imap.zoho.com | 993 | smtp.zoho.com | 465/587 | SSL | Domain-based auth |
| **Rackspace Email** | secure.emailsrvr.com | 993 | secure.emailsrvr.com | 587 | STARTTLS | Domain setup required |
| **Office 365** | outlook.office365.com | 993 | smtp.office365.com | 587 | STARTTLS | Same as Microsoft 365 |

## Regional/Local Providers

| Provider | IMAP Server | IMAP Port | SMTP Server | SMTP Port | SSL/TLS | Region |
|----------|-------------|-----------|-------------|-----------|---------|---------|
| **Mail.ru** | imap.mail.ru | 993 | smtp.mail.ru | 465 | SSL | Russia |
| **GMX** | imap.gmx.net | 993 | mail.gmx.net | 587 | STARTTLS | Germany |
| **1&1 IONOS** | imap.1and1.com | 993 | smtp.1and1.com | 587 | STARTTLS | Europe |
| **Yandex.Mail** | imap.yandex.com | 993 | smtp.yandex.com | 465 | SSL | Russia |
| **Naver Mail** | imap.naver.com | 993 | smtp.naver.com | 587 | STARTTLS | South Korea |

## Legacy/On-Premises

| System | Default IMAP | Default SMTP | Port Range | SSL Support | Notes |
|--------|-------------|--------------|------------|-------------|-------|
| **Exchange 2019** | mail.domain.com | mail.domain.com | 993/587 | Yes | Autodiscover available |
| **Exchange 2016** | mail.domain.com | mail.domain.com | 993/587 | Yes | Requires proper certificates |
| **Exchange 2013** | mail.domain.com | mail.domain.com | 993/587 | Yes | Legacy versions supported |
| **Zimbra** | mail.domain.com | mail.domain.com | 993/587 | Yes | Open source alternative |
| **MDaemon** | mail.domain.com | mail.domain.com | 993/587 | Yes | Small business focused |
| **Kerio Connect** | mail.domain.com | mail.domain.com | 993/587 | Yes | SMB solution |

## Authentication Methods

### App Passwords Required
- Gmail (with 2FA enabled)
- Yahoo Mail (with 2FA enabled)  
- iCloud Mail (always)
- Outlook.com (with 2FA enabled)
- AOL Mail (with 2FA enabled)

### OAuth2 Supported
- Gmail/Google Workspace
- Microsoft 365/Outlook.com
- Yahoo Mail (limited)

### Standard Password
- Zoho Mail
- Fastmail
- Most on-premises systems
- Regional providers (varies)

## Special Configuration Notes

### Gmail
- **Less secure app access**: Deprecated as of May 2022
- **Must use**: App passwords or OAuth2
- **IMAP folders**: All Mail, Spam, Trash have special behavior
- **Labels**: Become folders in IMAP clients

### Yahoo Mail
- **Free accounts**: IMAP access included
- **App passwords**: Required even without 2FA in some regions
- **Folders**: Limited folder depth on free accounts

### iCloud Mail
- **App passwords**: Always required regardless of 2FA
- **Generate at**: appleid.apple.com → Sign-In and Security
- **Limitations**: Some IMAP features limited on free accounts

### ProtonMail
- **IMAP access**: Only via ProtonMail Bridge (paid plans)
- **Bridge setup**: Acts as local IMAP/SMTP proxy
- **Free accounts**: No IMAP access available
- **Export**: Individual emails only via web interface

### Zoho Mail
- **Free tier**: 5GB storage, IMAP included
- **Business**: Full IMAP/API access
- **Migration tools**: Zoho provides assisted migration services
- **Custom domains**: Full DNS control required

## Testing Commands

```bash
# Test IMAP connectivity
telnet imap.provider.com 993
openssl s_client -connect imap.provider.com:993

# Test SMTP connectivity  
telnet smtp.provider.com 587
openssl s_client -starttls smtp -connect smtp.provider.com:587

# Check MX records
dig MX domain.com +short

# Verify SSL certificate
openssl s_client -connect imap.provider.com:993 -servername imap.provider.com
```

## Common Port Alternatives

| Service | Primary | Alternative | Notes |
|---------|---------|-------------|--------|
| **IMAP SSL** | 993 | 143+STARTTLS | 993 is encrypted from start |
| **SMTP SSL** | 465 | 587+STARTTLS | 465 legacy but still common |
| **POP3 SSL** | 995 | 110+STARTTLS | Not recommended for migration |

## Troubleshooting Matrix

| Error | Likely Cause | Check |
|-------|-------------|-------|
| Connection refused | Wrong server/port | Verify provider settings |
| Authentication failed | Wrong credentials | Try app password |
| SSL handshake failed | Certificate issues | Check SSL/TLS setting |
| Folder not found | IMAP folder quirks | Check provider documentation |
| Quota exceeded | Storage limit | Check account storage limits |

path: references/troubleshooting.md
content: # Email Migration Troubleshooting Guide

## Connection Issues

### "Connection Refused" or "Cannot Connect"

**Likely Causes:**
- Wrong server address or port
- Firewall blocking connections  
- Provider maintenance/downtime

**Diagnostic Steps:**
```bash
# Test basic connectivity
telnet imap.provider.com 993

# Test SSL connection
openssl s_client -connect imap.provider.com:993 -servername imap.provider.com

# Check DNS resolution
nslookup imap.provider.com
dig imap.provider.com A +short
```

**Solutions:**
1. Verify server settings against provider documentation
2. Try alternative ports (587 for SMTP, 143+STARTTLS for IMAP)
3. Check corporate firewall/proxy settings
4. Test from different network (mobile hotspot)
5. Contact provider support if widespread issue

### "SSL/TLS Handshake Failed"

**Likely Causes:**
- Certificate issues
- Outdated client
- Wrong encryption settings

**Diagnostic Steps:**
```bash
# Check certificate details
openssl s_client -connect imap.provider.com:993 -servername imap.provider.com

# Check supported ciphers
nmap --script ssl-enum-ciphers -p 993 imap.provider.com
```

**Solutions:**
1. Update email client to latest version
2. Try different SSL/TLS settings (SSL vs STARTTLS)
3. Disable certificate validation temporarily for testing
4. Check system date/time (affects certificate validation)
5. Clear SSL certificate cache in client

## Authentication Failures

### "Invalid Credentials" or "Authentication Failed"

**Common Causes by Provider:**

**Gmail:**
- Not using app password with 2FA enabled
- "Less secure app access" disabled (deprecated)
- Wrong Google Account selected (multiple accounts)

**Yahoo:**
- Account key/app password required
- Using wrong domain (@yahoo.com vs @yahoo.co.uk)
- 2FA blocking regular password

**iCloud:**
- App-specific password not generated
- Using @me.com instead of @icloud.com
- Case sensitivity in username

**Outlook.com:**
- Two-factor authentication enabled but using regular password
- Modern authentication required
- Wrong server for personal vs business account

**Diagnostic Steps:**
1. Test credentials on provider's webmail interface
2. Check if 2FA is enabled on account
3. Verify exact username format required
4. Try authentication in incognito/private browser

**Solutions by Provider:**

**Gmail Fix:**
```
1. Google Account → Security → 2-Step Verification → On
2. App passwords → Generate
3. Use 16-character generated password in client
4. Username: full email address
```

**Yahoo Fix:**
```
1. Account Security → Generate app password
2. Name it descriptively ("Migration Tool")
3. Use generated password immediately
4. Username: full email address including domain
```

**iCloud Fix:**
```
1. appleid.apple.com → Sign-In and Security
2. App-Specific Passwords → Generate
3. Use immediately (shown only once)
4. Username: must be @icloud.com format
```

### "Account Locked" or "Too Many Login Attempts"

**Immediate Actions:**
1. Stop migration tool immediately
2. Wait 15-30 minutes before retry
3. Check provider's account security page
4. Look for security alerts in email

**Prevention:**
- Reduce concurrent connections to 1-2
- Add delays between operations
- Use provider-recommended rate limits
- Implement exponential backoff

## Data Transfer Issues

### "Missing Emails" or "Incomplete Migration"

**Check These First:**
1. **Date range filters** — Migration tool may have date limits
2. **Folder selection** — Some folders might be excluded
3. **Size limits** — Large messages might be skipped
4. **Spam/Junk folders** — Often excluded by default

**Diagnostic Steps:**
```bash
# Check total message count via IMAP
# Use provided mailbox-size.py script
python3 scripts/mailbox-size.py [REDACTED_SECRET] password
```

**Solutions:**
1. Run migration in smaller date ranges
2. Migrate large folders separately
3. Check provider's trash/spam folders
4. Verify folder permissions (shared mailboxes)
5. Re-run migration for delta sync

### "Emails Corrupted" or "Encoding Issues"

**Symptoms:**
- Foreign characters displayed as "???" or boxes
- HTML emails show as plain text
- Attachments won't open

**Common Causes:**
- Character encoding mismatch (UTF-8 vs. Latin-1)
- MIME type conversion issues
- Client-side display problems

**Solutions:**
1. Set client to UTF-8 encoding
2. Use MBOX format for better compatibility
3. Test with different email client
4. Check source encoding in original provider
5. Consider format conversion tools

### "Slow Migration Speed"

**Typical Speeds by Provider:**
- Gmail: 500-1000 messages/hour
- Yahoo: 200-500 messages/hour  
- iCloud: 100-300 messages/hour
- Zoho: 300-800 messages/hour

**Optimization Steps:**
1. **Reduce concurrent connections** to 1
2. **Use off-peak hours** (night/weekend)
3. **Filter by date** — migrate recent first
4. **Exclude large attachments** initially
5. **Use dedicated network** (avoid shared Wi-Fi)

**Provider-Specific Tweaks:**

**Gmail:**
- Use Google Takeout for initial bulk export
- IMAP has daily bandwidth limits
- Multiple app passwords don't increase speed

**Yahoo:**
- Free accounts have lower limits
- Business accounts perform better
- Avoid Friday evenings (maintenance window)

**iCloud:**
- Inherently slow IMAP implementation  
- Break into very small batches
- Consider overnight migration runs

## Folder and Structure Issues

### "Folders Missing" or "Wrong Hierarchy"

**Gmail Specific:**
- Labels become folders in IMAP clients
- Nested labels create folder hierarchy
- "All Mail" contains everything (may cause duplicates)

**Exchange/Outlook Specific:**
- Some system folders have fixed names
- Public folders require special permissions
- Archive folders may be separate

**Solutions:**
1. **Map folder names** before migration
2. **Create target folders** manually if needed
3. **Check IMAP folder subscriptions** in client
4. **Use folder mapping tools** in migration software
5. **Document special folder behaviors**

### "Duplicate Messages"

**Common Causes:**
- Message exists in multiple labels/folders
- Migration tool ran multiple times
- IMAP "All Mail" folder included

**Prevention:**
1. Exclude "All Mail" folder in Gmail migrations
2. Use message-ID based deduplication
3. Run test migration on small subset first
4. Check migration tool's duplicate handling

**Cleanup:**
- Use client's built-in duplicate removal
- PowerShell scripts for Exchange
- Third-party deduplication tools

## Provider-Specific Error Codes

### Gmail Error Codes

| Error | Code | Meaning | Solution |
|-------|------|---------|----------|
| IMAP_LOGIN_FAILED | - | Wrong credentials | Use app password |
| QUOTA_EXCEEDED | - | Daily limit reached | Wait 24 hours |
| CONNECTION_FAILED | - | Too many connections | Reduce concurrency |

### Yahoo Error Codes

| Error | Meaning | Solution |
|-------|---------|----------|
| LOGIN invalid credentials | Wrong password | Generate app password |
| IMAP disabled | IMAP not enabled | Enable in account settings |
| Rate limited | Too many requests | Wait and retry |

### Microsoft Error Codes

| Error | Code | Meaning | Solution |
|-------|------|---------|----------|
| AUTHENTICATE failed | - | Modern auth required | Use OAuth2 or app password |
| CONNECTION_LOST | - | Network timeout | Increase timeout settings |
| QUOTA_EXCEEDED | - | Mailbox full | Clean up or upgrade storage |

## Migration Tool Specific Issues

### GWMMO (Google Workspace Migration for Microsoft Outlook)

**Common Issues:**
- Hangs at "Preparing migration"
- "Unable to connect to Google"
- Outlook profile corruption

**Solutions:**
1. Run as administrator
2. Create new Outlook profile
3. Disable antivirus temporarily
4. Check Windows user permissions

### Microsoft Migration Service

**Common Issues:**
- Service account permissions
- API rate limiting
- Delta sync failures

**Solutions:**
1. Re-authorize service account
2. Check Google API console quotas
3. Use smaller batch sizes
4. Monitor migration dashboard

### Third-Party Tools (ImapSync, etc.)

**Common Issues:**
- Perl dependencies missing
- SSL certificate problems
- Memory issues with large mailboxes

**Solutions:**
1. Install required dependencies
2. Use --nossl for testing
3. Process in smaller chunks
4. Monitor system resources

## Network and Infrastructure Issues

### Corporate Firewall Problems

**Required Outbound Ports:**
- 993 (IMAP SSL)
- 465 (SMTP SSL)  
- 587 (SMTP STARTTLS)
- 80/443 (authentication/OAuth)

**Proxy Configuration:**
- Many email clients don't support SOCKS proxies for IMAP
- HTTP proxies rarely work with IMAP
- Consider VPN instead of proxy

### DNS Issues

**Symptoms:**
- Intermittent connection failures
- Some domains work, others don't
- Works from one network but not another

**Diagnostic Steps:**
```bash
# Check DNS resolution
nslookup imap.gmail.com
dig @8.8.8.8 imap.gmail.com A

# Test different DNS servers
dig @1.1.1.1 imap.gmail.com A
dig @208.67.222.222 imap.gmail.com A
```

**Solutions:**
1. Use public DNS servers (8.8.8.8, 1.1.1.1)
2. Clear DNS cache
3. Check hosts file for overrides
4. Test with direct IP addresses

## Recovery Procedures

### When Migration Fails Completely

1. **Stop all migration processes**
2. **Document current state** — what was migrated, what failed
3. **Check source data integrity** — ensure nothing was lost
4. **Analyze logs** for patterns in failures
5. **Test with small subset** before full retry
6. **Consider alternative migration method**

### Partial Migration Recovery

1. **Identify successfully migrated data**
2. **Export list of processed items** from migration tool
3. **Create exclusion list** for retry
4. **Resume from last checkpoint** if tool supports it
5. **Validate data integrity** after completion

### Data Validation Checklist

After any migration issue resolution:

- [ ] **Email count matches** source vs. destination
- [ ] **Folder structure** preserved correctly  
- [ ] **Recent emails** (last 30 days) fully present
- [ ] **Sent items** migrated correctly
- [ ] **Attachments** open without errors
- [ ] **Search functionality** works in destination
- [ ] **Special characters** display correctly
- [ ] **User can login** and access all data

## Emergency Contacts

### When to Contact Provider Support

**Gmail/Google Workspace:**
- API quota issues
- Service account problems
- Unusual authentication errors

**Microsoft 365:**
- Tenant configuration issues
- Migration service failures
- Modern authentication problems

**Yahoo:**
- Account security lockouts
- Persistent authentication failures
- IMAP access problems

**Include in Support Request:**
1. Exact error messages
2. Migration tool and version
3. Timeline of when issue started
4. Steps already attempted
5. Affected user count/impact

path: scripts/imap-test.py
content: #!/usr/bin/env python3
"""
IMAP Connectivity Test Script
Tests IMAP connection to any email provider
Usage: python3 imap-test.py [--server SERVER] [--port PORT] [--username USER] [--password PASS] [--ssl]
"""

import imaplib
import argparse
import sys
import ssl
import socket
from getpass import getpass

def test_imap_connection(server, port, username, password, use_ssl=True, timeout=30):
    """Test IMAP connection with given parameters"""
    
    print(f"Testing IMAP connection to {server}:{port}")
    print(f"Username: {username}")
    print(f"SSL/TLS: {'Enabled' if use_ssl else 'Disabled'}")
    print(f"Timeout: {timeout} seconds")
    print("-" * 50)
    
    try:
        # Set socket timeout
        socket.setdefaulttimeout(timeout)
        
        # Create IMAP connection
        if use_ssl:
            print("Connecting with SSL/TLS...")
            if port == 993:
                imap = imaplib.IMAP4_SSL(server, port)
            else:
                # STARTTLS connection
                print("Using STARTTLS on non-standard port...")
                imap = imaplib.IMAP4(server, port)
                imap.starttls()
        else:
            print("Connecting without encryption (not recommended)...")
            imap = imaplib.IMAP4(server, port)
        
        print("✅ Connected successfully")
        
        # Test authentication
        print(f"Authenticating as {username}...")
        result = imap.login(username, password)
        print(f"✅ Authentication successful: {result[0]}")
        
        # List mailboxes
        print("Listing mailboxes...")
        result, mailboxes = imap.list()
        if result == 'OK':
            print(f"✅ Found {len(mailboxes)} mailboxes")
            
            # Show first few mailboxes
            print("Sample mailboxes:")
            for i, mailbox in enumerate(mailboxes[:5]):
                decoded_mailbox = mailbox.decode('utf-8')
                print(f"  {i+1}. {decoded_mailbox}")
            
            if len(mailboxes) > 5:
                print(f"  ... and {len(mailboxes) - 5} more")
        
        # Test selecting INBOX
        print("Selecting INBOX...")
        result, data = imap.select('INBOX')
        if result == 'OK':
            message_count = int(data[0])
            print(f"✅ INBOX selected successfully - {message_count} messages")
        else:
            print(f"❌ Failed to select INBOX: {result}")
        
        # Test search functionality
        print("Testing search functionality...")
        result, data = imap.search(None, 'ALL')
        if result == 'OK':
            message_ids = data[0].split() if data[0] else []
            print(f"✅ Search successful - found {len(message_ids)} message IDs")
        else:
            print(f"❌ Search failed: {result}")
        
        # Logout
        imap.logout()
        print("✅ Logged out successfully")
        print("\n🎉 All tests passed! IMAP connection is working correctly.")
        return True
        
    except imaplib.IMAP4.error as e:
        print(f"❌ IMAP Error: {e}")
        return False
    except ssl.SSLError as e:
        print(f"❌ SSL Error: {e}")
        print("💡 Try with --no-ssl flag or check certificate settings")
        return False
    except socket.timeout:
        print(f"❌ Connection timeout after {timeout} seconds")
        print("💡 Try increasing timeout or check firewall settings")
        return False
    except socket.gaierror as e:
        print(f"❌ DNS Error: {e}")
        print("💡 Check server address and DNS settings")
        return False
    except Exception as e:
        print(f"❌ Unexpected error: {e}")
        return False

def get_provider_presets():
    """Return common provider presets"""
    return {
        'gmail': {
            'server': 'imap.gmail.com',
            'port': 993,
            'ssl': True,
            'note': 'Requires app password if 2FA is enabled'
        },
        'yahoo': {
            'server': 'imap.mail.yahoo.com', 
            'port': 993,
            'ssl': True,
            'note': 'Requires app password'
        },
        'outlook': {
            'server': 'outlook.office365.com',
            'port': 993, 
            'ssl': True,
            'note': 'Works for both personal and business accounts'
        },
        'icloud': {
            'server': 'imap.mail.me.com',
            'port': 993,
            'ssl': True,
            'note': 'Requires app-specific password'
        },
        'zoho': {
            'server': 'imap.zoho.com',
            'port': 993,
            'ssl': True,
            'note': 'Regular password usually works'
        }
    }

def main():
    parser = argparse.ArgumentParser(
        description='Test IMAP connectivity to email providers',
        epilog='Examples:\n'
               '  python3 imap-test.py gmail\n'
               '  python3 imap-test.py --server imap.gmail.com --username [REDACTED_SECRET]\n'
               '  python3 imap-test.py custom --server mail.company.com --port 143 --no-ssl',
        formatter_class=argparse.RawDescriptionHelpFormatter
    )
    
    parser.add_argument('preset', nargs='?', help='Provider preset (gmail, yahoo, outlook, icloud, zoho, custom)')
    parser.add_argument('--server', help='IMAP server address')
    parser.add_argument('--port', type=int, help='IMAP port (default: 993 for SSL, 143 for plain)')
    parser.add_argument('--username', help='Email username/address')
    parser.add_argument('--password', help='Password (will prompt if not provided)')
    parser.add_argument('--no-ssl', action='store_true', help='Disable SSL/TLS encryption')
    parser.add_argument('--timeout', type=int, default=30, help='Connection timeout in seconds')
    parser.add_argument('--list-presets', action='store_true', help='List available provider presets')
    
    args = parser.parse_args()
    
    # List presets and exit
    if args.list_presets:
        presets = get_provider_presets()
        print("Available provider presets:")
        for name, config in presets.items():
            print(f"\n{name}:")
            print(f"  Server: {config['server']}:{config['port']}")
            print(f"  SSL: {config['ssl']}")
            print(f"  Note: {config['note']}")
        return
    
    # Get provider preset if specified
    presets = get_provider_presets()
    if args.preset and args.preset in presets:
        preset = presets[args.preset]
        server = args.server or preset['server']
        port = args.port or preset['port']
        use_ssl = not args.no_ssl and preset['ssl']
        print(f"Using {args.preset} preset")
        print(f"Note: {preset['note']}")
        print()
    else:
        # Use command line arguments or defaults
        server = args.server
        port = args.port or (993 if not args.no_ssl else 143)
        use_ssl = not args.no_ssl
        
        if not server:
            print("Error: Server address required")
            print("Use --server SERVER or choose a preset (gmail, yahoo, outlook, icloud, zoho)")
            print("Use --list-presets to see available presets")
            sys.exit(1)
    
    # Get username
    username = args.username
    if not username:
        username = input("Email address: ").strip()
    
    # Get password
    [REDACTED_SECRET]
    if not [REDACTED_SECRET] = getpass("Password (or app password): ")
    
    # Run the test
    success = test_imap_connection(server, port, username, password, use_ssl, args.timeout)
    sys.exit(0 if success else 1)

if __name__ == '__main__':
    main()

path: scripts/mailbox-size.py
content: #!/usr/bin/env python3
"""
Mailbox Size Estimation Script
Estimates mailbox size and message counts via IMAP
Usage: python3 mailbox-size.py [--server SERVER] [--username USER] [--password PASS]
"""

import imaplib
import argparse
import sys
import ssl
import socket
import re
from getpass import getpass
from datetime import datetime, timedelta

def format_bytes(bytes_count):
    """Format bytes in human readable format"""
    for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
        if bytes_count < 1024.0:
            return f"{bytes_count:.1f} {unit}"
        bytes_count /= 1024.0
    return f"{bytes_count:.1f} PB"

def estimate_mailbox_size(server, port, username, password, use_ssl=True, timeout=30):
    """Connect to mailbox and estimate size"""
    
    print(f"Connecting to {server}:{port} as {username}")
    print("-" * 60)
    
    try:
        # Set socket timeout
        socket.setdefaulttimeout(timeout)
        
        # Create IMAP connection
        if use_ssl:
            imap = imaplib.IMAP4_SSL(server, port)
        else:
            imap = imaplib.IMAP4(server, port)
        
        # Login
        imap.login(username, password)
        print("✅ Connected and authenticated successfully\n")
        
        # Get list of all mailboxes
        result, mailboxes = imap.list()
        if result != 'OK':
            print("❌ Failed to list mailboxes")
            return False
        
        total_messages = 0
        total_size_estimate = 0
        folder_stats = []
        
        print(f"📁 Found {len(mailboxes)} folders:")
        print()
        
        for mailbox_line in mailboxes:
            try:
                # Parse mailbox line to extract folder name
                mailbox_decoded = mailbox_line.decode('utf-8')
                # Extract folder name (handle quoted folder names)
                match = re.search(r'"([^"]*)"$|([^\s]+)$', mailbox_decoded)
                if match:
                    folder_name = match.group(1) or match.group(2)
                else:
                    continue
                
                # Select the folder
                try:
                    result, data = imap.select(f'"{folder_name}"', readonly=True)
                    if result != 'OK':
                        print(f"⚠️  Skipped {folder_name} (access denied)")
                        continue
                    
                    # Get message count
                    message_count = int(data[0]) if data[0] else 0
                    
                    if message_count == 0:
                        print(f"📂 {folder_name:<30} {message_count:>6} messages")
                        folder_stats.append((folder_name, message_count, 0))
                        continue
                    
                    # Sample a few messages to estimate average size
                    sample_size = min(10, message_count)
                    sample_total_size = 0
                    
                    if sample_size > 0:
                        # Get recent message IDs for sampling
                        result, data = imap.search(None, 'ALL')
                        if result == 'OK' and data[0]:
                            message_ids = data[0].split()
                            
                            # Sample from different parts of the mailbox
                            sample_indices = []
                            if len(message_ids) > sample_size:
                                step = len(message_ids) // sample_size
                                sample_indices = [i * step for i in range(sample_size)]
                            else:
                                sample_indices = list(range(len(message_ids)))
                            
                            for idx in sample_indices[:sample_size]:
                                if idx < len(message_ids):
                                    msg_id = message_ids[idx]
                                    try:
                                        result, data = imap.fetch(msg_id, 'RFC822.SIZE')
                                        if result == 'OK' and data[0]:
                                            # Parse size from response
                                            size_match = re.search(r'RFC822\.SIZE (\d+)', data[0].decode('utf-8'))
                                            if size_match:
                                                sample_total_size += int(size_match.group(1))
                                    except:
                                        continue
                    
                    # Calculate average and estimate total
                    if sample_size > 0 and sample_total_size > 0:
                        avg_size = sample_total_size / sample_size
                        folder_size_estimate = int(avg_size * message_count)
                    else:
                        # Fallback estimate: 50KB average per message
                        avg_size = 50 * 1024
                        folder_size_estimate = int(avg_size * message_count)
                    
                    total_messages += message_count
                    total_size_estimate += folder_size_estimate
                    folder_stats.append((folder_name, message_count, folder_size_estimate))
                    
                    print(f"📂 {folder_name:<30} {message_count:>6} messages  {format_bytes(folder_size_estimate):>8}")
                    
                except Exception as e:
                    print(f"⚠️  Error processing {folder_name}: {str(e)[:50]}")
                    continue
                    
            except Exception as e:
                print(f"⚠️  Error parsing mailbox line: {str(e)[:50]}")
                continue
        
        print("\n" + "=" * 60)
        print("📊 MAILBOX SUMMARY")
        print("=" * 60)
        print(f"Total folders scanned: {len(folder_stats)}")
        print(f"Total messages: {total_messages:,}")
        print(f"Estimated total size: {format_bytes(total_size_estimate)}")
        
        if total_messages > 0:
            avg_msg_size = total_size_estimate / total_messages
            print(f"Average message size: {format_bytes(avg_msg_size)}")
        
        print("\n📈 LARGEST FOLDERS:")
        # Sort by size and show top 5
        folder_stats.sort(key=lambda x: x[2], reverse=True)
        for i, (folder, count, size) in enumerate(folder_stats[:5]):
            print(f"{i+1}. {folder:<25} {count:>6} msgs  {format_bytes(size):>8}")
        
        # Migration time estimates
        print("\n⏱️  MIGRATION TIME ESTIMATES:")
        print("(Based on typical IMAP transfer rates)")
        
        # Estimates based on common speeds
        speed_estimates = [
            ("Fast IMAP (1000 msg/hour)", 1000),
            ("Medium IMAP (500 msg/hour)", 500),
            ("Slow IMAP (200 msg/hour)", 200),
        ]
        
        for desc, msgs_per_hour in speed_estimates:
            if total_messages > 0:
                hours = total_messages / msgs_per_hour
                if hours < 1:
                    time_str = f"{hours * 60:.0f} minutes"
                elif hours < 24:
                    time_str = f"{hours:.1f} hours"
                else:
                    days = hours / 24
                    time_str = f"{days:.1f} days"
                print(f"  {desc:<25} {time_str}")
        
        # Storage requirements
        print("\n💾 STORAGE REQUIREMENTS:")
        print(f"Source mailbox: {format_bytes(total_size_estimate)}")
        print(f"Backup space needed: {format_bytes(total_size_estimate * 1.2)} (with 20% buffer)")
        print(f"Temporary space: {format_bytes(total_size_estimate * 0.5)} (for staging)")
        
        # Age analysis
        print("\n📅 ANALYZING MESSAGE DATES...")
        try:
            imap.select('INBOX', readonly=True)
            
            # Check for very old messages (5+ years)
            old_date = (datetime.now() - timedelta(days=5*365)).strftime("%d-%b-%Y")
            result, data = imap.search(None, f'BEFORE {old_date}')
            old_count = len(data[0].split()) if result == 'OK' and data[0] else 0
            
            # Check for recent messages (last 30 days)  
            recent_date = (datetime.now() - timedelta(days=30)).strftime("%d-%b-%Y")
            result, data = imap.search(None, f'SINCE {recent_date}')
            recent_count = len(data[0].split()) if result == 'OK' and data[0] else 0
            
            print(f"Messages older than 5 years: {old_count:,}")
            print(f"Messages from last 30 days: {recent_count:,}")
            
            if old_count > 0:
                print("\n💡 Consider archiving very old messages to speed up migration")
            
        except Exception as e:
            print(f"⚠️  Could not analyze message dates: {str(e)[:50]}")
        
        # Logout
        imap.logout()
        print("\n✅ Analysis complete!")
        return True
        
    except imaplib.IMAP4.error as e:
        print(f"❌ IMAP Error: {e}")
        return False
    except ssl.SSLError as e:
        print(f"❌ SSL Error: {e}")
        return False
    except socket.timeout:
        print(f"❌ Connection timeout after {timeout} seconds")
        return False
    except Exception as e:
        print(f"❌ Unexpected error: {e}")
        return False

def get_provider_presets():
    """Return common provider presets"""
    return {
        'gmail': {'server': 'imap.gmail.com', 'port': 993},
        'yahoo': {'server': 'imap.mail.yahoo.com', 'port': 993},
        'outlook': {'server': 'outlook.office365.com', 'port': 993},
        'icloud': {'server': 'imap.mail.me.com', 'port': 993},
        'zoho': {'server': 'imap.zoho.com', 'port': 993}
    }

def main():
    parser = argparse.ArgumentParser(
        description='Estimate mailbox size via IMAP',
        epilog='Examples:\n'
               '  python3 mailbox-size.py gmail\n'
               '  python3 mailbox-size.py --server imap.gmail.com --username [REDACTED_SECRET]',
        formatter_class=argparse.RawDescriptionHelpFormatter
    )
    
    parser.add_argument('preset', nargs='?', help='Provider preset (gmail, yahoo, outlook, icloud, zoho)')
    parser.add_argument('--server', help='IMAP server address')
    parser.add_argument('--port', type=int, default=993, help='IMAP port (default: 993)')
    parser.add_argument('--username', help='Email username/address')
    parser.add_argument('--password', help='Password (will prompt if not provided)')
    parser.add_argument('--no-ssl', action='store_true', help='Disable SSL/TLS encryption')
    parser.add_argument('--timeout', type=int, default=60, help='Connection timeout in seconds')
    
    args = parser.parse_args()
    
    # Get provider preset if specified
    presets = get_provider_presets()
    if args.preset and args.preset in presets:
        preset = presets[args.preset]
        server = args.server or preset['server']
        port = args.port if args.server else preset['port']
    else:
        server = args.server
        port = args.port
        
        if not server:
            print("Error: Server address required")
            print("Use --server SERVER or choose a preset (gmail, yahoo, outlook, icloud, zoho)")
            sys.exit(1)
    
    # Get username
    username = args.username
    if not username:
        username = input("Email address: ").strip()
    
    # Get password
    [REDACTED_SECRET]
    if not [REDACTED_SECRET] = getpass("Password (or app password): ")
    
    use_ssl = not args.no_ssl
    
    # Run the analysis
    success = estimate_mailbox_size(server, port, username, password, use_ssl, args.timeout)
    sys.exit(0 if success else 1)

if __name__ == '__main__':
    main()

Security scan verdicts — ClawScan: suspicious | static analysis:  | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)