---
name: imap_connect
kind: function
lang: py
domain: infra
version: "1.0.0"
purity: impure
signature: "def imap_connect(host: str, port: int = 993, user: str = '', password: str = '', mailbox: str = 'INBOX', use_ssl: bool = True, timeout_s: float = 30.0) -> dict"
description: "Abre y autentica una conexion IMAP (IMAP4_SSL por defecto, IMAP4 en claro si use_ssl=False) con usuario + app-password (NO OAuth), hace login y select(mailbox), y devuelve el objeto imaplib vivo dentro del dict de estado para componer el resto de operaciones del grupo email/imap. Defaults Gmail: host imap.gmail.com, port 993. Devuelve {status:'ok', conn, mailbox, num_messages} o {status:'error', error}. Nunca lanza. Las credenciales las pasa la capa app (via pass/vault), no se resuelven aqui."
tags: [email, imap, infra, mailbox, network]
params:
  - name: host
    desc: "Servidor IMAP, ej. imap.gmail.com. Vacio devuelve status error."
  - name: port
    desc: "Puerto IMAP. Default 993 (IMAPS sobre SSL). 143 para STARTTLS/plano."
  - name: user
    desc: "Direccion de correo / usuario de la cuenta."
  - name: password
    desc: "App-password (16 chars en Gmail, requiere 2FA) o contrasena del proveedor. NO OAuth."
  - name: mailbox
    desc: "Buzon a seleccionar tras autenticar. Default 'INBOX'."
  - name: use_ssl
    desc: "True (default) usa IMAP4_SSL cifrado. False usa IMAP4 en claro (solo redes de confianza/test)."
  - name: timeout_s
    desc: "Timeout del socket en segundos para conectar/operar. Default 30.0."
output: "dict de estado. En exito {status:'ok', conn: <imaplib.IMAP4_SSL vivo autenticado con mailbox seleccionado>, mailbox: str, num_messages: int (mensajes en el buzon, de la respuesta de SELECT)}. En fallo (host vacio, auth invalida, red caida, buzon inexistente) {status:'error', error: str} y SIN clave conn."
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_py_core"
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "python/functions/infra/imap_connect.py"
---

## Ejemplo

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

# App-password de Gmail (16 chars, requiere 2FA). Pasalo desde pass/vault.
res = imap_connect(
    host="imap.gmail.com",
    port=993,
    user="gutierenmanuel15@gmail.com",
    password="abcd efgh ijkl mnop",   # app-password Gmail
    mailbox="INBOX",
)
print(res["status"])         # "ok"
print(res["num_messages"])   # p.ej. 1423
conn = res["conn"]           # objeto vivo: pasalo a imap_search / imap_fetch_message

# ... operar ...
conn.logout()                # cierra siempre al terminar
```

## Cuando usarla

Usala como PRIMER paso de cualquier flujo de lectura de correo por IMAP: antes
de listar carpetas (`imap_list_mailboxes`), buscar (`imap_search`) o leer un
mensaje (`imap_fetch_message`). Es la fabrica del objeto `conn` que el resto
del grupo consume. Para Gmail usa los defaults (`imap.gmail.com:993`); para
otros proveedores cambia `host`/`port` y pasa user+pass.

## Gotchas

- Funcion impura: hace red. No determinista (latencia, disponibilidad del
  servidor). Nunca lanza: comprueba `status` antes de tocar `conn`.
- El objeto `conn` VIVO viaja dentro del dict a proposito: este grupo se
  compone en heredocs Python, no por `fn run` (un proceso `fn run` no puede
  devolver un socket abierto entre invocaciones). Mantén `conn` en memoria del
  mismo proceso mientras lo uses.
- Cierra SIEMPRE con `conn.logout()` al terminar (o en un `finally`). Una
  conexion sin cerrar deja sesiones colgando en el servidor; Gmail limita el
  numero de conexiones IMAP simultaneas por cuenta.
- Auth = app-password, NO OAuth. En Gmail debes tener 2FA activado y generar
  una app-password; la contrasena normal de la cuenta NO funciona por IMAP.
- Si `select(mailbox)` falla (buzon inexistente, mayusculas mal en nombres
  tipo `[Gmail]/Sent Mail`), se hace `logout` y se devuelve `status:'error'`.
- `use_ssl=False` envia credenciales en claro: usalo solo contra servidores de
  test en redes de confianza.
