Formulário de Contato Node.js: Como Criar, Validar Dados e Enviar Emails

On junho 13, 2024
19min read
Ivan Djuric, an author at Mailtrap
Ivan Djuric Technical Content Writer @Mailtrap

Neste tutorial passo-a-passo, vou mostrar como criar um formulário de contato Node.js, dar um toque pessoal, recuperar e validar dados dele e, em seguida, enviar emails através do formulário via SMTP ou API.

Nota: você precisará ter o Node.js 6+ ou qualquer versão lançada a partir de maio de 2018 instalada em sua máquina para que os snippets de código fornecidos funcionem.

Como criar um formulário de contato Node.js

Como você está lendo este artigo, assumo que você sabe como instalar o Node.js e criar um novo projeto, então vou ser breve e ir direto para a configuração do projeto.

No entanto, para refrescar seus conhecimentos, você pode ler este artigo sobre instalação do Node.js.

Configurando o projeto

Primeiro de tudo, vamos instalar algumas dependências para nosso backend abrindo o terminal e digitando os seguintes comandos:

  • mkdir contact-form-test && cd contact-form-test – Ao executar este comando, criamos uma pasta para nosso projeto, garantindo que nossos arquivos do projeto estarão dentro dela em vez do diretório atual.
  • npm init -y – Isso criará um arquivo package.json que gerencia as dependências e configurações do projeto.
  • npm i express nodemailer – Precisamos instalar a biblioteca Express.js e o módulo Nodemailer, pois precisaremos deles para configurar nosso servidor e enviar emails via SMTP, respectivamente.
  • npm i -D nodemon – Esta é uma dependência de desenvolvimento que automatiza o processo de reiniciar nosso servidor sempre que alteramos nosso código, permitindo-nos ver as mudanças feitas sem ter que reiniciar o servidor manualmente.

Depois de instalar todas as dependências, seu arquivo package.json deve parecer algo assim:

{
  "name": "contact-form-test",          // Nome do projeto
  "version": "1.0.0",                   // Versão do projeto
  "description": "",                    // Descrição do projeto
  "main": "server.js",                  // Arquivo de entrada do projeto
  "scripts": {
    "dev": "nodemon --watch public --watch server.js --ext js,html,css", // Script para rodar o servidor com nodemon para desenvolvimento
    "start": "node server.js"           // Script para iniciar o servidor normalmente
  },
  "keywords": [],                       // Palavras-chave relacionadas ao projeto
  "author": "",                         // Autor do projeto
  "license": "ISC",                     // Tipo de licença
  "dependencies": {
    "express": "^4.19.2",               // Framework de servidor web Express
    "nodemailer": "^6.9.13"             // Nodemailer para enviar emails via SMTP
  },
  "devDependencies": {
    "nodemon": "^3.1.0"                 // Nodemon para reiniciar automaticamente o servidor em mudanças de código
  }
}

Dicas bônus:

  • npm i dotenv – Embora opcional, este comando instala o pacote dotenv, que carrega variáveis de ambiente onde você pode armazenar com segurança suas credenciais de autenticação, como uma chave API. Tudo o que você precisa fazer é executar o comando, criar um arquivo .env na raiz do diretório do seu projeto e colar suas credenciais desejadas lá.
  • A partir da versão 20.6.0, o Node.js tem suporte embutido para arquivos .env para configurar variáveis de ambiente. Portanto, não é necessário usar o pacote dotenv, mas muitos projetos ainda dependem do dotenv, então ele ainda é o padrão.

Configurando o servidor

Em seguida, na pasta do projeto, vamos criar um novo arquivo .js chamado server.js ao qual nos referimos no script de produção do arquivo package.json.

Em seguida, basta colar o seguinte snippet de código no arquivo server.js:

const express = require('express');
const app = express();
const path = require('path');


const PORT = process.env.PORT || 3000;


// Middleware
app.use(express.static('public'));
app.use(express.json());


app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, 'public', 'contactform.html'));
});


app.post('/send-email', (req, res) => {
    console.log(req.body);
    res.send('Dados recebidos');
});


app.listen(PORT, () => {
    console.log(`Servidor funconando na porta ${PORT}`);
});

Nota: Mais tarde no artigo, usaremos o arquivo server.js para adicionar o Nodemailer como um transporte via SMTP e uma lógica de API para enviar emails através do nosso formulário de contato.

Criando o formulário de contato

Agora, vamos criar uma nova pasta pública chamada public para os arquivos estáticos (style.css, contactform.html e app.js) que vamos usar para este formulário de contato.

No arquivo contactform.html, insira o seguinte código:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"> <!-- Especifica a codificação de caracteres para o documento HTML -->
    <link rel="stylesheet" href="/style.css"> <!-- Link para o arquivo CSS externo para estilização -->
    <link rel="preconnect" href="https://fonts.gstatic.com"> <!-- Preconexão para carregar fontes mais rapidamente -->
    <link href="https://fonts.googleapis.com/css2?family=Poppins&display=swap" rel="stylesheet"> <!-- Link para fontes Google para a fonte 'Poppins' -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Meta tag de design responsivo -->
    <title>Formulário de Contato</title> <!-- Título do documento mostrado na aba do navegador -->
