Dev Life

Criando fluxos de trabalho de e-mail transacional para notificações de envio com a API do Mailgun

Os clientes esperam atualizações em tempo real assim que o pedido é movimentado. Este guia mostra como criar um fluxo de trabalho de e-mail transacional confiável para notificações de envio usando a API do Mailgun e o BullMQ, para que seus e-mails cheguem à caixa de entrada exatamente quando deveriam.
Imagem para Criando fluxos de trabalho de e-mail transacional para notificações de envio com a API do Mailgun

Quando você faz um pedido on-line, espera saber exatamente onde ele está e quando chegará. Os fluxos de trabalho de e-mail transacional ajudam a tornar possível esse tipo de comunicação oportuna.

Diferente dos e-mails de marketing que promovem produtos, os e-mails transacionais são enviados em resposta a uma ação do usuário, como fazer um pedido ou receber uma atualização de envio. Eles fornecem detalhes em tempo real que mantêm os usuários informados em cada etapa do caminho.

Neste artigo, você aprenderá a criar um fluxo de trabalho de e-mail transacional para notificações de envio usando a API do Mailgun. O fluxo de trabalho incorporará o BullMQ, um poderoso sistema de fila de tarefas, para enfileirar e processar notificações de e-mail separadamente da lógica principal do aplicativo e melhorar a escalabilidade e o desempenho. Isso é útil para aplicativos de alto tráfego, onde o envio de e-mails diretamente em um ciclo de solicitação-resposta poderia desacelerar o sistema.

Implementando fluxos de trabalho de e-mail transacional para notificações de envio com a API do Mailgun

Para acompanhar, você precisa destas ferramentas e contas:

Antes de mergulhar na implementação, vamos dar uma olhada no fluxo de trabalho:

transactional email workflows diagram

Veja como o processo funciona:

  • A equipe de envio (ou qualquer pessoa responsável por gerenciar atualizações de envio) envia uma solicitação HTTP para atualizar o status do pedido
  • O servidor Express atualiza o status do pedido no banco de dados SQLite e coloca uma tarefa em fila no BullMQ
  • Um worker do BullMQ processa tarefas da fila e interage com a API do Mailgun para enviar um e-mail ao cliente
  • O worker tenta executar automaticamente as tarefas que falharam
  • O Mailgun entrega o e-mail ao cliente

Configuração da conta do Mailgun

Para usar a API do Mailgun, você precisa de um domínio do Mailgun e de uma chave de API para autenticação. O Mailgun fornece dois tipos de domínios: domínios de sandbox para testes e domínios personalizados para uso em ambientes de produção.

Neste guia, você usará um domínio de sandbox. Cada conta do Mailgun é provisionada automaticamente com um, portanto você não precisa criá-lo manualmente. Para obter seu domínio de sandbox, faça login na sua conta do Mailgun, depois acesse Send > Sending > Domains na barra lateral. Copie seu domínio:

Send > Sending > Domains Screen Image

Por padrão, um domínio de sandbox só pode enviar e-mails para destinatários autorizados. Para configurar um e-mail como um destinatário autorizado, clique no nome do seu domínio na página Domains para ver suas configurações. Na aba “Setup”, em “Add authorized recipients”, adicione o endereço de e-mail para o qual você deseja enviar e-mails. Certifique-se de seguir as instruções enviadas para o endereço de e-mail fornecido para configurá-lo como um destinatário autorizado:

Add authorized recipients Screen Image

Para obter sua chave de API, acesse a página “API Keys e clique em “Add new key” para criar uma nova chave de API. Dê um nome para a chave e clique em “Create Key”. Em seguida, certifique-se de copiar o valor da sua chave, pois ele será exibido apenas uma vez:

API Keys page Screen Image

Configuração do modelo inicial

Para manter este tutorial focado na criação de fluxos de trabalho de e-mail transacional, preparamos um modelo inicial para você usar como base. Clone o modelo para a sua máquina local executando o seguinte comando no seu terminal:

git clone --single-branch -b starter-template https://github.com/kimanikevin254/mailgun-transactional-email-workflows.git

Aqui estão os principais arquivos do projeto:

  • src/controllers/order.controller.ts contém dois métodos:
    • index renderiza a interface de administração, que é definida em src/views/admin.ejs
    • updateOrderStatus atualiza o status do pedido no banco de dados
  • src/database/entity/order.entity.ts define a entidade de pedido
  • src/database/entity/user.entity.ts define a entidade de usuário
  • src/database/seed.ts popula o banco de dados com um usuário e um pedido de exemplo
  • docker-compose.yml roda Redis no Docker, o que é exigido pelo BullMQ

Instale todas as dependências usando o seguinte comando:

npm install

Em seguida, renomeie o arquivo .env.example para .env e substitua os valores de placeholder para MAILGUN_DOMAIN e MAILGUN_API_KEY pelas credenciais que você obteve no painel do Mailgun. Para a variável MAIL_FROM, forneça seu endereço de e-mail como valor.

Em seguida, abra o arquivo src/database/seed.ts e substitua os detalhes de placeholder na constante userInfo pelos seus próprios dados. Para o e-mail, certifique-se de fornecer um que você adicionou como destinatário autorizado.

Por fim, popule o banco de dados executando o comando npm run db:seed no seu terminal. Agora você pode rodar o projeto usando o comando npm run dev e acessar a página http://localhost:3000 no seu navegador para visualizar e atualizar o status do pedido:

order status management screen image

Na próxima seção, você implementará um fluxo de trabalho que envia automaticamente um e-mail para o usuário assim que o status do pedido for atualizado.

Design dos modelos de e-mail

Modelos de e-mail bem projetados melhoram a legibilidade, aprimoram a experiência do usuário e garantem que seus e-mails pareçam profissionais em diferentes dispositivos. Nesta seção, você criará modelos que tornam seus e-mails transacionais claros, envolventes e eficazes.

Um pedido passa por três estados (enviado, saiu para entrega e entregue), conforme definido no tipo OrderStatus em src/types/index.ts. Você criará um modelo de e-mail correspondente para cada estado, a fim de manter a clientela informada em cada etapa.

Para isso, crie um arquivo em src/email-templates/html/shipped.html e adicione o seguinte código:

                                

                                    <!DOCTYPE html>rn<html>rn<head>rn    <meta charset="UTF-8" />rn    <title>Order Shipped</title>rn</head>rn<body style="font-family: Arial, sans-serif; background-color: #f4f4f4; padding: 20px; text-align: center;">rnrn    <div style="background: #ffffff; padding: 20px; border-radius: 8px; max-width: 600px; margin: auto; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);">rnrn        <div style="background-color: #007bff; color: white; padding: 15px; font-size: 22px; font-weight: bold; border-top-left-radius: 8px; border-top-right-radius: 8px;">rn            Your Order Has Been Shipped! ✈️rn        </div>rnrn        <div style="padding: 20px; font-size: 16px; color: #333; text-align: left;">rn            <p style="margin: 0 0 10px;">Hello, <%= name %></p>rn            <p style="margin: 0 0 10px;">Your order has been shipped and is on its way to you. 📦</p>rn            <p style="margin: 0 0 10px;"><strong>Tracking Number:</strong> <%= trackingNumber %></p>rn            <p style="margin: 0 0 10px;">You can track your package below. We hope you enjoy your purchase!</p>rnrn            <a href="https://yourwebsite.com/track?trackingNumber=<%= trackingNumber %>"rn               style="background-color: #007bff; color: white; text-decoration: none; padding: 12px 18px; border-radius: 5px; display: inline-block; margin-top: 15px; font-weight: bold;">rn                Track Your Shipmentrn            </a>rn        </div>rnrn        <div style="background-color: #f4f4f4; padding: 10px; font-size: 14px; color: #555; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px;">rn            Thank you for shopping with us! 🛒rn        </div>rn    </div>rn</body>rn</html>rn
                                
                            

Este modelo de e-mail é usado para notificar a clientela de que o pedido foi enviado. Ele inclui placeholders para o nome do cliente e número de rastreamento, que serão preenchidos dinamicamente por EJS durante a renderização do modelo. Os modelos para os outros dois status de pedido seguirão o mesmo formato.

