ff7da29638
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>
49 lines
1.3 KiB
Python
49 lines
1.3 KiB
Python
"""Construccion de EmailMessage Python con cuerpo HTML — funcion pura."""
|
|
|
|
from dataclasses import dataclass, field
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class EmailMessagePy:
|
|
"""Mensaje de email inmutable listo para enviar.
|
|
|
|
Construir con email_build_html() o email_build_text().
|
|
"""
|
|
from_addr: str
|
|
to: tuple[str, ...]
|
|
subject: str
|
|
body_html: str = ""
|
|
body_text: str = ""
|
|
cc: tuple[str, ...] = field(default_factory=tuple)
|
|
bcc: tuple[str, ...] = field(default_factory=tuple)
|
|
headers: tuple[tuple[str, str], ...] = field(default_factory=tuple)
|
|
|
|
|
|
def email_build_html(
|
|
from_addr: str,
|
|
to: list[str],
|
|
subject: str,
|
|
body_html: str,
|
|
) -> EmailMessagePy:
|
|
"""Construye un EmailMessagePy con cuerpo HTML.
|
|
|
|
Funcion pura — no tiene efectos secundarios. El slice `to` se convierte a
|
|
tupla para garantizar inmutabilidad.
|
|
|
|
Args:
|
|
from_addr: Direccion del remitente.
|
|
to: Lista de destinatarios principales.
|
|
subject: Asunto del correo.
|
|
body_html: Contenido HTML del cuerpo del mensaje.
|
|
|
|
Returns:
|
|
EmailMessagePy inmutable con cuerpo HTML. body_text queda vacio.
|
|
"""
|
|
return EmailMessagePy(
|
|
from_addr=from_addr,
|
|
to=tuple(to),
|
|
subject=subject,
|
|
body_html=body_html,
|
|
body_text="",
|
|
)
|