#!/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 getAccessToken(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 main() { const query = process.argv[2] || "Reservedele.nu FAKTURA 668926"; const credsPath = join(homedir(), ".openclaw/secrets/google-oauth.json"); const creds = JSON.parse(fs.readFileSync(credsPath, "utf8")); const accessToken = await getAccessToken(creds); console.log(`🔍 Searching for: "${query}"\n`); // Search for messages const searchUrl = `https://gmail.googleapis.com/gmail/v1/users/me/messages?q=${encodeURIComponent(query)}&maxResults=1`; const searchData = await httpsRequest(searchUrl, { headers: { Authorization: `Bearer ${accessToken}` }, }); if (!searchData.messages || searchData.messages.length === 0) { console.log("❌ No messages found"); return; } const messageId = searchData.messages[0].id; console.log(`📧 Found message ID: ${messageId}\n`); // Get full message with attachments const msgUrl = `https://gmail.googleapis.com/gmail/v1/users/me/messages/${messageId}?format=full`; const msg = await httpsRequest(msgUrl, { headers: { Authorization: `Bearer ${accessToken}` }, }); // Parse headers const headers = {}; for (const h of msg.payload.headers) { headers[h.name.toLowerCase()] = h.value; } console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); console.log(`From: ${headers.from || "Unknown"}`); console.log(`Subject: ${headers.subject || "No subject"}`); console.log(`Date: ${headers.date || "Unknown"}`); console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); // Get body let body = ""; function extractBody(part) { if (part.mimeType === "text/plain" && part.body?.data) { body += Buffer.from(part.body.data, "base64").toString("utf8"); } else if (part.mimeType === "text/html" && !body && part.body?.data) { // Fallback to HTML if no plain text const html = Buffer.from(part.body.data, "base64").toString("utf8"); // Strip HTML tags for basic display body += html .replace(/<[^>]*>/g, " ") .replace(/\s+/g, " ") .trim(); } if (part.parts) { for (const subpart of part.parts) { extractBody(subpart); } } } extractBody(msg.payload); if (body) { console.log("📄 MESSAGE BODY:\n"); console.log(body); console.log("\n"); } // Check for attachments const attachments = []; function findAttachments(part) { if (part.filename && part.body?.attachmentId) { attachments.push({ filename: part.filename, mimeType: part.mimeType, attachmentId: part.body.attachmentId, size: part.body.size, }); } if (part.parts) { for (const subpart of part.parts) { findAttachments(subpart); } } } findAttachments(msg.payload); if (attachments.length > 0) { console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); console.log(`📎 ATTACHMENTS (${attachments.length}):\n`); for (const att of attachments) { const sizeKB = (att.size / 1024).toFixed(2); console.log(` ${att.filename} (${sizeKB} KB)`); console.log(` Type: ${att.mimeType}`); // Download attachment const attUrl = `https://gmail.googleapis.com/gmail/v1/users/me/messages/${messageId}/attachments/${att.attachmentId}`; const attData = await httpsRequest(attUrl, { headers: { Authorization: `Bearer ${accessToken}` }, }); const buffer = Buffer.from(attData.data, "base64"); const outputPath = `/tmp/${att.filename}`; fs.writeFileSync(outputPath, buffer); console.log(` ✅ Downloaded to: ${outputPath}\n`); } } } main().catch((err) => { console.error("❌ Error:", err.message); process.exit(1); });