763e06c127
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
77 lines
3.3 KiB
Python
77 lines
3.3 KiB
Python
"""Guarda un borrador (mensaje RFC822 ya serializado) en un mailbox via IMAP APPEND.
|
|
|
|
Funcion IMPURA: usa el comando IMAP APPEND para anadir un mensaje completo (bytes
|
|
MIME ya serializados) a un mailbox de una conexion `imaplib.IMAP4_SSL` ya
|
|
autenticada, marcandolo con las banderas indicadas (por defecto `\\Draft`). No
|
|
construye el MIME ni resuelve credenciales: el caller arma los bytes con stdlib
|
|
(`email.message.EmailMessage().as_bytes()`) o con las funciones email_build_*
|
|
del registry + serializacion, y pasa una conexion ya lista.
|
|
|
|
A diferencia de las otras operaciones del grupo, APPEND no necesita un mailbox
|
|
seleccionado: el destino se indica como argumento. La marca de tiempo interna del
|
|
mensaje se fija con `imaplib.Time2Internaldate(time.time())`.
|
|
|
|
Nunca lanza: devuelve un dict con `status` ("ok"/"error").
|
|
"""
|
|
|
|
import imaplib
|
|
import time
|
|
|
|
|
|
def imap_save_draft(
|
|
conn,
|
|
raw_rfc822: bytes,
|
|
mailbox: str = "[Gmail]/Drafts",
|
|
flags: str = "\\Draft",
|
|
) -> dict:
|
|
"""Guarda `raw_rfc822` como borrador en `mailbox` via IMAP APPEND.
|
|
|
|
Ejecuta ``conn.append(mailbox, flags, imaplib.Time2Internaldate(time.time()),
|
|
raw_rfc822)``. Los bytes deben ser un mensaje RFC822/MIME completo (cabeceras
|
|
+ cuerpo) ya serializado por el caller.
|
|
|
|
Args:
|
|
conn: objeto ``imaplib.IMAP4_SSL`` (o ``IMAP4``) YA conectado y
|
|
autenticado. APPEND no requiere mailbox seleccionado (el destino es
|
|
``mailbox``).
|
|
raw_rfc822: bytes MIME ya serializados del email. El caller los construye
|
|
con ``email.message.EmailMessage(...).as_bytes()`` (stdlib) o con las
|
|
funciones ``email_build_*_py_infra`` del registry + serializacion.
|
|
Deben ser ``bytes``, no ``str``.
|
|
mailbox: mailbox destino del borrador. Default ``"[Gmail]/Drafts"`` (la
|
|
carpeta de borradores de Gmail, con su prefijo ``[Gmail]/``). En otros
|
|
servidores suele ser ``"Drafts"``.
|
|
flags: banderas IMAP a poner al mensaje, como string entre las que separa
|
|
espacios. Default ``"\\Draft"`` para que el cliente lo trate como
|
|
borrador. Se puede combinar, p.ej. ``"\\Draft \\Seen"``.
|
|
|
|
Returns:
|
|
dict. En exito: ``{"status": "ok", "mailbox": mailbox}``. En fallo (sin
|
|
lanzar): ``{"status": "error", "error": str}``. Tambien error si APPEND
|
|
responde algo distinto de ``OK`` o si ``raw_rfc822`` no son bytes.
|
|
"""
|
|
try:
|
|
if not isinstance(raw_rfc822, (bytes, bytearray)):
|
|
return {
|
|
"status": "error",
|
|
"error": (
|
|
"imap_save_draft: raw_rfc822 debe ser bytes MIME ya "
|
|
"serializados (usa EmailMessage().as_bytes()), no "
|
|
f"{type(raw_rfc822).__name__}"
|
|
),
|
|
}
|
|
date_time = imaplib.Time2Internaldate(time.time())
|
|
typ, data = conn.append(mailbox, flags, date_time, bytes(raw_rfc822))
|
|
if typ != "OK":
|
|
return {
|
|
"status": "error",
|
|
"error": f"imap_save_draft: APPEND a {mailbox!r} devolvio {typ!r}: {data!r}",
|
|
}
|
|
return {"status": "ok", "mailbox": mailbox}
|
|
except Exception as e: # noqa: BLE001
|
|
return {"status": "error", "error": str(e)}
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print("imap_save_draft: importable. Uso real requiere un conn IMAP autenticado.")
|