</head>
<body>
    <div class="form-container"> <!-- Container para o formulário para estilização específica -->
        <form class="contact-form"> <!-- Elemento de formulário onde as entradas do usuário serão enviadas -->
            <h2>CONTATO</h2> <!-- Cabeçalho do formulário -->
            <input type="text" id="name" placeholder="Full name"><br> <!-- Campo para o nome -->
            <input type="email" id="email" placeholder="Email"><br> <!-- Campo para o email, valida formato de email -->
            <input type="text" id="subject" placeholder="Subject"><br> <!-- Campo para o assunto -->
            <textarea id="message" placeholder="Message" cols="30" rows="10"></textarea><br> <!-- Textarea para o input de mensagem mais longa -->
            <input type="submit" class="submit" value="Send Message"> <!-- Botão de envio para enviar os dados do formulário -->
        </form>
    </div>
    <script src="/app.js"></script> <!-- Link para o arquivo JavaScript externo para scripts -->
</body>
</html>

Adicionei anotações neste snippet de código para ajudá-lo a navegar por ele, mas sinta-se à vontade para excluí-las para um código mais limpo. 🙂

Estilizando o formulário de contato

Que tal abordarmos o frontend por um momento e adicionar um toque pessoal ao nosso formulário de contato?

No arquivo style.css, insira o seguinte código, que tornará nosso formulário de contato mais bonito:

/* Estilos globais para todos os elementos para garantir consistência */
* {
    margin: 0;                          /* Remove a margem padrão */
    padding: 0;                         /* Remove o preenchimento padrão */
    box-sizing: border-box;             /* Inclui o preenchimento e a borda na largura e altura total do elemento */
    font-family: 'Poppins', sans-serif; /* Define uma família de fontes consistente em todo o app */
}


/* Estilização para os elementos html e body */
html, body {
    background: #c0b7b7;                /* Define a cor de fundo para toda a página */
}


/* Container para o formulário fornecendo contexto de posicionamento relativo */
.form-container {
    position: relative;                 /* Contexto de posicionamento para posicionamento absoluto dentro */
    left: 20%;                          /* Posiciona o container 20% da esquerda da janela de visualização */
    width: 60%;                         /* Define a largura do container para 60% da largura da janela de visualização */
    height: 100vh;                      /* Define a altura para ser 100% da altura da janela de visualização */
    background-color: white;            /* Define a cor de fundo do container do formulário */
}


/* Estilização para o próprio formulário de contato */
.contact-form {
    position: absolute;                 /* Posiciona o formulário absolutamente dentro de seu container parent */
    top: 10%;                           /* Posiciona o formulário a 10% do topo de seu container */
    left: 10%;                          /* Posiciona o formulário a 10% da esquerda de seu container */
    width: 80%;                         /* A largura do formulário é 80% de seu container */
    min-height: 600px;                  /* Altura mínima para o formulário */
}


/* Estilização para os campos de entrada e textarea dentro do formulário */
input, textarea {
    width: 100%;                        /* Faz com que os elementos de entrada e textarea ocupem 100% da largura do parent */
    margin-top: 2rem;                   /* Adiciona margem superior para espaçar os elementos */
    border: none;                       /* Remove bordas padrão */
    border-bottom: 1px solid black;     /* Adiciona uma borda inferior para um visual minimalista */
    padding: 10px; /* Adiciona preenchimento para melhor legibilidade */
}


/* Estilização para o botão de envio */
.submit {
    border: 1px solid black;            /* Adiciona uma borda sólida ao redor do botão de envio */
    padding: 1rem;                      /* Adiciona preenchimento dentro do botão para melhor clickability */
    text-align: center;                 /* Centraliza o texto dentro do botão */
    background-color: white;            /* Define a cor de fundo do botão */
    cursor: pointer;                    /* Altera o cursor para um ponteiro para indicar que é clicável */
}


/* Estilização para o botão de envio ao passar o mouse */
.submit:hover {
    opacity: 0.6;                       /* Altera a opacidade ao passar o mouse para dar um feedback visual */
}

Para ver como seu formulário de contato fica, você pode salvar o arquivo e digitar o seguinte comando no seu terminal:

npm run dev

Em seguida, você deve ver a mensagem dizendo que seu formulário de contato está sendo hospedado na porta personalizada que você definiu no seu arquivo .env ou na porta padrão 3000, permitindo que o tráfego chegue até ele.

Por fim, cole o seguinte link na barra de URL do seu navegador: http://localhost:3000/ e você deverá ver seu formulário de contato em toda a sua glória.

Como coletar dados de um formulário de contato Node.js

