where('is_active', true) // sichere Filter: E-Mail vorhanden und enthält genau ein "@" ->whereNotNull('email') ->where('email', 'like', '%@%'); if ($email = trim((string)$this->option('user'))) { $q->where('email', $email); } $users = $q->get(); if ($users->isEmpty()) { $this->warn('Keine passenden Mailboxen gefunden.'); return self::SUCCESS; } foreach ($users as $u) { $email = trim($u->email); if (!preg_match('/^[^@\s]+@[^@\s]+\.[^@\s]+$/', $email)) { // still und leise überspringen – kein „Überspringe @“ mehr continue; } [$local, $domain] = explode('@', $email, 2); $maildir = "/var/mail/vhosts/{$domain}/{$local}"; // 1) Größe in Bytes (rekursiv; ohne "du") $usedBytes = 0; if (is_dir($maildir)) { $it = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($maildir, \FilesystemIterator::SKIP_DOTS) ); foreach ($it as $file) { if ($file->isFile()) { $usedBytes += $file->getSize(); } } } // 2) Message-Count = Dateien in cur/ + new/ $messageCount = 0; foreach (['cur', 'new'] as $sub) { $dir = "{$maildir}/{$sub}"; if (is_dir($dir)) { $dh = opendir($dir); if ($dh) { while (($fn = readdir($dh)) !== false) { // echte Maildir-Dateien haben keinen führenden Punkt if ($fn !== '.' && $fn !== '..' && $fn[0] !== '.') { $messageCount++; } } closedir($dh); } } } // Update DB $u->forceFill([ 'used_bytes' => $usedBytes, 'message_count' => $messageCount, 'stats_refreshed_at'=> now(), ])->save(); $this->line(sprintf( "%-35s %7.1f MiB %5d msgs", $email, $usedBytes / 1024 / 1024, $messageCount )); } $this->info('Mailbox-Statistiken aktualisiert.'); return self::SUCCESS; } }