parent
c16fb74cd1
commit
45d0071302
|
|
@ -1,19 +1,20 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\MailUser;
|
||||
use Illuminate\Console\Command;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
class UpdateMailboxStats extends Command
|
||||
{
|
||||
protected $signature = 'mail:update-stats {--user=}';
|
||||
protected $description = 'Aktualisiert Mailquota und Nachrichtenzahl für alle Mailboxen (oder einen spezifischen Benutzer)';
|
||||
protected $description = 'Aktualisiert Mailquota und Nachrichtenzahl (Dovecot doveadm)';
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
$query = MailUser::query()->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;
|
||||
// }
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue