diff --git a/README.md b/README.md index 714be57..ce87031 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,9 @@ return [ 10, 25, 50, 'all', ], + 'attachments_disk' => 'local', + 'store_attachments' => true, + //Use this option for customize tenant model class //'tenant_model' => \App\Models\Team::class, ]; diff --git a/config/filament-email.php b/config/filament-email.php index aa28db0..61dec6a 100644 --- a/config/filament-email.php +++ b/config/filament-email.php @@ -39,6 +39,9 @@ 10, 25, 50, 'all', ], + 'attachments_disk' => 'local', + 'store_attachments' => true, + //Use this option for customize tenant model class //'tenant_model' => \App\Models\Team::class, ]; diff --git a/src/Filament/Resources/EmailResource.php b/src/Filament/Resources/EmailResource.php index 9b12cfb..65f3f2f 100644 --- a/src/Filament/Resources/EmailResource.php +++ b/src/Filament/Resources/EmailResource.php @@ -92,6 +92,7 @@ public static function form(Form $form): Form ->label(__('filament-email::filament-email.created_at')), ])->columns(4), Fieldset::make('attachments') + ->hidden(fn(): bool => !config('filament-email.store_attachments')) ->label(__('filament-email::filament-email.attachments')) ->schema([ View::make('filament-email::attachments') @@ -136,7 +137,7 @@ public static function table(Table $table): Table ->icon('heroicon-o-eye') ->iconSize(IconSize::Medium) ->modalFooterActions( - fn ($action): array => [ + fn($action): array => [ $action->getModalCancelAction(), ]) ->fillForm(function ($record) { @@ -193,7 +194,7 @@ public static function table(Table $table): Table ->nestedRecursiveRules([ 'email', ]) - ->default(fn ($record): array => ! empty($record->to) ? explode(',', $record->to) : []) + ->default(fn($record): array => !empty($record->to) ? explode(',', $record->to) : []) ->required(), TagsInput::make('cc') ->label(__('filament-email::filament-email.cc')) @@ -201,21 +202,21 @@ public static function table(Table $table): Table ->nestedRecursiveRules([ 'email', ]) - ->default(fn ($record): array => ! empty($record->cc) ? explode(',', $record->cc) : []), + ->default(fn($record): array => !empty($record->cc) ? explode(',', $record->cc) : []), TagsInput::make('bcc') ->label(__('filament-email::filament-email.bcc')) ->placeholder(__('filament-email::filament-email.insert_multiple_email_placelholder')) ->nestedRecursiveRules([ 'email', ]) - ->default(fn ($record): array => ! empty($record->bcc) ? explode(',', $record->bcc) : []), + ->default(fn($record): array => !empty($record->bcc) ? explode(',', $record->bcc) : []), Toggle::make('attachments') ->label(__('filament-email::filament-email.add_attachments')) ->onColor('success') ->offColor('danger') ->inline(false) - ->disabled(fn ($record): bool => empty($record->attachments)) - ->default(fn ($record): bool => ! empty($record->attachments)) + ->disabled(fn($record): bool => empty($record->attachments)) + ->default(fn($record): bool => !empty($record->attachments)) ->required(), ]) ->action(function (Email $record, array $data) { @@ -242,10 +243,10 @@ public static function table(Table $table): Table ]) ->columns([ TextColumn::make('from') - ->prefix(__('filament-email::filament-email.from').': ') - ->suffix(fn (Email $record): string => ! empty($record->attachments) ? ' ('.trans_choice('filament-email::filament-email.attachments_number', count($record->attachments)).')' : '') + ->prefix(__('filament-email::filament-email.from') . ': ') + ->suffix(fn(Email $record): string => !empty($record->attachments) ? ' (' . trans_choice('filament-email::filament-email.attachments_number', count($record->attachments)) . ')' : '') ->label(__('filament-email::filament-email.header')) - ->description(fn (Email $record): string => Str::limit(__('filament-email::filament-email.to').': '.$record->to, 40)) + ->description(fn(Email $record): string => Str::limit(__('filament-email::filament-email.to') . ': ' . $record->to, 40)) ->searchable(), TextColumn::make('subject') ->label(__('filament-email::filament-email.subject')) @@ -292,16 +293,16 @@ public static function table(Table $table): Table $indicators = []; $format = config('filament-email.resource.filter_date_format'); - if (! empty($data['created_from'])) { + if (!empty($data['created_from'])) { $from = Carbon::parse($data['created_from'])->format($format); - $indicators['created'] = __('filament-email::filament-email.from_filter')." $from"; + $indicators['created'] = __('filament-email::filament-email.from_filter') . " $from"; } - if (! empty($data['created_until'])) { + if (!empty($data['created_until'])) { $to = Carbon::parse($data['created_until'])->format($format); $toText = __('filament-email::filament-email.to_filter'); - if (! empty($indicators['created'])) { - $indicators['created'] .= ' '.strtolower($toText)." $to"; + if (!empty($indicators['created'])) { + $indicators['created'] .= ' ' . strtolower($toText) . " $to"; } else { $indicators['created'] = "$toText $to"; } @@ -323,30 +324,30 @@ public static function table(Table $table): Table return $query ->when( $data['to'], - fn (Builder $query, $value): Builder => $query->where('to', 'like', "%$value%"), + fn(Builder $query, $value): Builder => $query->where('to', 'like', "%$value%"), ) ->when( $data['cc'], - fn (Builder $query, $value): Builder => $query->where('cc', 'like', "%$value%"), + fn(Builder $query, $value): Builder => $query->where('cc', 'like', "%$value%"), ) ->when( $data['bcc'], - fn (Builder $query, $value): Builder => $query->where('bcc', 'like', "%$value%"), + fn(Builder $query, $value): Builder => $query->where('bcc', 'like', "%$value%"), ) ->when( $data['created_from'], - fn (Builder $query, $value): Builder => $query->where('created_at', '>=', $value), + fn(Builder $query, $value): Builder => $query->where('created_at', '>=', $value), ) ->when( $data['created_until'], - fn (Builder $query, $value): Builder => $query->where('created_at', '<=', $value), + fn(Builder $query, $value): Builder => $query->where('created_at', '<=', $value), ); }), ]) ->paginationPageOptions(function (Table $table) { $options = config('filament-email.pagination_page_options'); - return ! empty($options) && is_array($options) ? $options : $table->getPaginationPageOptions(); + return !empty($options) && is_array($options) ? $options : $table->getPaginationPageOptions(); }); } @@ -362,7 +363,7 @@ public static function canAccess(): bool { $roles = config('filament-email.can_access.role', []); - if (method_exists(auth()->user(), 'hasRole') && ! empty($roles)) { + if (method_exists(auth()->user(), 'hasRole') && !empty($roles)) { return auth()->user()->hasRole($roles); } diff --git a/src/Filament/Resources/EmailResource/Pages/ViewEmail.php b/src/Filament/Resources/EmailResource/Pages/ViewEmail.php index be97c92..2073155 100644 --- a/src/Filament/Resources/EmailResource/Pages/ViewEmail.php +++ b/src/Filament/Resources/EmailResource/Pages/ViewEmail.php @@ -30,9 +30,9 @@ public function downloadAction(): Action ->icon('heroicon-c-arrow-down-tray') ->size(ActionSize::ExtraSmall) ->action(function (array $arguments) { - $filePath = storage_path('app'.DIRECTORY_SEPARATOR.$arguments['path']); - if (file_exists($filePath)) { - return Storage::download($arguments['path'], $arguments['name']); + $fileExists = Storage::disk(config('filament-email.attachments_disk'))->exists($arguments['path']); + if ($fileExists) { + return Storage::disk(config('filament-email.attachments_disk'))->download($arguments['path'], $arguments['name']); } else { Notification::make() ->title(__('filament-email::filament-email.download_attachment_error')) diff --git a/src/Listeners/FilamentEmailLogger.php b/src/Listeners/FilamentEmailLogger.php index a5b0b9b..91aba0b 100644 --- a/src/Listeners/FilamentEmailLogger.php +++ b/src/Listeners/FilamentEmailLogger.php @@ -27,27 +27,35 @@ public function handle(object $event): void $rawMessage = $event->sent->getSymfonySentMessage(); $email = $event->message; + $attachmentsDisk = config('filament-email.attachments_disk', 'local'); + $storeAttachments = config('filament-email.store_attachments', true); + $model = config('filament-email.resource.model') ?? Email::class; $attachments = []; - $savePath = 'filament-email-log'.DIRECTORY_SEPARATOR.date('YmdHis').'_'.Str::random(5).DIRECTORY_SEPARATOR; + $savePath = 'filament-email-log' . DIRECTORY_SEPARATOR . date('YmdHis') . '_' . Str::random(5) . DIRECTORY_SEPARATOR; - foreach ($event->message->getAttachments() as $attachment) { - $filePath = $savePath.Str::random(5).'_'.$attachment->getFilename(); - Storage::disk('local') - ->put($filePath, $attachment->getBody()); - $attachments[] = [ - 'name' => $attachment->getFilename(), - 'contentType' => $attachment->getContentType(), - 'path' => $filePath, - ]; - } + if ($storeAttachments) { - $savePathRaw = $savePath.$rawMessage->getMessageId().'.eml'; + foreach ($event->message->getAttachments() as $attachment) { + $filePath = $savePath . Str::random(5) . '_' . $attachment->getFilename(); + Storage::disk($attachmentsDisk) + ->put($filePath, $attachment->getBody()); + $attachments[] = [ + 'name' => $attachment->getFilename(), + 'contentType' => $attachment->getContentType(), + 'path' => $filePath, + ]; + } - Storage::disk('local') - ->put($savePathRaw, $rawMessage->getMessage()->toString()); + $savePathRaw = $savePath . $rawMessage->getMessageId() . '.eml'; + Storage::disk($attachmentsDisk) + ->put($savePathRaw, $rawMessage->getMessage()->toString()); + + } else { + $savePathRaw = null; + } $model::create([ 'team_id' => Filament::getTenant()?->id ?? null, 'from' => $this->recipientsToString($email->getFrom()), @@ -59,7 +67,7 @@ public function handle(object $event): void 'text_body' => $email->getTextBody(), 'raw_body' => $savePathRaw, 'sent_debug_info' => $rawMessage->getDebug(), - 'attachments' => ! empty($attachments) ? $attachments : null, + 'attachments' => !empty($attachments) ? $attachments : null, ]); } @@ -69,7 +77,7 @@ private function recipientsToString(array $recipients): string return implode( ',', array_map(function ($email) { - return "{$email->getAddress()}".($email->getName() ? " <{$email->getName()}>" : ''); + return "{$email->getAddress()}" . ($email->getName() ? " <{$email->getName()}>" : ''); }, $recipients) ); }