Desarrolladores

Cómo codificar una plantilla de email para recibos con MJML y el lenguaje de plantillas de Mailjet

Codifica una plantilla para recibos por email con MJML y el lenguaje de plantillas con este tutorial paso a paso, con ejemplos y muestras de código.
Imagen paraCómo codificar una plantilla de email para recibos con MJML y el lenguaje de plantillas de Mailjet
octubre 3, 2025

Crear recibos por correo electrónico listos para la producción puede ser todo un reto, especialmente cuando tienes que gestionar múltiples escenarios, como clientes invitados frente a clientes registrados, diferentes métodos de envío, descuentos y compatibilidad con varias divisas. Esta completa guía te mostrará cómo crear una plantilla de email responsive y dinámico utilizando MJML para el diseño y el lenguaje de plantillas de Mailjet para la personalización de emails.

Al final de este tutorial tendrás una plantilla para recibos totalmente funcional que puede gestionar datos de pedidos complejos, adjuntar facturas en PDF y realizar entregas fiables a través de la API de envío v3.1 de Mailjet.

¿Por qué utilizar plantillas con el lenguaje de plantillas?

Antes de sumergirnos en la implementación, entendamos por qué este enfoque es superior a la creación de emails puntuales con HTML:

  • Menos plantillas que mantener: Una plantilla de recibo "smart" puede manejar múltiples escenarios (usuarios invitados frente a registrados, envíos frente a recogidas, descuentos, multidivisa…).
  • Personalización del lado del servidor: Inyecta datos dinámicos utilizando variables {{var:*}} o {{data:*}} y controla el renderizado con condiciones y bucles.
  • Integración más rápida: Almacena la plantilla una vez y actívala con una sola llamada a la API por pedido.

Qué crearás

Tu plantilla final de email para recibos incluirá:

  • Diseño MJML responsive que funciona en todos los clientes de email.
  • Bucles dinámicos de partidas para los detalles del pedido.
  • Cálculos de impuestos, descuentos y totales.
  • Visualización condicional de la información de envío.
  • Texto localizado y formato de moneda.
  • Adjuntos opcionales de facturas en PDF.
  • Entrega fiable a través de la API de envío v3.1 de Mailjet con seguimiento de eventos.

Requisitos previos

Antes de empezar asegúrate de que tienes:

  • Una cuenta de Mailjet con un dominio de remitente validado (configura SPF/DKIM para una entregabilidad óptima).
  • Un flujo de trabajo MJML (CLI o editor) para compilar MJML a HTML.
  • Credenciales de la API de Mailjet (clave y secreta de la API para HTTP Basic Auth).
  • Opcional: Un punto de conexión para webhooks para recibir eventos de entrega (enviados, abiertos, clics, rebotes, etc.).

Paso 1: Estructurar el recibo con MJML

Empecemos por crear la estructura básica de nuestra plantilla de recibos utilizando MJML. Esto garantizará que nuestro email sea responsive y se muestre de forma coherente en diferentes clientes de email.

                            

                                <mjml>
  <mj-head>
    <mj-title>Tu recibo</mj-title>
    <mj-attributes>
      <mj-text font-family="Montserrat, Arial, sans-serif"/>
      <mj-class name="muted" color="#6b7280" font-size="13px"/>
      <mj-class name="total" font-weight="700" font-size="16px"/>
    </mj-attributes>
  </mj-head>
  <mj-body background-color="#f6f7fb">
    <mj-section background-color="#ffffff" padding="24px">
      <mj-column>
        <mj-image width="120px" src="https://yourcdn.com/logo.png" alt="Marca"/>
        <mj-text font-size="20px" font-weight="700">¡Gracias por tu compra!</mj-text>
        <mj-text css-class="muted">
  Pedido {{var:order_id}} • {{var:order_date}} • {{var:currency}}
        </mj-text>

        <!-- Shipping notice (rendered conditionally in Step 2) -->
        <mj-text css-class="muted">
  Enviar a: {{var:shipping.name}}, {{var:shipping.address1}}, {{var:shipping.city}}
        </mj-text>

        <mj-divider border-color="#e5e7eb"/>

        <!-- Line items table (rendered via loop in Step 2) -->
        <mj-table>
          <tr style="text-align:left;">
            <th style="padding:8px 0;">Elemento</th>
            <th style="padding:8px 0;">Cant.</th>
            <th style="padding:8px 0; text-align:right;">Tarifa</th>
          </tr>
          <!-- row loop here -->
        </mj-table>

        <mj-divider border-color="#e5e7eb"/>

        <mj-text>
  Subtotal <span style="float:right;">{{var:money.subtotal}}</span>
        </mj-text>
        <mj-text>
  Impuestos <span style="float:right;">{{var:money.tax}}</span>
        </mj-text>
  {{var:money.discount_row}}  <!-- optional discount row via condition -->
        <mj-text css-class="total">
  Total <span style="float:right;">{{var:money.total}}</span>
        </mj-text>

        <mj-divider border-color="#e5e7eb"/>
        <mj-text css-class="muted">
  Pagado con {{var:payment.brand}} que termina en {{var:payment.last4}}. ¿Necesitas un PDF? Está adjuntado.
        </mj-text>
        <mj-text css-class="muted">
  ¿Alguna pregunta? Responde a este email o visita la página de tu pedido: {{var:order_url}}
        </mj-text>
      </mj-column>
    </mj-section>

    <mj-section>
      <mj-column>
        <mj-text css-class="muted" align="center">
  © {{var:year}} Tu empresa • {{var:support_email}}
        </mj-text>
      </mj-column>
    </mj-section>
  </mj-body>
</mjml>

                            
                        

Notas importantes:

  • Mantén el formato de la moneda en el servidor y pasa cadenas listas para ser procesadas (money.*) para evitar incoherencias de configuración regional.
  • MJML compila en HTML responsive que funciona en los principales clientes de email.

Paso 2: Añadir etiquetas de plantilla de Mailjet

Ahora mejoraremos nuestra plantilla con el lenguaje de plantillas de Mailjet para manejar contenido dinámico. Esto incluye variables, condiciones y bucles que se procesarán cuando se envíe el correo electrónico.

Tipos de variables

El lenguaje de plantillas de Mailjet admite varios tipos de variables:

  • Variables de pedido: {{var:order_id}}, {{var:currency}}, {{var:payment.brand}}
  • Datos de contacto: {{data:firstname:&quot;Cliente&quot;}} (con valores alternativos).
  • Condiciones: {% if var:has_shipping %} … {% endif %}.
  • Bucles: {% for item in var:items %} … {% endfor %}.

Añadir partidas dinámicas

Inserta este código dentro de tu tabla MJML para recorrer en bucle los elementos del pedido:

                            

                                {% for item in var:items %}
<tr>
  <td style="padding:6px 0;">{{item.name}}</td>
  <td style="padding:6px 0;">{{item.qty}}</td>
  <td style="padding:6px 0; text-align:right;">{{item.price}}</td>
</tr>
{% endfor %}

                            
                        

Información de envío condicional

Añade bloques condicionales para mostrar los detalles de envío solo cuando sean relevantes:

                            

                                {% if var:has_shipping %}
<mj-text css-class="muted">
  Enviar a: {{var:shipping.name}}, {{var:shipping.address1}}, {{var:shipping.city}}
</mj-text>
{% endif %}
                            
                        

Paso 3: Guardar el HTML como plantilla reutilizable

Una vez que hayas compilado tu MJML a HTML y añadido etiquetas de plantilla, tienes que guardarlo como plantilla en Mailjet. Tienes dos opciones:

Opción A: Utilizar el panel de control de Mailjet

Paste your compiled HTML into a new template in the Mailjet Email Editor.

Opción B: Utilizar la API de plantillas

Crear una plantilla nueva:

                            

                                curl -s -X POST \
  --user "$MJ_APIKEY_PUBLIC:$MJ_APIKEY_PRIVATE" \
  https://api.mailjet.com/v3/REST/template \
  -H 'Content-Type: application/json' \
  -d '{
  "Name":"Recibo v1",
  "OwnerType":"user",
  "IsTextPartGenerationEnabled":"true",
  "Locale":"es_ES"
  }'

                            
                        

