""" Script one-shot: corregge il body_text/body_html delle ricevute PEC gia' in DB. Problema: il parser EML sovrascriveva il body delle ricevute con il contenuto di postacert.eml (messaggio originale inviato), invece di mostrare il testo della ricevuta stessa. Questo script: 1. Trova tutti i messaggi in DB con pec_type di tipo ricevuta 2. Scarica l'EML grezzo da MinIO (raw_eml_path) 3. Lo ri-parsa con is_receipt=True (parser corretto) 4. Aggiorna body_text e body_html nel DB Uso: cd /opt/pechub docker compose exec pechub-worker-1 python /app/scripts/fix_receipt_body.py """ import asyncio import logging import sys from datetime import UTC, datetime from sqlalchemy import select, update from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession from sqlalchemy.orm import sessionmaker # Aggiungi il path dell'app sys.path.insert(0, "/app") from app.config import get_settings from app.models import Message from app.parsers.eml_parser import parse_eml from app.storage.minio_client import download_attachment logging.basicConfig( level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s", ) logger = logging.getLogger(__name__) # Tipi di ricevuta che potrebbero avere il body sbagliato RECEIPT_TYPES = { "accettazione", "non_accettazione", "presa_in_carico", "avvenuta_consegna", "mancata_consegna", "errore_consegna", "preavviso_mancata_consegna", "rilevazione_virus", } async def fix_receipt_bodies() -> None: settings = get_settings() engine = create_async_engine(settings.database_url, echo=False) async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False) async with async_session() as db: # Trova tutti i messaggi ricevuta con raw_eml_path result = await db.execute( select(Message).where( Message.pec_type.in_(RECEIPT_TYPES), Message.raw_eml_path.is_not(None), ).order_by(Message.created_at) ) messages = result.scalars().all() logger.info(f"Trovate {len(messages)} ricevute da verificare") fixed = 0 skipped = 0 errors = 0 for msg in messages: try: # Scarica EML grezzo da MinIO (download_attachment funziona per qualsiasi path) raw_eml = await download_attachment(msg.raw_eml_path) if not raw_eml: logger.warning(f"EML non trovato su MinIO per messaggio {msg.id} (path={msg.raw_eml_path!r})") skipped += 1 continue # Re-parsing con is_receipt=True (parser corretto) parsed = parse_eml(raw_eml, is_receipt=True) # Controlla se il body e' cambiato new_body_text = parsed.body_text new_body_html = parsed.body_html if new_body_text == msg.body_text and new_body_html == msg.body_html: logger.debug(f"Messaggio {msg.id} ({msg.pec_type}): body invariato, skip") skipped += 1 continue # Aggiorna nel DB msg.body_text = new_body_text msg.body_html = new_body_html msg.updated_at = datetime.now(UTC) logger.info( f"Fixato: id={msg.id} pec_type={msg.pec_type!r} subject={msg.subject!r} " f"body_text_len={len(new_body_text or '')}" ) fixed += 1 except Exception as e: logger.error(f"Errore su messaggio {msg.id}: {e}", exc_info=True) errors += 1 continue if fixed > 0: await db.commit() logger.info(f"Commit eseguito: {fixed} messaggi aggiornati") else: logger.info("Nessun messaggio da aggiornare") logger.info( f"Completato: fixed={fixed} skipped={skipped} errors={errors} " f"totale={len(messages)}" ) await engine.dispose() if __name__ == "__main__": asyncio.run(fix_receipt_bodies())