"""Marca o desmarca un mensaje IMAP como leido (\\Seen) operando por UID. Funcion IMPURA: emite un comando UID STORE contra un servidor IMAP a traves de una conexion `imaplib.IMAP4_SSL` ya autenticada y con un mailbox seleccionado. Anade (+FLAGS) o quita (-FLAGS) la bandera del sistema `\\Seen` sobre el mensaje identificado por su UID, que es estable dentro del mailbox seleccionado (a diferencia del numero de secuencia, que cambia cuando se borran mensajes). Nunca lanza: devuelve un dict con `status` ("ok"/"error"), siguiendo el estilo del contrato compartido del grupo email/imap del registry. No resuelve credenciales ni abre la conexion: el caller pasa `conn` ya conectado, autenticado y con `conn.select("")` hecho. """ def imap_mark_seen(conn, uid: int, seen: bool = True) -> dict: """Marca/desmarca como leido el mensaje `uid` del mailbox seleccionado. Ejecuta ``conn.uid("STORE", str(uid), "+FLAGS" | "-FLAGS", "(\\Seen)")``. Con ``seen=True`` anade la bandera ``\\Seen`` (mensaje leido); con ``seen=False`` la quita (mensaje no leido). La operacion es por UID, no por numero de secuencia. Args: conn: objeto ``imaplib.IMAP4_SSL`` (o ``IMAP4``) YA conectado, autenticado y con un mailbox seleccionado (``conn.select(...)``). uid: UID del mensaje dentro del mailbox seleccionado. Estable mientras no cambie la UIDVALIDITY del mailbox. seen: ``True`` para marcar como leido (``+FLAGS``), ``False`` para marcar como no leido (``-FLAGS``). Default ``True``. Returns: dict. En exito: ``{"status": "ok", "uid": uid, "seen": seen}``. En fallo (sin lanzar): ``{"status": "error", "error": str}``. Tambien se devuelve error si el servidor responde algo distinto de ``OK`` al comando STORE. """ try: op = "+FLAGS" if seen else "-FLAGS" typ, data = conn.uid("STORE", str(uid), op, "(\\Seen)") if typ != "OK": return { "status": "error", "error": f"imap_mark_seen: STORE devolvio {typ!r}: {data!r}", } return {"status": "ok", "uid": uid, "seen": seen} except Exception as e: # noqa: BLE001 return {"status": "error", "error": str(e)} if __name__ == "__main__": # Smoke manual (requiere un `conn` real de imap_connect). Se documenta el uso # en el .md; aqui solo dejamos constancia del patron, tolerando ausencia de conn. print("imap_mark_seen: importable. Uso real requiere un conn IMAP autenticado.")