diff --git a/.env.template b/.env.template index 4f504b4..f0a1595 100644 --- a/.env.template +++ b/.env.template @@ -20,6 +20,12 @@ SOURCE_IMAP_PORT=993 # Example: user@yourdomain.de SOURCE_EMAIL=user@example-domain.de +# SOURCE_USERNAME: Login username (if different from email) +# Some providers use separate username for login (e.g. hosteurope123, mail_user) +# Leave empty if login uses email address +# Host Europe: often uses email account name or specific username +SOURCE_USERNAME= + # SOURCE_PASSWORD: Email account password # Use your Host Europe email password (NOT app password needed here) SOURCE_PASSWORD=your_hosteurope_password @@ -29,24 +35,30 @@ SOURCE_PASSWORD=your_hosteurope_password SOURCE_IMAP_USE_SSL=True # ============================================================================ -# DESTINATION EMAIL ACCOUNT (migrating TO) - German Hosting Example +# DESTINATION EMAIL ACCOUNT (migrating TO) - Securehost.de Example # ============================================================================ # DEST_IMAP_SERVER: Destination IMAP server -# Common formats: mail.yourdomain.de | imap.provider.de -DEST_IMAP_SERVER=mail.yourdomain.de +# Securehost.de: mail.securehost.de | Common: mail.yourdomain.de | imap.provider.de +DEST_IMAP_SERVER=mail.securehost.de # DEST_IMAP_PORT: Destination IMAP port # 993 (SSL) | 143 (TLS/STARTTLS) DEST_IMAP_PORT=993 # DEST_EMAIL: Your destination email address -# Example: user@newdomain.de -DEST_EMAIL=user@newdomain.de +# Example: user@securehost.de +DEST_EMAIL=user@securehost.de + +# DEST_USERNAME: Login username for destination (if different from email) +# Some hosting providers use separate username (e.g. user123, cpanel_user) +# Leave empty if login uses email address +# Securehost.de: typically uses email or specific username +DEST_USERNAME= # DEST_PASSWORD: Destination email password -# Your hosting provider email password -DEST_PASSWORD=your_destination_password +# Your securehost.de email password +DEST_PASSWORD=your_securehost_password # DEST_IMAP_USE_SSL: Use SSL for destination # True (recommended) | False @@ -113,30 +125,60 @@ LOG_LEVEL=INFO # ./temp_emails (default) | /tmp/emails | C:\Temp\emails TEMP_DOWNLOAD_DIR=./temp_emails +# ============================================================================ +# AUTHENTICATION EXAMPLES +# ============================================================================ + +# Email-based login (most common): +# SOURCE_EMAIL=user@domain.de +# SOURCE_USERNAME= +# → Script tries: user@domain.de + +# Username-based login: +# SOURCE_EMAIL=user@domain.de +# SOURCE_USERNAME=mail_user123 +# → Script tries: mail_user123, fallback to user@domain.de + +# Host Europe specific: +# SOURCE_USERNAME=email_account_name (from Host Europe KIS) +# SOURCE_USERNAME= (if using Easy-Mail-Login) + # ============================================================================ # PROVIDER-SPECIFIC EXAMPLES # ============================================================================ -# Host Europe Settings: -# SOURCE_IMAP_SERVER=wpxxxxxxxx.mail.server-he.de -# SOURCE_IMAP_PORT=993 -# SOURCE_IMAP_USE_SSL=True -# Note: Replace 'wpxxxxxxxx' with your actual server name from Host Europe KIS +# Host Europe to Securehost.de Migration: +# SOURCE_IMAP_SERVER=wp123456.mail.server-he.de +# SOURCE_EMAIL=user@olddomain.de +# SOURCE_USERNAME=mail_account_he +# DEST_IMAP_SERVER=mail.securehost.de +# DEST_EMAIL=user@securehost.de +# DEST_USERNAME= -# Common German Hosting Providers: -# Strato: imap.strato.de:993 -# 1und1/IONOS: imap.1und1.de:993 -# All-Inkl: mail.all-inkl.com:993 -# Hetzner: mail.your-server.de:993 +# Host Europe Settings: +# Server format: wpxxxxxxxx.mail.server-he.de (get from KIS) +# Port: 993 (SSL) or 143 (TLS) +# Username: Check KIS for account name or use email if Easy-Mail-Login enabled + +# Securehost.de Settings: +# Server: mail.securehost.de (typical format) +# Port: 993 (SSL recommended) +# Authentication: Usually email-based, check with provider + +# Other German Providers: +# Strato: imap.strato.de:993 (email login) +# 1und1/IONOS: imap.1und1.de:993 (username: username@domain) +# All-Inkl: mail.all-inkl.com:993 (username varies) +# Hetzner: mail.your-server.de:993 (email login) # Gmail (if needed): -# Gmail: imap.gmail.com:993 (requires app password) +# imap.gmail.com:993 (requires app password, email login) # ============================================================================ # MIGRATION EXAMPLES # ============================================================================ -# Example 1: Host Europe to new hosting with organization +# Example 1: Host Europe to Securehost.de with organization # IMPORT_FOLDER_NAME=HostEurope_Migration # Result: Clean separation in destination diff --git a/README.md b/README.md index 516a80e..a7bdab1 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,17 @@ # Email Migration Script -A Python script to migrate emails from one IMAP account to another with flexible folder organization options. +A Python script to migrate emails from one IMAP account to another with flexible folder organization and dual authentication support. ## Features - **Flexible Import Options**: Choose between organized folder structure or consolidated inbox +- **Dual Authentication**: Supports both username and email-based login methods - **Folder Filtering**: Include/exclude specific folders from migration - **Metadata Preservation**: Maintain email flags, dates, and other metadata - **Batch Processing**: Configurable batch sizes for optimal performance - **Comprehensive Logging**: Detailed logs for monitoring and troubleshooting - **SSL Security**: Secure connections with SSL/TLS support +- **Provider Compatibility**: Works with various email providers and hosting services ## Quick Start @@ -21,7 +23,27 @@ A Python script to migrate emails from one IMAP account to another with flexible - Python 3.6+ (pre-installed on Linux & macOS) - IMAP access enabled on both email accounts -- App passwords (recommended for Gmail, Yahoo, Outlook) +- Email account credentials (username/email and password) + +## Authentication Methods + +The script supports two authentication methods and automatically tries both: + +### Method 1: Email-based Login (Most Common) +```env +SOURCE_EMAIL=user@domain.de +SOURCE_USERNAME= +``` +**Used by**: Gmail, Yahoo, Outlook, most modern providers + +### Method 2: Username-based Login +```env +SOURCE_EMAIL=user@domain.de +SOURCE_USERNAME=mail_user123 +``` +**Used by**: Some hosting providers, older email systems, cPanel hosting + +The script automatically tries username first (if provided), then falls back to email authentication. ## Import Folder Options @@ -57,36 +79,57 @@ IMPORT_FOLDER_NAME= ## Configuration Guide -### Email Account Setup +### Host Europe to Securehost.de Migration Example ```env -# Source account (migrating FROM) -SOURCE_IMAP_SERVER=imap.gmail.com -SOURCE_EMAIL=old@gmail.com -SOURCE_PASSWORD=your_app_password +# Source: Host Europe +SOURCE_IMAP_SERVER=wp123456.mail.server-he.de +SOURCE_IMAP_PORT=993 +SOURCE_EMAIL=user@olddomain.de +SOURCE_USERNAME=mail_account_name +SOURCE_PASSWORD=your_hosteurope_password +SOURCE_IMAP_USE_SSL=True -# Destination account (migrating TO) -DEST_IMAP_SERVER=imap.gmail.com -DEST_EMAIL=new@gmail.com -DEST_PASSWORD=your_app_password +# Destination: Securehost.de +DEST_IMAP_SERVER=mail.securehost.de +DEST_IMAP_PORT=993 +DEST_EMAIL=user@securehost.de +DEST_USERNAME= +DEST_PASSWORD=your_securehost_password +DEST_IMAP_USE_SSL=True + +# Import with organization +IMPORT_FOLDER_NAME=HostEurope_Migration ``` ### Common IMAP Servers -| Provider | IMAP Server | Port | SSL | -|----------|-------------|------|-----| -| Gmail | `imap.gmail.com` | 993 | Yes | -| Outlook/Hotmail | `outlook.office365.com` | 993 | Yes | -| Yahoo | `imap.mail.yahoo.com` | 993 | Yes | -| Apple iCloud | `imap.mail.me.com` | 993 | Yes | +| Provider | IMAP Server | Port | SSL | Authentication | +|----------|-------------|------|-----|----------------| +| Host Europe | `wpXXXXXX.mail.server-he.de` | 993 | Yes | Username or Email | +| Securehost.de | `mail.securehost.de` | 993 | Yes | Email (typical) | +| Gmail | `imap.gmail.com` | 993 | Yes | Email + App Password | +| Outlook/Hotmail | `outlook.office365.com` | 993 | Yes | Email + App Password | +| Strato | `imap.strato.de` | 993 | Yes | Email | +| 1und1/IONOS | `imap.1und1.de` | 993 | Yes | Username@domain | +| All-Inkl | `mail.all-inkl.com` | 993 | Yes | Username (varies) | -### App Password Setup +### Authentication Setup -**Gmail**: Google Account → Security → App Passwords -**Yahoo**: Account Security → Generate app password -**Outlook**: Account Security → App passwords +**Host Europe**: +1. Get server name from Host Europe KIS: `wpXXXXXX.mail.server-he.de` +2. Use email account name as username OR enable Easy-Mail-Login to use email +3. Check KIS for exact authentication method -⚠️ **Important**: Use app passwords, not regular login passwords! +**Securehost.de**: +1. Server typically: `mail.securehost.de` or `mail.yourdomain.de` +2. Usually uses email-based authentication +3. Contact support if unsure about authentication method + +**Gmail/Yahoo/Outlook**: +1. Must use app passwords (not regular passwords) +2. Enable IMAP access in account settings +3. Use email address for authentication ## Advanced Configuration @@ -123,13 +166,15 @@ LOG_LEVEL=ERROR # Errors only ## Usage Examples -### Example 1: Full Gmail Migration with Organization +### Example 1: Host Europe to Securehost.de with Organization ```bash # .env configuration -SOURCE_EMAIL=old@gmail.com -DEST_EMAIL=new@gmail.com -IMPORT_FOLDER_NAME=OldAccount -EXCLUDE_FOLDERS=Trash,Spam +SOURCE_IMAP_SERVER=wp987654.mail.server-he.de +SOURCE_EMAIL=old@company.de +SOURCE_USERNAME=company_mail +DEST_IMAP_SERVER=mail.securehost.de +DEST_EMAIL=new@company.de +IMPORT_FOLDER_NAME=HostEurope_Backup # Run migration python3 email_migration.py @@ -169,6 +214,8 @@ Example output: Email Migration Script ================================================== [INFO] Import folder configuration: All emails will be imported to subfolders within "Imported" +[INFO] Connected to wp123456.mail.server-he.de using username: mail_account +[INFO] Connected to mail.securehost.de using email: user@securehost.de [INFO] Found 5 folders to process [INFO] Processing folder: INBOX [INFO] Migrating 'INBOX' -> 'Imported/INBOX' @@ -188,14 +235,23 @@ Errors encountered: 0 ### Common Issues **Authentication Failed** -- Use app passwords instead of regular passwords +- Check if username is required (try both with and without `SOURCE_USERNAME`) +- Verify server address from your hosting provider +- For Host Europe: Get exact server name from KIS panel +- For Gmail/Yahoo: Use app passwords, not regular passwords - Enable IMAP access in email account settings -- Check server settings and ports **Connection Timeout** - Increase `IMAP_TIMEOUT` value - Reduce `BATCH_SIZE` for stability - Check network connection +- Verify server address and port + +**Username vs Email Login Issues** +- Try leaving `SOURCE_USERNAME` empty to use email login +- For Host Europe: Check if Easy-Mail-Login is enabled +- Contact your hosting provider for authentication method +- Check provider documentation for login format **Folder Creation Failed** - Verify destination account has folder creation permissions @@ -207,20 +263,39 @@ Errors encountered: 0 - Re-run script - it will skip already migrated emails - Use `INCLUDE_FOLDERS` to retry specific folders +### Provider-Specific Troubleshooting + +**Host Europe**: +- Server format: `wpXXXXXX.mail.server-he.de` (get exact name from KIS) +- Username: Use email account name from KIS or enable Easy-Mail-Login +- SSL: Port 993 recommended, port 143 with TLS also supported + +**Securehost.de**: +- Server typically: `mail.securehost.de` or `mail.yourdomain.de` +- Authentication: Usually email-based, contact support if unsure +- SSL: Port 993 standard + +**Gmail/Outlook**: +- Must generate app passwords from account security settings +- Regular passwords won't work due to security restrictions +- Enable IMAP in account settings first + ### Getting Help 1. **Enable Debug Logging**: Set `LOG_LEVEL=DEBUG` 2. **Check Log File**: Review `email_migration.log` 3. **Test Small First**: Use `INCLUDE_FOLDERS=INBOX` and `BATCH_SIZE=10` 4. **Verify Credentials**: Test account access with email client first +5. **Try Both Auth Methods**: Test with and without username ## Security Notes - Never commit `.env` file to version control -- Use app passwords instead of account passwords +- Use app passwords for Gmail, Yahoo, Outlook instead of account passwords - Ensure SSL is enabled (`*_IMAP_USE_SSL=True`) - Store credentials securely - Test with non-critical accounts first +- Enable two-factor authentication where supported ## File Structure @@ -234,6 +309,15 @@ email_migration/ └── README.md # This file ``` +## Migration Best Practices + +1. **Test First**: Always test with a small subset of emails first +2. **Backup**: Ensure you have backups of important emails +3. **Network**: Use stable internet connection for large migrations +4. **Authentication**: Verify login credentials work before starting +5. **Monitoring**: Watch logs during migration for any issues +6. **Cleanup**: Clean up temporary files after successful migration + ## License This script is provided as-is for educational and personal use. Test thoroughly before production use. \ No newline at end of file diff --git a/email_migration.py b/email_migration.py index 6812612..d9621f5 100755 --- a/email_migration.py +++ b/email_migration.py @@ -30,10 +30,11 @@ def setup_logging(log_level): return logging.getLogger(__name__) class IMAPConnection: - def __init__(self, server, port, email_addr, password, use_ssl=True, timeout=60): + def __init__(self, server, port, email_addr, username, password, use_ssl=True, timeout=60): self.server = server self.port = port self.email = email_addr + self.username = username self.password = password self.use_ssl = use_ssl self.timeout = timeout @@ -49,8 +50,34 @@ class IMAPConnection: self.connection = imaplib.IMAP4(self.server, self.port) self.connection.sock.settimeout(self.timeout) - self.connection.login(self.email, self.password) - self.logger.info(f"Connected to {self.server} as {self.email}") + + # Try authentication with username first (if provided), then fall back to email + login_success = False + login_user = None + + if self.username and self.username.strip(): + try: + self.connection.login(self.username, self.password) + login_user = self.username + login_success = True + self.logger.info(f"Connected to {self.server} using username: {self.username}") + except Exception as username_error: + self.logger.debug(f"Username login failed for {self.username}: {username_error}") + + # If username login failed or no username provided, try email + if not login_success: + try: + self.connection.login(self.email, self.password) + login_user = self.email + login_success = True + self.logger.info(f"Connected to {self.server} using email: {self.email}") + except Exception as email_error: + self.logger.error(f"Email login failed for {self.email}: {email_error}") + + if not login_success: + self.logger.error(f"Failed to authenticate with {self.server} using both username and email") + return False + return True except Exception as e: self.logger.error(f"Failed to connect to {self.server}: {e}") @@ -144,7 +171,10 @@ class EmailMigrator: if not self.import_folder_name: self.import_folder_name = None - self.logger.info(f"Import folder configuration: {'All emails will be imported to subfolders within \"' + self.import_folder_name + '\"' if self.import_folder_name else 'All emails will be imported directly to INBOX'}") + if self.import_folder_name: + self.logger.info(f"Import folder configuration: All emails will be imported to subfolders within \"{self.import_folder_name}\"") + else: + self.logger.info("Import folder configuration: All emails will be imported directly to INBOX") include_str = config.get('INCLUDE_FOLDERS', '') exclude_str = config.get('EXCLUDE_FOLDERS', '') @@ -158,6 +188,7 @@ class EmailMigrator: config['SOURCE_IMAP_SERVER'], int(config['SOURCE_IMAP_PORT']), config['SOURCE_EMAIL'], + config.get('SOURCE_USERNAME', ''), config['SOURCE_PASSWORD'], config.get('SOURCE_IMAP_USE_SSL', 'True').lower() == 'true', timeout @@ -167,6 +198,7 @@ class EmailMigrator: config['DEST_IMAP_SERVER'], int(config['DEST_IMAP_PORT']), config['DEST_EMAIL'], + config.get('DEST_USERNAME', ''), config['DEST_PASSWORD'], config.get('DEST_IMAP_USE_SSL', 'True').lower() == 'true', timeout