Reportia

Actualizado 4 junio 2026 · 15 min de lectura

Cómo enviar facturas PDF por email automáticamente

Generar facturas está bien. Pero el valor real está en generar + enviar automáticamente. En este tutorial construimos un script Python que:

  1. Genera un PDF personalizado por cliente (via API).
  2. Lo adjunta a un email profesional.
  3. Lo envía automáticamente.
  4. Registra el envío en un log CSV.

Todo con código que puedes copiar y ejecutar hoy. Sin frameworks, sin dependencias pesadas.

1 Generar el PDF con la API

Primero, creamos una función que genera el PDF a partir de los datos del cliente:

import requests

REPORTIA_URL = "https://reportia.4l3.org/v1/render"
# API_KEY = "rp_..."  # Solo necesario para plan Pro (sin marca de agua)

def generar_factura_pdf(cliente: dict, items: list) -> bytes:
    """Genera el PDF de la factura y devuelve los bytes."""
    total = sum(item["qty"] * item["price"] for item in items)

    r = requests.post(REPORTIA_URL, json={
        "template": "factura",  # Usa la plantilla built-in de factura
        "data": {
            "empresa": "Mi Empresa S.A. de C.V.",
            "rfc": "MEM250101XYZ",
            "cliente_nombre": cliente["nombre"],
            "cliente_rfc": cliente.get("rfc", "XAXX010101000"),
            "cliente_email": cliente["email"],
            "fecha": "2026-06-04",
            "folio": cliente.get("folio", "F-001"),
            "items": items,
            "subtotal": total,
            "iva": round(total * 0.16, 2),
            "total": round(total * 1.16, 2),
        },
        "format": "pdf",
    })
    r.raise_for_status()
    return r.content

# Ejemplo:
pdf_bytes = generar_factura_pdf(
    cliente={"nombre": "Juan Pérez", "email": "[email protected]", "folio": "F-042"},
    items=[
        {"desc": "Consultoría técnica", "qty": 8, "price": 1500},
        {"desc": "Soporte mensual", "qty": 1, "price": 3000},
    ],
)
print(f"PDF generado: {len(pdf_bytes):,} bytes")

2 Preparar y enviar el email

Ahora creamos la función que envía el email con el PDF adjunto. Usamos smtplib (incluido en Python):

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email import encoders

SMTP_SERVER = "smtp.gmail.com"   # o tu servidor SMTP
SMTP_PORT = 587
SMTP_USER = "[email protected]"
SMTP_PASS = "tu-contrasena-de-app"  # App password de Gmail

def enviar_factura_email(destinatario: str, nombre: str, folio: str, pdf_bytes: bytes):
    """Envía la factura PDF por email."""
    msg = MIMEMultipart()
    msg["From"] = f"Facturación <{SMTP_USER}>"
    msg["To"] = destinatario
    msg["Subject"] = f"Factura {folio} - Mi Empresa"

    cuerpo = f"""Hola {nombre},

Adjuntamos tu factura {folio} correspondiente al periodo actual.

Si tienes alguna duda sobre esta factura, responde este correo.

Saludos,
Mi Empresa S.A. de C.V."""

    msg.attach(MIMEText(cuerpo, "plain"))

    # Adjuntar PDF
    adjunto = MIMEBase("application", "pdf")
    adjunto.set_payload(pdf_bytes)
    encoders.encode_base64(adjunto)
    adjunto.add_header("Content-Disposition", f'attachment; filename="{folio}.pdf"')
    msg.attach(adjunto)

    with smtplib.SMTP(SMTP_SERVER, SMTP_PORT) as server:
        server.starttls()
        server.login(SMTP_USER, SMTP_PASS)
        server.send_message(msg)

    print(f"Factura {folio} enviada a {destinatario}")

3 Automatizar para múltiples clientes

Combinamos ambas funciones para procesar una lista de clientes desde un CSV:

import csv
from datetime import datetime

# Leer clientes desde CSV
with open("clientes.csv") as f:
    clientes = list(csv.DictReader(f))

# clientes.csv debe tener columnas: nombre, email, rfc, folio, concepto, cantidad, precio

log = []

for cliente in clientes:
    items = [{
        "desc": cliente["concepto"],
        "qty": int(cliente["cantidad"]),
        "price": float(cliente["precio"]),
    }]

    try:
        # 1. Generar PDF
        pdf = generar_factura_pdf(cliente, items)

        # 2. Enviar email
        enviar_factura_email(
            destinatario=cliente["email"],
            nombre=cliente["nombre"],
            folio=cliente["folio"],
            pdf_bytes=pdf,
        )

        log.append({
            "fecha": datetime.now().isoformat(),
            "folio": cliente["folio"],
            "email": cliente["email"],
            "status": "enviado",
            "pdf_size": len(pdf),
        })

    except Exception as e:
        log.append({
            "fecha": datetime.now().isoformat(),
            "folio": cliente["folio"],
            "email": cliente["email"],
            "status": f"error: {e}",
            "pdf_size": 0,
        })

# 3. Guardar log
with open("envios_log.csv", "w", newline="") as f:
    w = csv.DictWriter(f, fieldnames=["fecha", "folio", "email", "status", "pdf_size"])
    w.writeheader()
    w.writerows(log)

print(f"Procesados: {len(log)} facturas")

Genera PDFs profesionales gratis

50 PDFs al mes sin registro. Plan Pro desde $9/mes para facturación automática sin marca de agua.

Probar el editor visual →  |  Documentación API →

Alternativa: usar SendGrid o Mailgun

Si envías más de 100 emails/día, considera usar un servicio de email transaccional en vez de SMTP directo:

# Con SendGrid (pip install sendgrid)
import sendgrid
import base64
from sendgrid.helpers.mail import Mail, Attachment, FileContent, FileName, FileType

sg = sendgrid.SendGridAPIClient(api_key="SG.xxx")

message = Mail(
    from_email="[email protected]",
    to_emails=cliente["email"],
    subject=f"Factura {folio}",
    plain_text_content=f"Adjuntamos tu factura {folio}.",
)

attachment = Attachment(
    FileContent(base64.b64encode(pdf_bytes).decode()),
    FileName(f"{folio}.pdf"),
    FileType("application/pdf"),
)
message.attachment = attachment

sg.send(message)

Automatizar con cron (Linux) o Task Scheduler (Windows)

Para ejecutar el script automáticamente cada mes:

# Linux: ejecutar el 1 de cada mes a las 9:00 AM
# crontab -e
0 9 1 * * cd /home/user/facturacion && python3 enviar_facturas.py >> /var/log/facturas.log 2>&1

# Windows Task Scheduler:
# Trigger: Monthly, day 1, 9:00 AM
# Action: python C:\facturacion\enviar_facturas.py

Preguntas frecuentes

¿Puedo enviar facturas masivas?

Sí. El script procesa cada cliente secuencialmente. Con el plan Pro (1,000 PDFs/mes) puedes enviar hasta 1,000 facturas mensuales. Para volúmenes mayores, el plan Scale (10,000/mes) o contacta para enterprise.

¿Gmail tiene límite de envíos?

Sí: 500 emails/día para cuentas personales, 2,000/día para Google Workspace. Para más, usa SendGrid (100/día gratis) o Mailgun.

¿Puedo programar envíos recurrentes?

Sí. Combina el script con cron (Linux) o Task Scheduler (Windows). También puedes usar la integración con Google Sheets para que tu equipo de contabilidad lance los envíos desde una hoja de cálculo.

¿Listo para automatizar?

Empieza gratis. Genera tu primera factura PDF en 30 segundos.

Ver planes y precios →

Artículos relacionados