Envio de e-mail com nodemailer

Envio de e-mail com nodemailer
nodemailer

Nesta postagem vamos aprender como fazer o envio de e-mails utilizando o node mailer.

O código completo está disponível no github.

Primeiramente vamos criar uma aplicação de envio de email, para fazer o envio vamos utilizar o nodejs em conjunto com o nodemailer.

Para este exemplo temos que ter uma conta do Gmail, pois é com a conta do Gmail que vamos fazer o encaminhamento das mensagens para uma caixa postal de e-mail.

Vamos criar uma aplicação express, que mostra uma pagina web com um formulário para envio de mensagem. Após o usuário preencher os dados e clicar em enviar é feita a submissão de dados do formulário (utilizando o método HTTP post) para o e-mail, através do backend.

Crie um novo diretório que vai armazenar a sua aplicação, escolha um nome representativo e depois é só iniciar um novo projeto nodejs com o comando init.

Após criar o projeto basta adicionar duas dependências, o express e o nodemailer. Para isto execute o comando:

npm i express nodemailer

No código inicial, na raiz do diretório, crie um arquivo app.js que vai conter o esboço inicial da aplicação. E aos poucos vamos incrementar até ter um fluxo completo de envio de e-mail.

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

module.exports = app;

Depois criar o executável da aplicação, este executável vai conter apenas as instruções de fazer o listen da aplicação em uma porta.

Conteúdo do arquivo bin/www

#!/usr/bin/env node
const app = require('../app');
const port = process.env.PORT || 3000
try {
    app.listen(port);
    console.log(`Microsservice listening at http://localhost:${port}`);
} catch (err) {
    throw err;
}

Agora vamos apenas adicionar uma nova entrada na seção scripts do package.json.

{
  "name": "mailsender",
  "version": "1.0.0",
  "description": "mail sender with express nodemailer",
  "main": "app.js",
  "scripts": {
    "start": "node ./bin/www",
    "dev": "nodemon ./bin/www"
  },
  "keywords": [
    "express",
    "nodemailer"
  ],
  "dependencies": {
    "express": "^4.17.3",
    "nodemailer": "^6.6.3"
  }
}

Este era apenas o boilerplate inicial para a gente começar o projeto, vamos iniciar a implementação de nosso serviço, a aplicação vai seguir este fluxo para realizar o envio de um e-mail.

De maneira geral, o nosso formulário de contato vai seguir o fluxo deste diagrama de máquina de estado:

diagrama de máquina de estado fluxo formulário contato

Para isso basta implementar agora as rotas disponíveis em nossa aplicação.

Rota GET - Servindo o formulário

Vamos criar a rota GET /contato que vai servir o formulário e a rota POST /contato que vai fazer a submissão dos dados do  formulário.

Após fazer a submissão do formulário o usuário será redirecionado para uma página de enviado com sucesso.

Para implementar este fluxo, crie a rota /contato na aplicação. Para isso vamos estruturar o nossa aplicação e criar uma pasta server e dentro desta pasta vamos criar um arquivo chamado index.js

A estrutura atual do projeto deve estar desta forma:

.
├── _app.js
├── _server
│   └── index.js
└── _bin
    └── www

A seguir temos o conteúdo do arquivo server/index.js

const nodemailer = require('nodemailer');
const router = require('express').Router();
const html = `
<!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Contato</title>
      </head>
      <body>
        <form id="suggestion-form" method="post" action="/contato">
            <label><span>Name</span></label>
            <input id="name" name="name" type="text" placeholder="Name" required/>
            <br>
            <label>E-mail</label>
            <input id="email" name="email" type="email" placeholder="E-mail" required></input>
            <br>
            <label><span>Suggestions</span></label>
            <input id="message" name="message" type="text" placeholder="How can we improve?" required></input>
            <br>
            <button type="submit" value="submit"><span>Submit</span></button>
        </form>
      </body>
</html>`

router.get('/contato', (req, res) => {
    res.status(200).send(html);
});

module.exports = router;

Estamos declarando a variável html onde estamos servindo o html inline. Isso é apenas para facilitar o desenvolvimento da aplicação, ao final vamos refatorar para fazer a utilização correta, servindo o html via o sistema de arquivos da máquina.

Depois de criar esta rota, basta adicionar agora ao nosso app.js a referência para este arquivo criado.

require('dotenv').config();
const express = require('express');
const app = express();
app.use(express.json());

app.use(require('./server/index'));
module.exports = app;

Agora para visualizar o que já implementamos, basta iniciar a aplicação e via um browser entrar no endereço que está sendo servido pela aplicação express.

Para isto basta executar o comando:

npm start

Isso é o conteúdo de nossa página ao acessar via o browser:

formulário contato

Pronto, agora já temos a base para a iniciar a nossa página de contato e começar a utilizar o nodemailer.

A ideia aqui é não expor publicamente o nosso e-mail em uma página publica.

Rota POST - enviando e-mail com nodemailer.

Primeiramente vamos criar o transporter,  esse objeto vai ser o responsável por fazer a conexão com o servidor de e-mail. Para este exemplo vamos utilizar o Gmail. Vou deixar os valores para você preencher com os seus dados. Então use a sua conta do Gmail para fazer o acesso. Digite o nome do usuário no atributo user e a senha no atributo pass.

O transporter é um objeto compartilhado e global. Sempre que a gente quiser fazer o envio de email é com esta instância que vamos interagir.

Depois vamos definir um middleware para tratar quando houver uma chamada post na rota /contato, ela vai ser responsável por fazer o envio dos dados do form.

Vamos incrementar o conteúdo do arquivo server/index.js

const transporter = nodemailer.createTransport({
    service: 'smtp.gmail.com',
    host: 'smtp.gmail.com',
    port: 587,
    secure: false, // true for 465, false for other ports
    tls: {
        rejectUnauthorized: false
    },
    auth: {
        user: 'nomedousuario',
        pass: 'senha-do-endereço-de-email'
    },
    logger: false, // log to console
    debug: false // include SMTP traffic in the logs
});
sendEmail = (req, res) => {
    const mailmsg = {
        from: 'nomedousuario',
        subject: 'Teste',
        text: 'Mensagem de: ' + req.body.name + ', email: [' + req.body.email + '] ' + req.body.message,
        to: 'email@teste.com.br'
    }; // preencher destinatário do email
    transporter.sendMail(mailmsg).then((trans) => {
        res.status(200).send('E-mail enviado ✔️ com sucesso');
    }).catch((error) => {
        res.status(500).send('Houve um erro ao enviar e-mail. Detalhe: ' + error);
    });
}
router.post('/contato', sendEmail);

Agora ao preencher o atributo from você deve colocar o mesmo valor do atributo usuário. Ao preencher o atributo to devemos preencher com o endereço de email para o qual desejamos encaminhar as mensagens que serão enviadas a partir da nossa página de contato.

Com isso finalizamos o nosso fluxo de envio de mensagens.

Você pode baixar este projeto.