customDomain = Domain::where('is_active', true)->first()?->name ?? 'imail.app'; // Load current mailbox from session if exists $savedId = Session::get('current_mailbox_id'); if ($savedId && $this->getActiveMailboxesProperty()->contains('id', $savedId)) { $this->currentMailboxId = $savedId; } else { $this->currentMailboxId = $this->getActiveMailboxesProperty()->first()?->id; } // Auto-create a random mailbox if none exist (first-time visitor) if ($this->getActiveMailboxesProperty()->isEmpty()) { $this->isCreatingFirstMailbox = true; } } public function getActiveMailboxesProperty() { return MailboxModel::query() ->where(function ($query) { $query->where('session_id', Session::getId()); if (auth()->check()) { $query->orWhere('user_id', auth()->id()); } }) ->where('is_blocked', false) ->get(); } public function getAvailableDomainsProperty() { return Domain::query() ->where('is_active', true) ->where('is_archived', false) ->accessibleBy(auth()->user()) ->get(); } /** * Get Reverb/Echo event listeners for the current mailbox domain. * * @return array */ public function getListeners(): array { $currentMailbox = $this->active_mailboxes->firstWhere('id', $this->currentMailboxId); $domain = $currentMailbox ? explode('@', $currentMailbox->address)[1] ?? '' : ''; if (empty($domain)) { return []; } return [ "echo:mailbox.{$domain},.new.email" => 'onNewEmail', ]; } public function onNewEmail(array $eventData): void { // Simply refresh the list to pick up the new email from MariaDB // Since we order by received_at DESC, it will appear on top. $this->dispatch('$refresh'); } public function getEmailsProperty() { $currentMailbox = $this->active_mailboxes->firstWhere('id', $this->currentMailboxId); if (! $currentMailbox) { return Email::query()->whereRaw('1 = 0')->paginate(10); } return Email::query() ->where('recipient_email', $currentMailbox->address) ->when($this->search, function ($query) { $query->where(function ($q) { $q->where('subject', 'like', "%{$this->search}%") ->orWhere('sender_email', 'like', "%{$this->search}%") ->orWhere('sender_name', 'like', "%{$this->search}%"); }); }) ->orderByDesc('received_at') ->paginate(10); } public function getUnreadCountProperty(): int { $currentMailbox = $this->active_mailboxes->firstWhere('id', $this->currentMailboxId); if (! $currentMailbox) { return 0; } return Email::where('recipient_email', $currentMailbox->address) ->where('is_read', false) ->count(); } public function selectEmail($id) { $this->selectedEmailId = $id; $this->viewMode = 'text'; $this->allowRemoteContent = false; $email = Email::find($id); if ($email) { if (! $email->is_read) { $email->update(['is_read' => true]); } // Track analytics for reading email $currentMailbox = $this->active_mailboxes->firstWhere('id', $this->currentMailboxId); if ($currentMailbox) { TrackAnalytics::dispatch( eventType: 'email_read', mailboxHash: $currentMailbox->mailbox_hash, domainHash: $currentMailbox->domain_hash, metadata: ['email_id' => $email->id, 'subject' => $email->subject], userId: auth()->id(), userType: auth()->check() ? 'authenticated' : 'guest', ipAddress: request()->ip(), userAgent: request()->userAgent() ); } } } public function switchMailbox($id) { $this->currentMailboxId = $id; $this->selectedEmailId = null; $this->search = ''; $this->resetPage(); Session::put('current_mailbox_id', $id); // Track analytics for switching mailbox $currentMailbox = $this->active_mailboxes->firstWhere('id', $id); if ($currentMailbox) { TrackAnalytics::dispatch( eventType: 'mailbox_accessed', mailboxHash: $currentMailbox->mailbox_hash, domainHash: $currentMailbox->domain_hash, userId: auth()->id(), userType: auth()->check() ? 'authenticated' : 'guest', ipAddress: request()->ip(), userAgent: request()->userAgent() ); $currentMailbox->update([ 'last_accessed_at' => now(), 'last_accessed_ip' => request()->ip(), ]); } } public function createMailbox() { $domainModel = Domain::where('name', $this->customDomain) ->where('is_active', true) ->accessibleBy(auth()->user()) ->first(); if (! $domainModel) { return; } $address = $this->createType === 'random' ? fake()->userName().'_'.rand(10, 99).'@'.$this->customDomain : $this->customUsername.'@'.$this->customDomain; $mailbox = MailboxModel::create([ 'mailbox_hash' => bin2hex(random_bytes(32)), 'domain_hash' => $domainModel->domain_hash, 'user_id' => auth()->id(), 'session_id' => Session::getId(), 'address' => $address, 'type' => $this->createType === 'random' ? 'public' : 'custom', 'created_ip' => request()->ip(), 'last_accessed_ip' => request()->ip(), 'last_accessed_at' => now(), 'expires_at' => now()->addDays(7), // Default expiry ]); $this->currentMailboxId = $mailbox->id; $this->showCreateModal = false; $this->customUsername = ''; Session::put('last_mailbox_id', $mailbox->id); } /** * Auto-create a random mailbox on a public domain. * Called when no mailboxes exist (first visit, or all deleted). */ public function autoCreateRandomMailbox(): void { $domain = Domain::query() ->where('is_active', true) ->where('is_archived', false) ->accessibleBy(auth()->user()) ->whereJsonContains('allowed_types', 'public') ->inRandomOrder() ->first(); if (! $domain) { return; } $address = fake()->userName().'_'.rand(10, 99).'@'.$domain->name; $mailbox = MailboxModel::create([ 'mailbox_hash' => bin2hex(random_bytes(32)), 'domain_hash' => $domain->domain_hash, 'user_id' => auth()->id(), 'session_id' => Session::getId(), 'address' => $address, 'type' => 'public', 'created_ip' => request()->ip(), 'last_accessed_ip' => request()->ip(), 'last_accessed_at' => now(), 'expires_at' => now()->addDays(7), ]); $this->currentMailboxId = $mailbox->id; $this->isCreatingFirstMailbox = false; Session::put('current_mailbox_id', $mailbox->id); } public function finishAutoCreation(): void { if ($this->getActiveMailboxesProperty()->isEmpty()) { $this->autoCreateRandomMailbox(); } $this->isCreatingFirstMailbox = false; // Ensure the component re-renders fully with the new data $this->dispatch('$refresh'); } public function deleteMailbox($id) { $mailbox = MailboxModel::find($id); if ($mailbox) { $mailbox->delete(); } if ($this->currentMailboxId === $id) { $this->currentMailboxId = $this->active_mailboxes->first()?->id; $this->selectedEmailId = null; session(['current_mailbox_id' => $this->currentMailboxId]); } // If all mailboxes deleted, auto-create a new random one // Use a direct query or re-fetch the property to avoid cache issues $hasActive = MailboxModel::query() ->where(function ($query) { $query->where('session_id', Session::getId()); if (auth()->check()) { $query->orWhere('user_id', auth()->id()); } }) ->where('is_blocked', false) ->exists(); if (! $hasActive) { $this->isCreatingFirstMailbox = true; } } public function downloadEmail($id) { // Mock download logic $this->js("alert('Downloading email #{$id}... (Mock Action)')"); } public function printEmail($id) { // Mock print logic $this->js('window.print()'); } public function deleteEmail($id) { // Mock delete logic $this->js("alert('Email #{$id} deleted successfully! (Mock Action)')"); $this->selectedEmailId = null; } public function nextPage() { if ($this->page < $this->totalPages) { $this->page++; $this->selectedEmailId = null; } } public function previousPage() { if ($this->page > 1) { $this->page--; $this->selectedEmailId = null; } } public function generateQrCode($address) { // Mock QR generation with a slight delay usleep(800000); // 800ms $this->dispatch('qrCodeGenerated', address: $address); } public function getProcessedContent($email) { $body = EmailBody::where('unique_id_hash', $email->unique_id_hash)->first(); if (! $body) { return 'Email body not found.'; } $content = $body->body_html ?? $body->body_text; $isText = $this->viewMode === 'text'; // Fallback to HTML if text is selected but body_text is empty if ($isText && ! empty($body->body_text)) { return trim(e($body->body_text)); } if ($isText) { // If fallback occurred, we sanitize the HTML to text return trim(strip_tags($content)); } if (! $this->allowRemoteContent) { // Block remote assets by replacing src with data-src for img tags return preg_replace('/]*?\bsrc\s*=\s*([\'"])(.*?)\1/i', 'active_mailboxes->firstWhere('id', $this->currentMailboxId); return view('livewire.mailbox', [ 'emails' => $this->getEmailsProperty(), 'currentMailbox' => $currentMailbox, 'unreadCount' => $this->unread_count, ]); } }