Para coletar dados do nosso formulário de contato Node.js, vamos adicionar funcionalidade para lidar com submissões de formulários usando JavaScript, o que capturará os dados do formulário e os enviará para o servidor sem recarregar a página.

Para isso, usaremos uma requisição AJAX, que nos permite evitar um recarregamento completo da página.

Tornei isso fácil para você, então tudo o que você precisa fazer é navegar até seu arquivo app.js e inserir o seguinte código:

const contactForm = document.querySelector('.contact-form');
const name = document.getElementById('name');
const email = document.getElementById('email');
const subject = document.getElementById('subject');
const message = document.getElementById('message');


contactForm.addEventListener('submit', (e) => {
    e.preventDefault();  // Impede a submissão padrão do formulário


    const formData = {
        name: name.value,
        email: email.value,
        subject: subject.value,
        message: message.value
    };


    try {
        const response = await fetch('/send-email', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(formData)
        });


        // Aguarda a resposta JSON ser analisada
        const result = await response.json();


        if (!response.ok) {
            // Se a resposta não estiver OK, lida com isso mostrando um alerta
            alert(`Falha ao enviar mensagem: ${result.message}`);
            return;  // Sai da função cedo se houver um erro
        }


        // Verifica o status específico da aplicação no JSON quando a resposta está OK
        if (result.status === 'success') {
            alert('Email sent');


            // Faz reset dos campos do formulário após submissão bem-sucedida
            name.value = '';
            email.value = '';
            subject.value = '';
            message.value = '';
        } else {
            // Lida com falha no nível da aplicação não capturada por response.ok
            alert('Falha na operação: ' + result.message);
        }


    } catch (error) {
        // Lida com qualquer exceção que ocorra durante o fetch
        console.error('Erro:', error);
        alert('Erro de rede ou não é possível conectar ao servidor');
    }


});

Nota: Usei a API fetch aqui, que é uma alternativa mais moderna ao ‘XMLHttpRequest’ e aproveita a sintaxe async/await para melhor tratamento de erros.

Como validar dados de um formulário de contato

Para validar dados de um formulário de contato em Node.js, você pode usar:

  • Deep email validator – Um pacote de dependência abrangente e certificado pela MIT que garante que um email é válido, passando por várias verificações diferentes. Ele valida RegEx, erros comuns de digitação, listas de bloqueio de emails descartáveis, registros DNS e respostas de servidores SMTP.
  • Expressões regulares (Regex) – Padrões usados para corresponder combinações de caracteres em strings, garantindo que as entradas estejam em conformidade com um formato predefinido. Eles fornecem um nível mais básico de validação em comparação com pacotes de dependência como o Deep email validator.

Módulo Deep email validator

Para instalar o Deep email validator, geralmente uso o comando npm ou Yarn:

npm i deep-email-validator

# ou

yarn add deep-email-validator

Depois de importar const { validate } = require('deep-email-validator'); basta adicionar o seguinte código no seu controlador /send-email:

// Endpoint para lidar com submissão de formulário e enviar email
app.post('/send-email', async (req, res) => {
   const { name, email, subject, message } = req.body;


   if (!name || !email || !subject || !message) {
       return res.status(400).json({ status: 'error', message: 'Campos obrigatórios faltando!' })
   }


   // Valida o email
   const validationResult = await validate(email);


   if (!validationResult.valid) {
       return res.status(400).json({
           status: 'error',
           message: 'Email não é válido. Por favor, tente novamente!',
           reason: validationResult.reason
       });
   }


   // Lógica de envio de email


   // Resposta de placeholder para uma submissão de email bem-sucedida
   res.status(200).json({
       status: 'success',
       message: 'Email enviado com sucesso'
   });
});

Para mais informações sobre o Deep email validator, consulte a página oficial no GitHub.

Expressões regulares para validação de email

Se preferir realizar verificações básicas de ReGex nos IDs de email em vez de usar um pacote de dependência, você pode colar o seguinte código no seu arquivo de projeto (por exemplo, server.js):

const emailRegex = 

/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/


function isEmailValid(email) {
    // Verifica se o email está definido e não é muito longo
    if (!email || email.length > 254) return false;

    // Usa uma única verificação de regex para as partes padrão do email
    if (!emailRegex.test(email)) return false;

    // Divide uma vez e realiza verificações de comprimento nas partes
    const parts = email.split("@");
    if (parts[0].length > 64) return false;

    // Realiza verificações de comprimento nas partes do domínio
    const domainParts = parts[1].split(".");
    if (domainParts.some(part => part.length > 63)) return false;

    // Se todas as verificações passarem, o email é válido
    return true;
}

Em seguida, na sua rota /send-email, adicione o seguinte código para realizar a validação do email:

// Endpoint para lidar com submissão de formulário e enviar email
app.post('/send-email', async (req, res) => {
   const { name, email, subject, message } = req.body;


   if (!name || !email || !subject || !message) {
       res.status(400).json({ status: 'error', message: 'Campos obrigatórios faltando!' })
   }


   // Valida o email
   if (!isEmailValid(email)) {
       return res.status(400).json({
           status: 'error',
           message: 'Email não é válido. Por favor, tente novamente!'
       });
   }


   // Lógica de envio de email


   // Resposta de placeholder para uma submissão de email bem-sucedida
   res.status(200).json({
       status: 'success',
       message: 'Email enviado com sucesso'
   });
});

Para mais detalhes sobre a validação de emails em Node.js, sinta-se à vontade para consultar nosso artigo dedicado, onde você também pode aprender como verificar emails enviando um link/código de ativação que os usuários finais ativam a partir de sua caixa de entrada.

Como adicionar reCAPTCHA

Agora, vamos adicionar um reCAPTCHA ao nosso formulário de contato Node.js para garantir que nenhum robô o preencha. 🤖

Primeiro, você precisa obter sua ‘SITE KEY’ e ‘SECRET KEY’ no console de administração do Google reCAPTCHA.

Neste exemplo, usaremos o Challenge (v2), então certifique-se de selecioná-lo durante a criação e deixar a opção padrão “I’m not a robot Checkbox”.

Além disso, como estamos testando a partir de um computador local, precisamos adicionar ‘localhost’ aos domínios permitidos durante a criação. Nota: se você estiver em produção, precisará usar seus próprios domínios. E para usar este código, basta copiar sua SITE KEY e SECRET KEY.

Em seguida, no nosso contactform.html, adicione o seguinte snippet de código pouco antes do fechamento da seção head:

<script src="https://www.google.com/recaptcha/api.js" async defer></script> <!-- Carrega a API do Google reCAPTCHA -->

Dentro do nosso formulário, podemos adicionar o elemento reCAPTCHA após a textarea assim:

<div class="g-recaptcha" data-sitekey="SUA_SITE_KEY"></div><br> <!-- Elemento do Google reCAPTCHA -->

Importante: não se esqueça de substituir SUA_SITE_KEY pela sua SITE KEY real.

Depois, precisamos atualizar nosso app.js dentro da pasta pública para passar o token do reCAPTCHA para nosso formData para que o backend possa verificá-lo. Para fazer isso, após o e.preventDefault(); cole o seguinte código:

// Obter o token do reCAPTCHA
   const recaptchaToken = grecaptcha.getResponse();


   if (!recaptchaToken) {
       alert('Por favor, complete o reCAPTCHA');
       return;  // Sai da função cedo se o reCAPTCHA não for concluído
   }


   const formData = {
       name: name.value,
       email: email.value,
       subject: subject.value,
       message: message.value,
       'g-recaptcha-response': recaptchaToken
   };

Para verificar o reCAPTCHA no lado do servidor, precisamos fazer uma requisição. Para isso, podemos usar o Node.js nativo ‘https’, ou um pacote como ‘node-fetch’ ou ‘axios’.

E desde o Node.js versão 18, o método fetch está disponível no escopo global nativamente, então vamos usar ‘fetch’.

Primeiro, no nosso server.js, vamos criar uma função para verificar o reCAPTCHA (certifique-se de adicionar a SECRET KEY como RECAPTCHA_SECRET_KEY nas variáveis de ambiente, caso contrário, a verificação não terá sucesso):

// Função para verificar o reCAPTCHA
async function verifyRecaptcha(token) {
   const recaptchaSecret = process.env.RECAPTCHA_SECRET_KEY;
   const recaptchaUrl = `https://www.google.com/recaptcha/api/siteverify?secret=${recaptchaSecret}&response=${token}`;


   const response = await fetch(recaptchaUrl, { method: 'POST' });
   const result = await response.json();


   return result.success;
}

Em seguida, no nosso endpoint /send-email, podemos atualizar nosso código para isso:

// Endpoint para lidar com submissão de formulário e enviar email
app.post('/send-email', async (req, res) => {
   const { name, email, subject, message, 'g-recaptcha-response': recaptchaToken } = req.body;


   if (!name || !email || !subject || !message || !recaptchaToken) {
       res.status(400).json({ status: 'error', message: 'Campos obrigatórios faltando!' })
   }


   // Verifica o token do reCAPTCHA
   const isRecaptchaValid = await verifyRecaptcha(recaptchaToken);
   if (!isRecaptchaValid) {
       return res.status(400).json({
           status: 'error',
           message: 'Verificação do reCAPTCHA falhou. Por favor, tente novamente.'
       });
   }


   // Valida o email
   const validationResult = await validate(email);


   if (!validationResult.valid) {
       return res.status(400).json({
           status: 'error',
           message: 'Email não é válido. Por favor, tente novamente!',
           reason: validationResult.reason
       });
   }


   // Lógica de envio de email


   // Resposta de placeholder para uma submissão de email bem-sucedida
   res.status(200).json({
       status: 'success',
       message: 'Email enviado com sucesso'
   });
});

Enviar emails do formulário de contato Node.js usando SMTP

