---
name: smtp_send
kind: function
lang: py
domain: infra
version: "1.0.0"
purity: impure
signature: "smtp_send(cfg: SMTPConfigPy, from_addr: str, to: list[str], subject: str, body_html: str = '', body_text: str = '', cc: list[str] | None = None, bcc: list[str] | None = None, attachments: list[EmailAttachmentPy] | None = None, headers: dict[str, str] | None = None) -> None"
description: "Conecta al servidor SMTP, construye el mensaje MIME y envia el email en un solo paso. Soporta TLS directo (port 465), STARTTLS (port 587) y sin cifrado (port 25). Cierra la conexion automaticamente."
tags: [email, smtp, send, python, smtplib, mime, tls]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: ["smtplib", "email.mime.multipart", "email.mime.text", "email.mime.base", "email.encoders", "dataclasses"]
params:
  - name: cfg
    desc: "configuracion SMTP: host, port, username, password, tls_mode ('tls', 'starttls' o '')"
  - name: from_addr
    desc: "direccion del remitente"
  - name: to
    desc: "lista de destinatarios principales"
  - name: subject
    desc: "asunto del correo"
  - name: body_html
    desc: "cuerpo HTML (opcional; puede estar vacio si body_text esta presente)"
  - name: body_text
    desc: "cuerpo de texto plano (opcional; puede estar vacio si body_html esta presente)"
  - name: cc
    desc: "lista de destinatarios en copia visible (opcional)"
  - name: bcc
    desc: "lista de destinatarios en copia oculta (opcional)"
  - name: attachments
    desc: "lista de EmailAttachmentPy con filename, content_type y data binarios (opcional)"
  - name: headers
    desc: "diccionario de headers MIME adicionales como X-Mailer (opcional)"
output: "None si el envio fue exitoso; lanza RuntimeError con descripcion del fallo SMTP"
tested: true
tests:
  - "envia texto plano via mock smtpd"
  - "envia html via mock smtpd"
  - "envia con adjunto via mock smtpd"
  - "error si host no existe"
test_file_path: "python/functions/infra/smtp_send_test.py"
file_path: "python/functions/infra/smtp_send.py"
---

## Ejemplo

```python
from infra.smtp_send import smtp_send, SMTPConfigPy, EmailAttachmentPy

cfg = SMTPConfigPy(host="smtp.gmail.com", port=587, username="u@gmail.com", password="app-pw")
smtp_send(
    cfg,
    from_addr="u@gmail.com",
    to=["dest@example.com"],
    subject="Reporte",
    body_html="<h1>Hola</h1>",
    body_text="Hola",
)
```

## Notas

Funcion impura — abre conexion TCP real. Usa solo stdlib Python (smtplib, email). Para TLS directo (port 465) usa `SMTP_SSL`; para STARTTLS (port 587) usa `SMTP` + `starttls()`. Los adjuntos se codifican en base64. BCC se incluye en `sendmail` pero no en las cabeceras MIME visibles.
