loadMissing(['owner', 'agent', 'status', 'priority', 'category', 'project', 'team']); WorkflowTemplate::query() ->where('event', $event) ->where('is_active', true) ->get() ->each(function (WorkflowTemplate $template) use ($ticket, $event, $actor): void { $recipient = $this->recipient($template->to_role, $ticket, $actor); if ($recipient === null || blank($recipient->email ?? null)) { $this->log($template, $ticket, $event, null, 'skipped', 'No recipient email was available.'); return; } $subject = $this->renderText($template->subject, $ticket, $actor); $html = $this->wrapHtml($this->renderText($template->html_body, $ticket, $actor), $ticket); $text = $this->renderText($template->text_body ?: strip_tags($template->html_body), $ticket, $actor); try { Mail::html($html, function ($message) use ($recipient, $template, $subject): void { $message->to($recipient->email, $recipient->name ?? null)->subject($subject); if (filled($template->cc)) { $message->cc(array_map('trim', explode(',', (string) $template->cc))); } if (filled($template->bcc)) { $message->bcc(array_map('trim', explode(',', (string) $template->bcc))); } }); $this->log($template, $ticket, $event, (string) $recipient->email, 'sent', null, $subject); } catch (Throwable $exception) { Log::warning('Helpdesk workflow email failed.', ['event' => $event, 'ticket_id' => $ticket->id, 'error' => $exception->getMessage()]); $this->log($template, $ticket, $event, (string) $recipient->email, 'failed', $exception->getMessage(), $subject); } }); } /** @return User|null */ private function recipient(string $role, Ticket $ticket, ?User $actor): ?User { return match ($role) { 'agent' => $ticket->agent, 'actor' => $actor, default => $ticket->owner, }; } private function renderText(string $template, Ticket $ticket, ?User $actor): string { $tokens = [ '{{ ticket.reference }}' => $ticket->reference, '{{ ticket.subject }}' => $ticket->subject, '{{ ticket.status }}' => (string) ($ticket->status?->name ?? ''), '{{ ticket.priority }}' => (string) ($ticket->priority?->name ?? ''), '{{ ticket.category }}' => (string) ($ticket->category?->name ?? ''), '{{ ticket.project }}' => (string) ($ticket->project?->title ?? ''), '{{ ticket.team }}' => (string) ($ticket->team?->name ?? ''), '{{ requester.name }}' => (string) ($ticket->owner?->name ?? ''), '{{ agent.name }}' => (string) ($ticket->agent?->name ?? ''), '{{ actor.name }}' => (string) ($actor?->name ?? ''), '{{ ticket.url }}' => route('helpdesk.tickets.show', ['ticket' => $ticket->getKey()]), ]; return strtr($template, $tokens); } private function wrapHtml(string $body, Ticket $ticket): string { return '
' . '
' . '
' . '
Helpdesk notification
' . '

' . e($ticket->reference) . '

' . '

' . e($ticket->subject) . '

' . '
' . $body . '

Open ticket

' . '
'; } private function log(WorkflowTemplate $template, Ticket $ticket, string $event, ?string $recipient, string $status, ?string $error = null, ?string $subject = null): void { WorkflowLog::query()->create([ 'template_id' => $template->id, 'ticket_id' => $ticket->id, 'event' => $event, 'recipient' => $recipient, 'subject' => $subject, 'status' => $status, 'error' => $error, ]); } }