Add email integration for ticket system and IMAP inbound support
Email integration: IMAP polling via webklex/php-imap (M365/Zoho/MIAB
compatible), TicketEmailProcessor with 3-strategy ticket matching
(In-Reply-To, References, subject line [EZSCALE-{id}]), signature and
quote stripping, scheduled command every 2min.
Outbound: 4 notification classes (TicketCreated, CustomerReply,
StaffReply, StatusChanged) with email threading headers via
withSymfonyMessage(). Staff replies set Reply-To: support@ezscale.cloud.
Frontend: ticket reference chips on all pages, "Via Email" badges on
email-originated replies. 12 new tests (163 total, 816 assertions).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -173,6 +173,15 @@ function formatDate(dateStr: string): string {
|
||||
</td>
|
||||
<td class="text-body-2 font-weight-medium">
|
||||
{{ ticket.subject }}
|
||||
<VChip
|
||||
v-if="ticket.ticket_reference"
|
||||
size="x-small"
|
||||
color="secondary"
|
||||
variant="tonal"
|
||||
class="ms-2"
|
||||
>
|
||||
{{ ticket.ticket_reference }}
|
||||
</VChip>
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
|
||||
@@ -97,6 +97,14 @@ function getUserInitial(name: string): string {
|
||||
<div>
|
||||
<div class="d-flex align-center gap-2">
|
||||
<span class="text-h4 font-weight-bold">Ticket #{{ ticket.id }}</span>
|
||||
<VChip
|
||||
v-if="ticket.ticket_reference"
|
||||
size="small"
|
||||
color="secondary"
|
||||
variant="tonal"
|
||||
>
|
||||
{{ ticket.ticket_reference }}
|
||||
</VChip>
|
||||
<VChip
|
||||
:color="resolveTicketStatusColor(ticket.status)"
|
||||
size="small"
|
||||
@@ -162,7 +170,7 @@ function getUserInitial(name: string): string {
|
||||
</VAvatar>
|
||||
<div>
|
||||
<div class="text-body-1 font-weight-medium">
|
||||
{{ reply.user?.name ?? 'Unknown' }}
|
||||
{{ reply.user?.name ?? reply.from_email ?? 'Unknown' }}
|
||||
<VChip
|
||||
v-if="reply.is_staff_reply"
|
||||
size="x-small"
|
||||
@@ -171,6 +179,15 @@ function getUserInitial(name: string): string {
|
||||
>
|
||||
Staff
|
||||
</VChip>
|
||||
<VChip
|
||||
v-if="reply.via_email"
|
||||
size="x-small"
|
||||
color="info"
|
||||
variant="tonal"
|
||||
class="ms-2"
|
||||
>
|
||||
Via Email
|
||||
</VChip>
|
||||
</div>
|
||||
<div class="text-caption text-medium-emphasis">
|
||||
{{ formatDateTime(reply.created_at) }}
|
||||
|
||||
@@ -73,6 +73,15 @@ function formatStatus(status: string): string {
|
||||
<tr v-for="ticket in tickets.data" :key="ticket.id">
|
||||
<td class="text-body-2 font-weight-medium">
|
||||
{{ ticket.subject }}
|
||||
<VChip
|
||||
v-if="ticket.ticket_reference"
|
||||
size="x-small"
|
||||
color="secondary"
|
||||
variant="tonal"
|
||||
class="ms-2"
|
||||
>
|
||||
{{ ticket.ticket_reference }}
|
||||
</VChip>
|
||||
</td>
|
||||
<td>
|
||||
<VChip
|
||||
|
||||
@@ -76,6 +76,14 @@ function getUserInitial(name: string): string {
|
||||
<div>
|
||||
<div class="d-flex align-center ga-3 mb-2">
|
||||
<span class="text-h5 font-weight-bold">{{ ticket.subject }}</span>
|
||||
<VChip
|
||||
v-if="ticket.ticket_reference"
|
||||
size="small"
|
||||
color="secondary"
|
||||
variant="tonal"
|
||||
>
|
||||
{{ ticket.ticket_reference }}
|
||||
</VChip>
|
||||
<VChip
|
||||
:color="resolveTicketStatusColor(ticket.status)"
|
||||
size="small"
|
||||
@@ -134,7 +142,7 @@ function getUserInitial(name: string): string {
|
||||
</VAvatar>
|
||||
<div>
|
||||
<div class="text-body-1 font-weight-medium">
|
||||
{{ reply.user?.name ?? 'Unknown' }}
|
||||
{{ reply.user?.name ?? reply.from_email ?? 'Unknown' }}
|
||||
<VChip
|
||||
v-if="reply.is_staff_reply"
|
||||
size="x-small"
|
||||
@@ -143,6 +151,15 @@ function getUserInitial(name: string): string {
|
||||
>
|
||||
Staff
|
||||
</VChip>
|
||||
<VChip
|
||||
v-if="reply.via_email"
|
||||
size="x-small"
|
||||
color="info"
|
||||
variant="tonal"
|
||||
class="ms-2"
|
||||
>
|
||||
Via Email
|
||||
</VChip>
|
||||
</div>
|
||||
<div class="text-caption text-medium-emphasis">
|
||||
{{ formatDateTime(reply.created_at) }}
|
||||
|
||||
Reference in New Issue
Block a user