Añade tu contenido HTML a la plantilla:

                            

                                curl -s -X POST \
  --user "$MJ_APIKEY_PUBLIC:$MJ_APIKEY_PRIVATE" \
  https://api.mailjet.com/v3/REST/template/TEMPLATE_ID/detailcontent \
  -H 'Content-Type: application/json' \
  -d '{
  "Html-part":"...tu MJML compilado con etiquetas de plantilla...",
  "Text-part":"Tu texto sin formato como alternativa"
  }'
                            
                        

Paso 4: Enviar el recibo con la API de envíos v3.1

Ahora viene la parte más emocionante: Enviar tu email con tu recibo dinámico. Aquí tienes un ejemplo completo que incluye las variables de la plantilla, el PDF adjunto y la configuración adecuada:

                            

                                curl -s -X POST \
  --user "$MJ_APIKEY_PUBLIC:$MJ_APIKEY_PRIVATE" \
  https://api.mailjet.com/v3.1/send \
  -H 'Content-Type: application/json' \
  -d '{
  "Messages":[
 {
  "From":{"Email":"facturacion@tumarca.com","Name":"Facturación Tu Marca"},
  "To":[{"Email":"cliente@ejemplo.com","Name":"{{data:firstname:\"Cliente\"}}"}],
  "TemplateID": TEMPLATE_ID,
  "TemplateLanguage": true,
  &quot;Subject&quot;: &quot;Tu recibo {{var:order_id}}&quot;,
  "Variables": {
  "order_id": "ORD-98765",
  "order_date": "2025-08-27",
  "currency": "EUR",
  "items": [
  {"name":"Zapatillas","qty":1,"price":"99,00 €"},
  {"name":"Calcetines","qty":2,"price":"10,00 €"}
  ],
  "money":{"subtotal":"98,35 €","tax":"20,65 €","discount":"0,00 €","total":"119,00 €"},
  "has_shipping": true,
  "shipping":{"name":"A. García","dirección1":"Plaza Mercado Chico 5","ciudad":"Ávila"},
  "payment":{"brand":"Visa","last4":"4242"},
  "order_url":"https://tuapp.com/pedidos/ORD-98765",
  "support_email":"asistencia@tumarca.com",
  "year":"2025"
 },
  "Attachments":[
 {
  "ContentType":"application/pdf",
  "Filename":"Factura-ORD-98765.pdf",
  &quot;Base64Content&quot;:&quot;<base64-encoded-pdf>&quot;
 }
  ]
 }
  ]
  }'

                            
                        

Opciones de envío útiles

  • Globales: Evita la repetición en los envíos masivos (From, Subject, headers).
  • Modo Sandbox: Establécelo a true para validar la carga útil sin enviarla.
  • CustomID: Utiliza &quot;order-ORD-98765&quot; para correlacionar eventos.
  • URLTags: Añade &quot;utm_source=recibo&amp;utm_medium=email&quot; para el seguimiento.

URLTags: Añade &quot;utm_source=recibo&amp;utm_medium=email&quot; para el seguimiento.

Paso 5: Verificar la entrega y hacer un seguimiento de los eventos

Supervisar la entrega de tus emails es crucial para mantener la confianza del cliente y depurar los problemas.

Configurar webhooks

Registra tu punto de conexión para tus webhooks y así recibir eventos en tiempo real:

  • Enviados, entregados, abiertos, cliqueados.
  • Rebotados, quejas por spam, bloqueados.
  • Dados de baja.

Comprobar el estado del mensaje

  • Información del mensaje: GET /v3/REST/message/{Message_ID} para metadatos.
  • Cronología de eventos: GET /v3/REST/messagehistory/{Message_ID} para eventos detallados.
  • Estadísticas: Utiliza /v3/REST/statcounters para métricas de entrega agregadas.

Paso 6: Internacionalización y moneda

