RickDBCN / filament-email

Log emails in your Filament project
https://filament-email-demo.marcogermani.it/
MIT License
85 stars 22 forks source link

[Bug]: Corrupted path detected #75

Closed patriktoth67 closed 2 months ago

patriktoth67 commented 2 months ago

What happened?

I get the error Corrupted path detected every day at midnight.

The package runs the cron to prune emails older than 60 days, every day at midnight. I recently upgraded to v1.4.8, run the migrations, and from the next midnight every day I get this error.

I can see the first email in the database is exactly 60 days before the date I run the migrations.

The actual log looks like this (without the actual email addresses):

[2024-08-08 00:00:13] production.ERROR: Corrupted path detected: From: ■■■■
Reply-To: ■■■■
To: ■■■■
Subject: ■■■■
Message-ID: ■■■■
MIME-Version: 1.0
Date: Sat, 08 Jun 2024 07:39:53 +0000
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE html>
<html xmlns:v=3D"urn:schemas-microsoft-com:vml" xmlns:o=
=3D"urn:schemas-microsoft-com:office:office">

<head>
    <!--[if (gt=
e mso 9)|(IE)]>

...
(the rest of the html code of the email)
...

</body>

</html>

 at /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/league/flysystem/src/CorruptedPathDetected.php:11)

Here is the stacktrace:

at /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/league/flysystem/src/CorruptedPathDetected.php:11):

final class CorruptedPathDetected extends RuntimeException implements FilesystemException
{
    public static function forPath(string $path): CorruptedPathDetected
    {
        return new CorruptedPathDetected("Corrupted path detected: " . $path);
    }
}

[stacktrace]
#0 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/league/flysystem/src/WhitespacePathNormalizer.php(20): League\\Flysystem\\CorruptedPathDetected::forPath()
#1 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/league/flysystem/src/WhitespacePathNormalizer.php(12): League\\Flysystem\\WhitespacePathNormalizer->rejectFunkyWhiteSpace()
#2 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/league/flysystem/src/Filesystem.php(43): League\\Flysystem\\WhitespacePathNormalizer->normalizePath()
#3 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemAdapter.php(225): League\\Flysystem\\Filesystem->directoryExists()
#4 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/rickdbcn/filament-email/src/Models/Email.php(86): Illuminate\\Filesystem\\FilesystemAdapter->directoryExists()
#5 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(458): RickDBCN\\FilamentEmail\\Models\\Email::RickDBCN\\FilamentEmail\\Models\\{closure}()
#6 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(286): Illuminate\\Events\\Dispatcher->Illuminate\\Events\\{closure}()
#7 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(266): Illuminate\\Events\\Dispatcher->invokeListeners()
#8 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(232): Illuminate\\Events\\Dispatcher->dispatch()
#9 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasEvents.php(215): Illuminate\\Events\\Dispatcher->until()
#10 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php(1410): Illuminate\\Database\\Eloquent\\Model->fireModelEvent()
#11 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Prunable.php(55): Illuminate\\Database\\Eloquent\\Model->delete()
#12 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Collections/HigherOrderCollectionProxy.php(60): RickDBCN\\FilamentEmail\\Models\\Email->prune()
#13 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Collections/Traits/EnumeratesValues.php(259): Illuminate\\Support\\HigherOrderCollectionProxy->Illuminate\\Support\\{closure}()
#14 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Collections/HigherOrderCollectionProxy.php(59): Illuminate\\Support\\Collection->each()
#15 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Prunable.php(24): Illuminate\\Support\\HigherOrderCollectionProxy->__call()
#16 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Database/Concerns/BuildsQueries.php(184): RickDBCN\\FilamentEmail\\Models\\Email->Illuminate\\Database\\Eloquent\\{closure}()
#17 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Database/Concerns/BuildsQueries.php(124): Illuminate\\Database\\Eloquent\\Builder->orderedChunkById()
#18 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Prunable.php(23): Illuminate\\Database\\Eloquent\\Builder->chunkById()
#19 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Database/Console/PruneCommand.php(104): RickDBCN\\FilamentEmail\\Models\\Email->pruneAll()
#20 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Database/Console/PruneCommand.php(81): Illuminate\\Database\\Console\\PruneCommand->pruneModel()
#21 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Collections/Traits/EnumeratesValues.php(259): Illuminate\\Database\\Console\\PruneCommand->Illuminate\\Database\\Console\\{closure}()
#22 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Database/Console/PruneCommand.php(80): Illuminate\\Support\\Collection->each()
#23 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(36): Illuminate\\Database\\Console\\PruneCommand->handle()
#24 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Container/Util.php(41): Illuminate\\Container\\BoundMethod::Illuminate\\Container\\{closure}()
#25 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(93): Illuminate\\Container\\Util::unwrapIfClosure()
#26 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(35): Illuminate\\Container\\BoundMethod::callBoundMethod()
#27 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Container/Container.php(690): Illuminate\\Container\\BoundMethod::call()
#28 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Console/Command.php(213): Illuminate\\Container\\Container->call()
#29 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/symfony/console/Command/Command.php(279): Illuminate\\Console\\Command->execute()
#30 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Console/Command.php(182): Symfony\\Component\\Console\\Command\\Command->run()
#31 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/symfony/console/Application.php(1047): Illuminate\\Console\\Command->run()
#32 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/symfony/console/Application.php(316): Symfony\\Component\\Console\\Application->doRunCommand()
#33 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/symfony/console/Application.php(167): Symfony\\Component\\Console\\Application->doRun()
#34 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(196): Symfony\\Component\\Console\\Application->run()
#35 /home/1303878.cloudwaysapps.com/kavdejkrqz/public_html/artisan(35): Illuminate\\Foundation\\Console\\Kernel->handle()
#36 {main}