Agora que temos nosso fluxo de formulário de contato Node.js configurado, vamos adicionar uma funcionalidade de envio de email a ele.

Para isso, precisaremos de duas coisas:

  • Nodemailer – Se você está lendo este artigo, acho que já tem o Nodemailer instalado, mas se não tiver, aqui está como instalar.
  • Credenciais SMTP – Com o Nodemailer, você pode usar qualquer servidor SMTP, como, por exemplo, o Gmail. No entanto, o Gmail tem algumas limitações significativas, sobre as quais você pode saber mais no nosso tutorial dedicado ao Nodemailer Gmail.

Para superar as limitações do Gmail, configuraremos o Email API/SMTP do Mailtrap como o serviço SMTP em nosso objeto transportador do Nodemailer. Ele oferece uma infraestrutura com altas taxas de entregabilidade por padrão e por design, além de ser fácil de usar.

Primeiro, crie uma conta gratuita no Mailtrap e verifique seu domínio. Leva apenas alguns minutos, e você pode assistir ao vídeo que preparamos para você como um tutorial passo a passo.

Em seguida, prossiga para a seção Sending Domains, escolha seu domínio e, em Integration, selecione seu stream preferido (Transactional, neste caso). Lá, você encontrará suas credenciais SMTP, que você pode facilmente colar no arquivo de configuração do Nodemailer.

Página de integrações no Email API/SMTP do Mailtrap

Falando da configuração do Nodemailer, vamos inseri-la no arquivo server.js abaixo do comentário // Crie um objeto de transportet, assim:

// Cria um objeto de transporte
const transporter = nodemailer.createTransport({
  host: 'live.smtp.mailtrap.io',
  port: 587,
  secure: false, // use false para STARTTLS; true para SSL na porta 465
  auth: {
    user: '1a2b3c4d5e6f7g',
    pass: '1a2b3c4d5e6f7g',
  }
});

// Configura o objeto mailOptions
const mailOptions = {
  from: 'seuusername@email.com',
  to: 'seuamigo@email.com',
  subject: 'Enviando Email usando Node.js',
  text: 'Isso foi fácil!'
};

// Envia o email
transporter.sendMail(mailOptions, (error, info) => {
  if (error) {
    console.log('Erro:', error);
    return res.status(500).json({ status: 'error', message: 'Falha ao enviar email devido a erro no servidor.' });
  } else {
    console.log('Email enviado: ' + info.response);
    return res.status(200).json({
               status: 'success',
               message: 'Email enviado com sucesso'
           });
  }
});

Em seguida, basta inserir suas credenciais do Mailtrap nos respectivos campos, incluindo host, port, user e pass.

No final, seu arquivo server.js deve parecer algo assim:

require('dotenv').config();
const express = require('express');
const { validate } = require('deep-email-validator');
const path = require('path');


const app = express();
const PORT = process.env.PORT || 3000;


// Middleware
app.use(express.static('public'));
app.use(express.json());


app.get('/', (req, res) => {
   res.sendFile(path.join(__dirname, 'public', 'contactform.html'));
});


// Função para verificar o reCAPTCHA
async function verifyRecaptcha(token) {
   const recaptchaSecret = process.env.RECAPTCHA_SECRET_KEY;
   const recaptchaUrl = `https://www.google.com/recaptcha/api/siteverify?secret=${recaptchaSecret}&response=${token}`;


   const response = await fetch(recaptchaUrl, { method: 'POST' });
   const result = await response.json();


   return result.success;
}


// Endpoint para lidar com submissão de formulário e enviar email
app.post('/send-email', async (req, res) => {
   const { name, email, subject, message, 'g-recaptcha-response': recaptchaToken } = req.body;


   if (!name || !email || !subject || !message || !recaptchaToken) {
       return res.status(400).json({ status: 'error', message: 'Campos obrigatórios faltando!' })
   }


   // Verifica o token do reCAPTCHA
   const isRecaptchaValid = await verifyRecaptcha(recaptchaToken);
   if (!isRecaptchaValid) {
       return res.status(400).json({
           status: 'error',
           message: 'Verificação do reCAPTCHA falhou. Por favor, tente novamente.'
       });
   }


   // Valida o email
   const validationResult = await validate(email);


   if (!validationResult.valid) {
       return res.status(400).json({
           status: 'error',
           message: 'Email não é válido. Por favor, tente novamente!',
           reason: validationResult.reason
       });
   }


   // Lógica de envio de email
   // Cria um objeto de transporte
   const transporter = nodemailer.createTransport({
       host: process.env.SMTP_HOST,
       port: process.env.SMTP_PORT,
       secure: false, // use false para STARTTLS; true para SSL na porta 465
       auth: {
           user: process.env.SMTP_USER,
           pass: process.env.SMTP_PASS,
       }
   });


   // Configura o objeto mailOptions
   const mailOptions = {
       from: process.env.EMAIL_FROM,
       to: process.env.EMAIL_TO,
       replyTo: email,
       subject: subject,
       text: `From: ${name}\nEmail:${email}\n\n${message}`
   };


   // Envia o email
   transporter.sendMail(mailOptions, (error, info) => {
       if (error) {
           console.log('Erro:', error);
           return res.status(500).json({ status: 'error', message: 'Falha ao enviar email devido a erro no servidor.' });


       } else {
           console.log('Email enviado: ' + info.response);
           return res.status(200).json({
               status: 'success',
               message: 'Email enviado com sucesso'
           });
       }
   });
});


app.listen(PORT, () => {
   console.log(`Servidor funcionando na porta ${PORT}`);
});

Para armazenar com segurança suas credenciais do Mailtrap, você pode usar a variável de ambiente, ou o arquivo .env, assim:

PORT=3200
SMTP_HOST='live.smtp.mailtrap.io'
SMTP_PORT=587
SMTP_USER='1a2b3c4d5e6f7g'
SMTP_PASS='1a2b3c4d5e6f7g'
EMAIL_FROM='seunomedeusuario@email.com'
EMAIL_TO='destinatariodoformulario@seuemail.com'
RECAPTCHA_SECRET_KEY='SECRET-KEY'

Enviar emails do formulário de contato Node.js usando API

Se você quiser automatizar a funcionalidade de envio de email do seu formulário de contato, pode novamente confiar no Mailtrap, pois ele possui um robusto pacote de envio. O próprio pacote é atualizado regularmente por uma equipe de desenvolvedores, permite que você automatize seu processo de envio e é super fácil de usar.

Primeiro, você precisará de uma conta Mailtrap, que, se você ainda não tiver uma, pode criar seguindo as instruções fornecidas no capítulo anterior.

Em seguida, vamos instalar o pacote Mailtrap:

npm install mailtrap

# ou, se você estiver usando yarn:

yarn add mailtrap

Uma vez instalado, você pode usar o seguinte trecho de código para enviar emails:

import { MailtrapClient } from "mailtrap"

/**
 * Para que este exemplo funcione, você precisa configurar um domínio de envio
 * e obter um token que seja autorizado a enviar do domínio.
 */

const TOKEN = "<SEU-TOKEN-AQUI>";
const SENDER_EMAIL = "<REMETENTE@SEUDOMINIO.COM>";
const RECIPIENT_EMAIL = "<DESTINATARIO@EMAIL.COM>";

const client = new MailtrapClient({ token: TOKEN });

const sender = { name: "Teste Mailtrap", email: SENDER_EMAIL };

client
  .send({
    from: sender,
    to: [{ email: RECIPIENT_EMAIL }],
    subject: "Olá do Mailtrap!",
    text: "Bem-vindo ao envio de emails do Mailtrap!",
  })
 .then(response => {
    console.log("Email enviado com sucesso:", response);
  })
  .catch(error => {
    console.error("Erro ao enviar email:", error);
  });

Para sua conveniência, aqui está como seu arquivo server.js deve se parecer:

require('dotenv').config();
const express = require('express');
const { MailtrapClient } = require('mailtrap');
const { validate } = require('deep-email-validator');
const path = require('path');


const app = express();
const PORT = process.env.PORT || 3000;


// Middleware
app.use(express.static('public'));
app.use(express.json());


app.get('/', (req, res) => {
   res.sendFile(path.join(__dirname, 'public', 'contactform.html'));
});


// Function to verify reCAPTCHA
async function verifyRecaptcha(token) {
   const recaptchaSecret = process.env.RECAPTCHA_SECRET_KEY;
   const recaptchaUrl = `https://www.google.com/recaptcha/api/siteverify?secret=${recaptchaSecret}&response=${token}`;


   const response = await fetch(recaptchaUrl, { method: 'POST' });
   const result = await response.json();


   return result.success;
}


// Endpoint para lidar com submissão de formulário e enviar email
app.post('/send-email', async (req, res) => {
   const { name, email, subject, message, 'g-recaptcha-response': recaptchaToken } = req.body;


   if (!name || !email || !subject || !message || !recaptchaToken) {
       return res.status(400).json({ status: 'error', message: 'Campos obrigatórios faltando!' })
   }


   // Verifica o token do reCAPTCHA
   const isRecaptchaValid = await verifyRecaptcha(recaptchaToken);
   if (!isRecaptchaValid) {
       return res.status(400).json({
           status: 'error',
           message: 'Verificação do reCAPTCHA falhou. Por favor, tente novamente.'
       });
   }


   // Valida o email
   const validationResult = await validate(email);


   if (!validationResult.valid) {
       return res.status(400).json({
           status: 'error',
           message: 'Email não é válido. Por favor, tente novamente!',
           reason: validationResult.reason
       });
   }


   // Configura o provedor mailtrap e define o remetente
   console.log(process.env.MAILTRAP_TOKEN);
   const client = new MailtrapClient({ token: process.env.MAILTRAP_TOKEN });
   const sender = { name: "NodeJS App", email: process.env.EMAIL_FROM };


   // Envia email
   try {
       const response = await client.send({
           from: sender,
           to: [{ email: process.env.EMAIL_TO }],
           subject: subject,
           text: `From: ${name}\nEmail: ${email}\n\n${message}`,
       });


       console.log('Email enviado: ', response.message_ids);
       res.status(200).json({
           status: 'success',
           message: 'Email enviado com sucesso'
       });
   } catch (error) {
       console.log('Erro:', error);
       res.status(500).json({ status: 'error', message: 'Falha ao enviar email devido a erro no servidor.' });
   }


});


