Nesse tutorial você vai aprender de forma prática como criar sistema que se autentica no OAuth do Google para ler e-mails usando o Gmail API.
A API do Gmail é muito útil para a criação de aplicativos para poder identificar e-mails indesejados e também oferecer serviços em forma de SaaS para limpar caixas de entradas.
Utilizaremos a seguinte stack nesse tutorial:
- Frontend: Javascript (fetch + botão de login)
- Backend: Nodejs usando o módulo Express
- Biblioteca npm: googleapis
- OAuth: Google Cloud Console (GCP)
Criar as credenciais necessárias para autenticar no OAuth
- Vá em https://console.cloud.google.com
- Crie um novo projeto
- Acesse Google Auth Platform → Clientes → Criar cliente
Preencha o formulário, informando o tipo de aplicativo como Aplicativo da Web, dê um nome ao seu novo aplicativo, e em URIs de redirecionamento autorizados, informe http://localhost:4000/oauth/receive, que vai ser utilizado em nosso exemplo.
Clique em Criar e no próximo popup, anote o ID do cliente (Client ID) e a Chave secreta do cliente (Client Secret), vamos precisar dessas informações adiante. - Acesse Google Auth Platform → Branding e preencha o nome do app, e-mail para suporte do usuário e dados do contado do desenvolvedor para iniciarmos os testes.
Configurando o backend (Nodejs + Express)
Instalar dependências
Crie uma nova pasta para iniciar um novo projeto NodeJS.
Abra o terminal ou o prompt de comando e digite o código abaixo.
npm init -y npm install express express-session googleapis body-parser
Estrutura de pastas do nosso projeto
project/
├─ server.mjs
├─ tokens.json
└─ public/
└─ index.html
Arquivo server.mjs
Crie o arquivo server.mjs e altere a variável CLIENT_ID com o seu ID do cliente, e o CLIENT_SECRET com a Chave secreta do cliente
import express from "express";
import session from "express-session";
import fs from "fs";
import { google } from "googleapis";
import bodyParser from "body-parser";
const app = express();
const PORT = 4000;
const CLIENT_ID = "INSIRA_SEU_CLIENT_ID"; // Exemplo: 292545165314-jqgquadfjl5pjh53vbosj0k8djm91u6r.apps.googleusercontent.com
const CLIENT_SECRET = "INSIRA_SEU_CLIENT_SECRET"; // Exemplo: GOCSPX-2rmk...(omitido)
const REDIRECT_URI = "http://localhost:4000/oauth/receive";
const SCOPES = ["https://www.googleapis.com/auth/gmail.readonly"];
const oAuth2Client = new google.auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI);
app.use(express.static("public"));
app.use(bodyParser.json());
app.use(
session({
secret: "informar-string-aleatoria",
resave: false,
saveUninitialized: true,
})
);
const TOKENS_FILE = "./tokens.json";
let tokensDB = {};
if (fs.existsSync(TOKENS_FILE)) {
tokensDB = JSON.parse(fs.readFileSync(TOKENS_FILE));
}
function saveTokens() {
fs.writeFileSync(TOKENS_FILE, JSON.stringify(tokensDB, null, 2));
}
app.get("/oauth/redir/:email", (req, res) => {
const { email } = req.params;
if (!email) return res.status(400).send("Email é obrigatório.");
req.session.email = email;
const authUrl = oAuth2Client.generateAuthUrl({
access_type: "offline",
scope: SCOPES,
prompt: "consent",
});
res.json({ url: authUrl });
});
app.get("/oauth/receive", async (req, res) => {
const code = req.query.code;
const email = req.session.email;
if (!code || !email) return res.send("Erro: sessão expirada ou código inválido.");
const { tokens } = await oAuth2Client.getToken(code);
tokensDB[email] = tokens;
saveTokens();
res.send(`
<h2>Autorizado com sucesso!</h2>
<p>Conta: ${email}</p>
<a href="/">Voltar</a>
`);
});
app.get("/emails/:email", async (req, res) => {
const email = req.params.email;
const tokens = tokensDB[email];
if (!tokens) return res.status(400).send("Email não autorizado.");
oAuth2Client.setCredentials(tokens);
const gmail = google.gmail({ version: "v1", auth: oAuth2Client });
try {
const response = await gmail.users.messages.list({
userId: "me",
maxResults: 10,
});
const messages = response.data.messages || [];
const messageData = [];
for (const msg of messages) {
const fullMsg = await gmail.users.messages.get({
userId: "me",
id: msg.id,
});
const headers = fullMsg.data.payload.headers;
const subject = headers.find((h) => h.name === "Subject")?.value || "(Sem assunto)";
const from = headers.find((h) => h.name === "From")?.value || "(Desconhecido)";
messageData.push({ id: msg.id, subject, from });
}
res.json(messageData);
} catch (err) {
console.error(err);
res.status(500).send("Erro ao listar emails");
}
});
app.get("/email/:email/:id", async (req, res) => {
const { email, id } = req.params;
const tokens = tokensDB[email];
if (!tokens) return res.status(400).send("Email não autorizado.");
oAuth2Client.setCredentials(tokens);
const gmail = google.gmail({ version: "v1", auth: oAuth2Client });
try {
const message = await gmail.users.messages.get({
userId: "me",
id,
format: "full",
});
const body = message.data.payload.parts?.find(
(p) => p.mimeType === "text/html"
)?.body?.data;
const htmlBody = body
? Buffer.from(body, "base64").toString("utf8")
: "<p>(Sem conteúdo)</p>";
res.send(`
<h2>${id}</h2>
<div>${htmlBody}</div>
<a href="/">Voltar</a>
`);
} catch (err) {
console.error(err);
res.status(500).send("Erro ao carregar email");
}
});
app.listen(PORT, () => console.log(`🚀 Servidor rodando em http://localhost:${PORT}`));
Arquivo tokens.json
Crie um arquivo JSON vazio, inicializando o objeto JSON conforme o código abaixo.
{}
public/index.html
Crie o arquivo index.html dentro da pasta public. Altere o exemplo abaixo com o e-mail que você utilizará para testar a API. No meu caso, estou utilizando o meu e-mail pessoal para testar.
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8" />
<title></title>
<style>
body {
font-family: Arial;
margin: 20px;
}
input,
button {
padding: 8px;
margin-top: 5px;
}
.email-item {
border-bottom: 1px solid #ccc;
padding: 5px;
}
.email-item:hover {
background: #f5f5f5;
cursor: pointer;
}
</style>
</head>
<body>
<section id="auth">
<button id="authButton">Autenticar</button>
<button id="loadEmailsBtn">Carregar E-mails</button>
</section>
<h2>Emails</h2>
<div id="emailsList"></div>
<script>
const authButton = document.getElementById('authButton');
const loadEmailsBtn = document.getElementById('loadEmailsBtn');
const emailsList = document.getElementById('emailsList');
authButton.onclick = async () => {
if (!email) return;
// Nesse exemplo eu estou usando o meu e-mail, altere para o e-mail que você vai logar no oauth
// qualquer dúvida é só entrar em contato
try {
const response = await fetch(`http://localhost:4000/oauth/redir/leandro.edgedigital@gmail.com`, {
method: 'GET',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
}
});
const data = await res.json();
window.location.href = data.url;
} catch (error) {
console.error('Erro:', error);
}
};
loadEmailsBtn.onclick = async () => {
loadEmails("leandro.edgedigital@gmail.com");
}
async function loadEmails(email) {
const res = await fetch(`/emails/${email}`);
const emails = await res.json();
emailsList.innerHTML = emails.map(e => `
<div class="email-item" onclick="viewEmail('${email}','${e.id}')">
<strong>${e.subject}</strong><br>
<small>${e.from}</small>
</div>
`).join('');
}
async function viewEmail(email, id) {
window.location.href = `/email/${email}/${id}`;
}
</script>
</body>
</html>
Rodando o projeto
Para rodar o projeto, execute o código abaixo dentro da pasta do projeto.
node server.mjs
Ao executar o código acima, você deverá ver a seguinte mensagem em seu terminal/prompt de comando:
node server.mjs 🚀 Servidor rodando em http://localhost:4000
Abra o seu navegador na página http://localhost:4000 e teste clicando em Autenticar.

Após a autenticação, visualize os e-mails de sua caixa de entrada clicando em Carregar E-mails e visualize o conteúdo do e-mail clicando no e-mail ou acessando http://localhost:4000/email/:seu-email-gmail/:id-do-email
Espero que tenham gostado! Se tiver algum erro, é só entrar em contato comigo em meu e-mail leandro.edgedigital@gmail.com! Até!
Deixe uma resposta