#!/usr/bin/env node const fs = require("fs"); const https = require("https"); const { homedir } = require("os"); const { join } = require("path"); function httpsRequest(url, options = {}) { return new Promise((resolve, reject) => { const req = https.request(url, options, (res) => { let data = ""; res.on("data", (chunk) => (data += chunk)); res.on("end", () => { if (res.statusCode >= 400) { reject(new Error(`HTTP ${res.statusCode}: ${data}`)); } else { resolve(JSON.parse(data)); } }); }); req.on("error", reject); if (options.body) req.write(options.body); req.end(); }); } async function getGoogleAccessToken(creds) { const body = new URLSearchParams({ client_id: creds.client_id, client_secret: creds.client_secret, refresh_token: creds.refresh_token, grant_type: "refresh_token", }).toString(); const data = await httpsRequest("https://oauth2.googleapis.com/token", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "Content-Length": Buffer.byteLength(body), }, body, }); return data.access_token; } async function getMicrosoftAccessToken(creds) { const body = new URLSearchParams({ client_id: creds.client_id, refresh_token: creds.refresh_token, grant_type: "refresh_token", scope: "https://graph.microsoft.com/Mail.Read offline_access", }).toString(); const tenant = creds.tenant || "consumers"; const data = await httpsRequest(`https://login.microsoftonline.com/${tenant}/oauth2/v2.0/token`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "Content-Length": Buffer.byteLength(body), }, body, }); return data.access_token; } async function searchGmail(accessToken, query, maxResults = 20) { const encodedQuery = encodeURIComponent(query); const url = `https://gmail.googleapis.com/gmail/v1/users/me/messages?maxResults=${maxResults}&q=${encodedQuery}`; return await httpsRequest(url, { headers: { Authorization: `Bearer ${accessToken}` }, }); } async function getGmailMessage(accessToken, id) { const url = `https://gmail.googleapis.com/gmail/v1/users/me/messages/${id}`; return await httpsRequest(url, { headers: { Authorization: `Bearer ${accessToken}` }, }); } async function searchOutlook(accessToken, query, maxResults = 20) { const url = `https://graph.microsoft.com/v1.0/me/messages?$top=${maxResults}&$search="${query}"`; return await httpsRequest(url, { headers: { Authorization: `Bearer ${accessToken}` }, }); } function getHeader(headers, name) { const h = headers.find((h) => h.name.toLowerCase() === name.toLowerCase()); return h ? h.value : ""; } async function main() { const searchQuery = process.argv[2] || "BIOS graphics GPU grafikkort"; console.log(`šŸ” Searching for: "${searchQuery}"\n`); // Gmail console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); console.log("šŸ“§ Gmail"); console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); const gmailCreds = JSON.parse( fs.readFileSync(join(homedir(), ".openclaw/secrets/google-oauth.json"), "utf8"), ); const gmailToken = await getGoogleAccessToken(gmailCreds); const gmailResults = await searchGmail(gmailToken, searchQuery); if (gmailResults.messages && gmailResults.messages.length > 0) { for (const msg of gmailResults.messages.slice(0, 5)) { const full = await getGmailMessage(gmailToken, msg.id); const from = getHeader(full.payload.headers, "From"); const subject = getHeader(full.payload.headers, "Subject"); const date = getHeader(full.payload.headers, "Date"); const labels = full.labelIds || []; const isUnread = labels.includes("UNREAD"); console.log(`${isUnread ? "šŸ”“" : "āœ…"} From: ${from}`); console.log(` Subject: ${subject}`); console.log(` Date: ${date}`); console.log(` Preview: ${full.snippet}`); console.log("---"); } } else { console.log("No matches found.\n"); } // Outlook console.log("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); console.log("šŸ“§ Outlook"); console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); const outlookCreds = JSON.parse( fs.readFileSync(join(homedir(), ".openclaw/secrets/outlook-oauth.json"), "utf8"), ); const outlookToken = await getMicrosoftAccessToken(outlookCreds); const outlookResults = await searchOutlook(outlookToken, searchQuery); if (outlookResults.value && outlookResults.value.length > 0) { for (const msg of outlookResults.value.slice(0, 5)) { console.log( `${msg.isRead ? "āœ…" : "šŸ”“"} From: ${msg.from?.emailAddress?.name || msg.from?.emailAddress?.address}`, ); console.log(` Subject: ${msg.subject}`); console.log(` Date: ${msg.receivedDateTime}`); console.log(` Preview: ${msg.bodyPreview}`); console.log("---"); } } else { console.log("No matches found.\n"); } // Office365 console.log("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); console.log("šŸ“§ Office365"); console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); const o365Creds = JSON.parse( fs.readFileSync(join(homedir(), ".openclaw/secrets/outlook-o365-oauth.json"), "utf8"), ); const o365Token = await getMicrosoftAccessToken(o365Creds); const o365Results = await searchOutlook(o365Token, searchQuery); if (o365Results.value && o365Results.value.length > 0) { for (const msg of o365Results.value.slice(0, 5)) { console.log( `${msg.isRead ? "āœ…" : "šŸ”“"} From: ${msg.from?.emailAddress?.name || msg.from?.emailAddress?.address}`, ); console.log(` Subject: ${msg.subject}`); console.log(` Date: ${msg.receivedDateTime}`); console.log(` Preview: ${msg.bodyPreview}`); console.log("---"); } } else { console.log("No matches found.\n"); } } main().catch((err) => { console.error("Error:", err.message); process.exit(1); });