exec("CREATE TABLE IF NOT EXISTS admin.o365_tenants (id SERIAL PRIMARY KEY, name VARCHAR(255), tenant_id VARCHAR(255), client_id VARCHAR(255), client_secret TEXT, domain VARCHAR(255), accounts_count INTEGER DEFAULT 0, status VARCHAR(50) DEFAULT 'active', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)"); $pdo->exec("CREATE TABLE IF NOT EXISTS admin.o365_accounts (id SERIAL PRIMARY KEY, tenant_id INTEGER, email VARCHAR(255), display_name VARCHAR(255), daily_limit INTEGER DEFAULT 10000, sent_today INTEGER DEFAULT 0, status VARCHAR(50) DEFAULT 'active')"); class Office365API { private $tenantId, $clientId, $clientSecret; private $token; public function __construct($tenantId, $clientId, $clientSecret) { $this->tenantId = $tenantId; $this->clientId = $clientId; $this->clientSecret = $clientSecret; } public function getToken() { $ch = curl_init("https://login.microsoftonline.com/{$this->tenantId}/oauth2/v2.0/token"); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query([ 'client_id' => $this->clientId, 'client_secret' => $this->clientSecret, 'scope' => 'https://graph.microsoft.com/.default', 'grant_type' => 'client_credentials' ]) ]); $response = json_decode(curl_exec($ch), true); curl_close($ch); $this->token = $response['access_token'] ?? null; return $this->token; } public function getUsers() { if (!$this->token) $this->getToken(); $ch = curl_init('https://graph.microsoft.com/v1.0/users?$top=999'); curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $this->token]]); $response = json_decode(curl_exec($ch), true); curl_close($ch); return $response['value'] ?? []; } public function getDomains() { if (!$this->token) $this->getToken(); $ch = curl_init('https://graph.microsoft.com/v1.0/domains'); curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $this->token]]); $response = json_decode(curl_exec($ch), true); curl_close($ch); return $response['value'] ?? []; } public function sendMail($from, $to, $subject, $body) { if (!$this->token) $this->getToken(); $ch = curl_init("https://graph.microsoft.com/v1.0/users/$from/sendMail"); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $this->token, 'Content-Type: application/json'], CURLOPT_POSTFIELDS => json_encode([ 'message' => [ 'subject' => $subject, 'body' => ['contentType' => 'HTML', 'content' => $body], 'toRecipients' => [['emailAddress' => ['address' => $to]]] ] ]) ]); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); return ['success' => $code == 202]; } } $action = $_POST['action'] ?? $_GET['action'] ?? ''; switch ($action) { case 'add_tenant': $stmt = $pdo->prepare("INSERT INTO admin.o365_tenants (name, tenant_id, client_id, client_secret, domain) VALUES (?, ?, ?, ?, ?)"); $stmt->execute([$_POST['name'], $_POST['tenant_id'], $_POST['client_id'], $_POST['client_secret'], $_POST['domain']]); echo json_encode(['success' => true, 'id' => $pdo->lastInsertId()]); break; case 'list_tenants': $tenants = $pdo->query("SELECT id, name, tenant_id, domain, accounts_count, status, created_at FROM admin.o365_tenants ORDER BY id")->fetchAll(PDO::FETCH_ASSOC); echo json_encode(['tenants' => $tenants]); break; case 'sync_users': $stmt = $pdo->prepare("SELECT * FROM admin.o365_tenants WHERE id = ?"); $stmt->execute([$_POST['tenant_id']]); $tenant = $stmt->fetch(PDO::FETCH_ASSOC); if ($tenant) { $api = new Office365API($tenant['tenant_id'], $tenant['client_id'], $tenant['client_secret']); $users = $api->getUsers(); $count = 0; foreach ($users as $user) { if (!empty($user['mail'])) { $pdo->prepare("INSERT INTO admin.o365_accounts (tenant_id, email, display_name) VALUES (?, ?, ?) ON CONFLICT DO NOTHING")->execute([$tenant['id'], $user['mail'], $user['displayName'] ?? '']); $count++; } } $pdo->exec("UPDATE admin.o365_tenants SET accounts_count = $count WHERE id = {$tenant['id']}"); echo json_encode(['success' => true, 'synced' => $count]); } else { echo json_encode(['success' => false, 'error' => 'Tenant not found']); } break; case 'get_domains': $stmt = $pdo->prepare("SELECT * FROM admin.o365_tenants WHERE id = ?"); $stmt->execute([$_GET['tenant_id']]); $tenant = $stmt->fetch(PDO::FETCH_ASSOC); if ($tenant) { $api = new Office365API($tenant['tenant_id'], $tenant['client_id'], $tenant['client_secret']); echo json_encode(['domains' => $api->getDomains()]); } break; case 'list_accounts': $tenantId = intval($_GET['tenant_id'] ?? 0); $where = $tenantId ? "WHERE tenant_id = $tenantId" : ""; $accounts = $pdo->query("SELECT * FROM admin.o365_accounts $where ORDER BY email")->fetchAll(PDO::FETCH_ASSOC); echo json_encode(['accounts' => $accounts, 'count' => count($accounts)]); break; case 'stats': echo json_encode([ 'tenants' => $pdo->query("SELECT COUNT(*) FROM admin.o365_tenants")->fetchColumn(), 'accounts' => $pdo->query("SELECT COUNT(*) FROM admin.o365_accounts")->fetchColumn(), 'active' => $pdo->query("SELECT COUNT(*) FROM admin.o365_accounts WHERE status = 'active'")->fetchColumn() ]); break; default: echo json_encode(['actions' => ['add_tenant','list_tenants','sync_users','get_domains','list_accounts','stats']]); }