feat: funciones email SMTP en Python (infra)

smtp_send: conecta+envia+cierra en un paso via smtplib (TLS/STARTTLS/plain).
email_build_html: construye EmailMessagePy frozen dataclass con cuerpo HTML.
Solo stdlib Python: smtplib, email.mime. Tests con mock SMTP server threading.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-13 02:03:12 +02:00
parent 6019f2aafa
commit be081c68f2
6 changed files with 531 additions and 0 deletions
@@ -0,0 +1,54 @@
---
name: email_build_html
kind: function
lang: py
domain: infra
version: "1.0.0"
purity: pure
signature: "email_build_html(from_addr: str, to: list[str], subject: str, body_html: str) -> EmailMessagePy"
description: "Construye un EmailMessagePy inmutable con cuerpo HTML. El campo body_text queda vacio. Funcion pura sin efectos secundarios."
tags: [email, html, builder, pure, python, dataclass]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: ["dataclasses"]
params:
- name: from_addr
desc: "direccion del remitente (ej: 'alice@example.com')"
- name: to
desc: "lista de direcciones de destinatarios principales"
- name: subject
desc: "asunto del correo"
- name: body_html
desc: "contenido HTML del cuerpo del mensaje"
output: "EmailMessagePy inmutable con from_addr, to (como tupla), subject y body_html; body_text vacio"
tested: true
tests:
- "construye mensaje html con campos correctos"
- "convierte lista to a tupla inmutable"
- "body_text queda vacio"
test_file_path: "python/functions/infra/email_build_html_test.py"
file_path: "python/functions/infra/email_build_html.py"
---
## Ejemplo
```python
from infra.email_build_html import email_build_html
msg = email_build_html(
from_addr="alice@example.com",
to=["bob@example.com", "carol@example.com"],
subject="Reporte mensual",
body_html="<h1>Hola</h1><p>Ver adjunto.</p>",
)
assert msg.body_html == "<h1>Hola</h1><p>Ver adjunto.</p>"
assert msg.body_text == ""
assert isinstance(msg.to, tuple)
```
## Notas
Funcion pura. `EmailMessagePy` es un dataclass frozen — inmutable por construccion. La lista `to` se convierte a tupla para evitar mutacion externa. Para usar con smtp_send, pasar los campos del mensaje como argumentos individuales.