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

main v1.0.51
boban 2025-10-26 17:34:03 +01:00
parent f99790b1a5
commit 7a636fb496
4 changed files with 161 additions and 20 deletions

View File

@ -0,0 +1,45 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Cache;
use App\Models\Setting;
class SpamAvCollectCommand extends Command
{
protected $signature = 'spamav:collect';
protected $description = 'Collect Rspamd/ClamAV metrics and persist to Settings (DB→Redis)';
public function handle(): int
{
$this->info('Collecting Spam/AV metrics…');
$collect = function (): array {
$out = trim(@shell_exec('rspamc counters 2>/dev/null') ?? '');
$ham = preg_match('/\bham\s*:\s*(\d+)/i', $out, $m1) ? (int)$m1[1] : 0;
$spam = preg_match('/\bspam\s*:\s*(\d+)/i', $out, $m2) ? (int)$m2[1] : 0;
$reject = preg_match('/\breject\s*:\s*(\d+)/i', $out, $m3) ? (int)$m3[1] : 0;
$rspamdVer = trim(@shell_exec('rspamadm version 2>/dev/null') ?? '') ?: '';
$clamVer = trim(@shell_exec('clamd --version 2>/dev/null || clamscan --version 2>/dev/null') ?? '') ?: '';
$sigUpdated = null;
$log = @shell_exec('grep -i "Database updated" /var/log/clamav/freshclam.log | tail -n1 2>/dev/null');
if ($log) { $sigUpdated = trim($log); }
return compact('ham','spam','reject','rspamdVer','clamVer','sigUpdated') + ['ts' => time()];
};
$data = $collect();
Setting::set('spamav.metrics', $data);
Cache::put('dash.spamav', $data, 60);
$this->info(sprintf(
'ham=%d spam=%d reject=%d | rspamd=%s | clam=%s',
$data['ham'], $data['spam'], $data['reject'], $data['rspamdVer'], $data['clamVer']
));
return self::SUCCESS;
}
}

View File

@ -4,6 +4,7 @@ namespace App\Livewire\Ui\Security;
use Livewire\Component;
use Illuminate\Support\Facades\Cache;
use App\Models\Setting;
class SpamAvCard extends Component
{
@ -14,30 +15,122 @@ class SpamAvCard extends Component
public string $clamVer = '';
public ?string $sigUpdated = null;
public function mount(): void { $this->load(); }
public function render() { return view('livewire.ui.security.spam-av-card'); }
public function refresh(): void { $this->load(true); }
// wie frisch müssen Zahlen mindestens sein (Sek.)
protected int $maxAge = 300;
public function mount(): void
{
$this->load();
}
public function render()
{
return view('livewire.ui.security.spam-av-card');
}
public function refresh(): void
{
$this->load(true);
}
protected function load(bool $force = false): void
{
$data = Cache::remember('dash.spamav', $force ? 1 : 60, function () {
$out = trim(@shell_exec('rspamc counters 2>/dev/null') ?? '');
// very rough counters (adapt to your setup)
$ham = preg_match('/ham:\s*(\d+)/i', $out, $m1) ? (int)$m1[1] : 0;
$spam = preg_match('/spam:\s*(\d+)/i', $out, $m2) ? (int)$m2[1] : 0;
$reject = preg_match('/reject:\s*(\d+)/i', $out, $m3) ? (int)$m3[1] : 0;
// 1) Versuche erst aus Settings (DB/Redis), optional mit Cache-Shortcuts
$data = $force ? null : Cache::get('dash.spamav');
$rspamdVer = trim(@shell_exec('rspamadm version 2>/dev/null') ?? '') ?: '';
$clamVer = trim(@shell_exec('clamd --version 2>/dev/null || clamscan --version 2>/dev/null') ?? '') ?: '';
if (!$data) {
$data = Setting::get('spamav.metrics');
}
// last signatures update (freshclam log)
$sigUpdated = null;
$log = @shell_exec('grep -i "Database updated" /var/log/clamav/freshclam.log | tail -n1 2>/dev/null');
if ($log) $sigUpdated = trim($log);
// 2) Wenn keine Daten oder zu alt ⇒ neu sammeln
$stale = !is_array($data) || (time() - (int)($data['ts'] ?? 0) > $this->maxAge);
if ($force || $stale) {
$data = $this->collectMetrics();
// Persistenz: Settings (DB→Redis) + UI-Cache (kurz)
Setting::set('spamav.metrics', $data);
Cache::put('dash.spamav', $data, 60);
}
return compact('ham','spam','reject','rspamdVer','clamVer','sigUpdated');
});
// 3) Auf Properties mappen
$this->ham = (int)($data['ham'] ?? 0);
$this->spam = (int)($data['spam'] ?? 0);
$this->reject = (int)($data['reject'] ?? 0);
$this->rspamdVer = (string)($data['rspamdVer'] ?? '');
$this->clamVer = (string)($data['clamVer'] ?? '');
$this->sigUpdated = $data['sigUpdated'] ?? null;
}
foreach ($data as $k => $v) $this->$k = $v;
/** Sammelt live von rspamd/clamav robust und schnell */
protected function collectMetrics(): array
{
// rspamd counters
$out = trim(@shell_exec('rspamc counters 2>/dev/null') ?? '');
$ham = preg_match('/\bham\s*:\s*(\d+)/i', $out, $m1) ? (int)$m1[1] : 0;
$spam = preg_match('/\bspam\s*:\s*(\d+)/i', $out, $m2) ? (int)$m2[1] : 0;
$reject = preg_match('/\breject\s*:\s*(\d+)/i', $out, $m3) ? (int)$m3[1] : 0;
// Versionen
$rspamdVer = trim(@shell_exec('rspamadm version 2>/dev/null') ?? '') ?: '';
$clamVer = trim(@shell_exec('clamd --version 2>/dev/null || clamscan --version 2>/dev/null') ?? '') ?: '';
// Letztes Signatur-Update aus freshclam.log
$sigUpdated = null;
$log = @shell_exec('grep -i "Database updated" /var/log/clamav/freshclam.log | tail -n1 2>/dev/null');
if ($log) {
$sigUpdated = trim($log);
}
return [
'ts' => time(),
'ham' => $ham,
'spam' => $spam,
'reject' => $reject,
'rspamdVer' => $rspamdVer,
'clamVer' => $clamVer,
'sigUpdated' => $sigUpdated,
];
}
}
//
//namespace App\Livewire\Ui\Security;
//
//use Livewire\Component;
//use Illuminate\Support\Facades\Cache;
//
//class SpamAvCard extends Component
//{
// public int $ham = 0;
// public int $spam = 0;
// public int $reject = 0;
// public string $rspamdVer = '';
// public string $clamVer = '';
// public ?string $sigUpdated = null;
//
// public function mount(): void { $this->load(); }
// public function render() { return view('livewire.ui.security.spam-av-card'); }
// public function refresh(): void { $this->load(true); }
//
// protected function load(bool $force = false): void
// {
// $data = Cache::remember('dash.spamav', $force ? 1 : 60, function () {
// $out = trim(@shell_exec('rspamc counters 2>/dev/null') ?? '');
// // very rough counters (adapt to your setup)
// $ham = preg_match('/ham:\s*(\d+)/i', $out, $m1) ? (int)$m1[1] : 0;
// $spam = preg_match('/spam:\s*(\d+)/i', $out, $m2) ? (int)$m2[1] : 0;
// $reject = preg_match('/reject:\s*(\d+)/i', $out, $m3) ? (int)$m3[1] : 0;
//
// $rspamdVer = trim(@shell_exec('rspamadm version 2>/dev/null') ?? '') ?: '';
// $clamVer = trim(@shell_exec('clamd --version 2>/dev/null || clamscan --version 2>/dev/null') ?? '') ?: '';
//
// // last signatures update (freshclam log)
// $sigUpdated = null;
// $log = @shell_exec('grep -i "Database updated" /var/log/clamav/freshclam.log | tail -n1 2>/dev/null');
// if ($log) $sigUpdated = trim($log);
//
// return compact('ham','spam','reject','rspamdVer','clamVer','sigUpdated');
// });
//
// foreach ($data as $k => $v) $this->$k = $v;
// }
//}

View File

@ -108,6 +108,9 @@ class UpdateCard extends Component
if ($this->rc === 0 && !$this->postActionsDone) {
// Dienste neu starten (asynchron)
@shell_exec('nohup php /var/www/mailwolt/artisan mailwolt:restart-services >/dev/null 2>&1 &');
@shell_exec('nohup php /var/www/mailwolt/artisan settings:sync >/dev/null 2>&1 &');
@shell_exec('nohup php /var/www/mailwolt/artisan spamav:collect >/dev/null 2>&1 &');
$this->postActionsDone = true;
$ver = $this->displayCurrent ?? 'aktuelle Version';

View File

@ -9,8 +9,8 @@ Artisan::command('inspire', function () {
$this->comment(Inspiring::quote());
})->purpose('Display an inspiring quote');
Schedule::job(RunHealthChecks::class)->everyMinute()->withoutOverlapping();
//Schedule::command('woltguard:collect-services')->everyMinute();
Schedule::job(RunHealthChecks::class)->everyFiveMinutes()->withoutOverlapping();
Schedule::command('spamav:collect')->everyFiveMinutes()->withoutOverlapping();
//Schedule::command('mailwolt:check-updates')->dailyAt('04:10');
Schedule::command('mailwolt:check-updates')->everytwoMinutes();