Files
fn_registry/python/functions/infra/imap_save_draft.md
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

5.3 KiB

name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, params, output, tested, tests, test_file_path, file_path
name kind lang domain version purity signature description tags uses_functions uses_types returns returns_optional error_type imports params output tested tests test_file_path file_path
imap_save_draft function py infra 1.0.0 impure def imap_save_draft(conn, raw_rfc822: bytes, mailbox: str = '[Gmail]/Drafts', flags: str = '\Draft') -> dict Guarda un borrador en un mailbox via IMAP APPEND sobre una conexion imaplib.IMAP4_SSL ya autenticada. Ejecuta conn.append(mailbox, flags, imaplib.Time2Internaldate(time.time()), raw_rfc822): raw_rfc822 son los bytes MIME ya serializados de un email completo (cabeceras + cuerpo) que el caller arma con email.message.EmailMessage().as_bytes() (stdlib) o con las funciones email_build_*_py_infra del registry + serializacion. A diferencia de las demas operaciones del grupo, APPEND NO requiere un mailbox seleccionado: el destino es el argumento mailbox (default '[Gmail]/Drafts', con su prefijo [Gmail]/). flags default '\Draft' para que el cliente lo trate como borrador. Valida que raw_rfc822 sean bytes. No abre la conexion ni resuelve credenciales. Nunca lanza: devuelve {status:'ok', mailbox} o {status:'error', error}; tambien error si APPEND responde un typ distinto de OK. Parte del grupo email/imap. Solo stdlib (imaplib, time, email.message para construir el MIME).
email
imap
mail
draft
append
infra
false error_py_core
imaplib
time
name desc
conn objeto imaplib.IMAP4_SSL (o IMAP4) YA conectado y autenticado. Normalmente lo produce imap_connect. APPEND no requiere mailbox seleccionado: el destino se pasa en el argumento mailbox. La funcion no abre ni cierra conn.
name desc
raw_rfc822 bytes MIME ya serializados de un email completo (cabeceras From/To/Subject + cuerpo). El caller los construye con email.message.EmailMessage(...).as_bytes() (stdlib) o con email_build_*_py_infra del registry + serializacion. Debe ser bytes; un str devuelve {status:'error'}.
name desc
mailbox mailbox destino del borrador. Default '[Gmail]/Drafts' (carpeta de borradores de Gmail, con prefijo [Gmail]/). En otros servidores suele ser 'Drafts'. Debe existir en el servidor.
name desc
flags banderas IMAP a poner al mensaje, como string separado por espacios. Default '\Draft' para marcarlo como borrador. Combinable, p.ej. '\Draft \Seen'.
dict. En exito: {status:'ok', mailbox:str} reflejando el mailbox donde se guardo el borrador. En error (sin lanzar): {status:'error', error:str}, p.ej. si raw_rfc822 no son bytes o si APPEND responde un typ distinto de OK. false
python/functions/infra/imap_save_draft.py

Ejemplo

import sys
sys.path.insert(0, "python/functions")
from email.message import EmailMessage
from infra.imap_connect import imap_connect
from infra.imap_save_draft import imap_save_draft

# conn ya conectado y autenticado (lo produce imap_connect). APPEND no necesita select().
conn = imap_connect(...)["conn"]  # firma exacta la define imap_connect

# Armar un borrador minimo con stdlib y serializarlo a bytes MIME.
msg = EmailMessage()
msg["From"] = "yo@example.com"
msg["To"] = "destinatario@example.com"
msg["Subject"] = "Propuesta (borrador)"
msg.set_content("Hola, este es un borrador guardado por IMAP APPEND.")
raw = msg.as_bytes()

# Guardarlo en la carpeta de borradores de Gmail (nota el prefijo [Gmail]/).
print(imap_save_draft(conn, raw, mailbox="[Gmail]/Drafts"))
# {'status': 'ok', 'mailbox': '[Gmail]/Drafts'}

Cuando usarla

Cuando quieres dejar un correo a medio escribir guardado en el servidor (no enviarlo) para retomarlo desde cualquier cliente: el clasico "guardar borrador". Util para flujos donde un agente prepara una respuesta y la deja en Drafts para que el humano la revise y envie. Tambien sirve para archivar copias arbitrarias de mensajes en un mailbox (cambiando flags). El envio real es otra cosa: para enviar usa smtp_send_py_infra. Compone con email_build_*_py_infra (que producen el EmailMessage) + serializacion a bytes.

Gotchas

  • Impura: escribe un mensaje nuevo en el servidor (consume cuota de la cuenta).
  • raw_rfc822 son BYTES, no str: el mensaje MIME debe estar ya serializado a bytes (EmailMessage().as_bytes()). Pasar un str devuelve {status:'error'}. La funcion no construye el MIME: solo lo deposita.
  • APPEND no usa mailbox seleccionado: a diferencia de STORE/COPY/EXPUNGE, el destino de APPEND es el argumento mailbox, no el mailbox que el caller selecciono. No hace falta conn.select(...) previo.
  • Prefijo [Gmail]/ y existencia: en Gmail la carpeta de borradores es [Gmail]/Drafts (con prefijo). En otros servidores suele ser Drafts. El mailbox destino debe existir; si no, APPEND falla y se devuelve error.
  • No hay UID estable garantizado en la respuesta: APPEND crea un mensaje nuevo; algunos servidores devuelven su UID (APPENDUID) y otros no. Esta funcion no lo parsea — devuelve solo {status, mailbox}. Si necesitas el UID del borrador, busca despues con imap_search.
  • flags con backslash: las banderas del sistema llevan barra invertida (\\Draft, \\Seen). En el string Python recuerda escaparla ("\\Draft").
  • Nunca lanza: cualquier fallo (mailbox inexistente, conexion caida, bytes invalidos, respuesta no-OK) vuelve como {status:'error', error:str}.