</>inexpresivo

Cómo usar plantillas en Amazon SES con Python

Cómo crear, actualizar, listar y eliminar plantillas de correo en Amazon SES con boto3, y cómo enviar correos personalizados usando esas plantillas.

3 min read
awssespythonboto3email

Las plantillas de SES permiten definir el HTML y texto de un correo una sola vez y reutilizarlo con variables dinámicas. Este tutorial asume que ya tienes SES configurado y las credenciales listas.

Las operaciones disponibles con el SDK son:

  • Crear una plantilla
  • Listar todas las plantillas
  • Obtener una plantilla
  • Actualizar una plantilla
  • Eliminar una plantilla
  • Enviar un correo usando la plantilla

Setup

import json
import boto3
from botocore.exceptions import ClientError
 
client = boto3.client("ses", region_name="us-east-1")
python

Crear una plantilla

Las plantillas usan {{variable}} como marcadores de posición que se reemplazan al enviar.

def create_template(name: str) -> None:
    client.create_template(
        Template={
            "TemplateName": name,
            "SubjectPart": "Bienvenido, {{nombre}}!",
            "TextPart": (
                "Hola {{nombre}},\n\n"
                "Gracias por registrarte en {{sitio}}.\n\n"
                "Tu usuario es: {{usuario}}"
            ),
            "HtmlPart": """
                <html>
                  <body>
                    <h1>Bienvenido, {{nombre}}!</h1>
                    <p>Gracias por registrarte en <strong>{{sitio}}</strong>.</p>
                    <p>Tu usuario es: <code>{{usuario}}</code></p>
                  </body>
                </html>
            """,
        }
    )
    print(f"Plantilla '{name}' creada.")
 
 
create_template("bienvenida")
python

Listar plantillas

def list_templates() -> list[str]:
    response = client.list_templates(MaxItems=100)
    names = [t["Name"] for t in response["TemplatesMetadata"]]
    print("Plantillas:", names)
    return names
 
 
list_templates()
python

Obtener una plantilla

def get_template(name: str) -> dict:
    response = client.get_template(TemplateName=name)
    template = response["Template"]
    print(f"Nombre: {template['TemplateName']}")
    print(f"Asunto: {template['SubjectPart']}")
    return template
 
 
get_template("bienvenida")
python

Actualizar una plantilla

def update_template(name: str) -> None:
    client.update_template(
        Template={
            "TemplateName": name,
            "SubjectPart": "Hola de nuevo, {{nombre}}!",
            "TextPart": "Hola {{nombre}}, actualizamos el contenido.",
            "HtmlPart": "<h1>Hola {{nombre}}!</h1><p>Contenido actualizado.</p>",
        }
    )
    print(f"Plantilla '{name}' actualizada.")
 
 
update_template("bienvenida")
python

Eliminar una plantilla

def delete_template(name: str) -> None:
    client.delete_template(TemplateName=name)
    print(f"Plantilla '{name}' eliminada.")
 
 
delete_template("bienvenida")
python

Enviar correo usando la plantilla

send_templated_email acepta un TemplateData en formato JSON con los valores para cada variable:

def send_templated_email(
    sender: str,
    recipient: str,
    template_name: str,
    template_data: dict,
) -> str:
    try:
        response = client.send_templated_email(
            Source=sender,
            Destination={
                "ToAddresses": [recipient],
            },
            Template=template_name,
            TemplateData=json.dumps(template_data),
        )
    except ClientError as e:
        print(f"Error: {e.response['Error']['Message']}")
        raise
 
    return response["MessageId"]
 
 
message_id = send_templated_email(
    sender="remitente@tudominio.com",
    recipient="usuario@ejemplo.com",
    template_name="bienvenida",
    template_data={
        "nombre": "Pedro",
        "sitio": "inexpresivo.dev",
        "usuario": "pedro@dev",
    },
)
print(f"Correo enviado. MessageId: {message_id}")
python

Envío en bulk

Para enviar la misma plantilla a múltiples destinatarios con datos distintos se usa send_bulk_templated_email:

def send_bulk_templated_email(
    sender: str,
    template_name: str,
    destinations: list[dict],
) -> None:
    """
    destinations: lista de dicts con 'email' y 'data' (variables de plantilla)
    """
    bulk_destinations = [
        {
            "Destination": {"ToAddresses": [d["email"]]},
            "ReplacementTemplateData": json.dumps(d["data"]),
        }
        for d in destinations
    ]
 
    response = client.send_bulk_templated_email(
        Source=sender,
        Template=template_name,
        DefaultTemplateData=json.dumps({"nombre": "Usuario", "sitio": "inexpresivo.dev", "usuario": ""}),
        Destinations=bulk_destinations,
    )
 
    for status in response["Status"]:
        if status.get("Error"):
            print(f"Error en envío: {status['Error']}")
        else:
            print(f"Enviado: {status['MessageId']}")
 
 
send_bulk_templated_email(
    sender="remitente@tudominio.com",
    template_name="bienvenida",
    destinations=[
        {"email": "a@ejemplo.com", "data": {"nombre": "Ana", "sitio": "inexpresivo.dev", "usuario": "ana"}},
        {"email": "b@ejemplo.com", "data": {"nombre": "Luis", "sitio": "inexpresivo.dev", "usuario": "luis"}},
    ],
)
python

Referencias