Dev Life
Creación de flujos de trabajo de emails transaccionales para confirmaciones de pedidos con la API de Mailgun
A diferencia de los emails de marketing, los emails transaccionales (como las confirmaciones de pedidos, las notificaciones de envío y los restablecimientos de la contraseña) son desencadenados por acciones específicas de los usuarios y proporcionan actualizaciones en tiempo real sobre sus interacciones con tu plataforma. Ayudan a generar confianza, reducen las preguntas de asistencia y logran que la experiencia de compra sea fluida.
Las confirmaciones de pedidos son especialmente importantes, ya que permiten a tus clientes saber que su compra se realizó correctamente y proporcionan al usuario un registro con los detalles de la transacción.
En este tutorial, aprenderás a crear un flujo de trabajo de emails transaccionales para confirmaciones de pedidos utilizando la API de Mailgun.
Implementación de flujos de trabajo de emails transaccionales para confirmaciones de pedidos
Antes de comenzar, asegúrate de tener Cuenta de Mailgun y Node.js instalado en tu equipo.
Una vez que tu cuenta esté registrada y activada, haz clic en Empieza gratis y luego en Crear una clave de API para proporcionar una breve descripción de la clave. Una vez generada, copia y guarda la clave de API en un lugar seguro.

Esta clave se utilizará para autenticar tus solicitudes a la API de Mailgun.
Para simplificar las cosas, clona el siguiente repositorio de UI y configura las variables de entorno ejecutando los siguientes comandos de npm:
$ git clone https://github.com/Ikeh-Akinyemi/draftdev-mailgunnerrn$ cd draftdev-mailgunner; npm install rn$ echo -e "MAILGUN_API_KEY=your_api_key_here
MAILGUN_DOMAIN=your_domain_here
PORT=8080" >> .env
Este comando añade las bibliotecas mailgun.js, form-data, cors, dotenv y express para su uso en el servidor backend y crea algunos valores de marcador de posición para la clave de API de Mailgun y el dominio en un archivo .env que actualizarás durante el tutorial.
El dominio de Mailgun te ofrece la opción de configurar tu propio dominio personalizado o utilizar un entorno de pruebas (sandbox) para realizar pruebas. En este tutorial utilizarás un dominio sandbox. Puedes encontrar el dominio sandbox de Mailgun navegando a Envíos > Envíos > Ajustes del dominio en tu panel de control y haciendo clic en el botón Seleccionar en la opción de integración de la API:

Tu dominio sandbox se incluye en las plantillas (boilerplates) proporcionadas para la configuración de Mailgun. Recuerda actualizar el valor de MAILGUN_DOMAIN (actualmente your_domain_here) dentro del archivo .env.

Si deseas configurar un dominio personalizado, sigue las instrucciones detalladas en este tutorial de YouTube.
La interfaz de la aplicación
En este escenario, trabajarás con una sencilla aplicación de carrito de la compra creada con HTML, CSS y JavaScript. La aplicación permite a los usuarios añadir artículos a su carrito, ajustar las cantidades y proceder al pago. Cuando el usuario confirma su compra, la aplicación envía una solicitud al backend para procesar el pedido y enviar un email de confirmación. Para previsualizar la UI, abre el archivo ui/index.html en el navegador o ejecuta el comando de Python python3 -m http.server -d=./ui:

Esta UI está diseñada para ser intuitiva, con el objetivo de proporcionar una experiencia de pago fluida. El backend se encarga del trabajo pesado, incluyendo el procesamiento de pedidos y el envío de emails de confirmación.
Configurar la conexión de Mailgun
Para integrar Mailgun en tu backend, necesitas inicializar el cliente de Mailgun utilizando tu clave de API. A continuación te explicamos cómo configurar la conexión en tu backend de Node.js:
const formData = require('form-data');rnconst Mailgun = require('mailgun.js');rnrnconst mailgun = new Mailgun(formData);rnconst mg = mailgun.client({ username: 'api', key: process.env.MAILGUN_API_KEY });rnconst MAILGUN_DOMAIN = process.env.MAILGUN_DOMAIN;
Este código inicializa el cliente de Mailgun, que se utilizará para enviar emails transaccionales. Asegúrate de actualizar el valor de MAILGUN_API_KEY (actualmente your_api_key_here) dentro de tu archivo .env antes de continuar.
Prueba la conexión enviando una muestra de email de prueba:
mg.messages.create('<your-domain.com>', {rn from: "Excited User <mailgun@your-domain.com>",rn to: ["test@example.com"],rn subject: "Hello",rn text: "Testing some Mailgun awesomeness!"rn})rn.then(msg => console.log(msg)) // logs response datarn.catch(err => console.error(err)); // logs any error
Puedes usar el dominio sandbox proporcionado por Mailgun para las pruebas, pero necesitas añadir al menos un email verificado para realizar pruebas (hasta cinco). Para verificar tu dirección de email de prueba, ve a Envíos > Envíos > Ajustes del dominio en tu panel de control de Mailgun. A continuación, introduce tu dirección de email en el campo de entrada designado y haz clic en Añadir. Mailgun enviará un email de verificación a esta dirección.
Revisa tu bandeja de entrada y haz clic en el enlace de verificación Acepto para completar el proceso y registrarte como destinatario de prueba autorizado:

