#!/usr/bin/env node /** * Check anthonymau@gmail.com for new AI-related emails * Fetches full email content for summarization */ const Imap = require('imap'); const config = { user: 'anthonymau@gmail.com', password: 'wfux qjhw eqjo jswm', host: 'imap.gmail.com', port: 993, tls: true, tlsOptions: { rejectUnauthorized: false } }; // AI newsletter patterns to match const AI_PATTERNS = [ 'ai valley', 'the rundown', 'ai secret', 'byte-sized', 'bytesized', 'myclaw', 'openai global', 'deep view', 'khoj', 'synthetic', 'openhands', 'artificial intelligence', 'ai newsletter', 'benevolent', 'tldr', 'benedict' ]; function isAINewsletter(from, subject) { const text = (from + ' ' + subject).toLowerCase(); return AI_PATTERNS.some(pattern => text.includes(pattern.toLowerCase())); } const imap = new Imap(config); imap.once('ready', () => { imap.openBox('INBOX', false, (err, box) => { if (err) { console.log('STATUS:error'); console.log('ERROR:open_box:' + err.message); imap.end(); process.exit(1); } imap.search(['ALL'], (err, results) => { if (err) { console.log('STATUS:error'); console.log('ERROR:search:' + err.message); imap.end(); process.exit(1); } const total = results.length; const recent = results.slice(-200); // Get last 200 emails (covers ~2 days for most inboxes) const lastUid = recent.length > 0 ? recent[recent.length - 1] : 0; console.log('STATUS:connected'); console.log('TOTAL:' + total); console.log('LAST_UID:' + lastUid); console.log('RECENT:' + recent.join(',')); if (recent.length > 0) { // Fetch headers with UID const fetch = imap.fetch(recent, { bodies: 'HEADER.FIELDS (FROM SUBJECT DATE)', struct: false, uid: true }); const aiEmails = []; fetch.on('message', (msg) => { let headers = ''; let uid = null; msg.on('body', (stream, info) => { stream.on('data', (chunk) => { headers += chunk.toString('utf8'); }); }); msg.once('attributes', (attrs) => { uid = attrs.uid; }); msg.once('end', () => { const fromMatch = headers.match(/From: (.+)/i); const subjectMatch = headers.match(/Subject: (.+)/i); const dateMatch = headers.match(/Date: (.+)/i); const from = fromMatch ? fromMatch[1].trim() : ''; const subject = subjectMatch ? subjectMatch[1].trim() : ''; const dateStr = dateMatch ? dateMatch[1].trim() : ''; // Only include emails from the last 36 hours let isRecent = true; if (dateStr) { try { const emailDate = new Date(dateStr); const cutoff = new Date(Date.now() - 36 * 60 * 60 * 1000); isRecent = emailDate > cutoff; } catch(e) {} } if (isRecent && isAINewsletter(from, subject)) { aiEmails.push({ uid, from, subject }); } }); }); fetch.once('end', () => { console.log('AI_COUNT:' + aiEmails.length); if (aiEmails.length === 0) { imap.end(); process.exit(0); } // Get UIDs for body fetch const aiUids = aiEmails.map(e => e.uid).filter(u => u); if (aiUids.length === 0) { imap.end(); process.exit(0); } // Fetch full body for AI emails const bodyFetch = imap.fetch(aiUids, { bodies: ['1'], struct: false, uid: true }); let processed = 0; bodyFetch.on('message', (msg, seqno) => { let body = ''; let uid = null; msg.on('body', (stream) => { stream.on('data', (chunk) => { body += chunk.toString('utf8'); }); }); msg.once('attributes', (attrs) => { uid = attrs.uid; }); msg.once('end', () => { processed++; // Find matching email metadata const meta = aiEmails.find(e => e.uid === uid) || aiEmails[processed - 1]; // Clean content let content = body; try { // Decode quoted-printable soft line breaks FIRST content = content.replace(/=\r?\n/g, ''); // Decode quoted-printable hex codes content = content.replace(/=([0-9A-F]{2})/gi, (m, p) => String.fromCharCode(parseInt(p, 16))); // Strip HTML content = content.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim(); } catch (e) {} const truncated = content.substring(0, 3000).trim(); console.log(`AI_EMAIL:${meta.from} | ${meta.subject}`); console.log(`AI_CONTENT:${truncated}`); if (processed === aiUids.length) { imap.end(); process.exit(0); } }); }); bodyFetch.once('error', (err) => { console.log('ERROR:body_fetch:' + err.message); imap.end(); process.exit(1); }); }); } else { console.log('AI_COUNT:0'); imap.end(); process.exit(0); } }); }); }); imap.once('error', (err) => { console.log('STATUS:error'); console.log('ERROR:connect:' + err.message); process.exit(1); }); imap.once('end', () => { process.exit(0); }); imap.connect();