---
name: imap_delete_message
kind: function
lang: py
domain: infra
version: "1.0.0"
purity: impure
signature: "def imap_delete_message(conn, uid: int, expunge: bool = True) -> dict"
description: "Marca un mensaje IMAP (por UID) como borrado anadiendo la bandera del sistema \\Deleted en el mailbox seleccionado de una conexion imaplib.IMAP4_SSL ya autenticada, y opcionalmente ejecuta EXPUNGE para materializar el borrado. Ejecuta conn.uid('STORE', str(uid), '+FLAGS', '(\\Deleted)'); si expunge=True ademas conn.expunge() (que elimina TODOS los mensajes marcados \\Deleted del mailbox, no solo este). Opera siempre por UID (estable dentro del mailbox), nunca por numero de secuencia. No abre la conexion ni resuelve credenciales: el caller pasa conn ya conectado, autenticado y con conn.select() hecho. Nunca lanza: devuelve {status:'ok', uid, expunged} o {status:'error', error}. GOTCHA Gmail: marcar \\Deleted NO borra, solo quita la etiqueta de la carpeta actual; para borrar de verdad en Gmail hay que MOVER a '[Gmail]/Trash' (ver imap_move_message). Parte del grupo email/imap. Solo stdlib (imaplib)."
tags: [email, imap, mail, delete, expunge, infra]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_py_core"
imports: [imaplib]
params:
  - name: conn
    desc: "objeto imaplib.IMAP4_SSL (o IMAP4) YA conectado, autenticado y con un mailbox seleccionado (conn.select('INBOX')). Normalmente lo produce imap_connect. La funcion no lo abre ni lo cierra."
  - name: uid
    desc: "UID del mensaje dentro del mailbox seleccionado. Estable mientras no cambie la UIDVALIDITY (a diferencia del numero de secuencia, que se desplaza al borrar mensajes)."
  - name: expunge
    desc: "True (default) ejecuta EXPUNGE tras marcar \\Deleted, eliminando del mailbox TODOS los mensajes marcados \\Deleted (no solo este). False solo marca \\Deleted sin expurgar: el borrado se materializa en un EXPUNGE posterior o al cerrar el mailbox."
output: "dict. En exito: {status:'ok', uid:int, expunged:bool} reflejando el UID y si se ejecuto EXPUNGE. En error (sin lanzar): {status:'error', error:str}, incluyendo el caso en que STORE responde un typ distinto de OK."
tested: false
tests: []
test_file_path: ""
file_path: "python/functions/infra/imap_delete_message.py"
---

## Ejemplo

```python
import sys
sys.path.insert(0, "python/functions")
from infra.imap_connect import imap_connect
from infra.imap_delete_message import imap_delete_message

# conn ya conectado, autenticado y con INBOX seleccionado (lo produce imap_connect).
conn = imap_connect(...)["conn"]  # firma exacta la define imap_connect

# Borrado IMAP estandar: marca \\Deleted y expurga el mailbox.
print(imap_delete_message(conn, 12345))
# {'status': 'ok', 'uid': 12345, 'expunged': True}

# Marcar \\Deleted sin expurgar todavia (borrado diferido).
print(imap_delete_message(conn, 12346, expunge=False))
# {'status': 'ok', 'uid': 12346, 'expunged': False}
```

## Cuando usarla

Cuando quieres eliminar un mensaje en un servidor IMAP estandar (Dovecot, Courier,
proveedores no-Gmail) donde marcar `\\Deleted` + EXPUNGE si borra el mensaje del
mailbox. Para borrado en lote, llama con `expunge=False` por cada mensaje y haz un
unico EXPUNGE al final (o un solo `imap_delete_message(..., expunge=True)` en el
ultimo). **En Gmail no la uses para "borrar de verdad"**: alli marcar `\\Deleted`
solo quita la etiqueta de la carpeta; usa `imap_move_message(conn, uid,
"[Gmail]/Trash")` en su lugar.

## Gotchas

- **Impura y destructiva**: con `expunge=True` el mensaje desaparece del mailbox de
  forma permanente (salvo politicas de retencion del servidor).
- **Gmail \\Deleted vs Trash**: en Gmail marcar `\\Deleted` NO borra el mensaje,
  solo le quita la etiqueta de la carpeta actual (el correo sigue en "All Mail").
  Para borrar de verdad en Gmail hay que MOVER a `[Gmail]/Trash` con
  `imap_move_message`. Esta funcion es el borrado estandar de servidores no-Gmail.
- **EXPUNGE afecta a todo el mailbox**: `conn.expunge()` elimina TODOS los mensajes
  marcados `\\Deleted` del mailbox seleccionado, no solo el `uid` indicado. Si otros
  mensajes quedaron marcados antes, tambien se borran. Usa `expunge=False` para
  marcar varios y expurgar una sola vez de forma controlada.
- **UID estable, no secuencia**: se usa siempre `conn.uid("STORE", ...)`. El UID es
  estable dentro del mailbox mientras la UIDVALIDITY no cambie; el numero de
  secuencia se desplaza al expurgar y por eso nunca se usa.
- **Nunca lanza**: cualquier fallo (conexion caida, mailbox no seleccionado,
  respuesta no-OK) vuelve como `{status:'error', error:str}`.
