94 lines
4.8 KiB
PHP
94 lines
4.8 KiB
PHP
<?php
|
|
/**
|
|
* brain-test-safe.php — Safe Brain Config Tester via Graph API
|
|
* Max 3 tests/run, Graph API only, seeds only, manual trigger, rate limited
|
|
* Usage: php brain-test-safe.php [batch_size] [isp_filter]
|
|
*/
|
|
$MAX_BATCH = 3;
|
|
$LOCK = '/tmp/brain-test-safe.lock';
|
|
if (file_exists($LOCK) && (time() - filemtime($LOCK)) < 600) {
|
|
die("Rate limit: wait " . (600 - (time() - filemtime($LOCK))) . "s\n");
|
|
}
|
|
touch($LOCK);
|
|
|
|
$batch = min(intval($argv[1] ?? 3), $MAX_BATCH);
|
|
$ispF = strtoupper($argv[2] ?? '');
|
|
$pdo = new PDO("pgsql:host=localhost;dbname=adx_system", "admin", "admin123");
|
|
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
|
|
|
echo "Brain Safe Tester (Graph API) | Batch: $batch" . ($ispF ? " | ISP: $ispF" : "") . "\n\n";
|
|
|
|
$pdo->exec("CREATE TABLE IF NOT EXISTS admin.brain_test_results (
|
|
id SERIAL PRIMARY KEY, config_id INT, seed_email VARCHAR(200),
|
|
track_id VARCHAR(100), result VARCHAR(20) DEFAULT 'pending',
|
|
sender_email VARCHAR(200), tested_at TIMESTAMP DEFAULT NOW()
|
|
)");
|
|
|
|
$sql = "SELECT * FROM admin.brain_configs WHERE status IN ('untested','learning') AND total_sent < 10";
|
|
$p = [];
|
|
if ($ispF) { $sql .= " AND UPPER(isp_target) = ?"; $p[] = $ispF; }
|
|
$sql .= " ORDER BY RANDOM() LIMIT ?";
|
|
$p[] = $batch;
|
|
$st = $pdo->prepare($sql); $st->execute($p);
|
|
$configs = $st->fetchAll(PDO::FETCH_ASSOC);
|
|
if (!$configs) die("No configs to test\n");
|
|
|
|
$graphAccounts = $pdo->query("SELECT id, app_id, app_secret, tenant_id, admin_email FROM admin.office_accounts WHERE status='active' AND app_id IS NOT NULL AND app_id!='' AND id IN (13,15,22) ORDER BY RANDOM()")->fetchAll(PDO::FETCH_ASSOC);
|
|
if (!$graphAccounts) die("No Graph API account\n");
|
|
|
|
function getToken($a) {
|
|
$ch = curl_init("https://login.microsoftonline.com/{$a['tenant_id']}/oauth2/v2.0/token");
|
|
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER=>true, CURLOPT_POST=>true, CURLOPT_TIMEOUT=>10,
|
|
CURLOPT_POSTFIELDS=>http_build_query(['grant_type'=>'client_credentials','client_id'=>$a['app_id'],'client_secret'=>$a['app_secret'],'scope'=>'https://graph.microsoft.com/.default'])]);
|
|
$r = json_decode(curl_exec($ch), true); curl_close($ch);
|
|
return $r['access_token'] ?? null;
|
|
}
|
|
|
|
function graphSend($tok, $from, $to, $subj, $html) {
|
|
$ch = curl_init("https://graph.microsoft.com/v1.0/users/$from/sendMail");
|
|
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER=>true, CURLOPT_POST=>true, CURLOPT_TIMEOUT=>15,
|
|
CURLOPT_HTTPHEADER=>["Authorization: Bearer $tok","Content-Type: application/json"],
|
|
CURLOPT_POSTFIELDS=>json_encode(['message'=>['subject'=>$subj,'body'=>['contentType'=>'HTML','content'=>$html],'toRecipients'=>[['emailAddress'=>['address'=>$to]]]]])]);
|
|
$body = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch);
|
|
return ['code'=>$code, 'body'=>$body];
|
|
}
|
|
|
|
$token = null; $sender = null;
|
|
foreach ($graphAccounts as $a) { $t = getToken($a); if ($t) { $token=$t; $sender=$a; break; } }
|
|
if (!$token) die("No working token\n");
|
|
echo "Sender: {$sender['admin_email']}\n\n";
|
|
|
|
foreach ($configs as $i => $c) {
|
|
echo "--- " . ($i+1) . "/" . count($configs) . ": #{$c['id']} {$c['isp_target']} {$c['send_method']} ---\n";
|
|
$sd = $pdo->prepare("SELECT email FROM admin.brain_seeds WHERE UPPER(isp)=? AND is_active=true ORDER BY RANDOM() LIMIT 1");
|
|
$sd->execute([strtoupper($c['isp_target'])]);
|
|
$seed = $sd->fetchColumn();
|
|
if (!$seed) { echo " No seed for {$c['isp_target']}\n\n"; continue; }
|
|
echo " To: $seed\n";
|
|
|
|
$tid = 'bt_' . $c['id'] . '_' . time();
|
|
$subj = ($c['subject_template'] ?: 'Test') . ' [' . substr(md5($tid),0,6) . ']';
|
|
$body = "<html><body><p>Test {$c['isp_target']} " . date('H:i') . "</p><img src=\"https://e36lbat.com/op/{$tid}/pixel.gif\" width=\"1\" height=\"1\"/></body></html>";
|
|
|
|
$r = graphSend($token, $sender['admin_email'], $seed, $subj, $body);
|
|
$ok = ($r['code'] == 202);
|
|
if (!$ok) {
|
|
foreach ($graphAccounts as $a) {
|
|
if ($a['id']==$sender['id']) continue;
|
|
$t = getToken($a); if (!$t) continue;
|
|
$r = graphSend($t, $a['admin_email'], $seed, $subj, $body);
|
|
if ($r['code']==202) { $ok=true; $token=$t; $sender=$a; break; }
|
|
}
|
|
}
|
|
if ($ok) {
|
|
echo " ✅ SENT via {$sender['admin_email']}\n";
|
|
$pdo->prepare("UPDATE admin.brain_configs SET total_sent=total_sent+1, status=CASE WHEN status='untested' THEN 'learning' ELSE status END, last_success_at=NOW() WHERE id=?")->execute([$c['id']]);
|
|
// LOG DISABLED: $pdo->prepare("INSERT INTO admin.brain_test_results (config_id,seed_email,track_id,result,sender_email,tested_at) VALUES(?,?,?,'pending',?,NOW())")->execute([$c['id'],$seed,$tid,$sender['admin_email']]);
|
|
echo " Track: $tid\n";
|
|
} else {
|
|
echo " ❌ HTTP {$r['code']}: " . substr($r['body'],0,100) . "\n";
|
|
}
|
|
echo "\n"; sleep(2);
|
|
}
|
|
echo "Done.\n";
|