← back to George Gmail
trash-fleet-mailtests.js
76 lines
/**
* trash-fleet-mailtests.js — one-off cleanup.
*
* Trashes the fleet inbound-mail delivery TEST emails that piled up in the
* steve-office inbox while verifying the 44-domain dw-domain-fleet catch-all
* forwarding. Two batches were sent, each tagged with a unique random token:
* FLEETMAILTEST-75986316 (first delivery test)
* RETEST-a3cdc29a (re-test from a third-party account)
* Both tokens are cryptographically unique, so the query has zero
* false-positive risk against real mail.
*
* George's MCP exposes no delete tool, so this uses George's own OAuth creds
* directly (gmail.modify scope) — same pattern as trash-redfin-zillow.js.
* Trashing is reversible: messages sit in Trash for 30 days.
*
* node trash-fleet-mailtests.js
*/
const fs = require('fs');
const path = require('path');
const { google } = require('googleapis');
const ENV_PATH = path.join(process.env.HOME || '', 'Projects/Designer-Wallcoverings/DW-MCP/.env');
const env = {};
fs.readFileSync(ENV_PATH, 'utf8').split('\n').forEach(l => {
const m = l.match(/^([^#=]+)=(.+)/);
if (m) env[m[1].trim()] = m[2].trim();
});
const QUERY = 'subject:(RETEST-a3cdc29a OR FLEETMAILTEST-75986316)';
// sanity bounds: 44 RETEST + 44 FLEETMAILTEST + 1 bounced "Re:" = ~89.
const MIN_EXPECTED = 60;
const MAX_EXPECTED = 120;
(async () => {
const oc = new google.auth.OAuth2(
env.GMAIL_CLIENT_ID, env.GMAIL_CLIENT_SECRET, 'http://localhost:9850/oauth2callback');
oc.setCredentials({ refresh_token: env.GMAIL_REFRESH_TOKEN });
const gm = google.gmail({ version: 'v1', auth: oc });
console.log('=== steve@designerwallcoverings.com ===');
console.log('query:', QUERY);
// 1. Collect matching message IDs
const ids = [];
let pageToken = null;
do {
const r = await gm.users.messages.list({
userId: 'me', q: QUERY, maxResults: 500, pageToken: pageToken || undefined });
(r.data.messages || []).forEach(m => ids.push(m.id));
pageToken = r.data.nextPageToken || null;
} while (pageToken);
console.log(` collected ${ids.length} message IDs`);
// 2. Safety gate — abort if the count is wildly off what we expect
if (ids.length === 0) { console.log(' nothing to trash — exiting.'); return; }
if (ids.length < MIN_EXPECTED || ids.length > MAX_EXPECTED) {
console.error(` ABORT: ${ids.length} is outside the expected ${MIN_EXPECTED}-${MAX_EXPECTED} range.`);
console.error(' Re-check the query before trashing. No messages were modified.');
process.exit(1);
}
// 3. Trash — add TRASH, remove INBOX
const BATCH = 1000;
let trashed = 0;
for (let i = 0; i < ids.length; i += BATCH) {
const chunk = ids.slice(i, i + BATCH);
await gm.users.messages.batchModify({
userId: 'me',
requestBody: { ids: chunk, addLabelIds: ['TRASH'], removeLabelIds: ['INBOX'] }
});
trashed += chunk.length;
console.log(` trashed ${trashed}/${ids.length}`);
}
console.log(`\n=== DONE: ${trashed} fleet test emails moved to Trash ===`);
})().catch(e => { console.error('FAILED:', e.message); process.exit(1); });