Fix: Mailbox Stats über Dovecot mit config/mailpool.php

main v1.0.97
boban 2025-10-29 04:23:41 +01:00
parent 3c1093311c
commit aaae226c8d
2 changed files with 107 additions and 55 deletions

View File

@ -25,7 +25,7 @@ class DnsHealthCard extends Component
public function refresh(): void
{
$this->load(true);
$this->load();
}
public function openDnsModal(int $domainId): void
@ -33,62 +33,108 @@ class DnsHealthCard extends Component
$this->dispatch('openModal', component: 'ui.domain.modal.domain-dns-modal', arguments: ['domainId' => $domainId]);
}
protected function load(bool $force = false): void
// protected function load(bool $force = false): void
// {
// [$this->mtaHost, $this->tlsa, $this->rows] = Cache::remember('dash.dnshealth.v2', $force ? 1 : 600, function () {
//
// $base = trim((string) env('BASE_DOMAIN', ''));
// $mtaSub = trim((string) env('MTA_SUB', 'mx'));
// $mtaHost = $base !== '' ? "{$mtaSub}.{$base}" : $mtaSub; // z.B. mx.nexlab.at
//
// // ▼ gewünschter Filter:
// $domains = Domain::query()
// ->where('is_active', true)
// ->where('is_server', false) // <<< Server-Domain sauber ausschließen
// ->orderBy('domain')
// ->get(['id', 'domain']);
//
// $rows = [];
// foreach ($domains as $d) {
// $dom = $d->domain;
//
// // DKIM-Selector ermitteln: .env > DB > Fallback null
// $selector = trim((string) env('DKIM_SELECTOR', ''));
// if ($selector === '') {
// $selector = (string) DB::table('dkim_keys')
// ->where('domain_id', $d->id)
// ->where('is_active', 1)
// ->orderByDesc('id')
// ->value('selector') ?? '';
// }
//
// $missing = [];
//
// if (!$this->mxPointsTo($dom, [$mtaHost])) $missing[] = 'MX';
// if (!$this->hasSpf($dom)) $missing[] = 'SPF';
// if (!$this->hasDkim($dom, $selector)) $missing[] = 'DKIM';
// if (!$this->hasTxt("_dmarc.$dom")) $missing[] = 'DMARC';
//
// $rows[] = [
// 'id' => (int) $d->id,
// 'name' => $dom,
// 'ok' => empty($missing),
// 'missing' => $missing,
// ];
// }
//
// // Hostweites TLSA (nur Hinweis)
// $tlsa = $this->hasTlsa("_25._tcp.$mtaHost") || $this->hasTlsa("_465._tcp.$mtaHost") || $this->hasTlsa("_587._tcp.$mtaHost");
//
// return [$mtaHost, $tlsa, $rows];
// });
// }
protected function load(): void
{
[$this->mtaHost, $this->tlsa, $this->rows] = Cache::remember('dash.dnshealth.v2', $force ? 1 : 600, function () {
$base = trim((string) env('BASE_DOMAIN', ''));
$mtaSub = trim((string) env('MTA_SUB', 'mx'));
$mtaHost = $base !== '' ? "{$mtaSub}.{$base}" : $mtaSub; // z.B. mx.nexlab.at
$base = trim((string) env('BASE_DOMAIN', ''));
$mtaSub = trim((string) env('MTA_SUB', 'mx'));
$mtaHost = $base !== '' ? "{$mtaSub}.{$base}" : $mtaSub; // z.B. mx.nexlab.at
// nur aktive, NICHT-Server-Domains (System + Custom, solange is_server = false)
$domains = Domain::query()
->where('is_active', true)
->where('is_server', false)
->orderBy('domain')
->get(['id','domain']);
// ▼ gewünschter Filter:
$domains = Domain::query()
->where('is_active', true)
->where(function ($q) {
$q->where('is_system', false)
->orWhere(function ($q2) {
$q2->where('is_system', true)->where('is_server', false);
});
})
->orderBy('domain')
->get(['id', 'domain']);
$rows = [];
$rows = [];
foreach ($domains as $d) {
$dom = $d->domain;
foreach ($domains as $d) {
$dom = $d->domain;
// DKIM-Selector ermitteln: .env > DB > Fallback null
$selector = trim((string) env('DKIM_SELECTOR', ''));
if ($selector === '') {
$selector = (string) DB::table('dkim_keys')
->where('domain_id', $d->id)
->where('is_active', 1)
->orderByDesc('id')
->value('selector') ?? '';
}
$missing = [];
if (!$this->mxPointsTo($dom, [$mtaHost])) $missing[] = 'MX';
if (!$this->hasSpf($dom)) $missing[] = 'SPF';
if (!$this->hasDkim($dom, $selector)) $missing[] = 'DKIM';
if (!$this->hasTxt("_dmarc.$dom")) $missing[] = 'DMARC';
$rows[] = [
'id' => (int) $d->id,
'name' => $dom,
'ok' => empty($missing),
'missing' => $missing,
];
// DKIM-Selector: .env > DB > leer
$selector = trim((string) env('DKIM_SELECTOR', ''));
if ($selector === '') {
$selector = (string) DB::table('dkim_keys')
->where('domain_id', $d->id)
->where('is_active', 1)
->orderByDesc('id')
->value('selector') ?? '';
}
// Hostweites TLSA (nur Hinweis)
$tlsa = $this->hasTlsa("_25._tcp.$mtaHost") || $this->hasTlsa("_465._tcp.$mtaHost") || $this->hasTlsa("_587._tcp.$mtaHost");
$missing = [];
if (!$this->mxPointsTo($dom, [$mtaHost])) $missing[] = 'MX';
if (!$this->hasSpf($dom)) $missing[] = 'SPF';
if (!$this->hasDkim($dom, $selector)) $missing[] = 'DKIM';
if (!$this->hasTxt("_dmarc.$dom")) $missing[] = 'DMARC';
return [$mtaHost, $tlsa, $rows];
});
$rows[] = [
'id' => (int) $d->id,
'name' => $dom,
'ok' => empty($missing),
'missing' => $missing,
];
}
// Hostweites TLSA (nur Info)
$tlsa = $this->hasTlsa("_25._tcp.$mtaHost")
|| $this->hasTlsa("_465._tcp.$mtaHost")
|| $this->hasTlsa("_587._tcp.$mtaHost");
$this->mtaHost = $mtaHost;
$this->tlsa = $tlsa;
$this->rows = $rows;
}
/* ── DNS Helpers ───────────────────────────────────────────────────── */
protected function digShort(string $type, string $name): string
@ -119,13 +165,22 @@ class DnsHealthCard extends Component
// ▼ DKIM: bevorzugt konkreten Selector prüfen; wenn leer, versuche Policy (_domainkey)
protected function hasDkim(string $domain, string $selector = ''): bool
{
if ($selector !== '') {
return $this->hasTxt("{$selector}._domainkey.$domain");
if ($selector !== '' && $this->hasTxt("{$selector}._domainkey.$domain")) {
return true;
}
// Manche Betreiber veröffentlichen eine Policy auf _domainkey.<dom>
// Fallback: irgendein _domainkey-TXT vorhanden
return $this->hasTxt("_domainkey.$domain");
}
// protected function hasDkim(string $domain, string $selector = ''): bool
// {
// if ($selector !== '') {
// return $this->hasTxt("{$selector}._domainkey.$domain");
// }
// // Manche Betreiber veröffentlichen eine Policy auf _domainkey.<dom>
// return $this->hasTxt("_domainkey.$domain");
// }
protected function mxPointsTo(string $domain, array $allowedHosts): bool
{
$out = $this->digShort('MX', $domain);

View File

@ -6,10 +6,7 @@
</div>
<div class="flex items-center gap-3">
<button wire:click="refresh"
class="inline-flex items-center gap-1.5 rounded-full text-[12px] px-3 py-1.5
text-white/80 bg-white/10 border border-white/15
hover:bg-white/15 hover:text-white transition">
<i class="ph ph-arrows-clockwise text-[13px]"></i>
class="px-3 py-1.5 text-[12px] rounded-lg bg-white/5 border border-white/10 hover:bg-white/10">
Neu prüfen
</button>
</div>