From d1c4fd5bef598d03c37ef124cf54185f35b079e5 Mon Sep 17 00:00:00 2001 From: Sonny Spaan Date: Wed, 16 Feb 2022 17:06:17 +0100 Subject: [PATCH] Laravel 9.x Support --- .github/workflows/master.yml | 10 +- composer.json | 8 +- .../LaravelEmailDatabaseLog/EmailLogger.php | 105 ++++++++++-------- ...LaravelEmailDatabaseLogServiceProvider.php | 1 - tests/Feature/LaravelEmailDatabaseTest.php | 75 +++++++++++++ tests/Mail/TestMailWithAttachment.php | 36 ++++++ tests/stubs/demo.txt | 1 + 7 files changed, 177 insertions(+), 59 deletions(-) create mode 100644 tests/Mail/TestMailWithAttachment.php create mode 100644 tests/stubs/demo.txt diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index 9039816..eb2c3cc 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -13,14 +13,12 @@ jobs: fail-fast: true matrix: os: [ubuntu-latest, windows-latest] - php: [7.3, 7.4, 8.0] - laravel: [6.*, 8.*] + php: [8.0, 8.1] + laravel: [9.*] stability: [prefer-lowest, prefer-stable] include: - - laravel: 6.* - testbench: ^4.14 - - laravel: 8.* - testbench: ^6.20 + - laravel: 9.* + testbench: ^7.0 name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }} diff --git a/composer.json b/composer.json index 1046297..d52b73c 100644 --- a/composer.json +++ b/composer.json @@ -15,11 +15,13 @@ } ], "require": { - "illuminate/support": "~6.0|~8.0", - "doctrine/dbal": "^2.10" + "php": "^8.0.2", + "illuminate/support": "^9.0", + "doctrine/dbal": "^3.3", + "nesbot/carbon": "^2.0" }, "require-dev": { - "orchestra/testbench": "^4.0|^6.0", + "orchestra/testbench": "^7.0", "phpunit/phpunit": "^9.0" }, "autoload": { diff --git a/src/ShvetsGroup/LaravelEmailDatabaseLog/EmailLogger.php b/src/ShvetsGroup/LaravelEmailDatabaseLog/EmailLogger.php index 677781a..f5b8e0b 100644 --- a/src/ShvetsGroup/LaravelEmailDatabaseLog/EmailLogger.php +++ b/src/ShvetsGroup/LaravelEmailDatabaseLog/EmailLogger.php @@ -2,58 +2,65 @@ namespace ShvetsGroup\LaravelEmailDatabaseLog; +use Carbon\Carbon; +use Symfony\Component\Mime\Email; use Illuminate\Support\Facades\DB; +use Symfony\Component\Mime\Part\DataPart; use Illuminate\Mail\Events\MessageSending; class EmailLogger { - /** - * Handle the event. - * - * @param MessageSending $event - */ - public function handle(MessageSending $event) - { - $message = $event->message; - - DB::table('email_log')->insert([ - 'date' => date('Y-m-d H:i:s'), - 'from' => $this->formatAddressField($message, 'From'), - 'to' => $this->formatAddressField($message, 'To'), - 'cc' => $this->formatAddressField($message, 'Cc'), - 'bcc' => $this->formatAddressField($message, 'Bcc'), - 'subject' => $message->getSubject(), - 'body' => $message->getBody(), - 'headers' => (string)$message->getHeaders(), - 'attachments' => $message->getChildren() ? implode("\n\n", $message->getChildren()) : null, - ]); - } - - /** - * Format address strings for sender, to, cc, bcc. - * - * @param $message - * @param $field - * @return null|string - */ - function formatAddressField($message, $field) - { - $headers = $message->getHeaders(); - - if (!$headers->has($field)) { - return null; - } - - $mailboxes = $headers->get($field)->getFieldBodyModel(); - - $strings = []; - foreach ($mailboxes as $email => $name) { - $mailboxStr = $email; - if (null !== $name) { - $mailboxStr = $name . ' <' . $mailboxStr . '>'; - } - $strings[] = $mailboxStr; - } - return implode(', ', $strings); - } + /** + * Handle the actual logging. + * + * @param MessageSending $event + * @return void + */ + public function handle(MessageSending $event): void + { + $message = $event->message; + + DB::table('email_log')->insert([ + 'date' => Carbon::now()->format('Y-m-d H:i:s'), + 'from' => $this->formatAddressField($message, 'From'), + 'to' => $this->formatAddressField($message, 'To'), + 'cc' => $this->formatAddressField($message, 'Cc'), + 'bcc' => $this->formatAddressField($message, 'Bcc'), + 'subject' => $message->getSubject(), + 'body' => $message->getBody()->bodyToString(), + 'headers' => $message->getHeaders()->toString(), + 'attachments' => $this->saveAttachments($message), + ]); + } + + /** + * Format address strings for sender, to, cc, bcc. + * + * @param Email $message + * @param string $field + * @return null|string + */ + function formatAddressField(Email $message, string $field): ?string + { + $headers = $message->getHeaders(); + + return $headers->get($field)?->getBodyAsString(); + } + + /** + * Collect all attachments and format them as strings. + * + * @param Email $message + * @return string|null + */ + protected function saveAttachments(Email $message): ?string + { + if (empty($message->getAttachments())) { + return null; + } + + return collect($message->getAttachments()) + ->map(fn(DataPart $part) => $part->toString()) + ->implode("\n\n"); + } } diff --git a/src/ShvetsGroup/LaravelEmailDatabaseLog/LaravelEmailDatabaseLogServiceProvider.php b/src/ShvetsGroup/LaravelEmailDatabaseLog/LaravelEmailDatabaseLogServiceProvider.php index ed3fd83..ce924a9 100644 --- a/src/ShvetsGroup/LaravelEmailDatabaseLog/LaravelEmailDatabaseLogServiceProvider.php +++ b/src/ShvetsGroup/LaravelEmailDatabaseLog/LaravelEmailDatabaseLogServiceProvider.php @@ -3,7 +3,6 @@ namespace ShvetsGroup\LaravelEmailDatabaseLog; use Illuminate\Support\ServiceProvider; -use Illuminate\Mail\Events\MessageSending; class LaravelEmailDatabaseLogServiceProvider extends ServiceProvider { diff --git a/tests/Feature/LaravelEmailDatabaseTest.php b/tests/Feature/LaravelEmailDatabaseTest.php index 0acb67d..e3e4ed6 100644 --- a/tests/Feature/LaravelEmailDatabaseTest.php +++ b/tests/Feature/LaravelEmailDatabaseTest.php @@ -2,10 +2,13 @@ namespace ShvetsGroup\LaravelEmailDatabaseLog\Tests\Feature; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Mail; +use Symfony\Component\Mime\Encoder\Base64Encoder; use Illuminate\Foundation\Testing\RefreshDatabase; use ShvetsGroup\LaravelEmailDatabaseLog\Tests\TestCase; use ShvetsGroup\LaravelEmailDatabaseLog\Tests\Mail\TestMail; +use ShvetsGroup\LaravelEmailDatabaseLog\Tests\Mail\TestMailWithAttachment; class LaravelEmailDatabaseTest extends TestCase { @@ -28,4 +31,76 @@ public function the_email_is_logged_to_the_database() 'attachments' => null, ]); } + + /** @test */ + public function multiple_recipients_are_comma_separated() + { + Mail::to(['email@example.com', 'email2@example.com']) + ->send(new TestMail()); + + $this->assertDatabaseHas('email_log', [ + 'date' => now()->format('Y-m-d H:i:s'), + 'to' => 'email@example.com, email2@example.com', + 'cc' => null, + 'bcc' => null, + ]); + } + + /** @test */ + public function recipient_with_name_is_correctly_formatted() + { + Mail::to((object)['email' => 'email@example.com', 'name' => 'John Do']) + ->send(new TestMail()); + + $this->assertDatabaseHas('email_log', [ + 'date' => now()->format('Y-m-d H:i:s'), + 'to' => 'John Do ', + 'cc' => null, + 'bcc' => null, + ]); + } + + /** @test */ + public function cc_recipient_with_name_is_correctly_formatted() + { + Mail::cc((object)['email' => 'email@example.com', 'name' => 'John Do']) + ->send(new TestMail()); + + $this->assertDatabaseHas('email_log', [ + 'date' => now()->format('Y-m-d H:i:s'), + 'to' => null, + 'cc' => 'John Do ', + 'bcc' => null, + ]); + } + + /** @test */ + public function bcc_recipient_with_name_is_correctly_formatted() + { + Mail::bcc((object)['email' => 'email@example.com', 'name' => 'John Do']) + ->send(new TestMail()); + + $this->assertDatabaseHas('email_log', [ + 'date' => now()->format('Y-m-d H:i:s'), + 'to' => null, + 'cc' => null, + 'bcc' => 'John Do ', + ]); + } + + /** @test */ + public function attachement_is_saved() + { + Mail::to('email@example.com')->send(new TestMailWithAttachment()); + + $log = DB::table('email_log')->first(); + + // TODO: Is there a beter way to tests this ? + $encoded = (new Base64Encoder)->encodeString(file_get_contents(__DIR__ . '/../stubs/demo.txt')); + + $this->assertStringContainsString('Content-Type: text/plain; name=demo.txt', $log->attachments); + $this->assertStringContainsString('Content-Transfer-Encoding: base64', $log->attachments); + $this->assertStringContainsString('Content-Disposition: attachment; name=demo.txt; filename=demo.txt', $log->attachments); + $this->assertStringContainsString($encoded, $log->attachments); + } } diff --git a/tests/Mail/TestMailWithAttachment.php b/tests/Mail/TestMailWithAttachment.php new file mode 100644 index 0000000..94fe72d --- /dev/null +++ b/tests/Mail/TestMailWithAttachment.php @@ -0,0 +1,36 @@ +subject('The e-mail subject') + ->attach(__DIR__ . '/../stubs/demo.txt') + ->html('

Some random string.

'); + } +} diff --git a/tests/stubs/demo.txt b/tests/stubs/demo.txt new file mode 100644 index 0000000..0ed202c --- /dev/null +++ b/tests/stubs/demo.txt @@ -0,0 +1 @@ +This is a demo attachment.