Crie um modelo para notificar os usuários de que o pedido saiu para entrega, criando um arquivo chamado out_for_delivery.html na pasta src/email-templates/html e adicionando o seguinte código:

                                

                                    <!DOCTYPE html>rn<html>rn<head>rn    <meta charset="UTF-8" />rn    <title>Out for Delivery</title>rn</head>rn<body style="font-family: Arial, sans-serif; background-color: #f4f4f4; padding: 20px; text-align: center;">rnrn    <div style="background: #ffffff; padding: 20px; border-radius: 8px; max-width: 600px; margin: auto; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);">rnrn        <div style="background-color: #28a745; color: white; padding: 15px; font-size: 22px; font-weight: bold; border-top-left-radius: 8px; border-top-right-radius: 8px;">rn            Your Order Is Out for Delivery! 🚚rn        </div>rnrn        <div style="padding: 20px; font-size: 16px; color: #333; text-align: left;">rn            <p style="margin: 0 0 10px;">Hello, <%= name %></p>rn            <p style="margin: 0 0 10px;">Good news! Your package is out for delivery and will arrive soon. 📦</p>rn            <p style="margin: 0 0 10px;"><strong>Tracking Number:</strong> <%= trackingNumber %></p>rn            <p style="margin: 0 0 10px;">We appreciate your business and can't wait for you to receive your order!</p>rnrn            <a href="https://yourwebsite.com/track?trackingNumber=<%= trackingNumber %>"rn               style="background-color: #28a745; color: white; text-decoration: none; padding: 12px 18px; border-radius: 5px; display: inline-block; margin-top: 15px; font-weight: bold;">rn                Track Your Packagern            </a>rn        </div>rnrn        <div style="background-color: #f4f4f4; padding: 10px; font-size: 14px; color: #555; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px;">rn            Thank you for choosing us! 🛍️rn        </div>rn    </div>rn</body>rn</html>
                                
                            

Por fim, crie um modelo para notificar os usuários de que o pedido foi entregue, criando um arquivo chamado delivered.html na pasta src/email-templates/html e adicionando o seguinte código:

                                

                                    <!DOCTYPE html>rn<html>rn<head>rn    <meta charset="UTF-8" />rn    <title>Order Delivered</title>rn</head>rn<body style="font-family: Arial, sans-serif; background-color: #f4f4f4; padding: 20px; text-align: center;">rnrn    <div style="background: #ffffff; padding: 20px; border-radius: 8px; max-width: 600px; margin: auto; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);">rnrn        <div style="background-color: #ffc107; color: white; padding: 15px; font-size: 22px; font-weight: bold; border-top-left-radius: 8px; border-top-right-radius: 8px;">rn            Your Order Has Been Delivered! 🎉rn        </div>rnrn        <div style="padding: 20px; font-size: 16px; color: #333; text-align: left;">rn            <p style="margin: 0 0 10px;">Hello, <%= name %></p>rn            <p style="margin: 0 0 10px;">We're happy to inform you that your package has been successfully delivered. 🎁</p>rn            <p style="margin: 0 0 10px;"><strong>Tracking Number:</strong> <%= trackingNumber %></p>rn            <p style="margin: 0 0 10px;">We hope you enjoy your purchase! If you have any questions, feel free to contact us.</p>rnrn            <a href="https://yourwebsite.com/track?trackingNumber=<%= trackingNumber %>"rn               style="background-color: #ffc107; color: white; text-decoration: none; padding: 12px 18px; border-radius: 5px; display: inline-block; margin-top: 15px; font-weight: bold;">rn                Track Your Orderrn            </a>rn        </div>rnrn        <div style="background-color: #f4f4f4; padding: 10px; font-size: 14px; color: #555; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px;">rn            Thank you for shopping with us! 🛍️rn        </div>rn    </div>rn</body>rn</html>
                                
                            

