Files
fn_registry/python/functions/infra/imap_mark_seen.py
T
egutierrez 763e06c127 feat(browser): auto-commit con 178 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-20 18:22:23 +02:00

55 lines
2.5 KiB
Python

"""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("<mailbox>")` 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.")