├── resources
└── views
│ ├── .gitkeep
│ └── HtmlEmailView.blade.php
├── bootstrap
└── app.php
├── config
└── filament-email-log.php
├── src
├── Filament
│ └── Resources
│ │ ├── EmailResource
│ │ └── Pages
│ │ │ ├── ViewEmail.php
│ │ │ └── ListEmails.php
│ │ └── EmailResource.php
├── Providers
│ └── EmailMessageServiceProvider.php
├── Models
│ └── Email.php
├── FilamentEmailLogServiceProvider.php
└── Listeners
│ └── FilamentEmailLogger.php
├── CHANGELOG.md
├── database
├── factories
│ └── EmailFactory.php
└── migrations
│ ├── add_raw_and_debug_fields_to_filament_email_log_table.php.stub
│ └── create_filament_email_log_table.php.stub
├── LICENSE.md
├── .php-cs-fixer.dist.php
├── composer.json
└── README.md
/resources/views/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/bootstrap/app.php:
--------------------------------------------------------------------------------
1 | [
7 | 'group' => null,
8 | 'sort' => null,
9 | ],
10 |
11 | /**
12 | * Define the numbers of days to keep the emails in the log database
13 | */
14 | 'keep_email_for_days' => 90,
15 |
16 | ];
17 |
--------------------------------------------------------------------------------
/src/Filament/Resources/EmailResource/Pages/ViewEmail.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to `filament-email-log` will be documented in this file.
4 |
5 | ## 0.2.2 - 2022-07-27
6 |
7 | No new features.
8 |
9 | - Added proper testing for prunable email model.
10 |
11 | ## v0.2.1 - 2022-07-22
12 |
13 | - No functionality added or bugs fixed.
14 | - Added Laravel framework 9.1 dependency. Now testing works in --prefer-lowest and --prefer-stable
15 |
16 | ## 0.2.0 - 2022-06-29
17 |
18 | ### Added
19 |
20 | - `Email` model is now prunable.
21 | - A raw copy of the email is stored/displayed.
22 | - A debug send information is now stored/displayed.
23 |
24 | ## 0.1.0 - 2022-06-17
25 |
26 | Initial release
27 |
--------------------------------------------------------------------------------
/database/factories/EmailFactory.php:
--------------------------------------------------------------------------------
1 | $this->faker->email(),
16 | 'to' => $this->faker->email(),
17 | 'cc' => $this->faker->email(),
18 | 'subject' => $this->faker->words(5, asText: true),
19 | 'text_body' => $this->faker->paragraphs(3, asText: true),
20 | ];
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/Providers/EmailMessageServiceProvider.php:
--------------------------------------------------------------------------------
1 | [
13 | FilamentEmailLogger::class,
14 | ],
15 | ];
16 |
17 | /**
18 | * Register any events for your application.
19 | *
20 | * @return void
21 | */
22 | public function boot()
23 | {
24 | parent::boot();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/database/migrations/add_raw_and_debug_fields_to_filament_email_log_table.php.stub:
--------------------------------------------------------------------------------
1 | longText('raw_body')->nullable();
13 | $table->longText('sent_debug_info')->nullable();
14 | });
15 | }
16 |
17 | public function down()
18 | {
19 | Schema::dropColumns('filament_email_log', [
20 | 'raw_body',
21 | 'sent_debug_info',
22 | ]);
23 | }
24 | };
25 |
--------------------------------------------------------------------------------
/database/migrations/create_filament_email_log_table.php.stub:
--------------------------------------------------------------------------------
1 | id();
13 |
14 | $table->string('from')->nullable();
15 | $table->string('to')->nullable();
16 | $table->string('cc')->nullable();
17 | $table->string('bcc')->nullable();
18 | $table->string('subject')->nullable();
19 | $table->longText('text_body')->nullable();
20 | $table->longText('html_body')->nullable();
21 |
22 | $table->timestamps();
23 | });
24 | }
25 |
26 | public function down()
27 | {
28 | Schema::drop('filament_email_log');
29 | }
30 | };
31 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) ramnzys
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/Models/Email.php:
--------------------------------------------------------------------------------
1 | subDays(Config::get('filament-email-log.keep_email_for_days')));
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/FilamentEmailLogServiceProvider.php:
--------------------------------------------------------------------------------
1 | name('filament-email-log')
30 | ->hasConfigFile('filament-email-log')
31 | ->hasMigrations([
32 | 'create_filament_email_log_table',
33 | 'add_raw_and_debug_fields_to_filament_email_log_table',
34 | ]);
35 |
36 | $this->app->register(EmailMessageServiceProvider::class);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/.php-cs-fixer.dist.php:
--------------------------------------------------------------------------------
1 | in([
5 | __DIR__ . '/src',
6 | __DIR__ . '/tests',
7 | ])
8 | ->name('*.php')
9 | ->notName('*.blade.php')
10 | ->ignoreDotFiles(true)
11 | ->ignoreVCS(true);
12 |
13 | return (new PhpCsFixer\Config())
14 | ->setRules([
15 | '@PSR12' => true,
16 | 'array_syntax' => ['syntax' => 'short'],
17 | 'ordered_imports' => ['sort_algorithm' => 'alpha'],
18 | 'no_unused_imports' => true,
19 | 'not_operator_with_successor_space' => true,
20 | 'trailing_comma_in_multiline' => true,
21 | 'phpdoc_scalar' => true,
22 | 'unary_operator_spaces' => true,
23 | 'binary_operator_spaces' => true,
24 | 'blank_line_before_statement' => [
25 | 'statements' => ['break', 'continue', 'declare', 'return', 'throw', 'try'],
26 | ],
27 | 'phpdoc_single_line_var_spacing' => true,
28 | 'phpdoc_var_without_name' => true,
29 | 'class_attributes_separation' => [
30 | 'elements' => [
31 | 'method' => 'one',
32 | ],
33 | ],
34 | 'method_argument_space' => [
35 | 'on_multiline' => 'ensure_fully_multiline',
36 | 'keep_multiple_spaces_after_comma' => true,
37 | ],
38 | 'single_trait_insert_per_statement' => true,
39 | ])
40 | ->setFinder($finder);
41 |
--------------------------------------------------------------------------------
/src/Listeners/FilamentEmailLogger.php:
--------------------------------------------------------------------------------
1 | sent->getSymfonySentMessage();
28 | $email = $event->message;
29 |
30 | Email::create([
31 | 'from' => $this->RecipientsToString($email->getFrom()),
32 | 'to' => $this->RecipientsToString($email->getTo()),
33 | 'cc' => $this->RecipientsToString($email->getCc()),
34 | 'bcc' => $this->RecipientsToString($email->getBcc()),
35 | 'subject' => $email->getSubject(),
36 | 'html_body' => $email->getHtmlBody(),
37 | 'text_body' => $email->getTextBody(),
38 | 'raw_body' => $rawMessage->getMessage()->toString(),
39 | 'sent_debug_info' => $rawMessage->getDebug(),
40 | ]);
41 | }
42 |
43 | private function RecipientsToString(array $recipients): string
44 | {
45 | return implode(
46 | ',',
47 | array_map(function ($email) {
48 | return "{$email->getAddress()}".($email->getName() ? " <{$email->getName()}>" : '');
49 | }, $recipients)
50 | );
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ramnzys/filament-email-log",
3 | "description": "This package provides a Filament resource to view all Laravel outgoing emails.",
4 | "license": "MIT",
5 | "keywords": [
6 | "laravel",
7 | "filament",
8 | "email"
9 | ],
10 | "authors": [
11 | {
12 | "name": "Ramón E. Zayas",
13 | "email": "ramnzys@gmail.com",
14 | "role": "Developer"
15 | }
16 | ],
17 | "homepage": "https://github.com/ramnzys/filament-email-log",
18 | "require": {
19 | "php": "^8.1",
20 | "filament/filament": "^2.12",
21 | "illuminate/contracts": "^9.0",
22 | "laravel/framework": "^9.1",
23 | "spatie/laravel-package-tools": "^1.9.2"
24 | },
25 | "require-dev": {
26 | "ergebnis/composer-normalize": "^2.28",
27 | "fakerphp/faker": "^1.19",
28 | "friendsofphp/php-cs-fixer": "^3.8",
29 | "laravel/pint": "^1.1",
30 | "nunomaduro/collision": "^6.0",
31 | "nunomaduro/larastan": "^2.0.1",
32 | "orchestra/testbench": "^7.0",
33 | "pestphp/pest": "^1.21",
34 | "pestphp/pest-plugin-laravel": "^1.1",
35 | "phpstan/extension-installer": "^1.1",
36 | "phpstan/phpstan-deprecation-rules": "^1.0",
37 | "phpstan/phpstan-phpunit": "^1.0",
38 | "phpunit/phpunit": "^9.5",
39 | "spatie/laravel-ray": "^1.29"
40 | },
41 | "minimum-stability": "dev",
42 | "prefer-stable": true,
43 | "autoload": {
44 | "psr-4": {
45 | "Ramnzys\\FilamentEmailLog\\": "src",
46 | "Ramnzys\\FilamentEmailLog\\Database\\Factories\\": "database/factories"
47 | }
48 | },
49 | "autoload-dev": {
50 | "psr-4": {
51 | "Ramnzys\\FilamentEmailLog\\Tests\\": "tests"
52 | }
53 | },
54 | "config": {
55 | "allow-plugins": true,
56 | "sort-packages": true
57 | },
58 | "extra": {
59 | "laravel": {
60 | "aliases": {
61 | "FilamentEmailLog": "Ramnzys\\FilamentEmailLog\\Facades\\FilamentEmailLog"
62 | },
63 | "providers": [
64 | "Ramnzys\\FilamentEmailLog\\FilamentEmailLogServiceProvider"
65 | ]
66 | }
67 | },
68 | "scripts": {
69 | "analyse": "vendor/bin/phpstan analyse",
70 | "format": "vendor/bin/php-cs-fixer fix --allow-risky=yes",
71 | "style": "vendor/bin/pint",
72 | "test": "vendor/bin/pest",
73 | "test-coverage": "vendor/bin/pest --coverage"
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | [](https://packagist.org/packages/ramnzys/filament-email-log)
5 | [](https://github.com/ramnzys/filament-email-log/actions?query=workflow%3Arun-tests+branch%3Amain)
6 | [](https://github.com/ramnzys/filament-email-log/actions?query=workflow%3A"Check+%26+fix+styling"+branch%3Amain)
7 | [](https://packagist.org/packages/ramnzys/filament-email-log)
8 |
9 | This package provides a Filament resource to view all Laravel outgoing emails. It also provides a Model for the database stored emails.
10 |
11 | ## Installation
12 |
13 | You can install the package via composer:
14 |
15 | ```bash
16 | composer require ramnzys/filament-email-log
17 | ```
18 |
19 | You can publish and run the migrations with:
20 |
21 | ```bash
22 | php artisan vendor:publish --tag="filament-email-log-migrations"
23 | php artisan migrate
24 | ```
25 |
26 | You can publish the config file with:
27 |
28 | ```bash
29 | php artisan vendor:publish --tag="filament-email-log-config"
30 | ```
31 |
32 | This is the contents of the published config file:
33 |
34 | ```php
35 | return [
36 |
37 | 'resource' => [
38 | 'group' => null,
39 | 'sort' => null,
40 | ],
41 |
42 | 'keep_email_for_days' => 90,
43 |
44 | ];
45 | ```
46 |
47 | ## Usage
48 |
49 | This package will automatically register the `EmailResource`. You will be able to see it when you visit your Filament admin panel.
50 |
51 | ### Customization
52 |
53 | **Group and sort order**. You can customize the navigation group for the `EmailResource` by publishing the configuration file and updating the `resource.group` and `resource.sort` values.
54 |
55 | **Prunable model**. You can customize how many days to keep the email in the database by updating the `keep_email_for_days` value. Then you can use or schedule the command `artisan model:prune --model="Ramnzys\FilamentEmailLog\Models\Email"`. This will delete emails older than `keep_email_for_days` days old.
56 | ## Testing
57 |
58 | ```bash
59 | composer test
60 | ```
61 |
62 | ## Changelog
63 |
64 | Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.
65 |
66 | ## Contributing
67 |
68 | Contributions are welcome. Please see [CONTRIBUTING](.github/CONTRIBUTING.md) for details.
69 |
70 | ## Credits
71 |
72 | - [Ramón E. Zayas](https://github.com/ramnzys)
73 | - [All Contributors](../../contributors)
74 |
75 | ## License
76 |
77 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
78 |
--------------------------------------------------------------------------------
/src/Filament/Resources/EmailResource.php:
--------------------------------------------------------------------------------
1 | schema([
40 | Fieldset::make('Envelope')->schema([
41 | TextInput::make('created_at'),
42 | TextInput::make('from'),
43 | TextInput::make('to'),
44 | TextInput::make('cc'),
45 | TextInput::make('subject')->columnSpan(2),
46 | ])->columns(3),
47 | Tabs::make('Content')->tabs([
48 | Tab::make('HTML')
49 | ->schema([
50 | ViewField::make('html_body')->disableLabel()
51 | ->view('filament-email-log::HtmlEmailView'),
52 | ]),
53 | Tab::make('Text')
54 | ->schema([
55 | Textarea::make('text_body')->disableLabel(),
56 | ]),
57 | Tab::make('Raw')
58 | ->schema([
59 | Textarea::make('raw_body')
60 | ->extraAttributes(['class' => 'font-mono text-xs'])
61 | ->disableLabel(),
62 | ]),
63 | Tab::make('Debug information')
64 | ->schema([
65 | Textarea::make('sent_debug_info')
66 | ->extraAttributes(['class' => 'font-mono text-xs'])
67 | ->disableLabel(),
68 | ]),
69 | ])->columnSpan(2),
70 | ]);
71 | }
72 |
73 | public static function table(Table $table): Table
74 | {
75 | return $table
76 | ->columns([
77 | TextColumn::make('created_at')
78 | ->label(__('Date and time sent'))
79 | ->sortable(),
80 | TextColumn::make('from')
81 | ->label(__('From'))
82 | ->toggleable()
83 | ->searchable(),
84 | TextColumn::make('to')
85 | ->label(__('To'))
86 | ->searchable(),
87 | TextColumn::make('cc')
88 | ->label(__('Cc'))
89 | ->toggleable(isToggledHiddenByDefault: true)
90 | ->searchable(),
91 | TextColumn::make('subject')
92 | ->label(__('Subject'))
93 | ->limit(50)
94 | ->tooltip(function (TextColumn $column): ?string {
95 | $state = $column->getState();
96 | if (strlen($state) <= $column->getLimit()) {
97 | return null;
98 | }
99 |
100 | return $state;
101 | })
102 | ->searchable(),
103 | ])
104 | ->bulkActions([])
105 | ->filters([
106 | //
107 | ])
108 | ->defaultSort('created_at', 'desc');
109 | }
110 |
111 | public static function getRelations(): array
112 | {
113 | return [
114 | //
115 | ];
116 | }
117 |
118 | public static function getPages(): array
119 | {
120 | return [
121 | 'index' => ListEmails::route('/'),
122 | 'view' => ViewEmail::route('/{record}'),
123 | ];
124 | }
125 | }
126 |
--------------------------------------------------------------------------------