app.listen(PORT, () => {
   console.log(`Servidor funcionando na porta ${PORT}`);
});

Se você quiser armazenar com segurança suas credenciais em uma variável de ambiente, aqui está como seu .env deve se parecer:

PORT=3200
MAILTRAP_TOKEN='7ff93fc2453461800734fb5c8bbe735d'
EMAIL_FROM='seunomedeusuario@email.com'
EMAIL_TO='destinatariodoformulario@seuemail.com'
RECAPTCHA_SECRET_KEY='SECRET-KEY'

E voilà! Seu formulário de contato Node.js agora pode enviar emails via API.

Lembre-se de que o snippet de código que mostrei aqui é apenas para mensagens em texto simples. Se desejar enviar emails HTML ou adicionar imagens incorporadas ou anexos, consulte a pasta de exemplos no repositório do GitHub.

Testar emails e envio de email em staging

Se você está criando um formulário de contato, há grandes chances de que você o use para coletar informações críticas dos usuários, como endereços de email, nomes e outros dados sensíveis.

Portanto, você precisa garantir que a funcionalidade do seu formulário de contato esteja impecável e que seus formulários enviados estejam chegando aos endereços desejados como deveriam.

E é exatamente aí que entra o teste de email—uma prática padrão da indústria que garante que seu sistema de envio está funcionando conforme o esperado, que seus emails estão impecáveis e, mais importante, que seus emails não estão sendo marcados como spam.

Pessoalmente, eu uso o Email Testing do Mailtrap, outra parte integral da Plataforma de Email Delivery do Mailtrap que oferece um sandbox para você inspecionar e depurar emails em ambientes de staging, dev e QA.

Com o Email Testing do Mailtrap, você pode visualizar como seus emails aparecem em diferentes dispositivos/clientes, inspecionar seu HTML/CSS fonte e corrigir facilmente qualquer linha de código defeituosa.

Mailtrap Email Testing HTML Check

Além disso, graças ao recurso Spam Report, você estará ciente do seu spam score, que, se mantido abaixo de 5, previne uma quantidade considerável de possíveis problemas de entregabilidade de email.

Mailtrap Email Testing Spam Report

Além destes, você também tem acesso a outros recursos para melhorar sua entregabilidade de email, incluindo:

  • Pré-visualização de email em forma HTML e texto bruto
  • API de Teste de Email para automação de QA
  • Múltiplas caixas de entrada para diferentes projetos e estágios
  • Gerenciamento de usuários, SSO
  • Teste de templates de email

Agora, deixe-me mostrar como funciona!

SMTP

Para começar a testar seus emails com Nodemailer e SMTP, siga estes passos:

  • Crie uma conta gratuita no Mailtrap
  • Vá para Email Testing e selecione sua caixa de entrada
  • Copie suas credenciais na aba Integration
  • Insira as credenciais no seu arquivo server.js

Você também pode usar a integração pronta para uso do Mailtrap, assim:

  • Selecione Nodemailer na lista de integrações
Mailtrap Email Testing Integration page
  • Copie e cole o snippet de código no seu arquivo server.js

Aqui está como o snippet deve parecer:

const transport = nodemailer.createTransport({
  host: "sandbox.smtp.mailtrap.io",
  port: 2525,
  auth: {
    user: "1a2b3c4d5e6f7g",
    pass: "1a2b3c4d5e6f7g"
  }
});

API

Integrar a API de Teste de Email do Mailtrap para teste, automação e sequências automatizadas de teste é tão simples quanto usar o seguinte snippet de código:

require('dotenv').config();
const { MailtrapClient } = require('mailtrap');
const nodemailer = require('nodemailer');


// O pacote oficial do mailtrap não suporta envio de emails de teste, então enviamos um email primeiro com nodemailer

// Inicializa nodemailer com a configuração SMTP das variáveis de ambiente. */
const transport = nodemailer.createTransport({
   host: process.env.SMTP_HOST,
   port: process.env.SMTP_PORT,
   auth: {
       user: process.env.SMTP_USER,
       pass: process.env.SMTP_PASS
   }
});


