Add flexible authentication: email or username can be optional
Key improvements: - Either email OR username can be empty (but not both) - Enhanced validation logic for authentication methods - Improved error messages showing available auth methods - More flexible IMAPConnection constructor with better defaults Authentication options: 1. Email-only: SOURCE_EMAIL=user@domain.de, SOURCE_USERNAME= 2. Username-only: SOURCE_EMAIL=, SOURCE_USERNAME=username123 3. Both (fallback): Provide both for automatic fallback 4. Dual method: Username tried first, email as fallback Configuration updates: - Update .env.template with all four authentication examples - Clarify requirements and optional nature of fields - Add comprehensive authentication scenarios Documentation updates: - Expand README with four authentication options - Add troubleshooting for different auth combinations - Clarify flexible requirements (either email OR username required) This makes the script compatible with even more email providers and hosting scenarios.
This commit is contained in:
parent
1d7fe31845
commit
c8ca753c04
3 changed files with 77 additions and 21 deletions
|
|
@ -17,12 +17,13 @@ SOURCE_IMAP_SERVER=wp123456.mail.server-he.de
|
||||||
SOURCE_IMAP_PORT=993
|
SOURCE_IMAP_PORT=993
|
||||||
|
|
||||||
# SOURCE_EMAIL: Your source email address
|
# SOURCE_EMAIL: Your source email address
|
||||||
|
# Required if SOURCE_USERNAME is empty, optional if username is provided
|
||||||
# Example: user@yourdomain.de
|
# Example: user@yourdomain.de
|
||||||
SOURCE_EMAIL=user@example-domain.de
|
SOURCE_EMAIL=user@example-domain.de
|
||||||
|
|
||||||
# SOURCE_USERNAME: Login username (if different from email)
|
# SOURCE_USERNAME: Login username (alternative to email)
|
||||||
|
# Required if SOURCE_EMAIL is empty, optional if email is provided
|
||||||
# Some providers use separate username for login (e.g. hosteurope123, mail_user)
|
# 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
|
# Host Europe: often uses email account name or specific username
|
||||||
SOURCE_USERNAME=
|
SOURCE_USERNAME=
|
||||||
|
|
||||||
|
|
@ -47,12 +48,13 @@ DEST_IMAP_SERVER=mail.securehost.de
|
||||||
DEST_IMAP_PORT=993
|
DEST_IMAP_PORT=993
|
||||||
|
|
||||||
# DEST_EMAIL: Your destination email address
|
# DEST_EMAIL: Your destination email address
|
||||||
|
# Required if DEST_USERNAME is empty, optional if username is provided
|
||||||
# Example: user@securehost.de
|
# Example: user@securehost.de
|
||||||
DEST_EMAIL=user@securehost.de
|
DEST_EMAIL=user@securehost.de
|
||||||
|
|
||||||
# DEST_USERNAME: Login username for destination (if different from email)
|
# DEST_USERNAME: Login username for destination (alternative to email)
|
||||||
|
# Required if DEST_EMAIL is empty, optional if email is provided
|
||||||
# Some hosting providers use separate username (e.g. user123, cpanel_user)
|
# 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
|
# Securehost.de: typically uses email or specific username
|
||||||
DEST_USERNAME=
|
DEST_USERNAME=
|
||||||
|
|
||||||
|
|
@ -129,16 +131,26 @@ TEMP_DOWNLOAD_DIR=./temp_emails
|
||||||
# AUTHENTICATION EXAMPLES
|
# AUTHENTICATION EXAMPLES
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
# Email-based login (most common):
|
# Option 1: Email-based login (most common):
|
||||||
# SOURCE_EMAIL=user@domain.de
|
# SOURCE_EMAIL=user@domain.de
|
||||||
# SOURCE_USERNAME=
|
# SOURCE_USERNAME=
|
||||||
# → Script tries: user@domain.de
|
# → Script tries: user@domain.de
|
||||||
|
|
||||||
# Username-based login:
|
# Option 2: Username-based login:
|
||||||
# SOURCE_EMAIL=user@domain.de
|
# SOURCE_EMAIL=user@domain.de
|
||||||
# SOURCE_USERNAME=mail_user123
|
# SOURCE_USERNAME=mail_user123
|
||||||
# → Script tries: mail_user123, fallback to user@domain.de
|
# → Script tries: mail_user123, fallback to user@domain.de
|
||||||
|
|
||||||
|
# Option 3: Username-only (email optional):
|
||||||
|
# SOURCE_EMAIL=
|
||||||
|
# SOURCE_USERNAME=mail_user123
|
||||||
|
# → Script tries: mail_user123 only
|
||||||
|
|
||||||
|
# Option 4: Email-only (username optional):
|
||||||
|
# SOURCE_EMAIL=user@domain.de
|
||||||
|
# SOURCE_USERNAME=
|
||||||
|
# → Script tries: user@domain.de only
|
||||||
|
|
||||||
# Host Europe specific:
|
# Host Europe specific:
|
||||||
# SOURCE_USERNAME=email_account_name (from Host Europe KIS)
|
# SOURCE_USERNAME=email_account_name (from Host Europe KIS)
|
||||||
# SOURCE_USERNAME= (if using Easy-Mail-Login)
|
# SOURCE_USERNAME= (if using Easy-Mail-Login)
|
||||||
|
|
|
||||||
34
README.md
34
README.md
|
|
@ -27,23 +27,37 @@ A Python script to migrate emails from one IMAP account to another with flexible
|
||||||
|
|
||||||
## Authentication Methods
|
## Authentication Methods
|
||||||
|
|
||||||
The script supports two authentication methods and automatically tries both:
|
The script supports flexible authentication with four possible configurations:
|
||||||
|
|
||||||
### Method 1: Email-based Login (Most Common)
|
### Option 1: Email-based Login (Most Common)
|
||||||
```env
|
```env
|
||||||
SOURCE_EMAIL=user@domain.de
|
SOURCE_EMAIL=user@domain.de
|
||||||
SOURCE_USERNAME=
|
SOURCE_USERNAME=
|
||||||
```
|
```
|
||||||
**Used by**: Gmail, Yahoo, Outlook, most modern providers
|
**Used by**: Gmail, Yahoo, Outlook, most modern providers
|
||||||
|
|
||||||
### Method 2: Username-based Login
|
### Option 2: Username + Email (Dual Method)
|
||||||
```env
|
```env
|
||||||
SOURCE_EMAIL=user@domain.de
|
SOURCE_EMAIL=user@domain.de
|
||||||
SOURCE_USERNAME=mail_user123
|
SOURCE_USERNAME=mail_user123
|
||||||
```
|
```
|
||||||
**Used by**: Some hosting providers, older email systems, cPanel hosting
|
**Used by**: Some hosting providers - tries username first, falls back to email
|
||||||
|
|
||||||
The script automatically tries username first (if provided), then falls back to email authentication.
|
### Option 3: Username-only Login
|
||||||
|
```env
|
||||||
|
SOURCE_EMAIL=
|
||||||
|
SOURCE_USERNAME=mail_user123
|
||||||
|
```
|
||||||
|
**Used by**: Legacy systems, some cPanel hosting where email is unknown
|
||||||
|
|
||||||
|
### Option 4: Email-only Login
|
||||||
|
```env
|
||||||
|
SOURCE_EMAIL=user@domain.de
|
||||||
|
SOURCE_USERNAME=
|
||||||
|
```
|
||||||
|
**Used by**: When you're certain email authentication is the only method
|
||||||
|
|
||||||
|
**Requirements**: You must provide either SOURCE_EMAIL or SOURCE_USERNAME (or both). Same applies to destination settings.
|
||||||
|
|
||||||
## Import Folder Options
|
## Import Folder Options
|
||||||
|
|
||||||
|
|
@ -235,7 +249,10 @@ Errors encountered: 0
|
||||||
### Common Issues
|
### Common Issues
|
||||||
|
|
||||||
**Authentication Failed**
|
**Authentication Failed**
|
||||||
- Check if username is required (try both with and without `SOURCE_USERNAME`)
|
- Try different authentication combinations:
|
||||||
|
- Email only: Set `SOURCE_USERNAME=` (empty)
|
||||||
|
- Username only: Set `SOURCE_EMAIL=` (empty)
|
||||||
|
- Both: Provide both values for fallback
|
||||||
- Verify server address from your hosting provider
|
- Verify server address from your hosting provider
|
||||||
- For Host Europe: Get exact server name from KIS panel
|
- For Host Europe: Get exact server name from KIS panel
|
||||||
- For Gmail/Yahoo: Use app passwords, not regular passwords
|
- For Gmail/Yahoo: Use app passwords, not regular passwords
|
||||||
|
|
@ -248,7 +265,10 @@ Errors encountered: 0
|
||||||
- Verify server address and port
|
- Verify server address and port
|
||||||
|
|
||||||
**Username vs Email Login Issues**
|
**Username vs Email Login Issues**
|
||||||
- Try leaving `SOURCE_USERNAME` empty to use email login
|
- Try all combinations:
|
||||||
|
1. Email only: `SOURCE_EMAIL=user@domain.de`, `SOURCE_USERNAME=`
|
||||||
|
2. Username only: `SOURCE_EMAIL=`, `SOURCE_USERNAME=username123`
|
||||||
|
3. Both (fallback): Provide both values
|
||||||
- For Host Europe: Check if Easy-Mail-Login is enabled
|
- For Host Europe: Check if Easy-Mail-Login is enabled
|
||||||
- Contact your hosting provider for authentication method
|
- Contact your hosting provider for authentication method
|
||||||
- Check provider documentation for login format
|
- Check provider documentation for login format
|
||||||
|
|
|
||||||
|
|
@ -33,14 +33,18 @@ class IMAPConnection:
|
||||||
def __init__(self, server, port, email_addr, username, password, use_ssl=True, timeout=60):
|
def __init__(self, server, port, email_addr, username, password, use_ssl=True, timeout=60):
|
||||||
self.server = server
|
self.server = server
|
||||||
self.port = port
|
self.port = port
|
||||||
self.email = email_addr
|
self.email = email_addr or ""
|
||||||
self.username = username
|
self.username = username or ""
|
||||||
self.password = password
|
self.password = password
|
||||||
self.use_ssl = use_ssl
|
self.use_ssl = use_ssl
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
self.connection = None
|
self.connection = None
|
||||||
self.logger = logging.getLogger(__name__)
|
self.logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# Validate that we have at least one authentication method
|
||||||
|
if not self.email.strip() and not self.username.strip():
|
||||||
|
raise ValueError("Either email or username must be provided for authentication")
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
try:
|
try:
|
||||||
if self.use_ssl:
|
if self.use_ssl:
|
||||||
|
|
@ -65,7 +69,7 @@ class IMAPConnection:
|
||||||
self.logger.debug(f"Username login failed for {self.username}: {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 username login failed or no username provided, try email
|
||||||
if not login_success:
|
if not login_success and self.email.strip():
|
||||||
try:
|
try:
|
||||||
self.connection.login(self.email, self.password)
|
self.connection.login(self.email, self.password)
|
||||||
login_user = self.email
|
login_user = self.email
|
||||||
|
|
@ -75,7 +79,12 @@ class IMAPConnection:
|
||||||
self.logger.error(f"Email login failed for {self.email}: {email_error}")
|
self.logger.error(f"Email login failed for {self.email}: {email_error}")
|
||||||
|
|
||||||
if not login_success:
|
if not login_success:
|
||||||
self.logger.error(f"Failed to authenticate with {self.server} using both username and email")
|
available_methods = []
|
||||||
|
if self.username.strip():
|
||||||
|
available_methods.append("username")
|
||||||
|
if self.email.strip():
|
||||||
|
available_methods.append("email")
|
||||||
|
self.logger.error(f"Failed to authenticate with {self.server} using {' and '.join(available_methods)}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
@ -187,7 +196,7 @@ class EmailMigrator:
|
||||||
self.source = IMAPConnection(
|
self.source = IMAPConnection(
|
||||||
config['SOURCE_IMAP_SERVER'],
|
config['SOURCE_IMAP_SERVER'],
|
||||||
int(config['SOURCE_IMAP_PORT']),
|
int(config['SOURCE_IMAP_PORT']),
|
||||||
config['SOURCE_EMAIL'],
|
config.get('SOURCE_EMAIL', ''),
|
||||||
config.get('SOURCE_USERNAME', ''),
|
config.get('SOURCE_USERNAME', ''),
|
||||||
config['SOURCE_PASSWORD'],
|
config['SOURCE_PASSWORD'],
|
||||||
config.get('SOURCE_IMAP_USE_SSL', 'True').lower() == 'true',
|
config.get('SOURCE_IMAP_USE_SSL', 'True').lower() == 'true',
|
||||||
|
|
@ -197,7 +206,7 @@ class EmailMigrator:
|
||||||
self.destination = IMAPConnection(
|
self.destination = IMAPConnection(
|
||||||
config['DEST_IMAP_SERVER'],
|
config['DEST_IMAP_SERVER'],
|
||||||
int(config['DEST_IMAP_PORT']),
|
int(config['DEST_IMAP_PORT']),
|
||||||
config['DEST_EMAIL'],
|
config.get('DEST_EMAIL', ''),
|
||||||
config.get('DEST_USERNAME', ''),
|
config.get('DEST_USERNAME', ''),
|
||||||
config['DEST_PASSWORD'],
|
config['DEST_PASSWORD'],
|
||||||
config.get('DEST_IMAP_USE_SSL', 'True').lower() == 'true',
|
config.get('DEST_IMAP_USE_SSL', 'True').lower() == 'true',
|
||||||
|
|
@ -358,8 +367,9 @@ def main():
|
||||||
print(f"Error loading .env file: {e}")
|
print(f"Error loading .env file: {e}")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
required_vars = ['SOURCE_IMAP_SERVER', 'SOURCE_EMAIL', 'SOURCE_PASSWORD',
|
# Basic required variables
|
||||||
'DEST_IMAP_SERVER', 'DEST_EMAIL', 'DEST_PASSWORD']
|
required_vars = ['SOURCE_IMAP_SERVER', 'SOURCE_PASSWORD',
|
||||||
|
'DEST_IMAP_SERVER', 'DEST_PASSWORD']
|
||||||
|
|
||||||
missing_vars = [var for var in required_vars if not config.get(var)]
|
missing_vars = [var for var in required_vars if not config.get(var)]
|
||||||
if missing_vars:
|
if missing_vars:
|
||||||
|
|
@ -367,6 +377,20 @@ def main():
|
||||||
print("Please check your .env file.")
|
print("Please check your .env file.")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
# Validate authentication methods
|
||||||
|
source_email = config.get('SOURCE_EMAIL', '').strip()
|
||||||
|
source_username = config.get('SOURCE_USERNAME', '').strip()
|
||||||
|
dest_email = config.get('DEST_EMAIL', '').strip()
|
||||||
|
dest_username = config.get('DEST_USERNAME', '').strip()
|
||||||
|
|
||||||
|
if not source_email and not source_username:
|
||||||
|
print("Error: Either SOURCE_EMAIL or SOURCE_USERNAME must be provided for source account")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
if not dest_email and not dest_username:
|
||||||
|
print("Error: Either DEST_EMAIL or DEST_USERNAME must be provided for destination account")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
migrator = EmailMigrator(config)
|
migrator = EmailMigrator(config)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue