Pular para o conteúdo principal

Nodemailer e Google APIs

Por Rafaela Fernanda

Atualizado em: 20/02/2024

✏️ Introdução

Ao desenvolver um projeto, pode ser necessária a implementação de um form. A presença de um formulário em uma página aproxima o contato do nosso contratante com o público-alvo de seu serviço ou produto, permitindo que um potencial cliente consiga uma comunicação direta para esclarecimento de dúvidas ou demosntração de interesse em efetuar uma compra. Para que esse contato aconteça, é necessário que as informações preenchidas cheguem até o proprietário da página, não é mesmo? Com esse propósito, podemos fazer uso do Nodemailer, um módulo do Node.js que possibilita o envio rápido e prático de e-mails.

💡 O que precisamos para fazer o Nodemailer funcionar corretamente?

  • Instalar o nodemailer nas dependências do seu projeto;
  • Instalar também googleapis (biblioteca para uso de APIs do Google e que será utilizada para gerar tokens de acesso);
  • Instalar, por fim, dotenv (biblioteca para uso de variáveis de ambiente e para evitar API keys no código);
  • Ter uma conta Google para configuração das chaves e credenciais;
  • Criar um código que aplique tudo isso ao seu formulário.

⚙️ Passo a passo

Configurando as credenciais do OAuth 2.0:

Primeiro, vamos deixar o código do projeto de lado por um momento para gerar as variáveis de ambiente. Ao fazer uso delas, você evita que informações sensíveis como endereços de e-mail e senhas fiquem expostas no código.

Para isso, é necessário acessar o Google Developer Console e criar um projeto para gerar as credenciais necessárias.

É importante ter em mente que a conta de e-mail utilizada para realizar o processo, é a que ficará como remetente.


✔ TUTORIAL ✔

O site Dev possui uma explicação detalhada e completa fazendo uso de imagens para a demonstração das etapas de configuração. Seguindo corretamente o que é pedido, você terá tudo o que precisa para começar o próximo passo.

Por garantia caso o site saia do ar, salvamos a página como PDF no drive compartilhado interno da CT


Com os dados de client ID, client secret e client token em mãos, é hora de fazer tudo acontecer!

Criando os arquivos nas dependências do projeto

Primeiro, crie um arquivo .env.example na raiz do seu projeto contendo as informações que serão requeridas. Faça as modificações necessárias nos modelos fornecidos de acordo com as especificações do seu escopo.

NEXT_PUBLIC_MAIL_USER='email@dousuario.com.br'
NEXT_PUBLIC_MAIL_RECEIVER='email@dodestinatario.com.br'

NEXT_PUBLIC_OAUTH_CLIENTID='idClient'
NEXT_PUBLIC_OAUTH_CLIENT_SECRET='secretClient'
NEXT_PUBLIC_OAUTH_REFRESH_TOKEN='refreshToken'
Cuidado

Perceba que o prefixo

NEXT_PUBLIC_

deverá ser adicionado às variáveis de ambiente ao utilizar as tecnologias Next e Vercel, como informado nessa Documentação da Vercel

Em seguida, crie seu arquivo mailService.ts. Após realizar o devido import dos pacotes (não se esqueça do SMTPTransport, que tem import atrelado ao nodemailer), é preciso incluir:

  • Os parâmetros que a função deve receber (campos do seu formulário a serem enviados);
  • O objeto transporter;
  • O objeto mailOptions;
  • O método sendMail.

Para o transporter, utilizaremos SMTPTransport e além do service e type padrões, o user será o remetente especificado por você e os demais campos, as chaves previamente configuradas.

const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
type: 'OAuth2',
user: process.env.NEXT_PUBLIC_MAIL_USER,
clientId: process.env.NEXT_PUBLIC_OAUTH_CLIENTID,
clientSecret: process.env.NEXT_PUBLIC_OAUTH_CLIENT_SECRET,
refreshToken: process.env.NEXT_PUBLIC_OAUTH_REFRESH_TOKEN,
},
} as SMTPTransport.Options);

