Dev Life
Criando fluxos de trabalho de e-mail transacional para confirmações de pedidos com a API do Mailgun
Ao contrário dos e-mails de marketing, os e-mails transacionais (como confirmações de pedidos, notificações de envio e redefinições de senha) são acionados por ações específicas do usuário e fornecem atualizações em tempo real sobre as interações deles com sua plataforma. Eles ajudam a criar confiança, reduzir as perguntas de suporte e proporcionar uma experiência de compra tranquila.
As confirmações de pedidos são particularmente importantes, pois informam aos seus clientes que a compra foi bem-sucedida e fornecem ao usuário um registro dos detalhes da transação.
Neste tutorial, você aprenderá como criar um fluxo de trabalho de e-mail transacional para confirmações de pedidos usando a API do Mailgun.
Implementando fluxos de trabalho de e-mail transacional para confirmações de pedidos
Antes de começar, certifique-se de ter o conta do Mailgun e Node.js instalado em sua máquina.
Assim que sua conta estiver registrada e ativada, clique em Get started e depois em Create an API Key para fornecer uma breve descrição da chave de API. Depois de gerada, copie e salve a chave de API em um local seguro.

Essa chave será usada para autenticar suas solicitações para a API do Mailgun.
Para simplificar as coisas, clone o seguinte repositório de interface de usuário (UI) e configure as variáveis de ambiente executando os seguintes comandos do 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 adiciona as bibliotecas mailgun.js, form-data, cors, dotenv e express para uso no servidor backend e cria alguns valores de espaço reservado para a chave de API e o domínio do Mailgun em um arquivo .env que você atualizará durante o tutorial.
O domínio do Mailgun oferece a opção de configurar seu próprio domínio personalizado ou usar um sandbox para fins de teste. Você usará um domínio sandbox neste tutorial. Você pode encontrar o domínio sandbox do Mailgun navegando até Send > Sending > Domain settings em seu painel e clicando no botão Select na opção de integração da API:

Seu domínio sandbox está incluído nos modelos fornecidos para a configuração do Mailgun. Lembre-se de atualizar o valor de MAILGUN_DOMAIN (atualmente your_domain_here) dentro do arquivo .env.

Se você deseja configurar um domínio personalizado, siga as instruções detalhadas n este tutorial do YouTube.
A interface do aplicativo
Neste cenário, você trabalhará com um aplicativo simples de carrinho de compras criado com HTML, CSS e JavaScript. O aplicativo permite que os usuários adicionem itens ao carrinho, ajustem as quantidades e prossigam para o checkout. Quando o usuário confirma sua compra, o aplicativo envia uma solicitação ao backend para processar o pedido e enviar um e-mail de confirmação. Para pré-visualizar a UI, abra o arquivo ui/index.html no navegador ou execute o comando Python python3 -m http.server -d=./ui:

Esta interface de usuário foi projetada para ser intuitiva, com foco em fornecer uma experiência de checkout perfeita. O backend lida com o trabalho pesado, incluindo o processamento de pedidos e o envio de e-mails de confirmação.
Configurando a conexão do Mailgun
Para integrar o Mailgun ao seu backend, você precisa inicializar o cliente do Mailgun usando sua chave de API. Veja como configurar a conexão em seu backend 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 o cliente do Mailgun, que será usado para enviar e-mails transacionais. Certifique-se de atualizar o valor de MAILGUN_API_KEY (atualmente your_api_key_here) dentro do seu arquivo .env antes de continuar.
Teste a conexão enviando um e-mail de teste de amostra:
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
Você pode usar o domínio sandbox fornecido pelo Mailgun para teste, mas precisa adicionar pelo menos um e-mail verificado para teste (até cinco). Para verificar seu endereço de e-mail de teste, acesse Send > Sending > Domain settings no painel do Mailgun. Em seguida, insira seu endereço de e-mail no campo de entrada designado e clique em Add. O Mailgun enviará um e-mail de verificação para este endereço.
Verifique sua caixa de entrada e clique no link de verificação I Agree para concluir o processo e registrar-se como um destinatário de teste autorizado:

