← back to Purelymail Fleet Viewer
run-receive-test.js
72 lines
#!/usr/bin/env node
/* Purelymail 211-domain receive test.
* Sends one tagged probe to each info@<domain> via George's /api/send (over tailnet),
* ~3s apart, logs every send, updates the viewer's status file live, then waits
* 4 min for catch-all forwarding before exiting.
*
* GEORGE_ADMIN_PASS=... node run-receive-test.js
*/
'use strict';
const fs = require('fs');
const os = require('os');
const path = require('path');
const HEALTH = path.join(os.homedir(), 'Projects/email-deliverability-agent/output/domain-health.json');
const STATUS = path.join(__dirname, 'data/remediation-status.json');
const SENDS = path.join(__dirname, 'data/receive-test-sends.jsonl');
const RUNID_F= path.join(__dirname, 'data/receive-test-runid.txt');
const GEORGE = 'http://100.107.67.67:9850/api/send';
const PASS = process.env.GEORGE_ADMIN_PASS;
if (!PASS) { console.error('GEORGE_ADMIN_PASS not set'); process.exit(1); }
const AUTH = 'Basic ' + Buffer.from('admin:' + PASS).toString('base64');
const runId = 'PMRCV-' + new Date().toISOString().replace(/[-:T.]/g, '').slice(0, 14);
const domains = JSON.parse(fs.readFileSync(HEALTH, 'utf8')).domains.map(d => d.domain);
fs.writeFileSync(SENDS, '');
fs.writeFileSync(RUNID_F, runId);
function patch(fields) {
try {
const s = JSON.parse(fs.readFileSync(STATUS, 'utf8'));
Object.assign(s.receiveTest, fields);
s.receiveTest.runId = runId;
s.updatedAt = new Date().toISOString();
fs.writeFileSync(STATUS, JSON.stringify(s, null, 2));
} catch (e) { /* non-fatal */ }
}
const sleep = ms => new Promise(r => setTimeout(r, ms));
(async () => {
let sent = 0, okCount = 0;
for (const domain of domains) {
const subject = `PMRCV ${runId} ${domain}`;
const body = `<p>Purelymail receive probe. run=${runId} domain=${domain}. If this forwarded into the unified Gmail, ${domain}'s catch-all is working.</p>`;
let result;
try {
const res = await fetch(GEORGE, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'Authorization': AUTH },
// Send from agentabrams (NOT steve-office) — the catch-all forwards into
// steve-office's inbox, so sending from a different account avoids Gmail's
// same-Message-ID dedup that silently swallowed the v1 probes.
body: JSON.stringify({ account: 'agentabrams', to: 'info@' + domain, subject, body }),
});
const j = await res.json();
result = { domain, ok: !!j.success, messageId: j.messageId || null, error: j.error || null };
} catch (e) {
result = { domain, ok: false, messageId: null, error: String(e.message || e) };
}
if (result.ok) okCount++;
fs.appendFileSync(SENDS, JSON.stringify(result) + '\n');
sent++;
if (sent % 5 === 0 || sent === domains.length) {
patch({ done: sent, note: `sending — ${sent}/${domains.length} probes out (${okCount} accepted)` });
}
await sleep(3000);
}
patch({ done: sent, note: `${sent} probes sent (${okCount} accepted) — waiting 4 min for catch-all forwarding` });
await sleep(240000);
patch({ done: sent, note: `${sent} sent — forwarding window elapsed, ready for Gmail tabulation`, sendPhaseComplete: true });
console.log(`receive-test send phase complete: ${sent} sent, ${okCount} accepted, runId=${runId}`);
})();