Diseño de la plantilla de email
Los emails transaccionales a menudo requieren contenido dinámico, como el nombre del usuario, los detalles del pedido y la información de envío, por lo que necesitas crear una plantilla HTML con marcadores de posición para los datos dinámicos. Aquí tienes un ejemplo de una plantilla de confirmación de pedido sencilla:
<!DOCTYPE html>rn<html>rn<head>rn <title>Order Confirmation</title>rn</head>rn<body>rn <h1>Thank you for your order, {{name}}!</h1>rn <p>Your order number is {{orderNumber}}.</p>rn <p>We will ship your items to {{shippingAddress}}.</p>rn</body>rn</html>
Puedes usar un motor de plantillas como Handlebars o EJS para sustituir los marcadores de posición con los datos reales antes de enviar el email. También puedes usar el editor visual intuitivo de Mailgun para crear hermosas plantillas de email adaptativas sin ningún conocimiento de programación.
En este artículo, utilizarás la forma más sencilla de crear plantillas: la interpolación de cadenas mediante los literales de plantilla de JavaScript. Este enfoque te permite configurar una plantilla de email HTML completada con los datos dinámicos necesarios:
function emailTemplate(order) {rn // Format items for emailrn const itemsList = order.items.map(item => {rn return `rn <tr>rn <td style="padding: 10px 0; border-bottom: 1px solid #eee;">rn ${item.name}rn </td>rn <td style="padding: 10px 0; border-bottom: 1px solid #eee; text-align: center;">rn ${item.quantity}rn </td>rn <td style="padding: 10px 0; border-bottom: 1px solid #eee; text-align: right;">rn $${item.price.toFixed(2)}rn </td>rn <td style="padding: 10px 0; border-bottom: 1px solid #eee; text-align: right;">rn $${(item.price * item.quantity).toFixed(2)}rn </td>rn </tr>rn `;rn }).join('');rn};
Este código itera sobre los artículos de un pedido para generar un recibo en forma de tabla del pedido del cliente. El valor devuelto, itemsList, es una cadena literal que se utilizará para construir el resto de la plantilla de email de la siguiente manera:
function emailTemplate(order) {rn ...rnrn // Create email HTML templatern const emailHtml = `rn <!DOCTYPE html>rn <html>rn <head>rn <style>rn body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }rn .container { max-width: 600px; margin: 0 auto; }rn .header { background-color: #f8f9fa; padding: 20px; text-align: center; }rn .content { padding: 20px; }rn .order-details { margin-top: 20px; }rn .order-table { width: 100%; border-collapse: collapse; }rn .order-table th { text-align: left; padding: 10px 0; border-bottom: 2px solid #ddd; }rn .footer { margin-top: 30px; text-align: center; font-size: 14px; color: #777; }rn .total-row { font-weight: bold; }rn </style>rn </head>rn <body>rn <div class="container">rn <div class="header">rn <h2>Order Confirmation</h2>rn <p>Thank you for your purchase!</p>rn </div>rnrn <div class="content">rn <p>Hello ${order.customer.name},</p>rnrn <p>Your order has been confirmed. Here are your order details:</p>rnrn <div class="order-details">rn <p><strong>Order ID:</strong> ${order.id}</p>rn <p><strong>Order Date:</strong> ${new Date(order.createdAt).toLocaleString()}</p>rnrn <table class="order-table">rn <thead>rn <tr>rn <th>Item</th>rn <th style="text-align: center;">Qty</th>rn <th style="text-align: right;">Price</th>rn <th style="text-align: right;">Total</th>rn </tr>rn </thead>rn <tbody>rn ${itemsList}rn <tr>rn <td colspan="3" style="text-align: right; padding-top: 20px;"><strong>Subtotal:</strong></td>rn <td style="text-align: right; padding-top: 20px;"><strong>$${order.subtotal.toFixed(2)}</strong></td>rn </tr>rn <tr>rn <td colspan="3" style="text-align: right;"><strong>Tax:</strong></td>rn <td style="text-align: right;"><strong>$${order.tax.toFixed(2)}</strong></td>rn </tr>rn <tr class="total-row">rn <td colspan="3" style="text-align: right; padding-top: 10px;"><strong>Total:</strong></td>rn <td style="text-align: right; padding-top: 10px;"><strong>$${order.total.toFixed(2)}</strong></td>rn </tr>rn </tbody>rn </table>rn </div>rnrn <div style="margin-top: 30px;">rn <p><strong>Shipping Address:</strong></p>rn <p>rn ${order.shipping.address}<br>rn ${order.shipping.city}, ${order.shipping.state} ${order.shipping.zipCode}rn </p>rn </div>rnrn <div style="margin-top: 30px;">rn <p><strong>Payment Method:</strong> ${order.payment.method} (ending in ${order.payment.last4})</p>rn </div>rnrn <div style="margin-top: 30px;">rn <p>If you have any questions about your order, please contact our customer support.</p>rn <p>Thank you for shopping with us!</p>rn </div>rn </div>rnrn <div class="footer">rn <p>This is an automated email, please do not reply to this message.</p>rn <p>© 2025 Your Company. All rights reserved.</p>rn </div>rn </div>rn </body>rn </html>rn `;rnrn return emailHtml;rn}
Aquí, combinas el recibo con el resto de una cadena de plantilla HTML que contiene los detalles del cliente. El HTML contiene el estilo básico para la plantilla de email.
Obtén más información en nuestra Plantillas para correos transaccionales página, incluida la descarga de plantillas gratuitas.
Implementación de la funcionalidad de envío de emails
Ahora que tu plantilla está lista, es hora de escribir la función que envía el email utilizando la API de Mailgun. A continuación te explicamos cómo puedes implementar esta funcionalidad en tu backend:
async function sendOrderConfirmationEmail(order) {rn try {rnrn let emailHtml = emailTemplate(order)rnrn // Send email via Mailgunrn const response = await mg.messages.create(MAILGUN_DOMAIN, {rn from: `Your Store <orders@${MAILGUN_DOMAIN}>`,rn to: order.customer.email,rn subject: `Order Confirmation #${order.id}`,rn html: emailHtml,rn 'o:tag': ['order-confirmation'],rn 'o:tracking': truern });rnrn console.log('Email sent successfully:', response);rn return response;rnrn } catch (error) {rn console.error('Error sending confirmation email:', error);rn throw error;rn }rn}
Esta función toma un objeto de pedido, construye el contenido del email y lo envía utilizando la API de Mailgun. Las opciones o:tag y o:tracking te permiten seguir la entrega y la interacción del email.
Ahora, probemos la implementación con un simple objeto de pedido para ver si funciona:
const testOrder = {rn id: "TEST123",rn customer: {rn name: "Test User",rn email: "your-verified-email@example.com" // Use one of your verified emails for testingrn },rn items: [rn { name: "Test Product", quantity: 1, price: 29.99 }rn ],rn subtotal: 29.99,rn tax: 2.99,rn total: 32.98,rn shipping: {rn address: "123 Test Street",rn city: "Test City",rn state: "TS",rn zipCode: "12345"rn },rn payment: {rn method: "Credit Card",rn last4: "4242"rn },rn createdAt: new Date()rn};rnrnsendOrderConfirmationEmail(testOrder)rn .then(response => {rn console.log('Test email sent successfully!');rn console.log('Message ID:', response.id);rn console.log('Message status:', response.status);rn })rn .catch(error => {rn console.error('Failed to send test email:', error.message);rn });
Ejecuta este código con node ./src/server.js y revisa tu bandeja de entrada (recuerda usar un email verificado para el valor testOrder.customer.email si estás usando el dominio sandbox de Mailgun). Deberías recibir un email de confirmación de pedido básico con los datos de prueba:

En esta configuración, cualquier error que ocurra se traslada al que realiza la llamada, y el método .catch lo registra en la salida estándar. Este enfoque te permite identificar y solucionar rápidamente cualquier problema que pueda ocurrir durante el proceso de envío de emails.
En la siguiente sección, conectarás esto a tu frontend para poder enviar datos de pedidos reales desde los pagos de los clientes.
Integración con eventos de aplicaciones
Para asegurarte de que el flujo de trabajo de emails se desencadene automáticamente cuando se confirma un pedido, necesitas configurar un agente de escucha de eventos o ruta en tu aplicación.
Aquí, configurarás una aplicación de Express.js y definirás una ruta que maneje las confirmaciones de pedidos mientras llama a la función sendOrderConfirmationEmail:
const express = require('express');rnconst cors = require('cors');rn...rnrn// Load environment variablesrnrequire('dotenv').config();rnrn// Initialize Expressrnconst app = express();rnconst PORT = process.env.PORT || 3000;rnrn// Middlewarernapp.use(cors());rnapp.use(express.json());rnrnconst orders = [];rnrnapp.post('/api/orders', async (req, res) => {rn try {rn // Validate required fieldsrn if (!req.body.items || !req.body.customer || !req.body.customer.email) {rn return res.status(400).json({ rn success: false, rn error: 'Missing required order information' rn });rn }rnrn // Generate order IDrn const orderId = Date.now().toString(36) + Math.random().toString(36).substr(2, 5).toUpperCase();rnrn // Create order objectrn const order = {rn id: orderId,rn ...req.body,rn status: 'confirmed',rn createdAt: new Date()rn };rnrn // Save order (to database in a real app)rn orders.push(order);rnrn // Send confirmation emailrn await sendOrderConfirmationEmail(order);rnrn // Return success responsern res.status(201).json({rn success: true,rn order: {rn id: order.id,rn status: order.status,rn createdAt: order.createdAtrn },rn message: 'Order created successfully and confirmation email sent.'rn });rnrn } catch (error) {rn console.error('Error processing order:', error);rn res.status(500).json({rn success: false,rn error: 'Failed to process order'rn });rn }rn});
La ruta /api/orders maneja las solicitudes de pedidos entrantes, crea un objeto de pedido (order) y envía un email de confirmación utilizando la función sendOrderConfirmationEmail. El resto de la ruta incluye una sencilla lógica de informes de errores, pero en producción, es posible que desees implementar un mecanismo de reintento o un manejador de errores más robusto.
Probar el flujo de trabajo
Para probar la configuración hasta el momento, necesitas modificar el archivo /ui/index.html. Primero, encuentra la línea de código donde se define el objeto orderData y actualiza la propiedad del email del cliente (orderData.customer.email) para usar uno de tus emails verificados. También necesitas actualizar la constante api para que apunte a la URL de tu servidor.
A continuación, abre el archivo /ui/index.html en un navegador y desencadena el proceso de pago seleccionando artículos para su compra y haciendo clic en el botón Checkout Selected Items. Esto debería abrir un diálogo de confirmación donde puedes hacer clic en Confirm Purchase para completar el proceso de pago:

Revisa tu buzón de entrada y verifica que el email se haya enviado y mostrado correctamente con el contenido dinámico. Si usaste el dominio sandbox, es posible que necesites revisar tu carpeta de spam:

Recuerda probar cómo tu aplicación maneja los errores, como direcciones de correo electrónico inválidas o caídas de la API, usando intencionadamente valores incorrectos y verificando que tu manejo de errores funciona según lo esperado.
Todo el código utilizado en este tutorial está disponible en GitHub.
Seguimiento y gestión de emails
Mailgun proporciona métricas detalladas y funcionalidades de seguimiento que te permiten monitorizar el rendimiento de tus emails transaccionales. Puedes seguir las tasas de entrega y las tasas de aperturas además de gestionar rebotes o fallos directamente desde el panel de control de Mailgun.
Para acceder a los logs de cada email enviado, navega a la sección Envíos > Panel de informes > Logs en tu cuenta de Mailgun. Aquí, puedes ver la marca de tiempo y el estado de cada email enviado, incluyendo si fue entregado, abierto o rechazado:

Puedes hacer clic en cualquier entrada de log para ver todos sus detalles, como geolocation para emails abiertos, delivery-status para emails entregados, y otros:

También puedes ir a Envíos > Panel de informes > Métricas para ver un desglose gráfico de métricas clave de email, incluido el recuento de enviados, entregados, fallidos y abiertos:

En resumen
Acabas de crear un flujo de trabajo de confirmación de pedido operativo con la API de Mailgun.
Los emails transaccionales como estos mantienen a los clientes informados justo después del pago, reduciendo las incidencias de asistencia y mejorando la confianza sin gastos generales adicionales. Las confirmaciones de pedidos no son los únicos flujos de trabajo que importan a los consumidores. Echa un vistazo a nuestro tutorial sobre restablecer contraseñas para seguir optimizando tus emails transaccionales.