# utils/forward_handler.py import re import os from datetime import datetime from email.utils import parseaddr from models.mensaje_email import MensajeEmail # Patrones de inicio de mensaje reenviado en diferentes idiomas FORWARD_PATTERNS = [ r"[-]{3,}\s*Messaggio originale\s*[-]{3,}", # Italiano r"[-]{3,}\s*Original Message\s*[-]{3,}", # Inglés r"[-]{3,}\s*Mensaje original\s*[-]{3,}", # Español r"[-]{3,}\s*Message d'origine\s*[-]{3,}", # Francés r"[-]{3,}\s*Ursprüngliche Nachricht\s*[-]{3,}", # Alemán # Variantes más flexibles r"[-]{3,}\s*Forwarded message\s*[-]{3,}", r"[-]{3,}\s*Mensaje reenviado\s*[-]{3,}", r"[-]{3,}\s*Messaggio inoltrato\s*[-]{3,}", # Patrones con > que suelen aparecer en texto plano r"(?m)^>\s*[-]{3,}\s*Messaggio originale\s*[-]{3,}", r"(?m)^>\s*[-]{3,}\s*Original Message\s*[-]{3,}" ] # Patrones de headers en diferentes idiomas HEADER_PATTERNS = { 'from': [ r"Da:\s*(.*)", # Italiano r"From:\s*(.*)", # Inglés r"De:\s*(.*)", # Español r"Von:\s*(.*)", # Alemán r"De :\s*(.*)" # Francés ], 'date': [ r"Inviato:\s*(.*)", # Italiano r"Sent:\s*(.*)", # Inglés r"Enviado:\s*(.*)", # Español r"Gesendet:\s*(.*)", # Alemán r"Envoyé :\s*(.*)" # Francés ], 'subject': [ r"Oggetto:\s*(.*)", # Italiano r"Subject:\s*(.*)", # Inglés r"Asunto:\s*(.*)", # Español r"Betreff:\s*(.*)", # Alemán r"Sujet :\s*(.*)" # Francés ] } def extract_forwarded_messages(contenido): """ Extrae mensajes reenviados del contenido del email Retorna una lista de objetos MensajeEmail """ mensajes = [] # Crear el patrón de división combinando todos los patrones de reenvío split_pattern = '|'.join(f"({pattern})" for pattern in FORWARD_PATTERNS) # Dividir el contenido usando el patrón combinado partes = re.split(split_pattern, contenido) # El primer elemento es el contenido original del email contenido_original = partes[0].strip() # Procesar cada parte que coincide con un patrón de reenvío for i in range(1, len(partes), len(FORWARD_PATTERNS) + 1): # Encontrar qué patrón coincidió patron_encontrado = next((p for p in partes[i:i+len(FORWARD_PATTERNS)] if p), None) if patron_encontrado and i + len(FORWARD_PATTERNS) < len(partes): contenido_reenviado = partes[i + len(FORWARD_PATTERNS)].strip() if contenido_reenviado: mensaje = _procesar_contenido_reenviado(contenido_reenviado) if mensaje: mensajes.append(mensaje) return contenido_original, mensajes def _procesar_contenido_reenviado(contenido): """ Procesa el contenido de un mensaje reenviado y extrae la información relevante """ # Extraer headers remitente = None fecha_str = None subject = None cuerpo = contenido # Buscar headers al inicio del mensaje lineas = contenido.split('\n') headers_encontrados = 0 i = 0 while i < len(lineas) and headers_encontrados < 3: linea = lineas[i].strip() # Buscar remitente if not remitente: for pattern in HEADER_PATTERNS['from']: match = re.match(pattern, linea) if match: remitente = match.group(1).strip() headers_encontrados += 1 break # Buscar fecha if not fecha_str: for pattern in HEADER_PATTERNS['date']: match = re.match(pattern, linea) if match: fecha_str = match.group(1).strip() headers_encontrados += 1 break # Buscar asunto if not subject: for pattern in HEADER_PATTERNS['subject']: match = re.match(pattern, linea) if match: subject = match.group(1).strip() headers_encontrados += 1 break i += 1 # Si encontramos headers, el cuerpo comienza después de ellos if headers_encontrados > 0: cuerpo = '\n'.join(lineas[i:]).strip() # Si no tenemos la información mínima necesaria, retornar None if not (remitente or fecha_str or cuerpo): return None # Crear el objeto MensajeEmail try: return MensajeEmail( remitente=remitente or "Remitente Desconocido", fecha=fecha_str or datetime.now(), contenido=cuerpo, subject=subject, adjuntos=[] ) except Exception as e: print(f"Error creando mensaje reenviado: {str(e)}") return None