diff --git a/app/Console/Commands/UpdateMailboxStats.php b/app/Console/Commands/UpdateMailboxStats.php index bbe4660..627f1eb 100644 --- a/app/Console/Commands/UpdateMailboxStats.php +++ b/app/Console/Commands/UpdateMailboxStats.php @@ -1,19 +1,20 @@ where('is_active', true); - if ($email = $this->option('user')) { $query->where('email', $email); } @@ -22,31 +23,118 @@ class UpdateMailboxStats extends Command foreach ($users as $u) { $email = $u->email; - $domain = explode('@', $email)[1]; - $local = explode('@', $email)[0]; - $path = "/var/mail/vhosts/{$domain}/{$local}"; - $usedBytes = 0; - $messageCount = 0; + [$messages, $vsize] = $this->fetchViaDoveadm($email); - if (is_dir($path)) { - $usedBytes = (int) trim(shell_exec('du -sb '.escapeshellarg($path).' 2>/dev/null | cut -f1')); - } - - $out = trim(shell_exec('doveadm mailbox status -u '.escapeshellarg($email).' messages INBOX 2>/dev/null')); - if (preg_match('/messages=(\d+)/', $out, $m)) { - $messageCount = (int) $m[1]; + if ($messages === null || $vsize === null) { + if (config('mailpool.fallback_du')) { + [$messages, $vsize] = $this->fallbackDu($email); + } } $u->update([ - 'used_bytes' => $usedBytes, - 'message_count' => $messageCount, + 'message_count' => (int)($messages ?? 0), + 'used_bytes' => (int)($vsize ?? 0), 'stats_refreshed_at' => now(), ]); - $this->info(sprintf("%-35s %6.1f MiB %4d Nachrichten", $email, $usedBytes / 1024 / 1024, $messageCount)); + $this->line(sprintf( + '%-35s %6.1f MiB %5d msgs', + $email, + ($vsize ?? 0) / 1024 / 1024, + $messages ?? 0 + )); } + $this->info('Mailbox-Statistiken aktualisiert.'); return Command::SUCCESS; } + + /** @return array{0:int|null,1:int|null} [messages, vsize] */ + private function fetchViaDoveadm(string $email): array + { + $bin = config('mailpool.doveadm'); + $sudo = config('mailpool.doveadm_sudo'); + + $cmd = [$bin, 'mailbox', 'status', '-u', $email, 'messages', 'vsize', 'INBOX']; + if ($sudo) array_unshift($cmd, 'sudo', '-n'); + + $p = new Process($cmd); + $p->setTimeout(10); + $p->run(); + + if (!$p->isSuccessful()) { + return [null, null]; + } + + $out = trim($p->getOutput()); + $messages = preg_match('/\bmessages=(\d+)/', $out, $m) ? (int)$m[1] : null; + $vsize = preg_match('/\bvsize=(\d+)/', $out, $m) ? (int)$m[1] : null; + + return [$messages, $vsize]; + } + + /** Fallback mit du (nur Größe, keine Message-Zählung) */ + private function fallbackDu(string $email): array + { + [$local, $domain] = explode('@', $email, 2); + $path = rtrim(config('mailpool.mailroot'), '/') . "/{$domain}/{$local}"; + + $p = new Process(['bash', '-lc', 'du -sb ' . escapeshellarg($path) . ' 2>/dev/null | cut -f1']); + $p->setTimeout(10)->run(); + + $bytes = $p->isSuccessful() ? (int)trim($p->getOutput()) : 0; + return [null, $bytes]; + } } +// +//namespace App\Console\Commands; +// +//use App\Models\MailUser; +//use Illuminate\Console\Command; +// +//class UpdateMailboxStats extends Command +//{ +// protected $signature = 'mail:update-stats {--user=}'; +// protected $description = 'Aktualisiert Mailquota und Nachrichtenzahl für alle Mailboxen (oder einen spezifischen Benutzer)'; +// +// public function handle(): int +// { +// $query = MailUser::query()->where('is_active', true); +// +// if ($email = $this->option('user')) { +// $query->where('email', $email); +// } +// +// $users = $query->get(); +// +// foreach ($users as $u) { +// $email = $u->email; +// $domain = explode('@', $email)[1]; +// $local = explode('@', $email)[0]; +// $path = "/var/mail/vhosts/{$domain}/{$local}"; +// +// $usedBytes = 0; +// $messageCount = 0; +// +// if (is_dir($path)) { +// $usedBytes = (int) trim(shell_exec('du -sb '.escapeshellarg($path).' 2>/dev/null | cut -f1')); +// } +// +// $out = trim(shell_exec('doveadm mailbox status -u '.escapeshellarg($email).' messages INBOX 2>/dev/null')); +// if (preg_match('/messages=(\d+)/', $out, $m)) { +// $messageCount = (int) $m[1]; +// } +// +// $u->update([ +// 'used_bytes' => $usedBytes, +// 'message_count' => $messageCount, +// 'stats_refreshed_at' => now(), +// ]); +// +// $this->info(sprintf("%-35s %6.1f MiB %4d Nachrichten", $email, $usedBytes / 1024 / 1024, $messageCount)); +// } +// +// return Command::SUCCESS; +// } +//} diff --git a/config/mailpool.php b/config/mailpool.php index 0e5c1a1..05cda8f 100644 --- a/config/mailpool.php +++ b/config/mailpool.php @@ -12,6 +12,11 @@ return [ 'spf_extra' => array_filter(explode(',', env('MAILPOOL_SPF_EXTRA', ''))), 'dmarc_policy' => env('MAILPOOL_DMARC_POLICY', 'none'), + 'doveadm' => env('MAILPOOL_DOVEADM', '/usr/bin/doveadm'), + 'doveadm_sudo' => (bool) env('MAILPOOL_DOVEADM_SUDO', false), + 'mailroot' => env('MAILPOOL_MAILROOT', '/var/mail/vhosts'), + 'fallback_du' => (bool) env('MAILPOOL_FALLBACK_DU', true), + 'defaults' => [ 'dkim_selector' => 'mwl1', 'dkim_bits' => 2048,