Skip to content

Instantly share code, notes, and snippets.

@hisabimbola
Created February 3, 2023 19:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hisabimbola/cfc9df00b4d713cc2021c1d18b357764 to your computer and use it in GitHub Desktop.
Save hisabimbola/cfc9df00b4d713cc2021c1d18b357764 to your computer and use it in GitHub Desktop.
group emails by sender
import { promises as fs } from 'fs';
import * as path from 'path'
import { authenticate } from '@google-cloud/local-auth';
import { gmail_v1, google } from 'googleapis'
import { JSONClient } from 'google-auth-library/build/src/auth/googleauth';
import { OAuth2Client } from 'google-auth-library';
const SCOPES = ['https://mail.google.com/'];
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
const TOKEN_PATH = path.join(process.cwd(), 'token.json');
const MAIL_LIST_PATH = path.join(process.cwd(), 'mail-list.json')
const MAILS_PATH = path.join(process.cwd(), 'mails.json')
const CREDENTIALS_PATH = path.join(process.cwd(), 'credentials.json');
function getResultPath(email: string) {
return path.join(process.cwd(), `result2-${email}.json`)
}
async function loadSavedCredentialsIfExist() {
try {
const content = await fs.readFile(TOKEN_PATH) as unknown as string;
const credentials = JSON.parse(content);
return google.auth.fromJSON(credentials);
} catch (err) {
return null;
}
}
async function saveCredentials(client: JSONClient | OAuth2Client) {
const content = await fs.readFile(CREDENTIALS_PATH) as unknown as string;
const keys = JSON.parse(content);
const key = keys.installed || keys.web;
const payload = JSON.stringify({
type: 'authorized_user',
client_id: key.client_id,
client_secret: key.client_secret,
refresh_token: client.credentials.refresh_token,
});
await fs.writeFile(TOKEN_PATH, payload);
}
async function authorize() {
let client: JSONClient | OAuth2Client | null
client = await loadSavedCredentialsIfExist();
if (client) {
return client;
}
client = await authenticate({
scopes: SCOPES,
keyfilePath: CREDENTIALS_PATH,
});
if (client?.credentials) {
await saveCredentials(client);
}
return client;
}
const mailList: gmail_v1.Schema$Message[] = []
async function listEmails(auth: JSONClient | OAuth2Client) {
const gmail = google.gmail({version: 'v1', auth})
let nextPageToken: string | undefined
let count = 0
do {
const res = await gmail.users.messages.list({
userId: 'me',
maxResults: 500,
pageToken: nextPageToken
})
mailList.push(...(res.data.messages || []))
count += res.data.messages?.length || 0
nextPageToken = res.data.nextPageToken as string | undefined
} while (nextPageToken)
console.log('fetched', count, 'messages')
console.log(mailList.length, 'count of messages')
await fs.writeFile(MAIL_LIST_PATH, JSON.stringify(mailList));
return auth
}
async function getCurrentUserEmail(auth: JSONClient | OAuth2Client) {
const gmail = google.gmail({version: 'v1', auth})
const res = await gmail.users.getProfile({
userId: 'me'
})
const email = res.data.emailAddress as string
return email.toLowerCase()
}
const senderMap = new Map()
async function getMails(auth: JSONClient | OAuth2Client) {
const gmail = google.gmail({version: 'v1', auth})
const rawData = await fs.readFile(MAIL_LIST_PATH) as unknown as string;
const mailList = JSON.parse(rawData);
let count = 0
const currentUserEmail = await getCurrentUserEmail(auth);
if (mailList.length) {
while(count < mailList.length) {
const res = await gmail.users.messages.get({
userId: 'me',
id: mailList[count].id,
format: 'metadata'
})
const message = res.data
const fromHeader = message.payload?.headers?.find((val) => val.name?.toLowerCase() === 'from')
let sender = fromHeader?.value?.match(/<(.*)>/)?.[1].toLowerCase()
if (!sender) {
sender = fromHeader?.value?.toLowerCase() as string
}
if (sender !== currentUserEmail && sender) {
senderMap.set(sender.toLowerCase(), (senderMap.get(sender.toLowerCase()) || 0) + 1)
}
count++
}
}
const sortedArray = [...senderMap.entries()].sort((a,b) => b[1] - a[1])
console.log(sortedArray)
await fs.writeFile(getResultPath(currentUserEmail), JSON.stringify(sortedArray, null, 2));
return auth
}
async function cleanUp() {
await fs.rm(MAIL_LIST_PATH)
}
authorize().then(listEmails).then(getMails).then(cleanUp).catch(console.error);
{
"dependencies": {
"@google-cloud/local-auth": "^2.1.0",
"googleapis": "^105.0.0"
},
"devDependencies": {
"@types/node": "^18.11.18"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment