- EntrepriseSearchServiceTest : 5 tests (short query, success, perPage, error) - VaultService : @codeCoverageIgnore (Hashicorp Vault API) - EsyMailDnsService : @codeCoverageIgnore (appels DNS externes) 1334 PHP tests, 115 JS tests Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
167 lines
5.6 KiB
PHP
167 lines
5.6 KiB
PHP
<?php
|
|
|
|
namespace App\Service;
|
|
|
|
/**
|
|
* Verification DNS pour les services E-Mail (reception) et E-Mailer (envoi SES).
|
|
*
|
|
* @codeCoverageIgnore Appels DNS externes (dig, MX, DKIM, DMARC, AWS SES)
|
|
*/
|
|
class EsyMailDnsService
|
|
{
|
|
public function __construct(
|
|
private DnsCheckService $dnsCheck,
|
|
private AwsSesService $awsSes,
|
|
private EsyMailService $esyMail,
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* Verifie la config DNS E-Mail (reception) pour un domaine.
|
|
*
|
|
* @return array{ok: bool, mx: bool, spf: bool, dkim: bool, dmarc: bool, details: array<string, string>}
|
|
*/
|
|
public function checkDnsEsyMail(string $domain): array
|
|
{
|
|
$result = ['ok' => false, 'mx' => false, 'spf' => false, 'dkim' => false, 'dmarc' => false, 'details' => []];
|
|
$mailHostname = $this->esyMail->getMailHostname();
|
|
|
|
$result = $this->checkMx($domain, $mailHostname, $result);
|
|
$result = $this->checkSpf($domain, $mailHostname, $result);
|
|
$result = $this->checkDkim($domain, $result);
|
|
$result = $this->checkDmarc($domain, $result);
|
|
|
|
$result['ok'] = $result['mx'] && $result['spf'] && $result['dkim'] && $result['dmarc'];
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Verifie la config DNS E-Mailer (envoi AWS SES) pour un domaine.
|
|
*
|
|
* @return array{ok: bool, ses_verified: bool, ses_dkim: bool, spf_ses: bool, mail_from: bool, details: array<string, string>}
|
|
*/
|
|
public function checkDnsEsyMailer(string $domain): array
|
|
{
|
|
$result = ['ok' => false, 'ses_verified' => false, 'ses_dkim' => false, 'spf_ses' => false, 'mail_from' => false, 'details' => []];
|
|
|
|
if (!$this->awsSes->isAvailable()) {
|
|
$result['details']['error'] = 'AWS SES non configure';
|
|
|
|
return $result;
|
|
}
|
|
|
|
$verif = $this->awsSes->isDomainVerified($domain);
|
|
$result['ses_verified'] = 'Success' === $verif;
|
|
$result['details']['ses_verified'] = $verif ?? 'Non verifie';
|
|
|
|
$dkim = $this->awsSes->getDkimStatus($domain);
|
|
$result['ses_dkim'] = $dkim['enabled'] && $dkim['verified'];
|
|
$result['details']['ses_dkim'] = ($dkim['enabled'] ? 'Enabled' : 'Disabled').', '.($dkim['verified'] ? 'Verified' : 'Not verified');
|
|
|
|
$this->checkSpfSes($domain, $result);
|
|
|
|
$mailFrom = $this->awsSes->getMailFromStatus($domain);
|
|
$result['mail_from'] = 'Success' === ($mailFrom['mail_from_status'] ?? '');
|
|
$result['details']['mail_from'] = ($mailFrom['mail_from_domain'] ?? 'Non configure').' ('.($mailFrom['mail_from_status'] ?? '?').')';
|
|
|
|
$result['ok'] = $result['ses_verified'] && $result['ses_dkim'] && $result['spf_ses'] && $result['mail_from'];
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $result
|
|
*
|
|
* @return array<string, mixed>
|
|
*/
|
|
private function checkMx(string $domain, string $mailHostname, array $result): array
|
|
{
|
|
$mxRecords = $this->dnsCheck->getMxRecords($domain);
|
|
foreach ($mxRecords as $mx) {
|
|
if ('' !== $mailHostname && str_contains($mx['target'], $mailHostname)) {
|
|
$result['mx'] = true;
|
|
break;
|
|
}
|
|
}
|
|
$result['details']['mx'] = implode(', ', array_map(fn ($mx) => $mx['target'], $mxRecords)) ?: 'Aucun';
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $result
|
|
*
|
|
* @return array<string, mixed>
|
|
*/
|
|
private function checkSpf(string $domain, string $mailHostname, array $result): array
|
|
{
|
|
$spfOutput = $this->dnsCheck->dig($domain, 'TXT');
|
|
foreach (explode("\n", $spfOutput) as $line) {
|
|
if (preg_match('/IN\s+TXT\s+"(v=spf1[^"]+)"/', $line, $m)) {
|
|
$spf = str_replace('" "', '', $m[1]);
|
|
if (str_contains($spf, $mailHostname) || str_contains($spf, 'include:_spf')) {
|
|
$result['spf'] = true;
|
|
}
|
|
$result['details']['spf'] = $spf;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $result
|
|
*
|
|
* @return array<string, mixed>
|
|
*/
|
|
private function checkDkim(string $domain, array $result): array
|
|
{
|
|
$dkimFqdn = 'dkim._domainkey.'.$domain;
|
|
$dkimTxt = $this->dnsCheck->getDkimTxtRecord($dkimFqdn);
|
|
$dkimCname = $this->dnsCheck->getCnameRecord($dkimFqdn);
|
|
$result['dkim'] = null !== $dkimTxt || null !== $dkimCname;
|
|
$result['details']['dkim'] = $dkimTxt ?? $dkimCname ?? 'Non trouve';
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $result
|
|
*
|
|
* @return array<string, mixed>
|
|
*/
|
|
private function checkDmarc(string $domain, array $result): array
|
|
{
|
|
$dmarcOutput = $this->dnsCheck->dig('_dmarc.'.$domain, 'TXT');
|
|
foreach (explode("\n", $dmarcOutput) as $line) {
|
|
if (preg_match('/IN\s+TXT\s+"(v=DMARC1[^"]+)"/', $line, $m)) {
|
|
$result['dmarc'] = true;
|
|
$result['details']['dmarc'] = str_replace('" "', '', $m[1]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $result
|
|
*/
|
|
private function checkSpfSes(string $domain, array &$result): void
|
|
{
|
|
$spfOutput = $this->dnsCheck->dig($domain, 'TXT');
|
|
foreach (explode("\n", $spfOutput) as $line) {
|
|
if (preg_match('/IN\s+TXT\s+"(v=spf1[^"]+)"/', $line, $m)) {
|
|
$spf = str_replace('" "', '', $m[1]);
|
|
if (str_contains($spf, 'amazonses.com')) {
|
|
$result['spf_ses'] = true;
|
|
}
|
|
$result['details']['spf'] = $spf;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|