How to reproduce the bug

After upgrading to v1.4.8 and running migrations, the issue appeared with emails logged with version v1.2.2

Package Version

1.4.8

PHP Version

8.3

Laravel Version

11.16.0

Which operating systems does with happen with?

Linux

Notes

No response

RickDBCN commented 2 months ago

HI Patrick, did you run the storage:link command?

patriktoth67 commented 2 months ago

Ahh, I cloned my app to a new server recently, and forgot to run that command. I'll check next midnight if it solved the issue, thank you very much for the help!

patriktoth67 commented 2 months ago

So the storage:link has been run, but I still get the same error every midnight.

marcogermani87 commented 2 months ago

So the storage:link has been run, but I still get the same error every midnight.

Hi @patriktoth67 , you can show some entries from "filament_email_log" table? I think there's a problem into "raw_body" value.

The "raw_body" value must be like this:

filament-email-log/20240826144000_zPvtf/b6a225063e20fd432542bb6d0f07f8f4@test.example.com.eml

patriktoth67 commented 2 months ago

It is not like that for many rows, even for ones which were created after my update. They contain the full raw html of the email, and also the sender, reply-to, subject etc. before raw html.

The format you sent is only on emails sent after the update, and only on the default Laravel email verification email sent.

image

The emails manually sent out with Laravel's Mailable get the wrong format for the raw_body.

marcogermani87 commented 2 months ago

There's a breaking change made in version 1.4.8. For the new e-mail "raw_body" was not saved into DB but stored on filesystem. The "raw_body" contains the file path and not the original raw content.

You can try to replace the line 86 into src/Models/Email.php with:

 if (!Storage::disk($storageDisk)->exists($record->raw_body)) {

If working we can fix the codebase and made a new release.

marcogermani87 commented 2 months ago

There's a breaking change made in version 1.4.8. For the new e-mail "raw_body" was not saved into DB but stored on filesystem. The "raw_body" contains the file path and not the original raw content.

You can try to replace the line 86 into src/Models/Email.php with:

 if (!Storage::disk($storageDisk)->exists($record->raw_body)) {

If working we can fix the codebase and made a new release.

Sorry, you can try a more polish way to check if "raw_body" field is a valid path.

Replace line 85 at src/Models/Email.php with:

if (! empty($record->raw_body) && count(explode(DIRECTORY_SEPARATOR, $record->raw_body)) === 3) {
patriktoth67 commented 2 months ago

Alright changes done. Should I temporarily set 'prune_crontab' => '* * * * *' in the config file to check if it works?

marcogermani87 commented 2 months ago

Alright changes done. Should I temporarily set 'prune_crontab' => '* * * * *' in the config file to check if it works?

If you have access to server console you can run directly this command:

php artisan model:prune --model=Email

patriktoth67 commented 2 months ago

Perfect, this seems to have solved the issue:

if (! empty($record->raw_body) && count(explode(DIRECTORY_SEPARATOR, $record->raw_body)) === 3) {

Thank you for the help!