Projetando o modelo de e-mail
Os e-mails transacionais costumam exigir um conteúdo dinâmico, como o nome do usuário, detalhes do pedido e informações de envio. É por isso que você precisa criar um modelo em HTML com espaços reservados para os dados dinâmicos. Aqui está um exemplo de um modelo simples de confirmação de pedido:
<!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>
Você pode usar um mecanismo de modelo como o Handlebars ou EJS para substituir os espaços reservados por dados reais antes de enviar o e-mail. Você também pode usar o construtor visual intuitivo do Mailgun para criar modelos de e-mail bonitos e responsivos sem nenhum conhecimento de coding.
Neste artigo, você usará a forma mais simples de criação de modelos: a interpolação de strings usando literais de modelo do JavaScript. Esta abordagem permite configurar um modelo de e-mail em HTML preenchido com os dados dinâmicos necessários:
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 os itens de um pedido para gerar um recibo em forma de tabela do pedido do cliente. O valor retornado, itemsList, é um literal de string que será usado para construir o restante do modelo de e-mail da seguinte forma:
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}
Aqui, você combina o recibo com o restante de uma string de modelo em HTML contendo os detalhes do cliente. O HTML contém um estilo básico para o modelo de e-mail.
Saiba mais em nossa modelos de e-mail transacional página, incluindo o download de modelos gratuitos.
Implementando a funcionalidade de envio de e-mail
Agora que seu modelo está pronto, é hora de escrever a função que envia o e-mail usando a API do Mailgun. Veja como você pode implementar essa funcionalidade em seu 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 função recebe um objeto de pedido, constrói o conteúdo do e-mail e o envia usando a API do Mailgun. As opções o:tag e o:tracking permitem rastrear a entrega e o engajamento do e-mail.
Agora, vamos testar a implementação com um objeto de pedido simples para ver se 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 });
Execute este código com o node ./src/server.js e verifique sua caixa de entrada (lembre-se de usar um e-mail verificado para o valor de testOrder.customer.email se você estiver usando o domínio sandbox do Mailgun). Você deve receber um e-mail de confirmação de pedido básico com os dados de teste:

Nessa configuração, qualquer erro que ocorra é repassado ao chamador, e o método .catch o registra na saída padrão. Essa abordagem permite identificar e solucionar rapidamente quaisquer problemas que possam ocorrer durante o processo de envio de e-mail.
Na próxima seção, você conectará isso ao seu frontend para poder enviar dados reais de pedidos dos checkouts do cliente.
Integrando com eventos do aplicativo
Para garantir que o fluxo de trabalho de e-mail seja acionado automaticamente quando um pedido for confirmado, você precisa configurar um ouvinte de eventos ou rota em seu aplicativo.
Aqui, você vai configurar um aplicativo Express.js e definir uma rota que lida com as confirmações de pedidos enquanto chama a função 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});
A rota /api/orders lida com as solicitações de pedidos recebidas, cria um objeto order e envia um e-mail de confirmação usando a função sendOrderConfirmationEmail. O restante da rota inclui uma lógica simples de relatório de erros, mas em produção, talvez você queira implementar um mecanismo de repetição ou um tratador de erros mais robusto.
Testando o fluxo de trabalho
Para testar a configuração até agora, você precisa modificar o arquivo /ui/index.html. Primeiro, encontre a linha de código onde o objeto orderData está definido e atualize a propriedade de e-mail do cliente (orderData.customer.email) para usar um de seus e-mails verificados. Você também precisa atualizar a constante api para apontar para a URL do seu servidor.
Em seguida, abra o arquivo /ui/index.html em um navegador e acione o processo de checkout selecionando itens para checkout e clicando no botão Checkout Selected Items. Isso deve abrir uma caixa de diálogo de confirmação onde você pode clicar em Confirm Purchase para concluir o processo de checkout:

Verifique a caixa de entrada do seu e-mail e verifique se o e-mail foi enviado e renderizado corretamente com o conteúdo dinâmico. Se você usou o domínio sandbox, pode ser necessário verificar sua pasta de spam:

Lembre-se de testar como seu aplicativo lida com erros, como endereços de e-mail inválidos ou tempos de inatividade da API, usando intencionalmente valores incorretos e verificando se o tratamento de erros funciona conforme o esperado.
Todo o código usado neste tutorial está disponível no GitHub.
Monitorando e gerenciando e-mails
O Mailgun fornece métricas detalhadas e recursos de rastreamento que permitem monitorar o desempenho de seus e-mails transacionais. Você pode rastrear as taxas de entrega e as taxas de abertura, além de lidar com devoluções ou falhas diretamente no painel do Mailgun.
Para acessar os registros de cada e-mail enviado, navegue até a seção Send > Reporting > Logs na sua conta do Mailgun. Aqui, você pode ver o carimbo de data/hora e o status de cada e-mail enviado, incluindo se ele foi entregue, aberto ou rejeitado:

Você pode clicar em qualquer entrada de registro para visualizar seus detalhes completos, como geolocation para e-mails abertos, delivery-status para e-mails entregues e outros:

Você também pode acessar Send > Reporting > Metrics para visualizar um detalhamento gráfico das principais métricas de e-mail, incluindo a contagem de envios, entregas, falhas e aberturas:

Conclusão
Você acabou de criar um fluxo de trabalho funcional de confirmação de pedidos com a API do Mailgun.
E-mails transacionais como esses mantêm os clientes informados logo após o checkout, reduzindo os tickets de suporte e melhorando a confiança sem sobrecarga extra. As confirmações de pedidos não são os únicos fluxos de trabalho que importam para os consumidores. Confira nosso tutorial sobre redefinições de senha para continuar otimizando seus e-mails transacionais.