tenantId=$t; $this->clientId=$c; $this->clientSecret=$s; } public function getAppToken() { if (empty($this->tenantId)||empty($this->clientId)||empty($this->clientSecret)) { $this->lastError="Credentials manquants"; return false; } $ch = curl_init("https://login.microsoftonline.com/{$this->tenantId}/oauth2/v2.0/token"); curl_setopt_array($ch, [CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>http_build_query(['grant_type'=>'client_credentials','client_id'=>$this->clientId,'client_secret'=>$this->clientSecret,'scope'=>'https://graph.microsoft.com/.default']), CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>30]); $data = json_decode(curl_exec($ch), true); curl_close($ch); if (isset($data['access_token'])) { $this->accessToken = $data['access_token']; return true; } $this->lastError = $data['error_description'] ?? "Erreur"; return false; } private function graphRequest($ep, $m='GET', $b=null) { if (empty($this->accessToken) && !$this->getAppToken()) return ['error'=>$this->lastError]; $ch = curl_init("https://graph.microsoft.com/v1.0".$ep); curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER=>true, CURLOPT_HTTPHEADER=>['Authorization: Bearer '.$this->accessToken,'Content-Type: application/json']]); if ($m==='POST') { curl_setopt($ch, CURLOPT_POST, true); if($b) curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($b)); } $data = json_decode(curl_exec($ch), true) ?: []; $data['_httpCode'] = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); return $data; } public function listDomains() { $r=$this->graphRequest('/domains'); return isset($r['error']) ? ['success'=>false,'error'=>$r['error']['message']??''] : ['success'=>true,'domains'=>$r['value']??[],'count'=>count($r['value']??[])]; } public function getDomainVerificationRecords($n) { $r=$this->graphRequest("/domains/{$n}/verificationDnsRecords"); return isset($r['error']) ? ['success'=>false] : ['success'=>true,'records'=>$r['value']??[]]; } public function getLastError() { return $this->lastError; } } function testSMTPConnection($email, $password) { $result = ['success'=>false,'status'=>'unknown','message'=>'','smtp_response'=>'']; $socket = @fsockopen('smtp.office365.com', 587, $errno, $errstr, 10); if (!$socket) { $result['message']="Connexion impossible"; return $result; } fgets($socket,1024); fwrite($socket,"EHLO wevads\r\n"); while($l=fgets($socket,1024)) if(substr($l,3,1)==' ') break; fwrite($socket,"STARTTLS\r\n"); if(strpos(fgets($socket,1024),'220')===false) { fclose($socket); return $result; } stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); fwrite($socket,"EHLO wevads\r\n"); while($l=fgets($socket,1024)) if(substr($l,3,1)==' ') break; fwrite($socket,"AUTH LOGIN\r\n"); fgets($socket,1024); fwrite($socket,base64_encode($email)."\r\n"); fgets($socket,1024); fwrite($socket,base64_encode($password)."\r\n"); $resp=fgets($socket,1024); $result['smtp_response']=trim($resp); if (strpos($resp,'235')!==false) { fwrite($socket,"MAIL FROM:<{$email}>\r\n"); $r2=fgets($socket,1024); $result['success']=true; $result['status']=(strpos($r2,'250')!==false)?'ready':'need_connector'; } else { $result['status']='invalid'; } fwrite($socket,"QUIT\r\n"); fclose($socket); return $result; } function generateCredentialsScript($e,$p) { return "# PowerShell - Credentials Azure\nInstall-Module Microsoft.Graph -Force\nConnect-MgGraph -Scopes 'Application.ReadWrite.All' -NoWelcome\n\$App = New-MgApplication -DisplayName 'SMTP-'+(Get-Random)\n\$Secret = Add-MgApplicationPassword -ApplicationId \$App.Id -PasswordCredential @{EndDateTime=(Get-Date).AddMonths(24)}\nWrite-Host 'Client ID:' \$App.AppId\nWrite-Host 'Tenant ID:' (Get-MgOrganization).Id\nWrite-Host 'Secret:' \$Secret.SecretText\nDisconnect-MgGraph"; } function generateAntiSpamScript($e,$p,$ips) { $il=is_array($ips)?implode('","',$ips):$ips; return "# PowerShell - Anti-Spam\nInstall-Module ExchangeOnlineManagement -Force\n\$Cred = New-Object PSCredential('$e',(ConvertTo-SecureString '$p' -AsPlainText -Force))\nConnect-ExchangeOnline -Credential \$Cred -ShowBanner:\$false\n\$Headers = @('X-Forefront-Antispam-Report','X-MS-Exchange-CrossTenant-AuthAs')\n\$i=1; foreach(\$H in \$Headers) { New-TransportRule -Name \"RG\$i\" -RemoveHeader \$H -Priority \$i -Enabled \$true; \$i++ }\nforeach(\$IP in @(\"$il\")) { New-TransportRule -Name \"WL-\$IP\" -SenderIpRanges \$IP -SetSCL -1 -Enabled \$true }\nDisconnect-ExchangeOnline -Confirm:\$false"; }