From 122c4d8f89b1aa11e472506b4c76da0eb6746132 Mon Sep 17 00:00:00 2001 From: idevakk <219866223+idevakk@users.noreply.github.com> Date: Sun, 28 Sep 2025 22:43:41 +0530 Subject: [PATCH] feat: add backstage/filament-mails --- app/Providers/Filament/DashPanelProvider.php | 6 +- composer.json | 1 + composer.lock | 212 +++++++++++++++++- config/filament-mails.php | 17 ++ config/mails.php | 141 ++++++++++++ ...2025_09_28_162912_1_create_mails_table.php | 38 ++++ ...162913_2_create_mail_attachments_table.php | 25 +++ ...9_28_162914_2_create_mail_events_table.php | 32 +++ ..._09_28_162915_2_create_mailables_table.php | 19 ++ ...6_3_add_unsuppressed_at_to_mail_events.php | 29 +++ ...09_28_162917_4_add_tags_to_mails_table.php | 17 ++ ..._4_add_transport_column_to_mails_table.php | 17 ++ ...8_162919_5_change_columns_to_long_text.php | 25 +++ ...9_28_162920_5_change_link_to_long_text.php | 23 ++ .../views/vendor/filament-mails/.gitkeep | 0 .../filament-mails/mails/download.blade.php | 8 + .../filament-mails/mails/html.blade.php | 5 + .../filament-mails/mails/preview.blade.php | 6 + 18 files changed, 619 insertions(+), 2 deletions(-) create mode 100644 config/filament-mails.php create mode 100644 config/mails.php create mode 100644 database/migrations/2025_09_28_162912_1_create_mails_table.php create mode 100644 database/migrations/2025_09_28_162913_2_create_mail_attachments_table.php create mode 100644 database/migrations/2025_09_28_162914_2_create_mail_events_table.php create mode 100644 database/migrations/2025_09_28_162915_2_create_mailables_table.php create mode 100644 database/migrations/2025_09_28_162916_3_add_unsuppressed_at_to_mail_events.php create mode 100644 database/migrations/2025_09_28_162917_4_add_tags_to_mails_table.php create mode 100644 database/migrations/2025_09_28_162918_4_add_transport_column_to_mails_table.php create mode 100644 database/migrations/2025_09_28_162919_5_change_columns_to_long_text.php create mode 100644 database/migrations/2025_09_28_162920_5_change_link_to_long_text.php create mode 100644 resources/views/vendor/filament-mails/.gitkeep create mode 100644 resources/views/vendor/filament-mails/mails/download.blade.php create mode 100644 resources/views/vendor/filament-mails/mails/html.blade.php create mode 100644 resources/views/vendor/filament-mails/mails/preview.blade.php diff --git a/app/Providers/Filament/DashPanelProvider.php b/app/Providers/Filament/DashPanelProvider.php index d9feedb..f6c7350 100644 --- a/app/Providers/Filament/DashPanelProvider.php +++ b/app/Providers/Filament/DashPanelProvider.php @@ -2,6 +2,8 @@ namespace App\Providers\Filament; +use Backstage\FilamentMails\Facades\FilamentMails; +use Backstage\FilamentMails\FilamentMailsPlugin; use Boquizo\FilamentLogViewer\FilamentLogViewerPlugin; use Filament\Http\Middleware\Authenticate; use Filament\Http\Middleware\AuthenticateSession; @@ -60,6 +62,8 @@ class DashPanelProvider extends PanelProvider ->plugins([ FilamentLoggerPlugin::make(), FilamentLogViewerPlugin::make(), - ]); + FilamentMailsPlugin::make(), + ]) + ->routes(fn () => FilamentMails::routes()); } } diff --git a/composer.json b/composer.json index b01f1d8..cad5fbc 100644 --- a/composer.json +++ b/composer.json @@ -7,6 +7,7 @@ "license": "MIT", "require": { "php": "^8.2", + "backstage/filament-mails": "^3.0", "filament/filament": "~4.0", "gboquizosanchez/filament-log-viewer": "^2.1", "jacobtims/filament-logger": "^1.0", diff --git a/composer.lock b/composer.lock index 3cd81a8..e621aca 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "bae273ecc05278912300707444956065", + "content-hash": "418b6fd827d97cc67411610b6cff80a2", "packages": [ { "name": "anourvalar/eloquent-serialize", @@ -72,6 +72,159 @@ }, "time": "2025-07-30T15:45:57+00:00" }, + { + "name": "backstage/filament-mails", + "version": "v3.0.4", + "source": { + "type": "git", + "url": "https://github.com/backstagephp/filament-mails.git", + "reference": "24d5d50c5848f8e8d06a5f9f37b891aa9cc5e8b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/backstagephp/filament-mails/zipball/24d5d50c5848f8e8d06a5f9f37b891aa9cc5e8b4", + "reference": "24d5d50c5848f8e8d06a5f9f37b891aa9cc5e8b4", + "shasum": "" + }, + "require": { + "backstage/laravel-mails": "^2.0", + "filament/filament": "^4.0", + "php": "^8.2", + "spatie/laravel-package-tools": "^1.15.0" + }, + "require-dev": { + "laravel/pint": "^1.16", + "nunomaduro/collision": "^8.8.0", + "orchestra/testbench": "^9.0|^10.0", + "pestphp/pest": "^3.7", + "pestphp/pest-plugin-arch": "^3.1.0", + "pestphp/pest-plugin-laravel": "^3.0" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "FilamentMails": "Backstage\\FilamentMails\\Facades\\FilamentMails" + }, + "providers": [ + "Backstage\\FilamentMails\\FilamentMailsServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Backstage\\FilamentMails\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Baspa", + "email": "hello@baspa.dev", + "role": "Developer" + } + ], + "description": "View logged mails and events in a beautiful Filament UI.", + "homepage": "https://github.com/backstagephp/filament-mails", + "keywords": [ + "backstagephp", + "filament-mails", + "laravel" + ], + "support": { + "issues": "https://github.com/backstagephp/filament-mails/issues", + "source": "https://github.com/backstagephp/filament-mails" + }, + "funding": [ + { + "url": "https://github.com/vormkracht10", + "type": "github" + } + ], + "time": "2025-09-26T08:39:10+00:00" + }, + { + "name": "backstage/laravel-mails", + "version": "v2.1.0", + "source": { + "type": "git", + "url": "https://github.com/backstagephp/laravel-mails.git", + "reference": "b590728f2295be781ea19abd0275783d1598ca5c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/backstagephp/laravel-mails/zipball/b590728f2295be781ea19abd0275783d1598ca5c", + "reference": "b590728f2295be781ea19abd0275783d1598ca5c", + "shasum": "" + }, + "require": { + "illuminate/contracts": "^10.0 || ^11.0 || ^12.0", + "laravel/helpers": "^1.7.0", + "php": "^8.2", + "spatie/laravel-package-tools": "^1.15.0" + }, + "require-dev": { + "larastan/larastan": "^3.0", + "laravel-notification-channels/discord": "^1.6", + "laravel-notification-channels/telegram": "^4.0 || ^5.0 || ^6.0", + "laravel/pint": "^1.17.0", + "laravel/slack-notification-channel": "^2.5 || ^3.3.2", + "nunomaduro/collision": "^7.5.0|^8.4", + "orchestra/testbench": "^8.5.0|^9.4.0", + "pestphp/pest": "^3.0", + "pestphp/pest-plugin-laravel": "^3.0", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Backstage\\Mails\\MailsServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Backstage\\Mails\\": "src", + "Backstage\\Mails\\Database\\Factories\\": "database/factories" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark van Eijk", + "email": "mark@vormkracht10.nl", + "role": "Developer" + } + ], + "description": "Laravel Mails can collect everything you might want to track about the mails that has been sent by your Laravel app.", + "homepage": "https://github.com/backstagephp/laravel-mails", + "keywords": [ + "backstagephp", + "laravel", + "laravel-mails" + ], + "support": { + "issues": "https://github.com/backstagephp/laravel-mails/issues", + "source": "https://github.com/backstagephp/laravel-mails/tree/v2.1.0" + }, + "funding": [ + { + "url": "https://github.com/vormkracht10", + "type": "github" + } + ], + "time": "2025-07-22T08:08:52+00:00" + }, { "name": "bacon/bacon-qr-code", "version": "v3.0.1", @@ -2568,6 +2721,63 @@ }, "time": "2025-09-23T15:33:04+00:00" }, + { + "name": "laravel/helpers", + "version": "v1.8.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/helpers.git", + "reference": "d0094b4bc4364560c8ee3a9e956596d760d4afab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/helpers/zipball/d0094b4bc4364560c8ee3a9e956596d760d4afab", + "reference": "d0094b4bc4364560c8ee3a9e956596d760d4afab", + "shasum": "" + }, + "require": { + "illuminate/support": "~5.8.0|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "php": "^7.2.0|^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^7.0|^8.0|^9.0|^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Dries Vints", + "email": "dries@laravel.com" + } + ], + "description": "Provides backwards compatibility for helpers in the latest Laravel release.", + "keywords": [ + "helpers", + "laravel" + ], + "support": { + "source": "https://github.com/laravel/helpers/tree/v1.8.1" + }, + "time": "2025-09-02T15:31:25+00:00" + }, { "name": "laravel/pint", "version": "v1.25.1", diff --git a/config/filament-mails.php b/config/filament-mails.php new file mode 100644 index 0000000..e2680ec --- /dev/null +++ b/config/filament-mails.php @@ -0,0 +1,17 @@ + [ + 'mail' => MailResource::class, + 'event' => EventResource::class, + 'suppression' => SuppressionResource::class, + ], + + 'navigation' => [ + 'group' => null, + ], +]; diff --git a/config/mails.php b/config/mails.php new file mode 100644 index 0000000..a4483d1 --- /dev/null +++ b/config/mails.php @@ -0,0 +1,141 @@ + [ + 'mail' => Mail::class, + 'event' => MailEvent::class, + 'attachment' => MailAttachment::class, + ], + + // Table names for saving sent emails and polymorphic relations to database + + 'database' => [ + 'tables' => [ + 'mails' => 'mails', + 'attachments' => 'mail_attachments', + 'events' => 'mail_events', + 'polymorph' => 'mailables', + ], + + 'pruning' => [ + 'enabled' => true, + 'after' => 30, // days + ], + ], + + 'headers' => [ + 'uuid' => 'X-Mails-UUID', + + 'associate' => 'X-Mails-Associated-Models', + ], + + 'webhooks' => [ + 'routes' => [ + 'prefix' => 'webhooks/mails', + ], + + 'queue' => env('MAILS_QUEUE_WEBHOOKS', false), + ], + + // Logging mails + 'logging' => [ + + // Enable logging of all sent mails to database + + 'enabled' => env('MAILS_LOGGING_ENABLED', true), + + // Specify attributes to log in database + + 'attributes' => [ + 'subject', + 'from', + 'to', + 'reply_to', + 'cc', + 'bcc', + 'html', + 'text', + ], + + // Encrypt all attributes saved to database + + 'encrypted' => env('MAILS_ENCRYPTED', true), + + // Track following events using webhooks from email provider + + 'tracking' => [ + 'bounces' => true, + 'clicks' => true, + 'complaints' => true, + 'deliveries' => true, + 'opens' => true, + 'unsubscribes' => true, + ], + + // Enable saving mail attachments to disk + + 'attachments' => [ + 'enabled' => env('MAILS_LOGGING_ATTACHMENTS_ENABLED', true), + 'disk' => env('FILESYSTEM_DISK', 'local'), + 'root' => 'mails/attachments', + ], + ], + + // Notifications for important mail events + + 'notifications' => [ + 'mail' => [ + 'to' => ['test@example.com'], + ], + + 'discord' => [ + // 'to' => ['1234567890'], + ], + + 'slack' => [ + // 'to' => ['https://hooks.slack.com/services/...'], + ], + + 'telegram' => [ + // 'to' => ['1234567890'], + ], + ], + + 'events' => [ + 'soft_bounced' => [ + 'notify' => ['mail'], + ], + + 'hard_bounced' => [ + 'notify' => ['mail'], + ], + + 'bouncerate' => [ + 'notify' => [], + + 'retain' => 30, // days + + 'treshold' => 1, // % + ], + + 'deliveryrate' => [ + 'treshold' => 99, + ], + + 'complained' => [ + // + ], + + 'unsent' => [ + // + ], + ], + +]; diff --git a/database/migrations/2025_09_28_162912_1_create_mails_table.php b/database/migrations/2025_09_28_162912_1_create_mails_table.php new file mode 100644 index 0000000..a0d5880 --- /dev/null +++ b/database/migrations/2025_09_28_162912_1_create_mails_table.php @@ -0,0 +1,38 @@ +id(); + $table->string('uuid')->nullable()->index(); + $table->string('mail_class')->nullable()->index(); + $table->string('subject')->nullable(); + $table->json('from')->nullable(); + $table->json('reply_to')->nullable(); + $table->json('to')->nullable(); + $table->json('cc')->nullable(); + $table->json('bcc')->nullable(); + $table->text('html')->nullable(); + $table->text('text')->nullable(); + $table->unsignedBigInteger('opens')->default(0); + $table->unsignedBigInteger('clicks')->default(0); + $table->timestamp('sent_at')->nullable(); + $table->timestamp('resent_at')->nullable(); + $table->timestamp('accepted_at')->nullable(); + $table->timestamp('delivered_at')->nullable(); + $table->timestamp('last_opened_at')->nullable(); + $table->timestamp('last_clicked_at')->nullable(); + $table->timestamp('complained_at')->nullable(); + $table->timestamp('soft_bounced_at')->nullable(); + $table->timestamp('hard_bounced_at')->nullable(); + $table->timestamp('unsubscribed_at')->nullable(); + $table->timestamps(); + }); + } +}; diff --git a/database/migrations/2025_09_28_162913_2_create_mail_attachments_table.php b/database/migrations/2025_09_28_162913_2_create_mail_attachments_table.php new file mode 100644 index 0000000..e0461de --- /dev/null +++ b/database/migrations/2025_09_28_162913_2_create_mail_attachments_table.php @@ -0,0 +1,25 @@ +id(); + $table->foreignIdFor(config('mails.models.mail')) + ->constrained() + ->cascadeOnDelete(); + $table->string('disk'); + $table->string('uuid'); + $table->string('filename'); + $table->string('mime'); + $table->boolean('inline', false); + $table->bigInteger('size'); + $table->timestamps(); + }); + } +}; diff --git a/database/migrations/2025_09_28_162914_2_create_mail_events_table.php b/database/migrations/2025_09_28_162914_2_create_mail_events_table.php new file mode 100644 index 0000000..d34c068 --- /dev/null +++ b/database/migrations/2025_09_28_162914_2_create_mail_events_table.php @@ -0,0 +1,32 @@ +id(); + $table->foreignIdFor(config('mails.models.mail')) + ->constrained() + ->cascadeOnDelete(); + $table->string('type'); + $table->string('ip_address')->nullable(); + $table->string('hostname')->nullable(); + $table->string('platform')->nullable(); + $table->string('os')->nullable(); + $table->string('browser')->nullable(); + $table->string('user_agent')->nullable(); + $table->string('city')->nullable(); + $table->char('country_code', 2)->nullable(); + $table->string('link')->nullable(); + $table->string('tag')->nullable(); + $table->json('payload')->nullable(); + $table->timestamps(); + $table->timestamp('occurred_at')->nullable(); + }); + } +}; diff --git a/database/migrations/2025_09_28_162915_2_create_mailables_table.php b/database/migrations/2025_09_28_162915_2_create_mailables_table.php new file mode 100644 index 0000000..dba5ced --- /dev/null +++ b/database/migrations/2025_09_28_162915_2_create_mailables_table.php @@ -0,0 +1,19 @@ +id(); + $table->foreignIdFor(config('mails.models.mail')) + ->constrained() + ->cascadeOnDelete(); + $table->morphs('mailable'); + }); + } +}; diff --git a/database/migrations/2025_09_28_162916_3_add_unsuppressed_at_to_mail_events.php b/database/migrations/2025_09_28_162916_3_add_unsuppressed_at_to_mail_events.php new file mode 100644 index 0000000..b41149d --- /dev/null +++ b/database/migrations/2025_09_28_162916_3_add_unsuppressed_at_to_mail_events.php @@ -0,0 +1,29 @@ +timestamp('unsuppressed_at') + ->nullable() + ->after('occurred_at'); + }); + + Schema::table(config('mails.database.tables.mails', 'mails'), function (Blueprint $table): void { + $table->string('mailer') + ->after('uuid'); + + $table->string('stream_id') + ->nullable() + ->after('mailer'); + }); + } +}; diff --git a/database/migrations/2025_09_28_162917_4_add_tags_to_mails_table.php b/database/migrations/2025_09_28_162917_4_add_tags_to_mails_table.php new file mode 100644 index 0000000..101316d --- /dev/null +++ b/database/migrations/2025_09_28_162917_4_add_tags_to_mails_table.php @@ -0,0 +1,17 @@ +after('clicks', function (Blueprint $table) { + $table->json('tags')->nullable(); + }); + }); + } +}; diff --git a/database/migrations/2025_09_28_162918_4_add_transport_column_to_mails_table.php b/database/migrations/2025_09_28_162918_4_add_transport_column_to_mails_table.php new file mode 100644 index 0000000..fede6c7 --- /dev/null +++ b/database/migrations/2025_09_28_162918_4_add_transport_column_to_mails_table.php @@ -0,0 +1,17 @@ +string('transport') + ->nullable() + ->after('mailer'); + }); + } +}; diff --git a/database/migrations/2025_09_28_162919_5_change_columns_to_long_text.php b/database/migrations/2025_09_28_162919_5_change_columns_to_long_text.php new file mode 100644 index 0000000..59080d0 --- /dev/null +++ b/database/migrations/2025_09_28_162919_5_change_columns_to_long_text.php @@ -0,0 +1,25 @@ +longText('html')->nullable()->change(); + $table->longText('text')->nullable()->change(); + }); + + } + + public function down() + { + Schema::table(config('mails.database.tables.mails'), function (Blueprint $table) { + $table->text('html')->nullable()->change(); + $table->text('text')->nullable()->change(); + }); + } +}; diff --git a/database/migrations/2025_09_28_162920_5_change_link_to_long_text.php b/database/migrations/2025_09_28_162920_5_change_link_to_long_text.php new file mode 100644 index 0000000..f8c3ad4 --- /dev/null +++ b/database/migrations/2025_09_28_162920_5_change_link_to_long_text.php @@ -0,0 +1,23 @@ +longText('link')->nullable()->change(); + }); + + } + + public function down() + { + Schema::table(config('mails.database.tables.events', 'mail_events'), function (Blueprint $table) { + $table->string('link')->nullable()->change(); + }); + } +}; diff --git a/resources/views/vendor/filament-mails/.gitkeep b/resources/views/vendor/filament-mails/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/resources/views/vendor/filament-mails/mails/download.blade.php b/resources/views/vendor/filament-mails/mails/download.blade.php new file mode 100644 index 0000000..f94285c --- /dev/null +++ b/resources/views/vendor/filament-mails/mails/download.blade.php @@ -0,0 +1,8 @@ +Download diff --git a/resources/views/vendor/filament-mails/mails/html.blade.php b/resources/views/vendor/filament-mails/mails/html.blade.php new file mode 100644 index 0000000..3bb12fe --- /dev/null +++ b/resources/views/vendor/filament-mails/mails/html.blade.php @@ -0,0 +1,5 @@ +
+ {{ $html }}
+
+