mailwolt/resources/views/livewire/ui/system/sandbox-mailbox.blade.php

236 lines
14 KiB
PHP

<x-slot:breadcrumbParent>System</x-slot:breadcrumbParent>
<x-slot:breadcrumb>Mail-Sandbox</x-slot:breadcrumb>
<div wire:poll.5s>
<div class="mbx-page-header">
<div class="mbx-page-title">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
<rect x="1.5" y="3.5" width="13" height="9" rx="1.5" stroke="currentColor" stroke-width="1.3"/>
<path d="M1.5 5.5l6.5 4 6.5-4" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/>
</svg>
Mail-Sandbox
@if($unread > 0)
<span style="font-size:10px;padding:1px 7px;border-radius:10px;background:var(--mw-v);color:#fff;font-weight:600;margin-left:2px">{{ $unread }} neu</span>
@endif
</div>
<div class="mbx-page-actions">
<div class="mbx-search-wrap">
<svg width="13" height="13" viewBox="0 0 13 13" fill="none" style="flex-shrink:0;color:var(--mw-t4)"><circle cx="5.5" cy="5.5" r="4" stroke="currentColor" stroke-width="1.2"/><path d="M9 9l2.5 2.5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>
<input type="text" wire:model.live.debounce.250ms="search" class="mbx-search-input" placeholder="Von, An, Betreff …">
</div>
@if($mails->isNotEmpty())
<button wire:click="clearAll"
wire:confirm="Alle {{ $mails->count() }} Nachrichten löschen?"
class="mw-btn-del" style="font-size:12px;padding:5px 12px">
<svg width="11" height="11" viewBox="0 0 13 13" fill="none"><path d="M2 3h9M5 3V2h3v1M3.5 3l.5 8h5l.5-8" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg>
Alle löschen
</button>
@endif
</div>
</div>
{{-- Mail-Client Layout --}}
<div style="display:grid;grid-template-columns:320px 1fr;gap:0;border:1px solid var(--mw-b1);border-radius:10px;overflow:hidden;background:var(--mw-bg2);min-height:520px">
{{-- ═══ Left: Mail-Liste ═══ --}}
<div style="border-right:1px solid var(--mw-b1);overflow-y:auto;max-height:680px">
@if($mails->isEmpty())
<div style="padding:48px 16px;text-align:center">
<svg width="32" height="32" viewBox="0 0 16 16" fill="none" style="color:var(--mw-t4);margin:0 auto 12px;display:block">
<rect x="1.5" y="3.5" width="13" height="9" rx="1.5" stroke="currentColor" stroke-width="1.3"/>
<path d="M1.5 5.5l6.5 4 6.5-4" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/>
</svg>
<div style="font-size:12.5px;color:var(--mw-t2);font-weight:500;margin-bottom:4px">
{{ $search ? 'Keine Treffer' : 'Postfach leer' }}
</div>
<div style="font-size:11.5px;color:var(--mw-t4)">
{{ $search ? 'Suche anpassen.' : 'Eingehende Mails erscheinen hier sobald der Sandbox-Transport aktiv ist.' }}
</div>
</div>
@else
@foreach($mails as $mail)
<div wire:click="select({{ $mail->id }})"
style="padding:11px 14px;border-bottom:1px solid var(--mw-b1);cursor:pointer;transition:background .1s;
{{ $selectedId === $mail->id ? 'background:var(--mw-vbg);border-left:3px solid var(--mw-v);' : 'border-left:3px solid transparent;' }}
{{ !$mail->is_read && $selectedId !== $mail->id ? 'background:rgba(124,58,237,.04);' : '' }}"
onmouseover="if({{ $selectedId !== $mail->id ? 'true' : 'false' }})this.style.background='var(--mw-bg3)'"
onmouseout="this.style.background='{{ $selectedId === $mail->id ? 'var(--mw-vbg)' : (!$mail->is_read ? 'rgba(124,58,237,.04)' : '') }}'">
<div style="display:flex;justify-content:space-between;align-items:flex-start;gap:6px;margin-bottom:3px">
<div style="display:flex;align-items:center;gap:5px;min-width:0">
@if(!$mail->is_read)
<div style="width:6px;height:6px;border-radius:50%;background:var(--mw-v);flex-shrink:0"></div>
@endif
<span style="font-size:12px;font-weight:{{ $mail->is_read ? '400' : '600' }};color:var(--mw-t1);overflow:hidden;text-overflow:ellipsis;white-space:nowrap">
{{ $mail->from_name ?: $mail->from_address }}
</span>
</div>
<span style="font-size:10px;color:var(--mw-t4);flex-shrink:0">{{ $mail->received_at->format('H:i') }}</span>
</div>
<div style="font-size:11.5px;color:var(--mw-t2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-bottom:2px;font-weight:{{ $mail->is_read ? '400' : '500' }}">
{{ $mail->subject ?: '(kein Betreff)' }}
</div>
<div style="font-size:10.5px;color:var(--mw-t4);overflow:hidden;text-overflow:ellipsis;white-space:nowrap">
An: {{ $mail->to_preview }}
</div>
</div>
@endforeach
@endif
</div>
{{-- ═══ Right: Mail-Detail ═══ --}}
<div style="overflow-y:auto;max-height:680px">
@if(!$selected)
<div style="display:flex;align-items:center;justify-content:center;height:100%;min-height:400px;flex-direction:column;gap:12px">
<svg width="36" height="36" viewBox="0 0 16 16" fill="none" style="color:var(--mw-b2)">
<rect x="1.5" y="3.5" width="13" height="9" rx="1.5" stroke="currentColor" stroke-width="1.3"/>
<path d="M1.5 5.5l6.5 4 6.5-4" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/>
</svg>
<div style="font-size:12px;color:var(--mw-t4)">Nachricht auswählen</div>
</div>
@else
{{-- Header --}}
<div style="padding:16px 20px;border-bottom:1px solid var(--mw-b1)">
<div style="display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:12px">
<h2 style="font-size:14px;font-weight:600;color:var(--mw-t1);margin:0;line-height:1.4">{{ $selected->subject ?: '(kein Betreff)' }}</h2>
<button wire:click="deleteOne({{ $selected->id }})"
class="mbx-act-btn mbx-act-danger" title="Löschen" style="flex-shrink:0">
<svg width="12" height="12" viewBox="0 0 13 13" fill="none"><path d="M2 3h9M5 3V2h3v1M3.5 3l.5 8h5l.5-8" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg>
</button>
</div>
<div style="display:flex;flex-direction:column;gap:5px;font-size:11.5px">
<div style="display:flex;gap:8px">
<span style="color:var(--mw-t4);width:34px;flex-shrink:0">Von</span>
<span style="color:var(--mw-t2);font-family:monospace;font-size:11px">{{ $selected->sender }}</span>
</div>
<div style="display:flex;gap:8px">
<span style="color:var(--mw-t4);width:34px;flex-shrink:0">An</span>
<span style="color:var(--mw-t2);font-family:monospace;font-size:11px">{{ implode(', ', $selected->to_addresses) }}</span>
</div>
<div style="display:flex;gap:8px">
<span style="color:var(--mw-t4);width:34px;flex-shrink:0">Zeit</span>
<span style="color:var(--mw-t3)">{{ $selected->received_at->format('d.m.Y H:i:s') }}</span>
</div>
@if($selected->message_id)
<div style="display:flex;gap:8px">
<span style="color:var(--mw-t4);width:34px;flex-shrink:0">ID</span>
<span style="color:var(--mw-t4);font-family:monospace;font-size:10px">{{ $selected->message_id }}</span>
</div>
@endif
</div>
</div>
{{-- Body Tabs --}}
<div x-data="{tab: '{{ $selected->body_html ? 'html' : 'text' }}'}" style="display:flex;flex-direction:column;height:100%">
<div style="display:flex;gap:0;border-bottom:1px solid var(--mw-b1);padding:0 20px">
@if($selected->body_html)
<button @click="tab='html'"
:style="tab==='html' ? 'border-bottom:2px solid var(--mw-v);color:var(--mw-v2);font-weight:600' : 'border-bottom:2px solid transparent;color:var(--mw-t4)'"
style="padding:8px 14px;background:none;border:none;border-top:none;border-left:none;border-right:none;font-size:11.5px;cursor:pointer;transition:all .1s">
HTML
</button>
@endif
@if($selected->body_text)
<button @click="tab='text'"
:style="tab==='text' ? 'border-bottom:2px solid var(--mw-v);color:var(--mw-v2);font-weight:600' : 'border-bottom:2px solid transparent;color:var(--mw-t4)'"
style="padding:8px 14px;background:none;border:none;border-top:none;border-left:none;border-right:none;font-size:11.5px;cursor:pointer;transition:all .1s">
Plain Text
</button>
@endif
<button @click="tab='headers'"
:style="tab==='headers' ? 'border-bottom:2px solid var(--mw-v);color:var(--mw-v2);font-weight:600' : 'border-bottom:2px solid transparent;color:var(--mw-t4)'"
style="padding:8px 14px;background:none;border:none;border-top:none;border-left:none;border-right:none;font-size:11.5px;cursor:pointer;transition:all .1s">
Header
</button>
</div>
@if($selected->body_html)
<div x-show="tab==='html'" x-cloak style="flex:1">
<iframe srcdoc="{{ htmlspecialchars($selected->body_html) }}"
style="width:100%;min-height:420px;border:none;display:block"
sandbox="allow-same-origin"></iframe>
</div>
@endif
@if($selected->body_text)
<div x-show="tab==='text'" x-cloak style="padding:16px 20px">
<pre style="font-family:ui-monospace,monospace;font-size:11.5px;color:var(--mw-t2);white-space:pre-wrap;word-break:break-word;margin:0;line-height:1.7">{{ $selected->body_text }}</pre>
</div>
@endif
<div x-show="tab==='headers'" x-cloak style="padding:16px 20px">
<pre style="font-family:ui-monospace,monospace;font-size:10.5px;color:var(--mw-t3);white-space:pre-wrap;word-break:break-all;margin:0;line-height:1.7;background:var(--mw-bg4);padding:12px;border-radius:6px">{{ $selected->raw_headers }}</pre>
</div>
@if(!$selected->body_html && !$selected->body_text)
<div style="padding:32px;text-align:center;color:var(--mw-t4);font-size:12px">Kein Inhalt</div>
@endif
</div>
@endif
</div>
</div>
{{-- Setup Guide --}}
<div class="mbx-sections" style="margin-top:14px">
<div class="mbx-section">
<div class="mbx-domain-head">
<div class="mbx-domain-info">
<span class="mbx-badge-mute">Postfix-Konfiguration</span>
<span style="font-size:11px;color:var(--mw-t4);margin-left:6px"> Sandbox-Transport aktivieren</span>
</div>
</div>
<div style="padding:16px 18px;display:grid;grid-template-columns:1fr 1fr 1fr;gap:16px">
<div>
<div style="font-size:11px;color:var(--mw-t4);margin-bottom:6px;font-weight:500">1. master.cf Transport anlegen</div>
<pre style="font-family:monospace;font-size:10px;color:var(--mw-t3);background:var(--mw-bg4);padding:10px 12px;border-radius:6px;overflow-x:auto;margin:0;line-height:1.7">sandbox unix - n n - - pipe
flags=Rq user=www-data
argv=/usr/bin/php
{{ base_path('artisan') }}
sandbox:receive
--to=${recipient}</pre>
</div>
<div>
<div style="font-size:11px;color:var(--mw-t4);margin-bottom:6px;font-weight:500">2. main.cf Transport aktivieren</div>
<pre style="font-family:monospace;font-size:10px;color:var(--mw-t3);background:var(--mw-bg4);padding:10px 12px;border-radius:6px;overflow-x:auto;margin:0;line-height:1.7"># Alle Mails abfangen:
default_transport = sandbox
# Oder nur bestimmte Domains:
transport_maps =
hash:/etc/postfix/transport
# /etc/postfix/transport:
# example.com sandbox:</pre>
</div>
<div>
<div style="font-size:11px;color:var(--mw-t4);margin-bottom:6px;font-weight:500">3. Reload &amp; Test</div>
<pre style="font-family:monospace;font-size:10px;color:var(--mw-t3);background:var(--mw-bg4);padding:10px 12px;border-radius:6px;overflow-x:auto;margin:0;line-height:1.7">postmap /etc/postfix/transport
postfix reload
# Test:
echo "Test" | mail \
-s "Sandbox-Test" \
user@example.com</pre>
<div style="margin-top:8px;font-size:11px;color:var(--mw-t4)">
Die Mail erscheint nach wenigen Sekunden hier (Auto-Refresh alle 5s).
</div>
</div>
</div>
</div>
</div>
</div>