Para las empresas globales, una localización adecuada es esencial:

  • Formato de moneda: Formatea los importes en el servidor para la configuración regional del destinatario y pasa cadenas listas para procesar en Variables (p. ej, money.total = &quot;$129,90&quot;).
  • Texto alternativo: Utiliza {{data:firstname:&quot;Cliente&quot;}} para las alternativas en función del idioma.
  • Plantillas multilingües: Mantener una plantilla con bloques condicionales ({% if var:locale == &quot;fr&quot; % }…{% endif %}) o crear plantillas separadas por ubicación.

Paso 7: Entregabilidad y conformidad normativa

Asegúrate de que tus recibos llegan a la bandeja de entrada y cumplen la normativa:

Configuración técnica

  • Verifica tu dominio y configura los registros SPF/DKIM.
  • Envía desde tu dominio verificado para obtener la mejor reputación.
  • Mantén las plantillas ligeras con imágenes comprimidas y fuentes externas mínimas.
  • Proporciona siempre una versión en texto plano.

Seguridad y privacidad

  • Nunca incluyas los números completos de la tarjeta de pago: utiliza solo los 4 últimos dígitos y la marca.
  • Protege los archivos PDF adjuntos y minimiza la PII.
  • Respeta las preferencias para darse de baja de cualquier contenido promocional.

Paso 8: Consejos avanzados de producción

Para los equipos que envían a gran escala, considera estas optimizaciones:

Estrategias de fidelidad

  • Utiliza Attachments para los PDF que descarguen los usuarios.
  • Utiliza InlinedAttachments para los logotipos referenciados mediante cid: en HTML.

Organización de la campaña

  • Establece CustomCampaign: «transactional_receipts» para mejorar los informes.
  • Activa DeduplicateCampaign para evitar envíos duplicados en lotes.

Tratamiento de errores y observabilidad

  • Registra los errores de la API de envíos con códigos y campos específicos para depuración.
  • Etiqueta cada envío con CustomID para facilitar la correlación.
  • Incluye EventPayload con metadatos del pedido para la conciliación posterior.

Solución de problemas comunes

A continuación te indicamos algunas cuestiones que debes solucionar si tienes problemas con lo anterior.

Las variables de plantilla no se muestran

  • Asegúrate de que TemplateLanguage: true está establecido en tu llamada a la API de envío.
  • Comprueba que los nombres de las variables de tu plantilla coinciden con los del objeto Variables.

Errores de autenticación

  • «Sender not authorized»/»Remitente no autorizado»: Valida primero tu dominio/dirección del remitente.
  • Comprueba que tus credenciales API son correctas y tienen los permisos adecuados.

Falta contenido

  • «At least HTMLPart, TextPart or TemplateID must be provided»/»Al menos debes proporcionar HTMLPart, TextPart o TemplateID»: Asegúrate de que proporcionas un TemplateID.

Problemas de seguimiento de eventos

  • Confirma que tu punto de conexión de webhook devuelve HTTP 200.
  • Comprueba si hay limitación de velocidad en el punto de conexión de tu webhook.
  • Considera el uso de eventos agrupados para escenarios de gran volumen.

Next steps

¡Ya tienes un sistema de recibos por email completo y listo para la producción! Aquí tienes algunas formas de mejorarlo aún más:

  • Implementa tests A/B para diferentes diseños de recibos.
  • Añade una lógica condicional más sofisticada para distintos tipos de productos.
  • Establece un seguimiento y alerta automatizadas de los problemas de entrega.
  • Explora la API de estadísticas de Mailjet para obtener análisis de rendimiento detallados.

Para obtener recursos adicionales y ejemplos de código, consulta el repositorio de ejemplos de plantillas de Mailjet, que incluye un ejemplo de trabajo completo que puedes utilizar como punto de partida.

Resumen

Esta guía te acompañará a través de la creación de una plantilla de recibo de email profesional utilizando MJML para un diseño adaptable y el lenguaje de plantillas de Mailjet para contenido dinámico. Habrás aprendido a gestionar datos de pedidos complejos, adjuntar facturas en PDF, garantizar una entrega fiable y supervisar el rendimiento; todos ellos componentes esenciales para un sistema de emails de comercio electrónico de producción que se adapte a tu negocio.