Para gerenciar e renderizar modelos de e-mail dinamicamente, você precisa criar uma classe que carregue e organize modelos para diferentes status de pedido. Esta classe recuperará o modelo certo e o renderizará com dados específicos de cada cliente. Para isso, crie um novo arquivo chamado index.ts na pasta src/email-templates e adicione o seguinte código:

                                

                                    import { readFileSync } from "fs";rnimport { EmailTemplate, OrderStatus } from "../types";rnimport ejs from "ejs";rnrnexport class EmailTemplateManager {rn    private templates: Map<OrderStatus, EmailTemplate>;rnrn    constructor() {rn        this.templates = new Map();rn        this.loadTemplates();rn    }rnrn    private loadTemplates() {rn        // Load each template for different statusesrn        const statuses: OrderStatus[] = [rn            "shipped",rn            "out_for_delivery",rn            "delivered",rn        ];rn        const subjects: Record<OrderStatus, string> = {rn            shipped: "Your Order Has Been Shipped! ✈️",rn            out_for_delivery: "Your Order is Out for Delivery! 🚚",rn            delivered: "Your Order Has Been Delivered! 🎉",rn        };rnrn        statuses.forEach((status) => {rn            const htmlTemplate = readFileSync(rn                `src/email-templates/html/${status}.html`,rn                "utf-8"rn            );rnrn            this.templates.set(status, {rn                subject: subjects[status],rn                html: htmlTemplate,rn            });rn        });rn    }rnrn    getTemplate(status: OrderStatus): EmailTemplate {rn        const template = this.templates.get(status);rn        if (!template) {rn            throw new Error(`No template found for status: ${status}`);rn        }rn        return template;rn    }rnrn    renderTemplate(templateString: string, data: Record<string, any>): string {rn        return ejs.render(templateString, data); // Render the template with the provided datarn    }rn}
                                
                            

Esta classe inicializa uma variável privada chamada templates, que armazena os modelos de e-mail em um Map para pesquisa rápida com base no status do pedido. Usar um Map garante uma recuperação eficiente e evita a leitura repetida de arquivos do disco. A classe também define os seguintes métodos:

  • loadTemplates (privado) lê modelos HTML dos arquivos e os armazena no Map templates, juntamente com suas respectivas linhas de assunto.
  • getTemplate recupera o modelo de e-mail para um determinado status de pedido e gera um erro se nenhum modelo for encontrado.
  • renderTemplate usa o EJS para renderizar dinamicamente um modelo com os dados fornecidos.

Implementação da funcionalidade de envio de e-mails

Com os modelos de e-mail configurados, a próxima etapa é implementar a funcionalidade de envio de notificações. Isso envolve colocar trabalhos de e-mail na fila e processá-los de forma assíncrona.

Mas antes de fazer isso, você precisa instalar algumas dependências executando o seguinte comando:

npm i mailgun.js@11.1.0 form-data@4.0.2 bullmq@5.41.2 ioredis@5.5.0

Aqui está uma visão geral de cada uma dessas dependências:

  • mailgun.js é um cliente Node.js para interagir com a API do Mailgun. Você usará isso para enviar e-mails transacionais.
  • form-data é um pacote exigido pelo mailgun.js para lidar com envios de formulários ao enviar e-mails.
  • bullmq é uma biblioteca de fila de trabalhos para lidar com tarefas assíncronas. Isso permite colocar notificações por e-mail na fila e processá-las em segundo plano.
  • ioredis é um cliente Redis para Node.js, usado pelo BullMQ para armazenar e gerenciar trabalhos na fila.

Em seguida, você precisa definir um cliente da API do Mailgun que usará para enviar e-mails. Para isso, crie um novo arquivo em src/config/mailgun.config.ts e adicione o seguinte código:

                                

                                    import FormData from "form-data";rnimport Mailgun from "mailgun.js";rnrnconst mailgun = new Mailgun(FormData);rnexport const mgClient = mailgun.client({rn    username: "api",rn    key: process.env.MAILGUN_API_KEY,rn});
                                
                            

Este código configura e exporta um cliente Mailgun usando a biblioteca mailgun.js e o form-data, permitindo que sua aplicação envie e-mails através da API do Mailgun com a chave de API armazenada nas variáveis de ambiente.

Agora, você precisa definir uma conexão Redis que será usada pelo BullMQ para armazenar e gerenciar trabalhos em segundo plano. Para fazer isso, crie um novo arquivo chamado redis.config.ts na pasta src/config e adicione o código abaixo:

                                

                                    import IORedis from "ioredis";rnrnexport const redisConfig = new IORedis({rn    host: process.env.REDIS_HOST,rn    port: parseInt(process.env.REDIS_PORT),rn    maxRetriesPerRequest: null,rn});
                                
                            

Você precisa configurar uma fila BullMQ para as notificações de envio, que lidará com os trabalhos de notificação por e-mail em segundo plano usando a conexão Redis definida na etapa anterior. Para isso, crie um novo arquivo chamado queues.config.ts na pasta src/config e adicione o seguinte código:

                                

                                    import { Queue } from "bullmq";rnimport { redisConfig } from "./redis.config";rnrnexport const QUEUE_NAMES = {rn    SHIPPING_NOTICATIONS: "shipping-notifications",rn};rnrnexport const JOB_NAMES = {rn    SEND_NOTIFICATION: "send-notification",rn};rnrnexport const SHIPPING_NOTICATIONS_QUEUE = new Queue(rn    QUEUE_NAMES.SHIPPING_NOTICATIONS,rn    {rn        connection: redisConfig,rn    }rn);
                                
                            

Este código também define nomes para a fila e o tipo de trabalho que podem ser usados em outras partes da aplicação para evitar strings hardcoded.

Por fim, crie um novo arquivo em src/services/notifications.service.ts e adicione o seguinte código:

                                

                                    import { Job, Queue, Worker } from "bullmq";rnimport {rn    QUEUE_NAMES,rn    SHIPPING_NOTICATIONS_QUEUE,rn    JOB_NAMES,rn} from "../config/queues.config";rnimport { redisConfig } from "../config/redis.config";rnimport { mgClient } from "../config/mailgun.config";rnimport { IMailgunClient } from "mailgun.js/Interfaces";rnimport { EmailTemplateManager } from "../email-templates";rnimport { MailgunMessageData } from "mailgun.js";rnimport { NotificationJob } from "../types";rnrnexport class NotificationService {rn    private queue: Queue;rn    private mailgunClient: IMailgunClient;rn    private templateManager: EmailTemplateManager;rnrn    constructor() {rn        this.queue = SHIPPING_NOTICATIONS_QUEUE;rn        this.mailgunClient = mgClient;rn        this.templateManager = new EmailTemplateManager();rn        this.setupWorker();rn    }rnrn    private setupWorker() {rn        const worker = new Worker(rn            QUEUE_NAMES.SHIPPING_NOTICATIONS,rn            async (job) => {rn                console.log(`Processing job: ${job.id}`);rn                await this.processNotification(job);rn            },rn            {rn                connection: redisConfig,rn            }rn        );rnrn        worker.on("completed", (job) => {rn            console.log(`Job ${job.id} completed successfully`);rn        });rnrn        worker.on("failed", (job, error) => {rn            console.log(`Job ${job?.id} failed`, error);rn        });rn    }rnrn    private async processNotification(job: Job<NotificationJob>) {rn        const { email, trackingNumber, status, metadata } = job.data;rnrn        try {rn            const template = this.templateManager.getTemplate(status);rn            const emailData: MailgunMessageData = {rn                from: process.env.MAIL_FROM,rn                to: email,rn                subject: template.subject,rn                html: this.templateManager.renderTemplate(template.html, {rn                    trackingNumber,rn                    ...metadata,rn                }),rn            };rnrn            await this.mailgunClient.messages.create(rn                process.env.MAILGUN_DOMAIN,rn                emailDatarn            );rn        } catch (error) {rn            console.log(error);rn            throw error;rn        }rn    }rnrn    async queueNotification(data: NotificationJob) {rn        await this.queue.add(JOB_NAMES.SEND_NOTIFICATION, data, {rn            attempts: 5, // number of retry attempts before failing permanentlyrn            backoff: {rn                type: "exponential", // Retry using exponential backoffrn                delay: 5000, // Delay in ms before retryingrn            },rn        });rn        console.log("Job queued successfully");rn    }rn}
                                
                            

Este código define uma classe NotificationService que lida com notificações por e-mail usando um sistema de fila de trabalhos com BullMQ e Mailgun. Esta classe inicializa três propriedades privadas: queue, que é a fila onde os trabalhos de e-mail são adicionados; mailgunClient, que é o cliente Mailgun para o envio de e-mails; e templateManager, que é uma instância da classe TemplateManager criada anteriormente para gerenciar e recuperar modelos de e-mail. Esta classe também define os seguintes métodos:

  • setupWorker cria um worker que ouve novos trabalhos de e-mail e os processa. Ele registra o sucesso ou a falha do trabalho.
  • processNotification busca o modelo de e-mail correto, preenche-o com dados dinâmicos e envia o e-mail usando o Mailgun.
  • queueNotification adiciona um novo trabalho de e-mail à fila, com tentativas de repetição e backoff exponencial para tentativas que falharam. Este método pode ser chamado de outras partes da aplicação para adicionar trabalhos à fila.

Integrando com eventos do aplicativo

Para enviar notificações por e-mail quando o status de um pedido for atualizado, você precisa colocar um trabalho na fila do sistema de notificações. Para isso, abra o arquivo src/controllers/order.controller.ts e adicione a seguinte instrução para importar a classe NotificationService:

import { NotificationService } from "../services/notifications.service";

Em seguida, defina uma propriedade privada dentro da classe OrderController para armazenar uma instância da classe NotificationService:

private notificationService: NotificationService;

Inicialize esta propriedade adicionando o seguinte código dentro do método constructor:

this.notificationService = new NotificationService();

Por fim, adicione o seguinte código dentro do método updateOrderStatus, logo após await this.orderRepository.save(order);, para colocar um trabalho na fila assim que o status do pedido for atualizado com sucesso:

                                

                                    // Send notificationrnthis.notificationService.queueNotification({rn    email: order.user.email,rn    trackingNumber: order.trackingNumber,rn    status,rn    metadata: {rn        name: order.user.name.split(" ")[0],rn    },rn});
                                
                            

O fluxo de trabalho de e-mail transacional agora está concluído. Você já pode testar se tudo está funcionando conforme o esperado.

Testando o fluxo de trabalho

Para garantir que tudo funcione corretamente, inicie o Redis executando o seguinte comando no seu terminal:

docker compose up -d

Após rodar esse comando, você pode verificar se o Redis está em execução listando os contêineres:

docker ps

Este comando mostra uma lista de contêineres ativos, e você deve ver o contêiner redis rodando.

Em seguida, inicie o servidor Express usando o comando npm run dev e acesse http://localhost:3000 no seu navegador. No painel da aplicação, atualize o status do pedido para qualquer uma das opções disponíveis. Após a atualização, você receberá uma resposta instantânea:

Shipped Order Status Screen Image

No seu terminal, você receberá um log notificando que o trabalho de envio de e-mail foi colocado na fila com sucesso e está sendo processado:

Job queued successfully
Processing job: 1

E quando estiver concluído:

Job 1 completed successfully

Em seguida, você receberá um e-mail com o status do pedido atualizado:

Your order has shipped screen image

Sempre que você atualizar o status de um pedido, o sistema enviará automaticamente um e-mail correspondente para o usuário, mantendo-o informado:

Your Order has been delivered screen image 8

O código completo da aplicação está disponível no GitHub.

Monitorando e gerenciando e-mails

Para garantir que seus e-mails transacionais cheguem aos clientes de forma eficaz, você precisa monitorar o status de entrega e as taxas de abertura, além de lidar com possíveis falhas. O Mailgun fornece um painel onde você pode rastrear os e-mails enviados, verificar se eles foram entregues, abertos ou clicados e visualizar relatórios de devolução.

Você pode acessar este painel navegando até Send > Reporting > Metrics no Mailgun:

Send > Reporting > Metrics Screen Image

No entanto, as taxas de abertura não são rastreadas automaticamente, e você precisará configurá-las manualmente na aba Settings do seu domínio de envio:

Domain Settings Screen Tab image

Mais informações sobre como rastrear as taxas de abertura e de cliques estão disponíveis na documentação oficial.

Além disso, você pode usar webhooks para receber notificações em tempo real sobre entregas que falharam e tomar a ação adequada, como tentar enviar o e-mail novamente.

Ao monitorar ativamente o desempenho de seus e-mails, você pode melhorar a entregabilidade, reduzir as devoluções e garantir que notificações importantes cheguem aos seus clientes.

Conclusão

Neste artigo, você aprendeu a configurar um fluxo de trabalho de e-mail transacional para notificações de envio usando o Mailgun, o BullMQ e o Redis. Você aprendeu a configurar o Mailgun para enviar e-mails, definir uma fila de trabalhos com o BullMQ e integrá-la a um sistema de atualização de pedidos para garantir que os clientes recebam notificações por e-mail em tempo real. Essa abordagem melhora a comunicação e aprimora a experiência geral do cliente.

Isso foi útil? Assine a nossa newsletter para mais tutoriais e análises detalhadas como esta.