247 lines
7.6 KiB
PHP
247 lines
7.6 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire\Ui\Webmail;
|
|
|
|
use App\Services\ImapService;
|
|
use Livewire\Attributes\Layout;
|
|
use Livewire\Attributes\Title;
|
|
use Livewire\Attributes\Url;
|
|
use Livewire\Component;
|
|
|
|
#[Layout('layouts.webmail')]
|
|
#[Title('Posteingang · Webmail')]
|
|
class Inbox extends Component
|
|
{
|
|
#[Url(as: 'folder')]
|
|
public string $folder = 'INBOX';
|
|
|
|
#[Url(as: 'page')]
|
|
public int $page = 1;
|
|
|
|
#[Url(as: 'tab')]
|
|
public string $tab = 'all';
|
|
|
|
public array $messages = [];
|
|
public array $categories = [];
|
|
public int $total = 0;
|
|
public array $folders = [];
|
|
public int $perPage = 25;
|
|
|
|
public string $search = '';
|
|
public array $searchResults = [];
|
|
public bool $searching = false;
|
|
|
|
public function mount(): void
|
|
{
|
|
if (! session('webmail_email')) {
|
|
$this->redirect(route('ui.webmail.login'));
|
|
return;
|
|
}
|
|
$this->load();
|
|
}
|
|
|
|
public function load(): void
|
|
{
|
|
try {
|
|
$imap = app(ImapService::class);
|
|
$client = $imap->client(
|
|
session('webmail_email'),
|
|
session('webmail_password'),
|
|
);
|
|
|
|
$this->folders = $imap->folders($client);
|
|
|
|
if ($this->folder === '_starred') {
|
|
$result = $imap->starredMessages($client, $this->page, $this->perPage);
|
|
} else {
|
|
$result = $imap->messages($client, $this->folder, $this->page, $this->perPage);
|
|
}
|
|
|
|
$this->total = $result['total'];
|
|
$this->messages = in_array($this->folder, ['INBOX', '_starred'])
|
|
? array_map(fn($m) => array_merge($m, ['category' => $this->getCategory($m)]), $result['messages'])
|
|
: $result['messages'];
|
|
$this->categories = [];
|
|
|
|
$client->disconnect();
|
|
} catch (\Throwable) {
|
|
session()->forget(['webmail_email', 'webmail_password']);
|
|
$this->redirect(route('ui.webmail.login'));
|
|
}
|
|
}
|
|
|
|
private function getCategory(array $msg): string
|
|
{
|
|
$from = strtolower($msg['from'] ?? '');
|
|
foreach (['facebook','twitter','instagram','linkedin','tiktok','youtube','pinterest','reddit','snapchat','xing','mastodon'] as $kw) {
|
|
if (str_contains($from, $kw)) return 'social';
|
|
}
|
|
foreach (['newsletter','noreply','no-reply','no_reply','marketing','mailer','mailchimp','sendgrid','campaign','promo','offers','deals'] as $kw) {
|
|
if (str_contains($from, $kw)) return 'promo';
|
|
}
|
|
return 'general';
|
|
}
|
|
|
|
public function updatedSearch(string $value): void
|
|
{
|
|
if (mb_strlen(trim($value)) < 2) {
|
|
$this->searchResults = [];
|
|
$this->searching = false;
|
|
return;
|
|
}
|
|
$this->searching = true;
|
|
try {
|
|
$imap = app(ImapService::class);
|
|
$client = $imap->client(session('webmail_email'), session('webmail_password'));
|
|
$searchFolder = $this->folder === '_starred' ? 'INBOX' : $this->folder;
|
|
$this->searchResults = $imap->searchMessages($client, $searchFolder, trim($value));
|
|
$client->disconnect();
|
|
} catch (\Throwable) {
|
|
$this->searchResults = [];
|
|
}
|
|
$this->searching = false;
|
|
}
|
|
|
|
public function clearSearch(): void
|
|
{
|
|
$this->search = '';
|
|
$this->searchResults = [];
|
|
}
|
|
|
|
public function switchTab(string $tab): void
|
|
{
|
|
$allowed = ['all', 'general', 'promo', 'social'];
|
|
$this->tab = in_array($tab, $allowed, true) ? $tab : 'all';
|
|
}
|
|
|
|
public function switchFolder(string $folder): void
|
|
{
|
|
$this->folder = $folder;
|
|
$this->page = 1;
|
|
$this->tab = 'all';
|
|
$this->load();
|
|
}
|
|
|
|
public function nextPage(): void
|
|
{
|
|
if ($this->page * $this->perPage < $this->total) {
|
|
$this->page++;
|
|
$this->load();
|
|
}
|
|
}
|
|
|
|
public function prevPage(): void
|
|
{
|
|
if ($this->page > 1) {
|
|
$this->page--;
|
|
$this->load();
|
|
}
|
|
}
|
|
|
|
public function toggleFlag(int $uid): void
|
|
{
|
|
try {
|
|
$imap = app(ImapService::class);
|
|
$client = $imap->client(session('webmail_email'), session('webmail_password'));
|
|
$imap->toggleFlag($client, $this->folder, $uid);
|
|
$client->disconnect();
|
|
} catch (\Throwable) {}
|
|
$this->load();
|
|
}
|
|
|
|
public function deleteDraft(int $uid): void
|
|
{
|
|
try {
|
|
$imap = app(ImapService::class);
|
|
$client = $imap->client(session('webmail_email'), session('webmail_password'));
|
|
$imap->deleteMessage($client, 'Drafts', $uid);
|
|
$client->disconnect();
|
|
} catch (\Throwable) {}
|
|
$this->load();
|
|
}
|
|
|
|
public function bulkMarkUnseen(array $uids): void
|
|
{
|
|
try {
|
|
$imap = app(ImapService::class);
|
|
$client = $imap->client(session('webmail_email'), session('webmail_password'));
|
|
foreach ($uids as $uid) {
|
|
$imap->markUnseen($client, $this->folder, (int) $uid);
|
|
}
|
|
$client->disconnect();
|
|
} catch (\Throwable) {}
|
|
$this->load();
|
|
}
|
|
|
|
public function bulkMarkSeen(array $uids): void
|
|
{
|
|
try {
|
|
$imap = app(ImapService::class);
|
|
$client = $imap->client(session('webmail_email'), session('webmail_password'));
|
|
foreach ($uids as $uid) {
|
|
$imap->markSeen($client, $this->folder, (int) $uid);
|
|
}
|
|
$client->disconnect();
|
|
} catch (\Throwable) {}
|
|
$this->load();
|
|
}
|
|
|
|
public function bulkMoveTo(array $uids, string $target): void
|
|
{
|
|
$allowed = ['INBOX', 'Sent', 'Archive', 'Junk', 'Trash'];
|
|
if (! in_array($target, $allowed, true) || $target === $this->folder) return;
|
|
try {
|
|
$imap = app(ImapService::class);
|
|
$client = $imap->client(session('webmail_email'), session('webmail_password'));
|
|
foreach ($uids as $uid) {
|
|
$imap->moveMessage($client, $this->folder, (int) $uid, $target);
|
|
}
|
|
$client->disconnect();
|
|
} catch (\Throwable) {}
|
|
$this->load();
|
|
}
|
|
|
|
public function bulkDelete(array $uids): void
|
|
{
|
|
try {
|
|
$imap = app(ImapService::class);
|
|
$client = $imap->client(session('webmail_email'), session('webmail_password'));
|
|
foreach ($uids as $uid) {
|
|
if ($this->folder === 'Trash') {
|
|
$imap->deleteMessage($client, $this->folder, (int) $uid);
|
|
} else {
|
|
$imap->moveMessage($client, $this->folder, (int) $uid, 'Trash');
|
|
}
|
|
}
|
|
$client->disconnect();
|
|
} catch (\Throwable) {}
|
|
$this->load();
|
|
}
|
|
|
|
public function emptyTrash(): void
|
|
{
|
|
try {
|
|
$imap = app(ImapService::class);
|
|
$client = $imap->client(session('webmail_email'), session('webmail_password'));
|
|
$folder = $client->getFolder('Trash');
|
|
foreach ($folder->query()->all()->get() as $msg) {
|
|
$msg->delete(false);
|
|
}
|
|
$folder->expunge();
|
|
$client->disconnect();
|
|
} catch (\Throwable) {}
|
|
$this->load();
|
|
}
|
|
|
|
public function logout(): void
|
|
{
|
|
session()->forget(['webmail_email', 'webmail_password']);
|
|
$this->redirect(route('ui.webmail.login'));
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
return view('livewire.ui.webmail.inbox');
|
|
}
|
|
}
|