Skip to content

Instantly share code, notes, and snippets.

@GuilhermeRossato
Created January 15, 2024 11:48
Show Gist options
  • Save GuilhermeRossato/c9c438de03c0222764d4e4df097d3179 to your computer and use it in GitHub Desktop.
Save GuilhermeRossato/c9c438de03c0222764d4e4df097d3179 to your computer and use it in GitHub Desktop.
Node script to send an email through gmail using oauth2 (requires `googleapis` and `mimetext` npm modules)
// https://console.cloud.google.com/apis/credentials/oauthclient
const CLIENT_ID = "2######################################################################m";
const CLIENT_SECRET = "G#################################K";
const REDIRECT_URL = "http://localhost:8973/google-oauth/";
const targetEmail = process.argv[2];
const subject = process.argv[3] || "This is a test from a node script";
const htmlContent = process.argv[4] || "Hello world<br/>What's <b>Up?</b>";
const senderName = "Your Name";
const senderEmail = "your-email@gmail.com";
const { google } = require("googleapis"); // auth + send
const { createMimeMessage } = require("mimetext"); // creation of email
const fs = require("fs"); // cache credentials
const url = require("url"); // interactive login
const http = require("http"); // interactive login
const SCOPES = ["https://www.googleapis.com/auth/gmail.send"];
const CREDENTIALS_CACHE_FILE = "./tokens.json";
async function loadCredentials() {
const oauth2Client = new google.auth.OAuth2(
CLIENT_ID,
CLIENT_SECRET,
REDIRECT_URL
);
try {
// Try to authenticate from cache
const tokens = JSON.parse(
await fs.promises.readFile(CREDENTIALS_CACHE_FILE, "utf-8")
);
oauth2Client.setCredentials(tokens);
} catch (err) {
// Authenticate interactivetly
oauth2Client.on('tokens', (tokens) => {
fs.promises.writeFile(
CREDENTIALS_CACHE_FILE,
JSON.stringify(tokens, null, ' '),
"utf-8"
);
});
const urlToVisit = oauth2Client.generateAuthUrl({
access_type: "offline",
prompt: 'consent',
scope: SCOPES,
});
console.log("Enter this url to authenticate:");
console.log(urlToVisit);
const oauthCode = await new Promise((resolve, reject) => {
try {
const server = http.createServer((req, res) => {
if (req.url === "/favicon.ico") {
return res.writeHead(404).end();
}
try {
const searchParams = new url.URL(req.url, "http://localhost")
.searchParams;
const code = searchParams.get("code");
resolve(code);
} catch (err) {
reject(err);
}
res.end("You can close this page");
server.close();
});
server.on("error", reject);
server.listen(8973);
} catch (err) {
reject(err);
}
});
const response = await oauth2Client.getToken(oauthCode);
const tokens = response.tokens;
oauth2Client.setCredentials(tokens);
}
return oauth2Client;
}
async function init(oauth2Client) {
const gmail = google.gmail({ version: "v1", auth: oauth2Client });
const msg = createMimeMessage()
msg.setSender({name: senderName, addr: senderEmail})
msg.setRecipient(targetEmail)
msg.setSubject(subject)
msg.addMessage({
contentType: 'text/html',
data: htmlContent
});
const raw = msg.asRaw();
const response = await gmail.users.messages.send({
userId: "me",
requestBody: {
sizeEstimate: raw.length,
raw: Buffer.from(raw).toString("base64"),
},
});
if (!response || response.status !== 200 || !response.data) {
throw new Error(`Got unexpected response: ${JSON.stringify(response)}`);
}
console.log(JSON.stringify(response.data));
// {"id":"18d0ccf6xxxxxxxx","threadId":"18d0ccf6xxxxxxxx","labelIds":["UNREAD","SENT","INBOX"]}
}
loadCredentials().then(init).catch(console.error);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment