166 lines
5.5 KiB
PHP
166 lines
5.5 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire\Ui\Nx\Mail;
|
|
|
|
use Livewire\Attributes\Layout;
|
|
use Livewire\Attributes\On;
|
|
use Livewire\Attributes\Title;
|
|
use Livewire\Attributes\Url;
|
|
use Livewire\Component;
|
|
|
|
#[Layout('layouts.dvx')]
|
|
#[Title('Mail-Queue · Mailwolt')]
|
|
class QueueList extends Component
|
|
{
|
|
#[Url(as: 'filter', keep: true)]
|
|
public string $filter = 'all';
|
|
|
|
#[Url(as: 'q', keep: true)]
|
|
public string $search = '';
|
|
|
|
public array $selected = [];
|
|
public bool $selectAll = false;
|
|
|
|
#[On('queue:updated')]
|
|
public function refresh(): void {}
|
|
|
|
public function updatedSelectAll(bool $val): void
|
|
{
|
|
$messages = $this->fetchQueue();
|
|
$this->selected = $val ? array_column($messages, 'id') : [];
|
|
}
|
|
|
|
public function flush(): void
|
|
{
|
|
@shell_exec('sudo postqueue -f >/dev/null 2>&1 &');
|
|
$this->dispatch('toast', type: 'info', title: 'Queue-Flush gestartet');
|
|
}
|
|
|
|
public function deleteSelected(): void
|
|
{
|
|
$count = count($this->selected);
|
|
foreach ($this->selected as $id) {
|
|
@shell_exec('sudo postsuper -d ' . escapeshellarg($id) . ' 2>&1');
|
|
}
|
|
$this->selected = [];
|
|
$this->selectAll = false;
|
|
$this->dispatch('toast', type: 'success', title: "{$count} Nachricht(en) gelöscht");
|
|
}
|
|
|
|
public function deleteAll(): void
|
|
{
|
|
@shell_exec('sudo postsuper -d ALL 2>&1');
|
|
$this->selected = [];
|
|
$this->selectAll = false;
|
|
$this->dispatch('toast', type: 'warning', title: 'Alle Queue-Nachrichten gelöscht');
|
|
}
|
|
|
|
public function openMessage(string $queueId): void
|
|
{
|
|
$this->dispatch('openModal',
|
|
component: 'ui.nx.mail.modal.queue-message-modal',
|
|
arguments: ['queueId' => $queueId]
|
|
);
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
$all = $this->fetchQueue();
|
|
|
|
$counts = [
|
|
'all' => count($all),
|
|
'active' => count(array_filter($all, fn($m) => $m['queue'] === 'active')),
|
|
'deferred' => count(array_filter($all, fn($m) => $m['queue'] === 'deferred')),
|
|
'hold' => count(array_filter($all, fn($m) => $m['queue'] === 'hold')),
|
|
];
|
|
|
|
$messages = $all;
|
|
|
|
if ($this->filter !== 'all') {
|
|
$messages = array_values(array_filter($messages, fn($m) => $m['queue'] === $this->filter));
|
|
}
|
|
|
|
if ($this->search !== '') {
|
|
$s = strtolower($this->search);
|
|
$messages = array_values(array_filter($messages, fn($m) =>
|
|
str_contains(strtolower($m['sender'] ?? ''), $s) ||
|
|
str_contains(strtolower($m['recipient'] ?? ''), $s) ||
|
|
str_contains(strtolower($m['id'] ?? ''), $s)
|
|
));
|
|
}
|
|
|
|
return view('livewire.ui.nx.mail.queue-list', compact('messages', 'counts'));
|
|
}
|
|
|
|
// ── helpers ──────────────────────────────────────────────────────────────
|
|
|
|
public function fetchQueue(): array
|
|
{
|
|
$out = trim(@shell_exec('postqueue -j 2>/dev/null') ?? '');
|
|
if ($out !== '') {
|
|
return $this->parseJson($out);
|
|
}
|
|
return $this->parseText(trim(@shell_exec('postqueue -p 2>/dev/null') ?? ''));
|
|
}
|
|
|
|
private function parseJson(string $out): array
|
|
{
|
|
$rows = [];
|
|
foreach (explode("\n", $out) as $line) {
|
|
$line = trim($line);
|
|
if ($line === '') continue;
|
|
$m = json_decode($line, true);
|
|
if (!is_array($m)) continue;
|
|
|
|
$recipients = $m['recipients'] ?? [];
|
|
$rcptList = array_column($recipients, 'address');
|
|
$reason = $recipients[0]['delay_reason'] ?? '';
|
|
|
|
$rows[] = [
|
|
'id' => $m['queue_id'] ?? '',
|
|
'queue' => $m['queue_name'] ?? 'deferred',
|
|
'sender' => $m['sender'] ?? '',
|
|
'recipient' => implode(', ', $rcptList),
|
|
'size' => (int)($m['message_size'] ?? 0),
|
|
'arrival' => (int)($m['arrival_time'] ?? 0),
|
|
'reason' => $this->trimReason($reason),
|
|
];
|
|
}
|
|
return $rows;
|
|
}
|
|
|
|
private function parseText(string $out): array
|
|
{
|
|
$rows = [];
|
|
$current = null;
|
|
|
|
foreach (explode("\n", $out) as $line) {
|
|
if (preg_match('/^([A-F0-9]{9,})\*?\s+(\d+)\s+\S+\s+\S+\s+\d+\s+\d{1,2}:\d{2}:\d{2}\s+(.*)/i', $line, $m)) {
|
|
if ($current) $rows[] = $current;
|
|
$current = [
|
|
'id' => $m[1],
|
|
'queue' => 'active',
|
|
'sender' => trim($m[3]),
|
|
'recipient' => '',
|
|
'size' => (int)$m[2],
|
|
'arrival' => 0,
|
|
'reason' => '',
|
|
];
|
|
} elseif ($current && preg_match('/^\s+([\w.+%-]+@[\w.-]+)/', $line, $m)) {
|
|
$current['recipient'] = $m[1];
|
|
} elseif ($current && preg_match('/^\s+\((.+)\)/', $line, $m)) {
|
|
$current['reason'] = $this->trimReason($m[1]);
|
|
$current['queue'] = 'deferred';
|
|
}
|
|
}
|
|
if ($current) $rows[] = $current;
|
|
return $rows;
|
|
}
|
|
|
|
private function trimReason(string $r): string
|
|
{
|
|
$r = preg_replace('/^\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}\s+/', '', trim($r));
|
|
return mb_strlen($r) > 100 ? mb_substr($r, 0, 100) . '…' : $r;
|
|
}
|
|
}
|