Nodemail: Envio de email em ReactJS + Node.js + Nodemailer

No tutorial de hoje vou te ensinar a criar uma aplicação simples para envio de e-mail usando ReactJS, Node.js e Nodemailer. Apesar de simples, acredito que vai te ajudar a aprender uma série de coisas novas.

Use o sumário abaixo caso você queira aprender apenas frontend (interface) ou apenas o backend desta aplicação (que envia os emails).

Atenção: este é um tutorial intermediário. Se você não sabe programar NADA em ReactJS, comece por esta série aqui. E se não sabe programar NADA em Node.js, recomendo começar pela minha playlist no Youtube abaixo.

Frontend em ReactJS

O que acha de começarmos a nossa aplicação pelo frontend?

Nesta primeira etapa deste tutorial vou te ensinar a criar a camada de interface da nossa aplicação, que nada mais é do que um formulário de envio de email.

Vamos começar criando nosso projeto ReactJS, usando o comando abaixo.

Sim, isso vai demorar um pouco.

Depois de terminar, entre na pasta frontend e coloque o projeto a rodar com npm start. Agora toda vez que editar alguma coisa na aplicação, apenas salve e verá atualizado no seu navegador em localhost:3000.

Agora vamos editar o App.js dentro de src, para termos um formulário de envio de email, como abaixo.

E para estilizá-lo, altere o arquivo App.css substituindo os estilos dele pelos abaixo.

O resultado esperado você vê na imagem abaixo.

Nodemail Form
Nodemail Form

Vamos importar agora uma function do React chamada useState, que usaremos para mapear as mudanças de estados dos inputs do formulário.

E usaremos ela da seguinte maneira, definindo valores iniciais para as variáveis de estados que iremos monitorar.

A function handleInputChange irá ser disparada toda vez que um campo do formulário for alterado. Ela recebe um objeto event por parâmetro que, dentre suas várias propriedades tem o target, que é o campo que originou o evento. Com este target, conseguimos descobrir o name e o value atualizado do mesmo.

Cada vez que essa function for disparada, vamos chamar o setCampos atualizando uma propriedade dinamicamente com base no event.target.name e o seu valor com o event.target.value.

A única diferença é quando o campo é o input-file, porque nele temos de ler a propriedade files ao invés de value.

Ok, preparamos o terreno para a leitura dos campos, agora falta associarmos  a function handleInputChange a cada um dos componentes do formulário. Todos eles possuem uma propriedade onChange, que você deve preencher com o nome da função. Abaixo, apenas o exemplo do input de nome, preencha também os demais.

E para ver se nossos campos foram lidos corretamente a cada modificação, ou seja, se o estado dos campos está sendo monitorado corretamente, vamos criar uma function para mapear a submissão do formulário (ainda dentro da function principal do App.js):

Essa função é bem simples, além de imprimir no console o campos mapeados, ela previne o comportamento padrão do formulário de acontecer. Isso porque, por padrão, o HTML FORM tem uma série de comportamentos ligados à sua submissão como enviar todos a página para o servidor, mas não queremos isso.

Essa função deve ser adicionada no campo onSubmit da tag FORM do seu HTML, como abaixo.

Agora, ao rodar a nossa aplicação ReactJS, preencher os campos do formulário e clicar no botão de Salvar, o console do navegador deve exibir o objeto JSON dos campos mapeados.

Form Preparado
Form Preparado

Isso mostra que nosso frontend está pronto!

Backend em Node.js

Quer você já tenha criado o frontend deste mesmo tutorial ou tem o seu próprio frontend, seja ele web ou mobile, esta seção vai te ajudar a construir uma web API em Node.js como sendo o seu backend, responsável pelo recebimento das informações da interface e envio do email em si, usando Nodemailer, a biblioteca mais popular em Node.js para esta finalidade.

Crie uma pasta backend e rode um npm init dentro dela para inicializar um projeto Node.js. Depois, instale as dependências que vamos usar:

