PDO::ERRMODE_EXCEPTION]); $pdo->exec(" CREATE TABLE IF NOT EXISTS admin.domain_auth ( id SERIAL PRIMARY KEY, domain VARCHAR(255) UNIQUE, spf_record TEXT, spf_status VARCHAR(50) DEFAULT 'pending', dkim_selector VARCHAR(100) DEFAULT 'default', dkim_public_key TEXT, dkim_private_key TEXT, dkim_status VARCHAR(50) DEFAULT 'pending', dmarc_policy VARCHAR(20) DEFAULT 'none', dmarc_record TEXT, dmarc_status VARCHAR(50) DEFAULT 'pending', bimi_logo_url TEXT, bimi_status VARCHAR(50) DEFAULT 'pending', last_check TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); "); class AuthWizard { private $pdo; public function __construct($pdo) { $this->pdo = $pdo; } public function analyzeDomain($domain) { $results = [ 'domain' => $domain, 'spf' => $this->checkSPF($domain), 'dkim' => $this->checkDKIM($domain), 'dmarc' => $this->checkDMARC($domain), 'mx' => $this->checkMX($domain) ]; $results['score'] = $this->calculateScore($results); $results['recommendations'] = $this->generateRecommendations($results); return $results; } private function checkSPF($domain) { $records = @dns_get_record($domain, DNS_TXT); foreach ($records ?: [] as $r) { if (strpos($r['txt'] ?? '', 'v=spf1') === 0) { return ['found' => true, 'record' => $r['txt'], 'valid' => true]; } } return ['found' => false, 'record' => null, 'valid' => false]; } private function checkDKIM($domain, $selector = 'default') { $dkimDomain = "$selector._domainkey.$domain"; $records = @dns_get_record($dkimDomain, DNS_TXT); foreach ($records ?: [] as $r) { if (strpos($r['txt'] ?? '', 'v=DKIM1') !== false) { return ['found' => true, 'selector' => $selector, 'record' => $r['txt']]; } } return ['found' => false, 'selector' => $selector, 'record' => null]; } private function checkDMARC($domain) { $dmarcDomain = "_dmarc.$domain"; $records = @dns_get_record($dmarcDomain, DNS_TXT); foreach ($records ?: [] as $r) { if (strpos($r['txt'] ?? '', 'v=DMARC1') === 0) { preg_match('/p=(\w+)/', $r['txt'], $m); return ['found' => true, 'record' => $r['txt'], 'policy' => $m[1] ?? 'none']; } } return ['found' => false, 'record' => null, 'policy' => null]; } private function checkMX($domain) { $records = @dns_get_record($domain, DNS_MX); return ['found' => !empty($records), 'records' => $records ?: []]; } private function calculateScore($results) { $score = 0; if ($results['spf']['found']) $score += 25; if ($results['dkim']['found']) $score += 25; if ($results['dmarc']['found']) $score += 25; if ($results['dmarc']['policy'] === 'reject') $score += 15; elseif ($results['dmarc']['policy'] === 'quarantine') $score += 10; if ($results['mx']['found']) $score += 10; return $score; } private function generateRecommendations($results) { $recs = []; if (!$results['spf']['found']) { $recs[] = ['type' => 'spf', 'priority' => 'high', 'message' => 'Add SPF record', 'record' => 'v=spf1 include:_spf.google.com ~all']; } if (!$results['dkim']['found']) { $recs[] = ['type' => 'dkim', 'priority' => 'high', 'message' => 'Configure DKIM signing']; } if (!$results['dmarc']['found']) { $recs[] = ['type' => 'dmarc', 'priority' => 'high', 'message' => 'Add DMARC record', 'record' => 'v=DMARC1; p=none; rua=mailto:dmarc@' . $results['domain']]; } elseif ($results['dmarc']['policy'] === 'none') { $recs[] = ['type' => 'dmarc', 'priority' => 'medium', 'message' => 'Upgrade DMARC to quarantine or reject']; } return $recs; } public function generateDKIM($domain, $selector = 'default') { // Generate DKIM key pair $config = ['digest_alg' => 'sha256', 'private_key_bits' => 2048, 'private_key_type' => OPENSSL_KEYTYPE_RSA]; $res = openssl_pkey_new($config); openssl_pkey_export($res, $privateKey); $publicKey = openssl_pkey_get_details($res)['key']; // Format for DNS $publicKeyClean = str_replace(['-----BEGIN PUBLIC KEY-----', '-----END PUBLIC KEY-----', "\n", "\r"], '', $publicKey); $dkimRecord = "v=DKIM1; k=rsa; p=$publicKeyClean"; // Save to database $this->pdo->prepare("INSERT INTO admin.domain_auth (domain, dkim_selector, dkim_public_key, dkim_private_key) VALUES (?, ?, ?, ?) ON CONFLICT (domain) DO UPDATE SET dkim_selector = ?, dkim_public_key = ?, dkim_private_key = ?") ->execute([$domain, $selector, $publicKey, $privateKey, $selector, $publicKey, $privateKey]); return [ 'domain' => $domain, 'selector' => $selector, 'dns_record' => "$selector._domainkey.$domain", 'dns_value' => $dkimRecord, 'private_key' => $privateKey ]; } public function generateRecords($domain) { return [ 'spf' => [ 'type' => 'TXT', 'name' => '@', 'value' => 'v=spf1 ip4:89.167.40.150 include:_spf.google.com ~all' ], 'dkim' => [ 'type' => 'TXT', 'name' => 'default._domainkey', 'value' => 'v=DKIM1; k=rsa; p=[YOUR_PUBLIC_KEY]' ], 'dmarc' => [ 'type' => 'TXT', 'name' => '_dmarc', 'value' => "v=DMARC1; p=quarantine; rua=mailto:dmarc@$domain; pct=100" ] ]; } } $wizard = new AuthWizard($pdo); $action = $_POST['action'] ?? $_GET['action'] ?? ''; switch ($action) { case 'analyze': echo json_encode($wizard->analyzeDomain($_GET['domain'] ?? $_POST['domain'])); break; case 'generate_dkim': echo json_encode($wizard->generateDKIM($_POST['domain'], $_POST['selector'] ?? 'default')); break; case 'generate_records': echo json_encode($wizard->generateRecords($_GET['domain'])); break; case 'domains': echo json_encode(['domains' => $pdo->query("SELECT * FROM admin.domain_auth ORDER BY domain")->fetchAll(PDO::FETCH_ASSOC)]); break; default: echo json_encode(['name' => 'Auth Wizard', 'actions' => ['analyze','generate_dkim','generate_records','domains']]); }