PHPackages                             jeffersongoncalves/laravel-help-desk - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. jeffersongoncalves/laravel-help-desk

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

jeffersongoncalves/laravel-help-desk
====================================

A comprehensive help desk and ticket management system for Laravel applications with email integration.

v1.2.6(2mo ago)31641MITPHPPHP ^8.2

Since Feb 4Pushed 2mo agoCompare

[ Source](https://github.com/jeffersongoncalves/laravel-help-desk)[ Packagist](https://packagist.org/packages/jeffersongoncalves/laravel-help-desk)[ Docs](https://github.com/jeffersongoncalves/laravel-help-desk)[ GitHub Sponsors](https://github.com/jeffersongoncalves)[ RSS](/packages/jeffersongoncalves-laravel-help-desk/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (11)Versions (13)Used By (1)

[![Laravel Help Desk](https://raw.githubusercontent.com/jeffersongoncalves/laravel-help-desk/master/art/jeffersongoncalves-laravel-help-desk.png)](https://raw.githubusercontent.com/jeffersongoncalves/laravel-help-desk/master/art/jeffersongoncalves-laravel-help-desk.png)

Laravel Help Desk
=================

[](#laravel-help-desk)

A comprehensive help desk and ticket management system for Laravel applications with email integration.

Requirements
------------

[](#requirements)

- PHP 8.1+
- Laravel 10, 11, or 12

Installation
------------

[](#installation)

```
composer require jeffersongoncalves/laravel-help-desk
```

The package uses Laravel's auto-discovery, so the service provider and facade are registered automatically.

### Publish Configuration

[](#publish-configuration)

```
php artisan vendor:publish --tag=help-desk-config
```

### Publish Migrations

[](#publish-migrations)

```
php artisan vendor:publish --tag=help-desk-migrations
```

### Run Migrations

[](#run-migrations)

```
php artisan migrate
```

### Publish Translations (optional)

[](#publish-translations-optional)

```
php artisan vendor:publish --tag=help-desk-translations
```

Configuration
-------------

[](#configuration)

The configuration file is located at `config/help-desk.php`. Key options:

```
return [
    // Models used by the help desk
    'models' => [
        'user'     => \App\Models\User::class,  // Model that creates tickets
        'operator' => \App\Models\User::class,   // Model that manages tickets
    ],

    // Ticket settings
    'ticket' => [
        'reference_prefix'   => 'HD',           // Ticket reference format: HD-00001
        'default_status'     => 'open',
        'default_priority'   => 'medium',
        'attachment_disk'    => 'local',         // Storage disk for attachments
        'auto_close_days'    => null,            // Auto-close resolved tickets (null = disabled)
        'allow_reopen'       => true,
    ],

    // Email integration
    'email' => [
        'enabled' => true,
        'inbound' => [
            'driver' => null, // 'imap', 'mailgun', 'sendgrid', or 'resend'
        ],
    ],

    // Notification settings
    'notifications' => [
        'channels' => ['mail'],
        'queue'    => 'default',
    ],
];
```

Setup
-----

[](#setup)

### 1. Add Traits to Your User Model

[](#1-add-traits-to-your-user-model)

For regular users (ticket creators):

```
use JeffersonGoncalves\HelpDesk\Concerns\HasTickets;

class User extends Authenticatable
{
    use HasTickets;
}
```

For operators/agents (ticket managers):

```
use JeffersonGoncalves\HelpDesk\Concerns\IsOperator;

class User extends Authenticatable
{
    use IsOperator; // Includes HasTickets
}
```

### 2. Create Departments

[](#2-create-departments)

```
use JeffersonGoncalves\HelpDesk\Facades\HelpDesk;

$department = HelpDesk::createDepartment([
    'name' => 'Technical Support',
    'slug' => 'technical-support',
    'email' => 'support@example.com',
    'is_active' => true,
]);
```

### 3. Assign Operators to Departments

[](#3-assign-operators-to-departments)

```
HelpDesk::addOperator($department, $user, 'operator'); // 'operator', 'manager', or 'admin'
```

Usage
-----

[](#usage)

### Creating Tickets

[](#creating-tickets)

```
use JeffersonGoncalves\HelpDesk\Facades\HelpDesk;

$ticket = HelpDesk::createTicket([
    'title' => 'Cannot access my account',
    'description' => 'I get an error when trying to log in...',
    'department_id' => $department->id,
    'priority' => 'high',
], $user);

// $ticket->reference_number => "HD-00001"
// $ticket->uuid => "550e8400-e29b-41d4-a716-446655440000"
```

### Managing Tickets

[](#managing-tickets)

```
// Find tickets
$ticket = HelpDesk::findTicketByReference('HD-00001');
$ticket = HelpDesk::findTicketByUuid('550e8400-...');

// Assign to operator
HelpDesk::assignTicket($ticket, $operator);
HelpDesk::unassignTicket($ticket);

// Change status
use JeffersonGoncalves\HelpDesk\Enums\TicketStatus;

HelpDesk::changeStatus($ticket, TicketStatus::InProgress);
HelpDesk::closeTicket($ticket);
HelpDesk::reopenTicket($ticket);

// Update ticket
HelpDesk::updateTicket($ticket, [
    'priority' => 'urgent',
    'category_id' => $category->id,
]);

// Delete ticket (soft delete)
HelpDesk::deleteTicket($ticket);
```

### Comments

[](#comments)

```
// Add a public reply
$comment = HelpDesk::addComment($ticket, $user, 'Thank you for contacting us.');

// Add an internal note (not visible to end user)
$note = HelpDesk::addNote($ticket, $operator, 'Escalating to senior engineer.');

// Add comment with attachments
$comment = HelpDesk::addComment($ticket, $user, 'See attached screenshot.', [
    'attachments' => [$uploadedFile],
]);
```

### Watchers

[](#watchers)

```
HelpDesk::addWatcher($ticket, $anotherUser);
HelpDesk::removeWatcher($ticket, $anotherUser);
```

### Querying Tickets

[](#querying-tickets)

```
use JeffersonGoncalves\HelpDesk\Models\Ticket;
use JeffersonGoncalves\HelpDesk\Enums\TicketStatus;
use JeffersonGoncalves\HelpDesk\Enums\TicketPriority;

// Open tickets
$open = Ticket::open()->get();

// Closed tickets
$closed = Ticket::closed()->get();

// By status
$inProgress = Ticket::byStatus(TicketStatus::InProgress)->get();

// By priority
$urgent = Ticket::byPriority(TicketPriority::Urgent)->get();

// Overdue tickets
$overdue = Ticket::overdue()->get();

// Unassigned tickets
$unassigned = Ticket::unassigned()->get();

// User's tickets (via trait)
$user->helpDeskTickets;

// Operator's assigned tickets (via trait)
$operator->helpDeskAssignedTickets;
```

### Canned Responses

[](#canned-responses)

```
use JeffersonGoncalves\HelpDesk\Models\CannedResponse;

CannedResponse::create([
    'title' => 'Greeting',
    'body' => 'Thank you for contacting our support team...',
    'department_id' => $department->id,
    'is_active' => true,
]);

// Get canned responses for a department
$responses = CannedResponse::active()
    ->forDepartment($department->id)
    ->ordered()
    ->get();
```

### Categories

[](#categories)

```
use JeffersonGoncalves\HelpDesk\Models\Category;

$category = Category::create([
    'department_id' => $department->id,
    'name' => 'Billing',
    'slug' => 'billing',
    'is_active' => true,
]);

// Subcategories
$sub = Category::create([
    'department_id' => $department->id,
    'parent_id' => $category->id,
    'name' => 'Refunds',
    'slug' => 'refunds',
]);
```

Ticket Statuses
---------------

[](#ticket-statuses)

StatusDescription`open`New ticket, awaiting response`pending`Awaiting user response`in_progress`Being worked on by an operator`on_hold`Temporarily on hold`resolved`Issue has been resolved`closed`Ticket is closedStatus transitions are validated automatically. For example, a `closed` ticket can only transition to `open` (reopen).

Ticket Priorities
-----------------

[](#ticket-priorities)

PriorityNumeric Value`low`1`medium`2`high`3`urgent`4Events
------

[](#events)

The package dispatches events that you can listen to in your application:

EventDescription`TicketCreated`A new ticket was created`TicketUpdated`A ticket was updated`TicketStatusChanged`Ticket status changed`TicketPriorityChanged`Ticket priority changed`TicketAssigned`Ticket was assigned to an operator`TicketClosed`Ticket was closed`TicketReopened`Ticket was reopened`TicketDeleted`Ticket was deleted`CommentAdded`A comment was added to a ticket`AttachmentAdded`An attachment was added`AttachmentRemoved`An attachment was removed`InboundEmailReceived`An inbound email was received`InboundEmailProcessed`An inbound email was processed### Disabling Default Listeners

[](#disabling-default-listeners)

If you want to handle events yourself:

```
// config/help-desk.php
'register_default_listeners' => false,
```

Email Integration
-----------------

[](#email-integration)

### Outbound Notifications

[](#outbound-notifications)

Notifications are sent automatically when events occur (configurable via `notifications.notify_on`). Email threading is supported via `Message-ID`, `In-Reply-To`, and `References` headers.

### Inbound Email

[](#inbound-email)

The package supports receiving emails via 5 drivers:

#### IMAP

[](#imap)

```
HELPDESK_INBOUND_DRIVER=imap
HELPDESK_IMAP_HOST=imap.example.com
HELPDESK_IMAP_PORT=993
HELPDESK_IMAP_ENCRYPTION=ssl
HELPDESK_IMAP_USERNAME=support@example.com
HELPDESK_IMAP_PASSWORD=your-password
HELPDESK_IMAP_FOLDER=INBOX
```

Requires the `webklex/php-imap` package:

```
composer require webklex/php-imap
```

Schedule the polling command in your `app/Console/Kernel.php` or `routes/console.php`:

```
$schedule->command('help-desk:poll-imap')->everyFiveMinutes();
```

#### Mailgun

[](#mailgun)

```
HELPDESK_INBOUND_DRIVER=mailgun
HELPDESK_MAILGUN_SIGNING_KEY=your-signing-key
```

Configure your Mailgun route to forward to:

```
POST https://your-app.com/help-desk/webhooks/mailgun

```

#### SendGrid

[](#sendgrid)

```
HELPDESK_INBOUND_DRIVER=sendgrid
HELPDESK_SENDGRID_WEBHOOK_USERNAME=your-username
HELPDESK_SENDGRID_WEBHOOK_PASSWORD=your-password
```

Configure your SendGrid Inbound Parse to forward to:

```
POST https://your-app.com/help-desk/webhooks/sendgrid

```

#### Resend

[](#resend)

```
HELPDESK_INBOUND_DRIVER=resend
HELPDESK_RESEND_API_KEY=re_your-api-key
HELPDESK_RESEND_WEBHOOK_SECRET=whsec_your-webhook-secret
```

Configure your Resend receiving domain webhook to forward to:

```
POST https://your-app.com/help-desk/webhooks/resend

```

Select the `email.received` event type in your Resend webhook configuration.

#### Postmark

[](#postmark)

```
HELPDESK_INBOUND_DRIVER=postmark
HELPDESK_POSTMARK_WEBHOOK_USERNAME=your-username
HELPDESK_POSTMARK_WEBHOOK_PASSWORD=your-password
```

In your Postmark server, go to the Inbound Message Stream settings and set the webhook URL to:

```
POST https://your-username:your-password@your-app.com/help-desk/webhooks/postmark

```

Postmark sends the full email content (body, headers, attachments) directly in the webhook payload. The package also uses Postmark's `StrippedTextReply` field for cleaner reply parsing.

### Email Channels

[](#email-channels)

You can configure multiple email channels, each mapped to a department:

```
use JeffersonGoncalves\HelpDesk\Models\EmailChannel;

EmailChannel::create([
    'department_id' => $department->id,
    'name' => 'Support Inbox',
    'driver' => 'mailgun',
    'email_address' => 'support@example.com',
    'settings' => [], // Driver-specific settings (encrypted)
    'is_active' => true,
]);
```

### Email Threading

[](#email-threading)

When an inbound email is received, the package resolves it to an existing ticket using:

1. `In-Reply-To` header
2. `References` header
3. Subject line reference number (e.g., `HD-00001`)

If no match is found, a new ticket is created.

Artisan Commands
----------------

[](#artisan-commands)

```
# Poll IMAP mailboxes for new emails
php artisan help-desk:poll-imap

# Clean old processed inbound emails
php artisan help-desk:clean-emails --days=30

# Auto-close stale tickets
php artisan help-desk:close-stale --days=14 --status=resolved

# Dry run (see what would be closed)
php artisan help-desk:close-stale --days=14 --dry-run
```

Using the Services Directly
---------------------------

[](#using-the-services-directly)

For more control, you can inject the service classes directly:

```
use JeffersonGoncalves\HelpDesk\Services\TicketService;
use JeffersonGoncalves\HelpDesk\Services\CommentService;
use JeffersonGoncalves\HelpDesk\Services\DepartmentService;
use JeffersonGoncalves\HelpDesk\Services\AttachmentService;

class MyController
{
    public function __construct(
        private TicketService $tickets,
        private CommentService $comments,
    ) {}

    public function store(Request $request)
    {
        $ticket = $this->tickets->create([
            'title' => $request->title,
            'description' => $request->description,
            'department_id' => $request->department_id,
        ], $request->user());

        return $ticket;
    }
}
```

Translation
-----------

[](#translation)

The package ships with English and Brazilian Portuguese translations. To customize:

```
php artisan vendor:publish --tag=help-desk-translations
```

This publishes translation files to `lang/vendor/help-desk/`. You can modify them or add new locales.

```
// Using translations in your code
__('help-desk::tickets.messages.created')  // "Ticket created successfully."
__('help-desk::statuses.open')             // "Open"
__('help-desk::priorities.urgent')         // "Urgent"
```

Testing
-------

[](#testing)

```
composer test
```

Static Analysis
---------------

[](#static-analysis)

```
composer analyse
```

Code Formatting
---------------

[](#code-formatting)

```
composer format
```

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

44

—

FairBetter than 92% of packages

Maintenance84

Actively maintained with recent releases

Popularity18

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity54

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~2 days

Total

12

Last Release

83d ago

PHP version history (2 changes)1.0.0PHP ^8.1

v1.2.0PHP ^8.2

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/411493?v=4)[Jefferson Gonçalves](/maintainers/jeffersongoncalves)[@jeffersongoncalves](https://github.com/jeffersongoncalves)

---

Top Contributors

[![jeffersongoncalves](https://avatars.githubusercontent.com/u/411493?v=4)](https://github.com/jeffersongoncalves "jeffersongoncalves (29 commits)")

---

Tags

composercustomer-supportemail-integrationhelp-deskjeffersongoncalveslaravellaravel-packagephpsupportticketticket-managementticketing-systemlaravelsupporthelp deskticketcustomer-supportemail-integration

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/jeffersongoncalves-laravel-help-desk/health.svg)

```
[![Health](https://phpackages.com/badges/jeffersongoncalves-laravel-help-desk/health.svg)](https://phpackages.com/packages/jeffersongoncalves-laravel-help-desk)
```

###  Alternatives

[spatie/laravel-health

Monitor the health of a Laravel application

86910.0M83](/packages/spatie-laravel-health)[psalm/plugin-laravel

Psalm plugin for Laravel

3274.9M308](/packages/psalm-plugin-laravel)[dyrynda/laravel-model-uuid

This package allows you to easily work with UUIDs in your Laravel models.

4802.8M8](/packages/dyrynda-laravel-model-uuid)[spatie/laravel-livewire-wizard

Build wizards using Livewire

4061.0M4](/packages/spatie-laravel-livewire-wizard)[laracraft-tech/laravel-useful-additions

A collection of useful Laravel additions!

58109.4k](/packages/laracraft-tech-laravel-useful-additions)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

245.2k](/packages/aedart-athenaeum)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