Primeiro, vamos fazer a web API apenas receber os dados do formulário e devolver na própria resposta. A construção abaixo é de um arquivo api.js usa ExpressJS como web framework criando apenas uma rota GET simples e um POST que ecoa o request recebido. Note que usei o CORS aqui, para permitir que essa web API seja chamada pelo frontend mais tarde.

Se você colocar este arquivo para rodar ele vai ficar aguardando um POST em http://localhost:3030/send.Você pode testar no Postman, Insomnia ou via cURL mesmo.

Abaixo, resultado no Postman.

Send no Postman
Send no Postman

O próximo passo, é criarmos um módulo de envio de emails, que vamos chamar de nodemail.js, com o conteúdo abaixo.

Este módulo exporta somente uma única função de envio que recebe os dados do destinatário, possui as configurações SMTP no seu interior e envia o email, retornando uma Promise para ser tratada externamente. Minha sugestão pessoal é que use serviços profissionais de SMTP Gateway como Mailchimp Transactional, SendGrid e AWS SES.

Note que tomei o cuidado de fazer um tratamento especial quando vier um anexo, para adicioná-lo adequadamente à mensagem de email.

Agora, vamos alterar o conteúdo do nosso POST para usar o módulo que criamos anteriormente.

Note que adicionei um middleware ‘upload’ baseado em Multer. Este middleware servirá para receber o anexo que for enviado para a API, quando houver, pois ele é transferido como uma stream de bytes, ao invés de JSON tradicional, que será carregado em req.file ao invés de req.body.

Este ponto é muito importante: para que sua Web API consiga receber tanto o JSON quanto arquivos anexos, o Content-Type do HTTP Request deve ser multipart/form-data.

Se você testar novamente com Postman, dessa vez além de ver que continua funcionando, o email chegará no destino que você preencheu. Note na imagem abaixo que usei o tipo de request form-data, onde além de colocar key-values para os campos da mensagem, consigo adicionar um campo File contendo um arquivo qualquer (basta passar o mouse sobre a key do campo e aparece a opção File).

Postman form-data
Postman form-data

Isso garante que o nosso backend está funcionando, inclusive com anexos.

Plugando as partes

Agora que temos o nosso frontend e nosso backend construídos, é hora de conectar as duas pontas.

Vamos fazer isso no frontend, usando o Axios, um pacote muito popular em Node.js para fazer chamadas HTTP, para fazer a comunicação. Primeiramente, instale-o via NPM.

E no cabeçalho do arquivo App.js do frontend, vamos alterar os imports no topo.

Dentro da função  principal do App.js, vamos criar uma nova função para envio dos campos para a API, usando Axios, além de alterar o handleFormSubmit para chamar esta nova função.

Este uso do Axios é ligeiramente diferente do que você já deve ter visto na internet. Como o request vai conter tanto campos quanto um possível anexo ao email, teremos de usar o Content-Type multipart/form-data em nossa requisição POST. Esse tipo de conteúdo espera receber um objeto FormData com todos os campos e arquivos a serem postados.

Repare também no uso de um boundary que serve para a web API saber como separar os conteúdos do FormData.

Agora, se você subir o seu backend Node.js e o seu frontend ReactJS, verá que você consegue usar o formulário de envio normalmente, incluindo anexos quando quiser enviar mensagens com eles.

Ufa, enfim chegamos no final deste tutorial!

Espero que tenha gostado e, se tiver qualquer dúvida, deixe nos comentários.

Para receber os fontes, cadastre-se no formulário ao final deste artigo.

Como próximo passo, que tal aprender como publicar a sua aplicação na Amazon AWS? Clique neste link.

E se quiser aprender a aumentar a escalabilidade dessa web api, dá uma olhada no vídeo abaixo.

E para conhecer o meu curso de Node.js e MongoDB, clique no banner abaixo!

Curso Node.js e MongoDB
Curso Node.js e MongoDB

Publicado por

Luiz Duarte

Pós-graduado em computação, professor, empreendedor, autor, Agile Coach e programador nas horas vagas.