From 0b539c186ec494e83e506853e02a931ec0837362 Mon Sep 17 00:00:00 2001 From: Rick de Graaf Date: Wed, 20 Dec 2017 17:14:03 +0100 Subject: [PATCH 1/3] Added functionality to add from e-mail address and from name --- .../2017_12_14_151403_create_emails_table.php | 1 + src/Email.php | 21 +++++++++++++++++++ src/EmailComposer.php | 11 ++++++++++ src/Encrypter.php | 16 ++++++++++++++ src/HasEncryptedAttributes.php | 2 ++ src/MailableReader.php | 20 ++++++++++++++++++ src/Preparer.php | 18 ++++++++++++++++ src/Sender.php | 8 ++++++- 8 files changed, 96 insertions(+), 1 deletion(-) diff --git a/database/migrations/2017_12_14_151403_create_emails_table.php b/database/migrations/2017_12_14_151403_create_emails_table.php index dc49d1f..9733c98 100644 --- a/database/migrations/2017_12_14_151403_create_emails_table.php +++ b/database/migrations/2017_12_14_151403_create_emails_table.php @@ -21,6 +21,7 @@ public function up() $table->increments('id'); $table->string('label')->nullable(); $table->binary('recipient'); + $table->binary('from')>nullable(); $table->binary('cc')->nullable(); $table->binary('bcc')->nullable(); $table->binary('subject'); diff --git a/src/Email.php b/src/Email.php index 38d6505..7dd0ce1 100644 --- a/src/Email.php +++ b/src/Email.php @@ -10,6 +10,7 @@ * @property $id * @property $label * @property $recipient + * @property $from * @property $cc * @property $bcc * @property $subject @@ -84,6 +85,16 @@ public function getRecipient() return $this->recipient; } + /** + * Get the e-mail from. + * + * @return string|null + */ + public function getFrom() + { + return $this->from; + } + /** * Get the e-mail recipient(s) as string. * @@ -231,6 +242,16 @@ public function getError() return $this->error; } + /** + * Determine if the e-mail should be sent with custom from values. + * + * @return bool + */ + public function hasFrom() + { + return strlen($this->getOriginal('from')) > 0; + } + /** * Determine if the e-mail should be sent as a carbon copy. * diff --git a/src/EmailComposer.php b/src/EmailComposer.php index 67135f4..39e895f 100644 --- a/src/EmailComposer.php +++ b/src/EmailComposer.php @@ -92,6 +92,17 @@ public function label($label) return $this->setData('label', $label); } + /** + * Set the e-mail from address and aname. + * + * @param array $from + * @return static + */ + public function from($address, $name) + { + return $this->setData('from', ['address' => $address, 'name' => $name]); + } + /** * Set the e-mail recipient(s). * diff --git a/src/Encrypter.php b/src/Encrypter.php index 4a6649f..4bf5b4f 100644 --- a/src/Encrypter.php +++ b/src/Encrypter.php @@ -15,6 +15,8 @@ public function encrypt(EmailComposer $composer) $this->encryptRecipients($composer); + $this->encryptFrom($composer); + $this->encryptSubject($composer); $this->encryptVariables($composer); @@ -48,6 +50,20 @@ private function encryptRecipients(EmailComposer $composer) ]); } + /** + * Encrypt the e-mail addresses for the from field. + * + * @param EmailComposer $composer + */ + private function encryptFrom(EmailComposer $composer) + { + $email = $composer->getEmail(); + + $email->fill([ + 'from' => encrypt($email->from), + ]); + } + /** * Encrypt the e-mail subject. * diff --git a/src/HasEncryptedAttributes.php b/src/HasEncryptedAttributes.php index 162e293..74b1412 100644 --- a/src/HasEncryptedAttributes.php +++ b/src/HasEncryptedAttributes.php @@ -13,6 +13,7 @@ trait HasEncryptedAttributes */ private $encrypted = [ 'recipient', + 'from', 'cc', 'bcc', 'subject', @@ -27,6 +28,7 @@ trait HasEncryptedAttributes */ private $encoded = [ 'recipient', + 'from', 'cc', 'bcc', 'variables', diff --git a/src/MailableReader.php b/src/MailableReader.php index 44b8330..e3925c1 100644 --- a/src/MailableReader.php +++ b/src/MailableReader.php @@ -16,6 +16,12 @@ public function read(EmailComposer $composer) { $this->readRecipient($composer); + + + $this->readFrom($composer); + + + $this->readCc($composer); $this->readBcc($composer); @@ -54,6 +60,20 @@ private function readRecipient(EmailComposer $composer) $composer->recipient($to); } + /** + * Read the mailable from field to the email composer. + * + * @param EmailComposer $composer + */ + private function readFrom(EmailComposer $composer) + { + $from = $this->convertMailableAddresses( + $composer->getData('mailable')->from + ); + + $composer->from($from); + } + /** * Read the mailable cc to the email composer. * diff --git a/src/Preparer.php b/src/Preparer.php index 87cf576..dd85ded 100644 --- a/src/Preparer.php +++ b/src/Preparer.php @@ -17,6 +17,8 @@ public function prepare(EmailComposer $composer) $this->prepareRecipient($composer); + $this->prepareFrom($composer); + $this->prepareCc($composer); $this->prepareBcc($composer); @@ -66,6 +68,22 @@ private function prepareRecipient(EmailComposer $composer) ]); } + /** + * Prepare the from values for database storage. + * + * @param EmailComposer $composer + */ + private function prepareFrom(EmailComposer $composer) + { + if (!$composer->hasData('from')) { + return; + } + + $composer->getEmail()->fill([ + 'from' => json_encode($composer->getData('from')), + ]); + } + /** * Prepare the carbon copies for database storage. * diff --git a/src/Sender.php b/src/Sender.php index 88bd8a8..3f0575b 100644 --- a/src/Sender.php +++ b/src/Sender.php @@ -45,11 +45,17 @@ private function getMailerInstance() */ private function buildMessage(Message $message, Email $email) { + + $from = $email->hasFrom() ? $email->getFrom() : ['address' => config('mail.from.address'), 'name' => config('mail.from.name')]; + foreach ($from as $key => $val) { + $from[$key] = !empty($val) ? $val : config('mail.from.' . $key); + } + $message->to($email->getRecipient()) ->cc($email->hasCc() ? $email->getCc() : []) ->bcc($email->hasBcc() ? $email->getBcc() : []) ->subject($email->getSubject()) - ->from(config('mail.from.address'), config('mail.from.name')) + ->from($from['address'], $from['name']) ->setBody($email->getBody(), 'text/html'); $attachmentMap = [ From 77be0fb63d4e6750f8f329ce3d00e0b858ca3e42 Mon Sep 17 00:00:00 2001 From: Rick de Graaf Date: Wed, 20 Dec 2017 17:14:28 +0100 Subject: [PATCH 2/3] Removed default from attachments field for earlier versions of mysql --- .../2017_12_14_151421_add_attachments_to_emails_table.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/migrations/2017_12_14_151421_add_attachments_to_emails_table.php b/database/migrations/2017_12_14_151421_add_attachments_to_emails_table.php index f515068..2f142e1 100644 --- a/database/migrations/2017_12_14_151421_add_attachments_to_emails_table.php +++ b/database/migrations/2017_12_14_151421_add_attachments_to_emails_table.php @@ -18,7 +18,7 @@ public function up() } Schema::table('emails', function (Blueprint $table) { - $table->binary('attachments')->after('body')->default(''); + $table->binary('attachments')->after('body'); }); } From b68b38f4969a4f01b74c683acb40e69b4a2a3715 Mon Sep 17 00:00:00 2001 From: Marick van Tuil Date: Fri, 22 Dec 2017 12:49:10 +0100 Subject: [PATCH 3/3] refactor code and added tests --- .../2017_12_14_151403_create_emails_table.php | 1 - ...151421_add_attachments_to_emails_table.php | 2 +- ..._12_22_114011_add_from_to_emails_table.php | 34 +++++++++++++++++++ src/Email.php | 24 +++++++++++-- src/EmailComposer.php | 7 ++-- src/MailableReader.php | 13 +++---- src/Preparer.php | 6 +--- src/Sender.php | 8 +---- tests/DatabaseInteractionTest.php | 16 +++++++++ tests/EncryptionTest.php | 16 ++++++++- tests/MailableReaderTest.php | 31 +++++++++++++++++ tests/SenderTest.php | 25 ++++++++++++++ 12 files changed, 155 insertions(+), 28 deletions(-) create mode 100644 database/migrations/2017_12_22_114011_add_from_to_emails_table.php diff --git a/database/migrations/2017_12_14_151403_create_emails_table.php b/database/migrations/2017_12_14_151403_create_emails_table.php index 9733c98..dc49d1f 100644 --- a/database/migrations/2017_12_14_151403_create_emails_table.php +++ b/database/migrations/2017_12_14_151403_create_emails_table.php @@ -21,7 +21,6 @@ public function up() $table->increments('id'); $table->string('label')->nullable(); $table->binary('recipient'); - $table->binary('from')>nullable(); $table->binary('cc')->nullable(); $table->binary('bcc')->nullable(); $table->binary('subject'); diff --git a/database/migrations/2017_12_14_151421_add_attachments_to_emails_table.php b/database/migrations/2017_12_14_151421_add_attachments_to_emails_table.php index 2f142e1..e0fa3fa 100644 --- a/database/migrations/2017_12_14_151421_add_attachments_to_emails_table.php +++ b/database/migrations/2017_12_14_151421_add_attachments_to_emails_table.php @@ -18,7 +18,7 @@ public function up() } Schema::table('emails', function (Blueprint $table) { - $table->binary('attachments')->after('body'); + $table->binary('attachments')->nullable()->after('body'); }); } diff --git a/database/migrations/2017_12_22_114011_add_from_to_emails_table.php b/database/migrations/2017_12_22_114011_add_from_to_emails_table.php new file mode 100644 index 0000000..de25f07 --- /dev/null +++ b/database/migrations/2017_12_22_114011_add_from_to_emails_table.php @@ -0,0 +1,34 @@ +binary('from')->after('body')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +} diff --git a/src/Email.php b/src/Email.php index 7dd0ce1..f56c69b 100644 --- a/src/Email.php +++ b/src/Email.php @@ -88,13 +88,33 @@ public function getRecipient() /** * Get the e-mail from. * - * @return string|null + * @return array */ public function getFrom() { return $this->from; } + /** + * Get the e-mail from address. + * + * @return string|null + */ + public function getFromAddress() + { + return $this->from['address'] ?? config('mail.from.address'); + } + + /** + * Get the e-mail from address. + * + * @return string|null + */ + public function getFromName() + { + return $this->from['name'] ?? config('mail.from.name'); + } + /** * Get the e-mail recipient(s) as string. * @@ -249,7 +269,7 @@ public function getError() */ public function hasFrom() { - return strlen($this->getOriginal('from')) > 0; + return is_array($this->from) && count($this->from) > 0; } /** diff --git a/src/EmailComposer.php b/src/EmailComposer.php index 39e895f..9aef7df 100644 --- a/src/EmailComposer.php +++ b/src/EmailComposer.php @@ -95,12 +95,13 @@ public function label($label) /** * Set the e-mail from address and aname. * - * @param array $from + * @param array $address + * @param array $name * @return static */ - public function from($address, $name) + public function from($address = null, $name = null) { - return $this->setData('from', ['address' => $address, 'name' => $name]); + return $this->setData('from', compact('address', 'name')); } /** diff --git a/src/MailableReader.php b/src/MailableReader.php index e3925c1..9e6fed6 100644 --- a/src/MailableReader.php +++ b/src/MailableReader.php @@ -16,12 +16,8 @@ public function read(EmailComposer $composer) { $this->readRecipient($composer); - - $this->readFrom($composer); - - $this->readCc($composer); $this->readBcc($composer); @@ -67,11 +63,12 @@ private function readRecipient(EmailComposer $composer) */ private function readFrom(EmailComposer $composer) { - $from = $this->convertMailableAddresses( - $composer->getData('mailable')->from - ); + $from = reset($composer->getData('mailable')->from); - $composer->from($from); + $composer->from( + $from['address'], + $from['name'] + ); } /** diff --git a/src/Preparer.php b/src/Preparer.php index dd85ded..07612a7 100644 --- a/src/Preparer.php +++ b/src/Preparer.php @@ -75,12 +75,8 @@ private function prepareRecipient(EmailComposer $composer) */ private function prepareFrom(EmailComposer $composer) { - if (!$composer->hasData('from')) { - return; - } - $composer->getEmail()->fill([ - 'from' => json_encode($composer->getData('from')), + 'from' => json_encode($composer->getData('from', '')), ]); } diff --git a/src/Sender.php b/src/Sender.php index 3f0575b..927dd15 100644 --- a/src/Sender.php +++ b/src/Sender.php @@ -45,17 +45,11 @@ private function getMailerInstance() */ private function buildMessage(Message $message, Email $email) { - - $from = $email->hasFrom() ? $email->getFrom() : ['address' => config('mail.from.address'), 'name' => config('mail.from.name')]; - foreach ($from as $key => $val) { - $from[$key] = !empty($val) ? $val : config('mail.from.' . $key); - } - $message->to($email->getRecipient()) ->cc($email->hasCc() ? $email->getCc() : []) ->bcc($email->hasBcc() ? $email->getBcc() : []) ->subject($email->getSubject()) - ->from($from['address'], $from['name']) + ->from($email->getFromAddress(), $email->getFromName()) ->setBody($email->getBody(), 'text/html'); $attachmentMap = [ diff --git a/tests/DatabaseInteractionTest.php b/tests/DatabaseInteractionTest.php index 368f6e5..82938e6 100644 --- a/tests/DatabaseInteractionTest.php +++ b/tests/DatabaseInteractionTest.php @@ -101,6 +101,22 @@ function the_body_should_be_saved_correctly() $this->assertSame($expectedBody, $email->getBody()); } + /** @test */ + function from_should_be_saved_correctly() + { + $email = $this->composeEmail()->send(); + + $this->assertFalse($email->hasFrom()); + $this->assertEquals(config('mail.from.address'), $email->getFromAddress()); + $this->assertEquals(config('mail.from.name'), $email->getFromName()); + + $email = $this->composeEmail()->from('marick@dolphiq.nl', 'Marick')->send(); + + $this->assertTrue($email->hasFrom()); + $this->assertEquals('marick@dolphiq.nl', $email->getFromAddress()); + $this->assertEquals('Marick', $email->getFromName()); + } + /** @test */ function variables_should_be_saved_correctly() { diff --git a/tests/EncryptionTest.php b/tests/EncryptionTest.php index 9d16e0f..099ac14 100644 --- a/tests/EncryptionTest.php +++ b/tests/EncryptionTest.php @@ -62,7 +62,7 @@ function the_variables_should_be_encrypted_and_decrypted() $email = $this->sendEmail(['variables' => ['name' => 'Jane Doe']]); $this->assertEquals( - ['name'=> 'Jane Doe'], + ['name' => 'Jane Doe'], decrypt($email->getOriginal('variables')) ); @@ -83,4 +83,18 @@ function the_body_should_be_encrypted_and_decrypted() $this->assertEquals($expectedBody, $email->getBody()); } + + /** @test */ + function from_should_be_encrypted_and_decrypted() + { + $email = $this->composeEmail()->from('marick@dolphiq.nl', 'Marick')->send(); + + $expect = [ + 'address' => 'marick@dolphiq.nl', + 'name' => 'Marick', + ]; + + $this->assertEquals($expect, decrypt($email->getOriginal('from'))); + $this->assertEquals($expect, $email->getFrom()); + } } diff --git a/tests/MailableReaderTest.php b/tests/MailableReaderTest.php index c15ca5a..2b81c44 100644 --- a/tests/MailableReaderTest.php +++ b/tests/MailableReaderTest.php @@ -71,6 +71,37 @@ function it_extracts_attachments() $this->assertEquals('order.html', $attachments[1]['attachment']['name']); $this->assertEquals('

Thanks for your oder

', $attachments[1]['attachment']['data']); } + + /** @test */ + function it_extracts_the_from_address_and_or_name() + { + $email = Email::compose()->mailable( + (new TestMailable()) + ->from('marick@dolphiq.nl', 'Marick') + )->send(); + + $this->assertTrue($email->hasFrom()); + $this->assertEquals('marick@dolphiq.nl', $email->getFromAddress()); + $this->assertEquals('Marick', $email->getFromName()); + + $email = Email::compose()->mailable( + (new TestMailable()) + ->from('marick@dolphiq.nl') + )->send(); + + $this->assertTrue($email->hasFrom()); + $this->assertEquals('marick@dolphiq.nl', $email->getFromAddress()); + $this->assertEquals(config('mail.from.name'), $email->getFromName()); + + $email = Email::compose()->mailable( + (new TestMailable()) + ->from(null, 'Marick') + )->send(); + + $this->assertTrue($email->hasFrom()); + $this->assertEquals(config('mail.from.address'), $email->getFromAddress()); + $this->assertEquals('Marick', $email->getFromName()); + } } class TestMailable extends Mailable diff --git a/tests/SenderTest.php b/tests/SenderTest.php index e7d95da..9a0afa7 100644 --- a/tests/SenderTest.php +++ b/tests/SenderTest.php @@ -43,6 +43,31 @@ function the_email_has_a_correct_from_email_and_from_name() $this->assertEquals('testfromaddress@gmail.com', key($from)); $this->assertEquals('From CI test', $from[key($from)]); + + // custom from... + $this->sent = []; + + $this->composeEmail()->from('marick@dolphiq.nl', 'Marick')->send(); + $this->artisan('email:send'); + $from = reset($this->sent)->getMessage()->getFrom(); + $this->assertEquals('marick@dolphiq.nl', key($from)); + $this->assertEquals('Marick', $from[key($from)]); + + // only address + $this->sent = []; + $this->composeEmail()->from('marick@dolphiq.nl')->send(); + $this->artisan('email:send'); + $from = reset($this->sent)->getMessage()->getFrom(); + $this->assertEquals('marick@dolphiq.nl', key($from)); + $this->assertEquals(config('mail.from.name'), $from[key($from)]); + + // only name + $this->sent = []; + $this->composeEmail()->from(null, 'Marick')->send(); + $this->artisan('email:send'); + $from = reset($this->sent)->getMessage()->getFrom(); + $this->assertEquals(config('mail.from.address'), key($from)); + $this->assertEquals('Marick', $from[key($from)]); } /** @test */