==================================================================== Migrador y respaldador de cuentas IMAP ==================================================================== Este programa copia o migra el contenido completo de una cuenta de correo IMAP (carpetas, mensajes, adjuntos, flags y fechas) desde un servidor origen (A) hacia un servidor destino (B). Puede usarse tanto para migrar una cuenta a un servidor nuevo como para mantener un respaldo periódico de una cuenta en otro servidor. El programa NUNCA borra, mueve ni modifica mensajes en el servidor origen. -------------------------------------------------------------------- 1. Requisitos -------------------------------------------------------------------- - Python 3.10 o superior. - No se requieren dependencias externas (solo librería estándar). -------------------------------------------------------------------- 2. Creación del entorno virtual -------------------------------------------------------------------- Linux / macOS: python3 -m venv python-env source python-env/bin/activate Windows: python -m venv python-env python-env\Scripts\activate -------------------------------------------------------------------- 3. Instalación de dependencias -------------------------------------------------------------------- pip install --upgrade pip pip install -r requirements.txt (requirements.txt no declara dependencias externas: todo el programa usa la librería estándar de Python.) -------------------------------------------------------------------- 4. Ejecución -------------------------------------------------------------------- Ejemplo básico (las contraseñas se piden de forma interactiva si se omiten): python3 imap_migrate.py \ --aserver mail.oldserver.com \ --auser usuario@dominio.com \ --bserver mail.newserver.com \ --buser usuario@dominio.com Ejemplo completo, con contraseñas por parámetro: python3 imap_migrate.py \ --aserver imap.servidor-a.com --aport 993 \ --auser usuario@dominio.com --apassword 'passwordA' \ --bserver imap.servidor-b.com --bport 993 \ --buser usuario@dominio.com --bpassword 'passwordB' Ejemplo usando una IP directa pero validando el certificado TLS contra el nombre de host real (útil cuando el DNS no resuelve o se quiere evitar la resolución DNS): python3 imap_migrate.py \ --aserver mail.oldserver.com --aip 203.0.113.10 \ --auser usuario@dominio.com \ --bserver mail.newserver.com \ --buser usuario@dominio.com Ejemplo con servidor destino de certificado autofirmado (ver sección 6 para la advertencia de seguridad): python3 imap_migrate.py \ --aserver mail.oldserver.com --auser usuario@dominio.com \ --bserver mail.interno.local --buser usuario@dominio.com \ --b-no-verify-tls -------------------------------------------------------------------- 5. Parámetros disponibles -------------------------------------------------------------------- Servidor origen (A): --aserver Host del servidor IMAP origen (obligatorio) --aport Puerto (por defecto 993) --auser Usuario/cuenta en el servidor origen (obligatorio) --apassword Password (si se omite, se solicita interactivamente o se toma de la variable de entorno IMAP_A_PASSWORD) --adomain Dominio lógico de la cuenta (informativo / uso futuro para migración de múltiples cuentas) --aip IP a la que conectar, usando --aserver como nombre de host para la validación TLS --a-no-verify-tls Deshabilita la verificación de certificado TLS SOLO para el servidor origen (inseguro) --a-no-ssl Conecta sin SSL/TLS al servidor origen (inseguro) Servidor destino (B): --bserver, --bport, --buser, --bpassword, --bdomain, --bip, --b-no-verify-tls, --b-no-ssl Mismo significado que los anteriores, aplicados al servidor destino. La contraseña también puede tomarse de la variable de entorno IMAP_B_PASSWORD. Generales: --no-verify-tls Deshabilita la verificación de certificado TLS en AMBOS servidores (inseguro). Muestra una advertencia de seguridad en consola y en el log. --timeout Timeout de conexión en segundos (por defecto 30) --retries Número de reintentos ante errores de red/IMAP (por defecto 3) --state-file Archivo de estado de la migración (por defecto migration-state.json) --log-dir Directorio de logs (por defecto logs/) --header-batch-size Cantidad de mensajes cuyos encabezados se analizan por cada lote de red (por defecto 500) --verbose Muestra en consola el mismo detalle que se registra en el archivo de log -h, --help Muestra la ayuda completa -------------------------------------------------------------------- 6. Certificados autofirmados / servidores internos -------------------------------------------------------------------- Por defecto el programa valida los certificados TLS de ambos servidores. Si alguno usa un certificado autofirmado (típico en servidores internos), se puede deshabilitar la validación con: --no-verify-tls (para ambos servidores) --a-no-verify-tls (solo para el servidor origen) --b-no-verify-tls (solo para el servidor destino) Al usar cualquiera de estas opciones se imprime y registra una advertencia de seguridad explícita. Úsese solo con servidores de confianza. -------------------------------------------------------------------- 7. Cómo reanudar / re-ejecutar una migración incremental -------------------------------------------------------------------- El programa mantiene un archivo de estado (por defecto "migration-state.json" en el directorio de trabajo) con, por cada carpeta: - el UID de origen hasta el cual ya se analizó de forma segura; - la huella (fingerprint, basada en Message-ID o en tamaño+fecha) de cada mensaje ya copiado; - el UIDVALIDITY visto la última vez. Para reanudar una migración interrumpida (por CTRL+C, pérdida de conexión, reinicio del servidor, etc.) o para hacer una nueva pasada incremental (por ejemplo, para respaldar los mensajes nuevos desde la última ejecución), simplemente se vuelve a ejecutar el mismo comando apuntando al mismo --state-file: python3 imap_migrate.py --aserver ... --auser ... --bserver ... --buser ... El programa detectará automáticamente qué mensajes ya fueron copiados y solo transferirá los mensajes nuevos o los que quedaron pendientes por un error anterior. Si un mensaje falló en una ejecución anterior, se reintenta en la siguiente ejecución sin volver a analizar toda la carpeta desde cero. Si el UIDVALIDITY de una carpeta cambia en el servidor origen (esto puede pasar tras una reconstrucción del buzón), el programa vuelve a escanear esa carpeta completa, pero sigue evitando duplicados gracias a que la huella de cada mensaje se basa principalmente en su Message-ID. -------------------------------------------------------------------- 8. Cómo detener correctamente una migración -------------------------------------------------------------------- Presionar CTRL+C durante la ejecución hace que el programa: 1. termine de forma segura la operación IMAP en curso; 2. guarde el estado de la migración; 3. cierre las conexiones con ambos servidores; 4. muestre las estadísticas parciales acumuladas; 5. finalice. La siguiente ejecución continuará desde el punto en que se quedó. -------------------------------------------------------------------- 9. Dónde están los logs -------------------------------------------------------------------- Los logs se escriben en el directorio indicado por --log-dir (por defecto "logs/"), con un archivo por día: logs/migration-2026-09-09.log El log incluye inicio de ejecución, conexiones, reconexiones, creación de carpetas, mensajes copiados/omitidos, errores, reintentos y el resumen final. Nunca se registran contraseñas. -------------------------------------------------------------------- 10. Dónde está el archivo de estado -------------------------------------------------------------------- Por defecto: "migration-state.json" en el directorio desde el que se ejecuta el programa (configurable con --state-file). Nunca contiene contraseñas. -------------------------------------------------------------------- 11. Códigos de salida -------------------------------------------------------------------- 0 = migración terminada correctamente 1 = migración terminada con errores (ver el resumen final y el log) 2 = error de parámetros 3 = error de conexión con alguno de los servidores -------------------------------------------------------------------- 12. Ejecutar las pruebas -------------------------------------------------------------------- Las pruebas usan únicamente "unittest" (librería estándar) y mocks; no requieren servidores IMAP reales. python3 -m unittest discover -s tests -t . -------------------------------------------------------------------- 13. Estructura del proyecto -------------------------------------------------------------------- imap_migrate.py Punto de entrada de línea de comandos config.py Parseo de argumentos y configuración imap_client.py Cliente IMAP (conexión, carpetas, fetch, append) migrator.py Orquestador de la migración (análisis + copia) state.py Persistencia del estado de migración fingerprint.py Cálculo de huellas para detectar duplicados progress.py Progreso en consola, ETA, resumen final logger.py Configuración de logging utf7.py Codificación UTF-7 modificada para nombres de carpeta requirements.txt Leame.txt logs/ Logs de ejecución tests/ Pruebas unitarias -------------------------------------------------------------------- 14. Migración de múltiples cuentas (extensión futura) -------------------------------------------------------------------- Actualmente el programa migra una cuenta por ejecución. El diseño (Migrator recibe un objeto de configuración por cuenta) permite extenderlo fácilmente para leer un archivo "usuarios.csv" o "usuarios.json" con varias cuentas y ejecutar la migración de cada una en un bucle, sin cambios estructurales.