j87nl / laravel-vue-mailbox
A VueJS/Inertia shared mailbox UI for j87nl/laravel-mailbox, built on the FormBuilder and TableBuilder
Requires
- php: ^8.4
- inertiajs/inertia-laravel: ^2.0|^3.0
- j87nl/laravel-mailbox: ^0.3
- spatie/laravel-package-tools: ^1.16
- spatie/laravel-query-builder: ^6.0|^7.0
- tranquil-tools/laravel-vue-form-builder: ^1.10
- tranquil-tools/laravel-vue-table-builder: ^1.9
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.14
- orchestra/testbench: ^9.0.0||^10.0.0||^11.0.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Vue 3 / Inertia UI for j87nl/laravel-mailbox: folder list, message list (TableBuilder), message view in a sandboxed iframe, compose/reply/forward (FormBuilder) and mailbox settings with access management.
Requirements
- PHP 8.4+, Laravel with Inertia (v2 or v3) and Vue 3
tranquil-tools/laravel-vue-form-builderandtranquil-tools/laravel-vue-table-builder, with their@form-builderand@table-builderVite aliases
Installation
composer require j87nl/laravel-vue-mailbox php artisan mailbox:install php artisan migrate
mailbox:install publishes the core and Vue config and the migrations, adds the @mailbox Vite alias (./vendor/j87nl/laravel-vue-mailbox/resources/js) and the @mailbox/* tsconfig path, and with --pages copies the default pages to resources/js/pages/Mailbox for customising. Running it again changes nothing that is already there.
The compose editor defaults to HugeRTE:
npm install hugerte @hugerte/hugerte-vue
import HugeRteEditor from '@form-builder/wysiwyg/HugeRteEditor.vue' import { registerWysiwygEditor } from '@form-builder/wysiwyg/registry' import 'hugerte/plugins/autolink' import 'hugerte/plugins/link' import 'hugerte/plugins/lists' registerWysiwygEditor('hugerte', HugeRteEditor)
The pages use plain Tailwind utility classes and no host UI kit. Let Tailwind scan the package so those classes are generated, e.g. in Tailwind 4:
@source '../../vendor/j87nl/laravel-vue-mailbox/resources/js';
Then follow the core package README for admins, the sync schedule, the queue worker and the configuration keys (MAILBOX_DISPLAY_TIMEZONE, MAILBOX_CONNECTION_TIMEOUT, …).
Pages and props
The default pages read their texts from the Inertia prop vue_mailbox_translations (the core mailbox::mailbox file, nl and en) through useMailboxTranslations() from @mailbox/translations. The prop is shared only on the mailbox routes; a host page outside them that needs it adds the J87NL\VueMailbox\Http\Middleware\ShareMailboxTranslations middleware.
Page (vue-mailbox.pages.*) |
Props |
|---|---|
Mailbox/Index |
composeUrl, contactsUrl, folder (id, label, name, role) or null, folderForm, folders, mailbox, mailboxes, settingsUrl, syncing, table |
Mailbox/Show |
actionsUrl, attachments, backUrl, composeUrl, contactUrl, folders, hasRemoteImages, history, html, imageOrigin, mailbox, message, remoteImages |
Mailbox/Compose |
backUrl, folders, form, mailbox, mode |
Mailbox/Contacts/Index |
backUrl, createUrl, folders, mailbox, table |
Mailbox/Contacts/Edit |
backUrl, destroyUrl, form, mailbox, title |
Mailbox/Settings/Index, Mailbox/Settings/Edit |
unchanged |
Reply, reply all and forward put the original HTML in the compose body (Gmail-style header or "On … wrote:" blockquote). Its inline images use signed inline URLs with data-mailbox-cid; keep that attribute in your editor (the default HugeRTE options do). Inline SVG images are served with a locked-down CSP. After sending a reply or forward the app returns to the folder of the original message.
The message table polls every vue-mailbox.poll_seconds (30); pass :only="['table']" to TableBuilder so a tick reloads only the table. Unread rows get font-semibold from the server.
Routes
All routes live under config('vue-mailbox.routes.prefix') (default /mailbox) with the web and auth middleware. Menu links: route('mailbox.index') (show it with @can('accessAnyMailbox') / $can('accessAnyMailbox')) and route('mailbox.settings.index'). Every route is gated with the core abilities (accessMailbox, workInMailbox, manageMailbox, manageMailboxes); the pages hide controls the user cannot use.
| Route | Ability |
|---|---|
mailbox.contacts.index GET {mailbox}/contacts |
accessMailbox |
mailbox.contacts.create, .store, .edit, .update, .destroy |
workInMailbox |
mailbox.messages.contact POST {mailbox}/messages/{message}/contact (add the sender to the address book) |
workInMailbox |
mailbox.addresses GET {mailbox}/addresses?q= (recipient suggestions, JSON) |
workInMailbox |
Development
The core package comes from Packagist (j87nl/laravel-mailbox). To work against a local checkout of the core, add a path repository temporarily and do not commit it:
composer config repositories.core path ../laravel-mailbox composer require j87nl/laravel-mailbox:@dev # when done git checkout composer.json && composer update j87nl/laravel-mailbox
composer install
composer test
composer analyse
composer format