/* Envia um email de teste assíncrono usando nodemailer. */
async function sendTestEmail() {
   const info = await transport.sendMail({
       from: process.env.EMAIL_FROM,
       to: "user@domain.com",
       subject: "Mailtrap Email Testing",
       html: '<h1>Mailtrap Email Testing</h1>',
       text: 'Mailtrap Email Testing'
   });


   console.log("Message sent: %s", info.messageId);
   return info;
}


/* Configura o cliente Mailtrap e obtém informações sobre o email para teste e automação. */
const client = new MailtrapClient({
   token: process.env.MAILTRAP_TOKEN,
   testInboxId: process.env.TEST_INBOX_ID,
   accountId: process.env.ACCOUNT_ID
});


const inboxesClient = client.testing.inboxes;
const messagesClient = client.testing.messages;


/* Envia o email de teste e, em seguida, recupera-o do Mailtrap para análise. */
sendTestEmail().then(() => {
   inboxesClient.getList()
       .then(async (inboxes) => {
           if (inboxes && inboxes.length > 0) {
               const firstInboxId = inboxes[0].id;
               console.log(`First inbox ID: ${firstInboxId}`);


               const messages = await messagesClient.get(firstInboxId);
               if (messages && messages.length > 0) {
                   const firstMessageId = messages[0].id;
                   console.log(`First message ID: ${firstMessageId}`);


                   const analysis = await messagesClient.getHtmlAnalysis(firstInboxId, firstMessageId);
                   console.log('Análise HTML:', analysis);

                   const htmlMessage = await messagesClient.getHtmlMessage(firstInboxId, firstMessageId);
                   console.log('Mensagem HTML:', htmlMessage);

                   const textMessage = await messagesClient.getTextMessage(firstInboxId, firstMessageId);
                   console.log('Mensagem de Texto:', textMessage);

                   const headers = await messagesClient.getMailHeaders(firstInboxId, firstMessageId);
                   console.log('Cabeçalhos de Email:', headers);

                   const eml = await messagesClient.getMessageAsEml(firstInboxId, firstMessageId);
                   console.log('Mensagem como EML:', eml);

                   const htmlSource = await messagesClient.getMessageHtmlSource(firstInboxId, firstMessageId);
                   console.log('Fonte HTML:', htmlSource);

                   const rawMessage = await messagesClient.getRawMessage(firstInboxId, firstMessageId);
                   console.log('Mensagem Bruta:', rawMessage);

                   const spamScore = await messagesClient.getSpamScore(firstInboxId, firstMessageId);
                   console.log('Spam Score:', spamScore);

                   const emailMessage = await messagesClient.showEmailMessage(firstInboxId, firstMessageId);
                   console.log('Mensagem de Email:', emailMessage);

                   const updateStatus = await messagesClient.updateMessage(firstInboxId, firstMessageId, {
                       isRead: false
                   });
                   console.log('Status de Atualização:', updateStatus);

                   // Encaminha a mensagem (precisa ser um email confirmado para encaminhamento no Mailtrap)
                   // await messagesClient.forward(firstInboxId, firstMessageId, 'mock@mail.com');
                   // console.log('Mensagem encaminhada.');

                   // Exclui a mensagem
                   const response = await messagesClient.deleteMessage(firstInboxId, firstMessageId);
                   console.log('Resposta de Exclusão:', response);

               } else {
                   console.log('Nenhuma mensagem encontrada na primeira caixa de entrada.');
               }
           } else {
               console.log('Nenhuma caixa de entrada encontrada.');
           }
       })
       .catch(error => {
           console.error('Erro ao buscar caixas de entrada ou mensagens:', error);
       });
}).catch(console.error);

Com este código, estamos primeiro enviando um email de teste usando Nodemailer e recuperando as informações relacionadas ao email de teste programaticamente. Isso pode ser usado potencialmente para realizar automação. Este código apenas registra as informações do email de teste.

E claro, aqui está como seu arquivo .env deve se parecer para a API de Teste de Email:

MAILTRAP_TOKEN=''
SMTP_HOST='sandbox.smtp.mailtrap.io'
SMTP_PORT=2525
SMTP_USER=''
SMTP_PASS=''
EMAIL_FROM=''
TEST_INBOX_ID=
ACCOUNT_ID=

Para mais informações e casos de uso da API de Teste de Email do Mailtrap, confira a página oficial no GitHub.

Concluindo

E com isso, chegamos ao fim da linha!

Agora que você pegou o jeito, pode estilizar seu formulário de contato Node.js de acordo com seu olho artístico e fazê-lo funcionar de acordo com as necessidades específicas de sua aplicação.

Então, continue codificando e não deixe de dar uma olhada no nosso blog! Temos uma infinidade de artigos úteis relacionados ao JavaScript, incluindo:

Ivan Djuric, an author at Mailtrap
Article by Ivan Djuric Technical Content Writer @Mailtrap

I’m a Technical Content Writer with 5 years of background covering email-related topics in tight collaboration with software engineers and email marketers. I just love to research and share actionable insights with you about email sending, testing, deliverability improvements, and more. Happy to be your guide in the world of emails!