import imaplib
import re
import time
import ssl

# =====================================================================
# SERVER CONFIGURATION
# =====================================================================
YAHOO_SERVER = "imap.mail.yahoo.com"
YAHOO_USER = "delvecchiosergio@yahoo.com.au"
YAHOO_PASS = "sgpmfuujscflnmxs"  # Your secure App Password

NEW_SERVER = "mail.raditel.net"
NEW_USER = "sergioyahoobackup@raditel.net"
NEW_PASS = "$@23Rg10B@ckup?!"

def parse_folder_name(line):
    """Helper function to clean up server folder names."""
    match = re.search(r'\(.*?\)\s+"."\s+"?([^"]+)"?', line.decode('utf-8'))
    if match:
        return match.group(1)
    return None

def connect_to_servers():
    """Establishes connections to both Yahoo and the destination server."""
    print("Connecting to Yahoo...")
    source = imaplib.IMAP4_SSL(YAHOO_SERVER)
    source.login(YAHOO_USER, YAHOO_PASS)

    print("Connecting to New Server...")
    dest = imaplib.IMAP4_SSL(NEW_SERVER)
    dest.login(NEW_USER, NEW_PASS)
    
    return source, dest

def run_unlimited_migration():
    # Initial connections
    try:
        source, dest = connect_to_servers()
    except Exception as e:
        print(f"Initial connection failed: {e}")
        return

    # Automatically fetch ALL folders from your Yahoo account
    print("Scanning Yahoo for all existing folders...")
    try:
        status, folder_list = source.list()
        if status != 'OK':
            print("Failed to retrieve folder list from Yahoo.")
            return
    except Exception as e:
        print(f"Failed to scan folders: {e}")
        return

    # Process each folder found on Yahoo
    for line in folder_list:
        yahoo_folder = parse_folder_name(line)
        if not yahoo_folder:
            continue

        # Skip spam/trash
        if yahoo_folder.lower() in ['bulk mail', 'spam']:
            continue

        print(f"\n--------------------------------------------------")
        print(f"Processing folder: {yahoo_folder}")
        print(f"--------------------------------------------------")

        # Outer loop to handle folder processing and reconnection if needed
        retry_folder = True
        while retry_folder:
            try:
                # Open the Yahoo folder
                status, _ = source.select(f'"{yahoo_folder}"', readonly=True)
                if status != 'OK':
                    print(f"Could not open Yahoo folder '{yahoo_folder}'. Skipping.")
                    retry_folder = False
                    continue

                # Automatically create the exact same folder name on the new server
                try:
                    dest.create(f'"{yahoo_folder}"')
                except:
                    pass  # Ignore if it already exists

                # Search for 'ALL' emails with no date limits
                _, response = source.search(None, "ALL")
                if response and response[0]:
                    msg_ids = response[0].split()
                else:
                    msg_ids = []

                total = len(msg_ids)
                print(f"Found {total} total emails in this folder.")
                if total == 0:
                    retry_folder = False
                    continue

                # Loop through and transfer each email
                for index, msg_id in enumerate(msg_ids, start=1):
                    msg_id_str = msg_id.decode('utf-8')
                    try:
                        # Fetch message data from Yahoo
                        _, data = source.fetch(msg_id, "(RFC822)")
                        if not data or not data[0]:
                            continue
                        email_bytes = data[0][1]

                        # Upload directly to the new server folder
                        dest.append(f'"{yahoo_folder}"', None, None, email_bytes)

                        # Live counter printout
                        if index % 100 == 0 or index == total:
                            print(f"[{yahoo_folder}] Copied {index} of {total} emails...")

                    except (imaplib.IMAP4.abort, ssl.SSLError) as conn_err:
                        # Catch the SSL and connection abort errors specifically
                        print(f"\n[!] Connection dropped by server on Msg ID {msg_id_str}: {conn_err}")
                        print("Re-establishing connections and resuming...")
                        time.sleep(5)
                        
                        # Reconnect safely
                        source, dest = connect_to_servers()
                        
                        # Break inner loop to re-initialize folder selection and index search
                        break 
                        
                    except Exception as e:
                        print(f"Error copying message ID {msg_id_str}: {e}")
                        continue
                else:
                    # Executes only if the inner loop finishes without breaking (folder complete)
                    retry_folder = False

            except (imaplib.IMAP4.abort, ssl.SSLError, ConnectionResetError):
                print("[!] Server error outside message loop. Reconnecting in 5 seconds...")
                time.sleep(5)
                source, dest = connect_to_servers()

    # Log out safely
    try:
        source.logout()
        dest.logout()
    except:
        pass
        
    print("\nAll folders processed and full migration is complete!")

if __name__ == "__main__":
    run_unlimited_migration()