Partindo para o mailOptions, é onde você poderá definir os detalhes do destinatário e dados do e-mail.

const mailOptions = {
from: `"${name} via Formulário de Teste do CT Junior Docs. Email: <${email}>"`,
to: process.env.NEXT_PUBLIC_MAIL_RECEIVER,
subject: 'Aqui vai o assunto do e-mail'
text: 'Aqui vai o conteúdo:\n Email: ${email}\nName: ${name}\nPhone: ${phone}'
};

  • FROM: Breve especificação que aparecerá no campo "De" do e-mail, elucidando de onde ele foi gerado;

  • TO: Recebe o endereço de e-mail do destinatário;

  • SUBJECT: Defina uma mensagem objetiva que facilite a filtragem da caixa de entrada;

  • TEXT: Você pode especificar uma mensagem padrão e não se esqueça de incluir os dados obtidos através do preenchimento do formulário pelo usuário, afinal, é o objetivo de tudo.


Passamos então para o sendMail, que efetuará a ação utilizando o transporter. A função é encapsulada em uma promise para garantir que o envio seja assíncrono.

await new Promise((resolve, reject) => {
transporter.sendMail(mailOptions, (err, response) => {
if (err) {
reject(err);
throw err;
} else {
resolve(response);
}
});
});

Após configurar este arquivo, crie a pasta api/emailRouting contendo o arquivo route.ts. Lembre-se de substituir os "data.xxxx" pelos dados que de fato estão sendo coletados no seu formulário.

Esse arquivo é uma rota de API para uma aplicação do Next.js, exportando uma função POST que recebe os dados do formulário. Dentro dela os dados são extraídos, e então, a função sendMail é chamada. Se o e-mail for enviado com sucesso, a rota retorna success: true, retornando success: false caso contrário.

import { NextRequest, NextResponse } from 'next/server';

import sendMail from '@/app/mailService';

export async function POST(req: NextRequest) {
const data = await req.json();

if (req.method === 'POST') {
try {
await sendMail(data.name, data.email, data.phone);
return NextResponse.json({ success: true });
} catch (err) {
return NextResponse.json({ success: false });
}
}
}

É importante tomar cuidado pois a identificação da rota pode ser um problema. O Next.js tem algumas formas de fazer roteamento, como API Routes e Route Handlers. É sugerida a leitura das documentações linkadas para prevenir possíveis problemas.

Fazendo as devidas verificações no Forms

Com tudo isso feito, hora de implementar as funções no seu arquivo de formulário que farão as devidas verificações de input válido ou inválido. Não se esqueça de incluir verificações que não permitam o envio de campos vazios. Defina os devidos valores nas tags de input e inclua a função de envio do form.

Adicione a função try-catch que faz a requisição para a rota já configurada. O código exemplo usa a verificação para retornar um toast de sucesso ou de erro no envio do e-mail em forma de mensagem pop-up na tela do usuário. Personalize conforme necessário.

try {
await fetch('api/emailRouting', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body,
});
toast({
title: 'Email enviado com sucesso!',
status: 'success',
isClosable: true,
position: 'bottom-left',
});
setIsLoading(false);
} catch (error) {
toast({
title: 'Email não enviado!',
status: 'error',
isClosable: true,
position: 'bottom-left',
});
setIsLoading(false);
}

Configurando as variáveis de ambiente na Vercel

Após longas etapas, você está chegando ao final! O passo agora é configurar as variáveis já obtidas ao fazer deploy na Vercel.

❗ Não se esqueça que o e-mail utilizado para configurar o Google, deve ser o mesmo declarado como MAIL_USER.

Está pronto, agora seu formulário é funcional!

🤝 Dicas úteis: (ou Observações)

Caso você precise de referências de projetos que utilizem o que foi explicado no presente manual, faça estudo dos repositórios ZanelatoBarreto, LandingPage-Civil e Redes - Site no GitHub da CT Junior.