diff --git a/README.md b/README.md index bcc5514..3f3cfbf 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Laravel SendGrid Driver ==== -[![SymfonyInsight](https://insight.symfony.com/projects/4232643f-006c-473b-97ff-d0f67fa497ee/mini.svg)](https://insight.symfony.com/projects/4232643f-006c-473b-97ff-d0f67fa497ee) +[![SymfonyInsight](https://insight.symfony.com/projects/8955bc55-16f6-4ac9-8203-1cdce3d209a8/mini.svg)](https://insight.symfony.com/projects/8955bc55-16f6-4ac9-8203-1cdce3d209a8) [![Build Status](https://scrutinizer-ci.com/g/s-ichikawa/laravel-sendgrid-driver/badges/build.png?b=master)](https://scrutinizer-ci.com/g/s-ichikawa/laravel-sendgrid-driver/build-status/master) A Mail Driver with support for Sendgrid Web API, using the original Laravel API. @@ -10,17 +10,12 @@ This library extends the original Laravel classes, so it uses exactly the same m To use this package required your [Sendgrid Api Key](https://sendgrid.com/docs/User_Guide/Settings/api_keys.html). Please make it [Here](https://app.sendgrid.com/settings/api_keys). -# Notification - -If your project using guzzlehttp/guzzle 6.2.0 or less, you can use version [1.0.0](https://github.com/s-ichikawa/laravel-sendgrid-driver/tree/1.0.0) -But the old version has [security issues](https://github.com/guzzle/guzzle/releases/tag/6.2.1), - -# Install (Laravel) +# Install (for [Laravel](https://laravel.com/)) Add the package to your composer.json and run composer update. ```json "require": { - "s-ichikawa/laravel-sendgrid-driver": "~3.0" + "s-ichikawa/laravel-sendgrid-driver": "^4.0" }, ``` @@ -37,18 +32,18 @@ Add the sendgrid service provider in config/app.php: ]; ``` -# Install (Lumen) +# Install (for [Lumen](https://lumen.laravel.com/)) Add the package to your composer.json and run composer update. ```json "require": { - "s-ichikawa/laravel-sendgrid-driver": "~2.0" + "s-ichikawa/laravel-sendgrid-driver": "^4.0" }, ``` or installed with composer ```bash -$ composer require "s-ichikawa/laravel-sendgrid-driver:~2.0" +$ composer require "s-ichikawa/laravel-sendgrid-driver:^4.0" ``` Add the sendgrid service provider in bootstrap/app.php @@ -105,69 +100,14 @@ For example, calls to SendGrid API through a proxy, call endpoint for confirming ], ``` -## Request Body Parameters +## How to use Every request made to /v3/mail/send will require a request body formatted in JSON containing your email’s content and metadata. Required parameters are set by Laravel's usually mail sending, but you can also use useful features like "categories" and "send_at". -```php -\Mail::send('view', $data, function (Message $message) { - $message - ->to('foo@example.com', 'foo_name') - ->from('bar@example.com', 'bar_name') - ->embedData([ - 'categories' => ['user_group1'], - 'send_at' => $send_at->getTimestamp(), - ], 'sendgrid/x-smtpapi'); -}); -``` - more info https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/index.html#-Request-Body-Parameters - -## API v3 - -```php -\Mail::send('view', $data, function (Message $message) { - $message - ->to('foo@example.com', 'foo_name') - ->from('bar@example.com', 'bar_name') - ->replyTo('foo@bar.com', 'foobar'); - ->embedData([ - 'personalizations' => [ - [ - 'to' => [ - 'email' => 'user1@example.com', - 'name' => 'user1', - ], - 'substitutions' => [ - '-email-' => 'user1@example.com', - ], - ], - [ - 'to' => [ - 'email' => 'user2@example.com', - 'name' => 'user2', - ], - 'substitutions' => [ - '-email-' => 'user2@example.com', - ], - ], - ], - 'categories' => ['user_group1'], - 'custom_args' => [ - 'user_id' => "123" // Make sure this is a string value - ] - ], 'sendgrid/x-smtpapi'); -}); -``` - -- custom_args values have to be strings. Sendgrid API gives a non-descriptive error message when you enter non-string values. - - -## Use in Mailable - ```php sendgrid([ 'personalizations' => [ [ - 'substitutions' => [ - ':myname' => 's-ichikawa', + 'to' => [ + ['email' => 'to1@gmail.com', 'name' => 'to1'], + ['email' => 'to2@gmail.com', 'name' => 'to2'], + ], + 'cc' => [ + ['email' => 'cc1@gmail.com', 'name' => 'cc1'], + ['email' => 'cc2@gmail.com', 'name' => 'cc2'], + ], + 'bcc' => [ + ['email' => 'bcc1@gmail.com', 'name' => 'bcc1'], + ['email' => 'bcc2@gmail.com', 'name' => 'bcc2'], ], ], ], + 'categories' => ['user_group1'], ]); } } @@ -202,10 +152,14 @@ Illuminate\Mailer has generally required a view file. But in case of using template id, set an empty array at view function. ```php to('to@example.com') - ->embedData([ + public function build() + { + return $this + ->view('template name') + ->subject('subject') + ->from('from@example.com') + ->to(['to@example.com']) + ->sendgrid([ 'personalizations' => [ [ 'dynamic_template_data' => [ @@ -215,24 +169,6 @@ But in case of using template id, set an empty array at view function. ], ], 'template_id' => config('services.sendgrid.templates.dynamic_template_id'), - ], SendgridTransport::SMTP_API_NAME); -}); -``` - -## Using with Telescope - -In case [telescope](https://laravel.com/docs/5.7/telescope) is active and set array to first variable in embedData, telescope's watcher happen error in encoding. -In ordar to avoid this probrem, you can use sgEncode function. -```php -to('foo@example.com', 'foo_name') - ->from('bar@example.com', 'bar_name') - ->embedData(sgEncode([ - 'categories' => ['user_group1'], - ]), 'sendgrid/x-smtpapi'); -}); + ]); + } ``` diff --git a/composer.json b/composer.json index 82abf62..f447ed7 100644 --- a/composer.json +++ b/composer.json @@ -4,16 +4,16 @@ "keywords": ["laravel", "sendgrid"], "license": "MIT", "require": { - "illuminate/mail": ">=7.0", - "illuminate/support": ">=7.0", - "guzzlehttp/guzzle": "^6.3 || ^7.0" + "illuminate/mail": "^9.0", + "illuminate/support": "^9.0", + "guzzlehttp/guzzle": "^7.2" }, "require-dev": { - "illuminate/container": ">=7.0", - "illuminate/filesystem": ">=7.0", - "phpunit/phpunit": "^8.5", + "illuminate/container": "^9.0", + "illuminate/filesystem": "^9.0", + "phpunit/phpunit": "^9.5.8", "laravel/helpers": "^1.2", - "vlucas/phpdotenv": "^4.1 || ^5.2" + "vlucas/phpdotenv": "^5.4.1" }, "autoload": { "psr-4": { @@ -43,5 +43,7 @@ "Sichikawa\\LaravelSendgridDriver\\SendgridTransportServiceProvider" ] } - } + }, + "minimum-stability": "dev", + "prefer-stable": true } diff --git a/src/SendGrid.php b/src/SendGrid.php index 61adb43..3eac5b5 100644 --- a/src/SendGrid.php +++ b/src/SendGrid.php @@ -3,9 +3,8 @@ namespace Sichikawa\LaravelSendgridDriver; use Illuminate\Mail\Mailable; -use Illuminate\Notifications\Messages\MailMessage; use Sichikawa\LaravelSendgridDriver\Transport\SendgridTransport; -use Swift_Message; +use Symfony\Component\Mime\Email; trait SendGrid { @@ -16,9 +15,9 @@ trait SendGrid */ public function sendgrid($params) { - if (($this instanceof Mailable || $this instanceof MailMessage) && $this->mailDriver() == "sendgrid") { - $this->withSwiftMessage(function (Swift_Message $message) use ($params) { - $message->embed(new \Swift_Image(static::sgEncode($params), SendgridTransport::SMTP_API_NAME)); + if (($this instanceof Mailable) && $this->mailDriver() == "sendgrid") { + $this->withSymfonyMessage(function (Email $email) use ($params) { + $email->embed(static::sgEncode($params), SendgridTransport::REQUEST_BODY_PARAMETER); }); } return $this; @@ -51,7 +50,7 @@ public static function sgEncode($params) public static function sgDecode($strParams) { if (!is_string($strParams)) { - return (array) $strParams; + return (array)$strParams; } $params = json_decode($strParams, true); return is_array($params) ? $params : []; diff --git a/src/SendgridTransportServiceProvider.php b/src/SendgridTransportServiceProvider.php index 6b637a5..5e785d3 100644 --- a/src/SendgridTransportServiceProvider.php +++ b/src/SendgridTransportServiceProvider.php @@ -11,7 +11,7 @@ class SendgridTransportServiceProvider extends ServiceProvider { /** - * Register the Swift Transport instance. + * Register the Sendgrid Transport instance. * * @return void */ @@ -23,7 +23,7 @@ public function register() $config = $this->app['config']->get('services.sendgrid', []); } $client = new HttpClient(Arr::get($config, 'guzzle', [])); - $endpoint = isset($config['endpoint']) ? $config['endpoint'] : null; + $endpoint = $config['endpoint'] ?? null; return new SendgridTransport($client, $config['api_key'], $endpoint); }); diff --git a/src/Transport/SendgridTransport.php b/src/Transport/SendgridTransport.php index aa1389d..d31b3cc 100644 --- a/src/Transport/SendgridTransport.php +++ b/src/Transport/SendgridTransport.php @@ -1,27 +1,37 @@ client = $client; $this->apiKey = $api_key; - $this->endpoint = isset($endpoint) ? $endpoint : self::BASE_URL; + $this->endpoint = $endpoint ?? self::BASE_URL; + + parent::__construct(); } - /** - * {@inheritdoc} - */ - public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) + protected function doSend(SentMessage $message): void { - $this->beforeSendPerformed($message); + $email = MessageConverter::toEmail($message->getOriginalMessage()); $data = [ - 'personalizations' => $this->getPersonalizations($message), - 'from' => $this->getFrom($message), - 'subject' => $message->getSubject(), + 'personalizations' => $this->getPersonalizations($email), + 'from' => $this->getFrom($email), + 'subject' => $email->getSubject(), ]; - if ($contents = $this->getContents($message)) { + if ($contents = $this->getContents($email)) { $data['content'] = $contents; } - if ($reply_to = $this->getReplyTo($message)) { + if ($reply_to = $this->getReplyTo($email)) { $data['reply_to'] = $reply_to; } - $attachments = $this->getAttachments($message); + $attachments = $this->getAttachments($email); if (count($attachments) > 0) { $data['attachments'] = $attachments; } - $data = $this->setParameters($message, $data); + $data = $this->setParameters($email, $data); $payload = [ 'headers' => [ @@ -74,218 +83,183 @@ public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = nul 'json' => $data, ]; - $response = $this->post($payload); - - $message->getHeaders()->addTextHeader('X-Sendgrid-Message-Id', $response->getHeaderLine('X-Message-Id')); - - $this->sendPerformed($message); - - return $this->numberOfRecipients ?: $this->numberOfRecipients($message); + $this->post($payload); } /** - * @param Swift_Mime_SimpleMessage $message - * @return array + * @param Email $email + * @return array[] */ - private function getPersonalizations(Swift_Mime_SimpleMessage $message) + private function getPersonalizations(Email $email): array { - $setter = function (array $addresses) { - $recipients = []; - foreach ($addresses as $email => $name) { - $address = []; - $address['email'] = $email; - if ($name) { - $address['name'] = $name; - } - $recipients[] = $address; - } - return $recipients; - }; + $personalization['to'] = $this->setAddress($email->getTo()); - $personalization['to'] = $setter($message->getTo()); + if (count($email->getCc()) > 0) { + $personalization['cc'] = $this->setAddress($email->getCc()); - if ($cc = $message->getCc()) { - $personalization['cc'] = $setter($cc); } - if ($bcc = $message->getBcc()) { - $personalization['bcc'] = $setter($bcc); + if (count($email->getBcc()) > 0) { + $personalization['bcc'] = $this->setAddress($email->getBcc()); + } return [$personalization]; } /** - * Get From Addresses. - * - * @param Swift_Mime_SimpleMessage $message + * @param Address[] $addresses * @return array */ - private function getFrom(Swift_Mime_SimpleMessage $message) + private function setAddress(array $addresses): array { - if ($message->getFrom()) { - foreach ($message->getFrom() as $email => $name) { - return ['email' => $email, 'name' => $name]; + $recipients = []; + foreach ($addresses as $address) { + $recipient = ['email' => $address->getAddress()]; + if ($address->getName() !== '') { + $recipient['name'] = $address->getName(); } + $recipients[] = $recipient; } - return []; + return $recipients; } /** - * Get ReplyTo Addresses. - * - * @param Swift_Mime_SimpleMessage $message + * @param Email $email * @return array */ - private function getReplyTo(Swift_Mime_SimpleMessage $message) + private function getFrom(Email $email): array { - if ($message->getReplyTo()) { - foreach ($message->getReplyTo() as $email => $name) { - return ['email' => $email, 'name' => $name]; + if (count($email->getFrom()) > 0) { + foreach ($email->getFrom() as $from) { + return ['email' => $from->getAddress(), 'name' => $from->getName()]; } } - return null; + return []; } /** - * Get contents. - * - * @param Swift_Mime_SimpleMessage $message + * @param Email $email * @return array */ - private function getContents(Swift_Mime_SimpleMessage $message) + private function getContents(Email $email): array { - $contentType = $message->getContentType(); - switch ($contentType) { - case 'text/plain': - return [ - [ - 'type' => 'text/plain', - 'value' => $message->getBody(), - - ], - ]; - case 'text/html': - return [ - [ - 'type' => 'text/html', - 'value' => $message->getBody(), - ], - ]; + $contents = []; + if (!is_null($email->getTextBody())) { + $contents[] = [ + 'type' => 'text/plain', + 'value' => $email->getTextBody(), + ]; } - // Following RFC 1341, text/html after text/plain in multipart - $content = []; - foreach ($message->getChildren() as $child) { - if ($child instanceof Swift_MimePart && $child->getContentType() === 'text/plain') { - $content[] = [ - 'type' => 'text/plain', - 'value' => $child->getBody(), - ]; - } + if (!is_null($email->getHtmlBody())) { + $contents[] = [ + 'type' => 'text/html', + 'value' => $email->getHtmlBody(), + ]; } - if (is_null($message->getBody())) { - return null; - } + return $contents; + } - $content[] = [ - 'type' => 'text/html', - 'value' => $message->getBody(), - ]; - return $content; + /** + * @param Email $email + * @return array|null + */ + private function getReplyTo(Email $email): ?array + { + if (count($email->getReplyTo()) > 0) { + $replyTo = $email->getReplyTo()[0]; + return [ + 'email' => $replyTo->getAddress(), + 'name' => $replyTo->getName(), + ]; + } + return null; } /** - * @param Swift_Mime_SimpleMessage $message + * @param Email $email * @return array */ - private function getAttachments(Swift_Mime_SimpleMessage $message) + private function getAttachments(Email $email): array { $attachments = []; - foreach ($message->getChildren() as $attachment) { - if ((!$attachment instanceof Swift_Attachment && !$attachment instanceof Swift_Image) - || $attachment->getFilename() === self::SMTP_API_NAME - ) { + foreach ($email->getAttachments() as $attachment) { + $filename = $this->getAttachmentName($attachment); + if ($filename === self::REQUEST_BODY_PARAMETER) { continue; } + $attachments[] = [ - 'content' => base64_encode($attachment->getBody()), - 'filename' => $attachment->getFilename(), - 'type' => $attachment->getContentType(), - 'disposition' => $attachment->getDisposition(), - 'content_id' => $attachment->getId(), + 'content' => base64_encode($attachment->getBody()), + 'filename' => $this->getAttachmentName($attachment), + 'type' => $this->getAttachmentContentType($attachment), + 'disposition' => $attachment->getPreparedHeaders()->getHeaderParameter('Parameterized', 'Content-Disposition'), + 'content_id' => $attachment->getContentId(), ]; } - return $this->attachments = $attachments; + return $attachments; + } + + private function getAttachmentName(DataPart $dataPart): string + { + return $dataPart->getPreparedHeaders()->getHeaderParameter('Content-Disposition', 'filename'); + } + + private function getAttachmentContentType(Datapart $dataPart): string + { + return $dataPart->getMediaType() . '/' . $dataPart->getMediaSubtype(); } /** - * Set Request Body Parameters - * - * @param Swift_Mime_SimpleMessage $message + * @param Email $email * @param array $data * @return array - * @throws \Exception */ - protected function setParameters(Swift_Mime_SimpleMessage $message, $data) + private function setParameters(Email $email, array $data): array { - $this->numberOfRecipients = 0; - $smtp_api = []; - foreach ($message->getChildren() as $attachment) { - if (!$attachment instanceof Swift_Image - || !in_array(self::SMTP_API_NAME, [$attachment->getFilename(), $attachment->getContentType()]) - ) { - continue; + foreach ($email->getAttachments() as $attachment) { + $name = $attachment->getPreparedHeaders()->getHeaderParameter('Content-Disposition', 'filename'); + if ($name === self::REQUEST_BODY_PARAMETER) { + $smtp_api = self::decode($attachment->getBody()); } - $smtp_api = self::decode($attachment->getBody()); } - if (!is_array($smtp_api)) { + if (count($smtp_api) < 1) { return $data; } foreach ($smtp_api as $key => $val) { - switch ($key) { - case 'api_key': $this->apiKey = $val; continue 2; - case 'personalizations': $this->setPersonalizations($data, $val); continue 2; - case 'attachments': $val = array_merge($this->attachments, $val); break; - - case 'unique_args': - throw new \Exception('Sendgrid v3 now uses custom_args instead of unique_args'); - - case 'custom_args': - foreach ($val as $name => $value) { - if (!is_string($value)) { - throw new \Exception('Sendgrid v3 custom arguments have to be a string.'); - } - } - break; - } - Arr::set($data, $key, $val); } + return $data; } - private function setPersonalizations(&$data, $personalizations) + /** + * @param array $data + * @param array $personalizations + * @return void + */ + private function setPersonalizations(array &$data, array $personalizations): void { foreach ($personalizations as $index => $params) { foreach ($params as $key => $val) { if (in_array($key, ['to', 'cc', 'bcc'])) { - Arr::set($data, 'personalizations.' . $index . '.' . $key, [$val]); + Arr::set($data, 'personalizations.' . $index . '.' . $key, $val); ++$this->numberOfRecipients; } else { Arr::set($data, 'personalizations.' . $index . '.' . $key, $val); @@ -297,10 +271,15 @@ private function setPersonalizations(&$data, $personalizations) /** * @param $payload * @return ResponseInterface - * @throws GuzzleException + * @throws ClientException */ private function post($payload) { return $this->client->request('POST', $this->endpoint, $payload); } + + public function __toString(): string + { + return 'sendgrid'; + } } diff --git a/tests/Transport/SendgridTransportTest.php b/tests/Transport/SendgridTransportTest.php index 1b7f604..159a1e4 100644 --- a/tests/Transport/SendgridTransportTest.php +++ b/tests/Transport/SendgridTransportTest.php @@ -1,301 +1,250 @@ transport = new SendgridTransport($client, $this->api_key); + $this->reflection = new \ReflectionClass($this->transport); } + public function testGetPersonalizations() + { + $email = (new Email()) + ->to( + (new Address('to1@sink.sendgrid.net', 'test_to1')), + (new Address('to2@sink.sendgrid.net', 'test_to2')), + ) + ->cc( + (new Address('cc1@sink.sendgrid.net', 'test_cc1')), + (new Address('cc2@sink.sendgrid.net', 'test_cc2')), + ) + ->bcc( + (new Address('bcc1@sink.sendgrid.net', 'test_bcc1')), + (new Address('bcc2@sink.sendgrid.net', 'test_bcc2')), + ); + + $method = $this->reflection->getMethod('getPersonalizations'); + $method->setAccessible(true); + + $result = $method->invoke($this->transport, $email); + self::assertEquals([ + [ + 'to' => [ + ['email' => 'to1@sink.sendgrid.net', 'name' => 'test_to1'], + ['email' => 'to2@sink.sendgrid.net', 'name' => 'test_to2'], + ], + 'cc' => [ + ['email' => 'cc1@sink.sendgrid.net', 'name' => 'test_cc1'], + ['email' => 'cc2@sink.sendgrid.net', 'name' => 'test_cc2'], + ], + 'bcc' => [ + ['email' => 'bcc1@sink.sendgrid.net', 'name' => 'test_bcc1'], + ['email' => 'bcc2@sink.sendgrid.net', 'name' => 'test_bcc2'], + ], + ] + ], $result); + } - public function testSend() + public function testGetFrom() { - $message = new Message($this->getMessage()); - $message->from('from@google.com', 'test_from') - ->to('to@sink.sendgrid.net', 'test_to'); - $res = $this->transport->send($message->getSwiftMessage()); - $this->assertEquals(1, $res); + $email = (new Email()) + ->from( + (new Address('from1@sink.sendgrid.net', 'test_from1')), + ); + + $method = $this->reflection->getMethod('getFrom'); + $method->setAccessible(true); + + $result = $method->invoke($this->transport, $email); + self::assertEquals([ + 'email' => 'from1@sink.sendgrid.net', + 'name' => 'test_from1', + ], $result); } - public function testXMessageID() + public function testGetContent() { - $client = $this->getMockBuilder(\GuzzleHttp\Client::class) - ->onlyMethods(['request']) - ->getMock(); - $transport = new SendgridTransport($client, $this->api_key); + $email = (new Email()) + ->text('test body') + ->html('test body'); - $messageId = Str::random(32); - $client->expects($this->once()) - ->method('request') - ->willReturn(new \GuzzleHttp\Psr7\Response(200, [ - 'X-Message-ID' => $messageId, - ])); - $message = new Message($this->getMessage()); - $message->from('from@google.com', 'test_from') - ->to('to@sink.sendgrid.net', 'test_to'); - $transport->send($message->getSwiftMessage()); - $this->assertEquals($messageId, $message->getSwiftMessage()->getHeaders()->get('X-Sendgrid-Message-ID')->getFieldBody()); + $method = $this->reflection->getMethod('getContents'); + $method->setAccessible(true); + + $result = $method->invoke($this->transport, $email); + self::assertEquals([ + [ + 'type' => 'text/plain', + 'value' => 'test body' + ], + [ + 'type' => 'text/html', + 'value' => 'test body' + ], + ], $result); } - public function testMultipleSend() + public function testGetReplyTo() { - $message = new Message($this->getMessage()); - $message->from('from@google.com', 'test_from') - ->to('foo@sink.sendgrid.net', 'foo') - ->cc('foo2@sink.sendgrid.net', 'foo2'); - $res = $this->transport->send($message->getSwiftMessage()); + $email = (new Email()) + ->replyTo((new Address('from1@sink.sendgrid.net', 'test_from1'))); - $this->assertEquals(2, $res); + $method = $this->reflection->getMethod('getReplyTo'); + $method->setAccessible(true); - $message = new Message($this->getMessage()); - $message->from('from@google.com', 'test_from') - ->to('bar@sink.sendgrid.net', 'bar') - ->bcc('bar2@sink.sendgrid.net', 'bar2'); - $res = $this->transport->send($message->getSwiftMessage()); - - $this->assertEquals(2, $res); + $result = $method->invoke($this->transport, $email); + self::assertEquals([ + 'email' => 'from1@sink.sendgrid.net', + 'name' => 'test_from1', + ], $result); } - public function testSendByPersonalization() + public function testGetAttachments() { - $message = new Message($this->getMessage()); - $message->from('from@google.com', 'test_from') - ->to('dummy@sink.sendgrid.net') - ->embedData([ + $file = file_get_contents(__DIR__ . '/test.png'); + $email = (new Email()) + ->attach($file, 'test.png', 'image/png') + ->embed(self::sgEncode([ 'personalizations' => [ [ 'to' => [ - 'email' => 'foo@sink.sendgrid.net', - 'name' => 'foo', + 'email' => 'to1@sink.sendgrid.net', + 'name' => 'test_to1', ], ], ], - ], 'sendgrid/x-smtpapi'); - $res = $this->transport->send($message->getSwiftMessage()); + 'categories' => ['test_category'] + ]), SendgridTransport::REQUEST_BODY_PARAMETER); - $this->assertEquals(1, $res); + $method = $this->reflection->getMethod('getAttachments'); + $method->setAccessible(true); - $message = new Message($this->getMessage()); - $message->from('from@google.com', 'test_from') - ->to('dummy@sink.sendgrid.net') - ->embedData([ + $result = $method->invoke($this->transport, $email); + unset($result[0]['content_id']); + self::assertEquals([ + [ + 'content' => base64_encode($file), + 'filename' => 'test.png', + 'type' => 'image/png', + 'disposition' => null, + ] + ], $result); + } + + public function testSetParameters() + { + $email = (new Email()) + ->embed(self::sgEncode([ 'personalizations' => [ [ 'to' => [ - 'email' => 'to1@sink.sendgrid.net', - 'name' => 'to1', - ], - ], - [ - 'to' => [ - 'email' => 'to2@sink.sendgrid.net', - 'name' => 'to2', + ['email' => 'to1@sink.sendgrid.net', 'name' => 'test_to1'], + ['email' => 'to2@sink.sendgrid.net', 'name' => 'test_to2'], ], 'cc' => [ - 'email' => 'cc1@sink.sendgrid.net', - 'name' => 'cc1', - ], - ], - [ - 'to' => [ - 'email' => 'to3@sink.sendgrid.net', - 'name' => 'to3', + ['email' => 'cc1@sink.sendgrid.net', 'name' => 'test_cc1'], + ['email' => 'cc2@sink.sendgrid.net', 'name' => 'test_cc2'], ], 'bcc' => [ - 'email' => 'bcc1@sink.sendgrid.net', - 'name' => 'bcc1', + ['email' => 'bcc1@sink.sendgrid.net', 'name' => 'test_bcc1'], + ['email' => 'bcc2@sink.sendgrid.net', 'name' => 'test_bcc2'], ], ], ], - ], 'sendgrid/x-smtpapi'); - $res = $this->transport->send($message->getSwiftMessage()); - - $this->assertEquals(5, $res); - } - - public function testGetPersonalizations() - { - - - $getPersonalizations = \Closure::bind(function ($message) { - return $this->getPersonalizations($message); - }, $this->transport, SendgridTransport::class); - - $message = $this->getMessage(); - - $to = 'to_user@exsample.com'; - $to_name = 'to_user'; - $message->setTo($to, $to_name); - - $cc = 'cc_user@exsample.com'; - $cc_name = 'cc_user'; - $message->setCc($cc, $cc_name); - - $bcc = 'bcc_user@exsample.com'; - $bcc_name = 'bcc_user'; - $message->setBcc($bcc, $bcc_name); - - $res = $getPersonalizations($message); - - $this->assertEquals($to, Arr::get($res, '0.to.0.email')); - $this->assertEquals($to_name, Arr::get($res, '0.to.0.name')); - $this->assertEquals($cc, Arr::get($res, '0.cc.0.email')); - $this->assertEquals($cc_name, Arr::get($res, '0.cc.0.name')); - $this->assertEquals($bcc, Arr::get($res, '0.bcc.0.email')); - $this->assertEquals($bcc_name, Arr::get($res, '0.bcc.0.name')); - } - - public function testGetContents() - { - $getContents = \Closure::bind(function ($message) { - return $this->getContents($message); - }, $this->transport, SendgridTransport::class); - - $message = new Message($this->getMessage()); - $message->getSwiftMessage()->setChildren([new Swift_MimePart( - 'This is a test.' - )]); - - $res = $getContents($message->getSwiftMessage()); - $this->assertEquals('text/plain', Arr::get($res, '0.type')); - $this->assertEquals('This is a test.', Arr::get($res, '0.value')); - $this->assertEquals('text/html', Arr::get($res, '1.type')); - $this->assertEquals('Test body.', Arr::get($res, '1.value')); - } + 'categories' => ['test_category'] + ]), SendgridTransport::REQUEST_BODY_PARAMETER); - public function testGetAttachments() - { - $getAttachment = \Closure::bind(function ($message) { - return $this->getAttachments($message); - }, $this->transport, SendgridTransport::class); - - $message = new Message($this->getMessage()); - - $file = __DIR__ . '/test.png'; - $message->attach($file); + $method = $this->reflection->getMethod('setParameters'); + $method->setAccessible(true); - $res = $getAttachment($message->getSwiftMessage()); - $this->assertEquals(base64_encode(file_get_contents($file)), Arr::get($res, '0.content')); - $this->assertEquals('test.png', Arr::get($res, '0.filename')); - } - - public function testSetParameters() - { - $setParameters = \Closure::bind(function ($message, $data) { - return $this->setParameters($message, $data); - }, $this->transport, SendgridTransport::class); - - $parameters = [ - 'categories' => 'category1', - ]; - $message = new Message($this->getMessage()); - $message->embedData($parameters, 'sendgrid/x-smtpapi'); $data = []; - $data = $setParameters($message->getSwiftMessage(), $data); - $this->assertEquals($parameters, $data); - } - - public function testSetPersonalizations() - { - $setParameters = \Closure::bind(function ($message, $data) { - return $this->setParameters($message, $data); - }, $this->transport, SendgridTransport::class); - - $personalizations = [ - [ - 'substitutions' => [ - 'substitutions_key' => 'substitutions_value', - ], - 'custom_args' => [ - 'custom_args_key' => 'custom_args_value', + $result = $method->invoke($this->transport, $email, $data); + unset($result[0]['content_id']); + self::assertEquals([ + 'personalizations' => [ + [ + 'to' => [ + ['email' => 'to1@sink.sendgrid.net', 'name' => 'test_to1'], + ['email' => 'to2@sink.sendgrid.net', 'name' => 'test_to2'], + ], + 'cc' => [ + ['email' => 'cc1@sink.sendgrid.net', 'name' => 'test_cc1'], + ['email' => 'cc2@sink.sendgrid.net', 'name' => 'test_cc2'], + ], + 'bcc' => [ + ['email' => 'bcc1@sink.sendgrid.net', 'name' => 'test_bcc1'], + ['email' => 'bcc2@sink.sendgrid.net', 'name' => 'test_bcc2'], + ], ], - 'send_at' => time(), ], - ]; - - $message = new Message($this->getMessage()); - $message->embedData([ - 'personalizations' => $personalizations, - ], 'sendgrid/x-smtpapi'); - $data = []; - $data = $setParameters($message->getSwiftMessage(), $data); - $this->assertEquals(['personalizations' => $personalizations], $data); + 'categories' => ['test_category'] + ], $result); } - public function testGetFrom() + public function testSetParameters_with_SMTP_API_NAME() { - $getFrom = \Closure::bind(function ($message) { - return $this->getFrom($message); - }, $this->transport, SendgridTransport::class); - - $from = 'test@exsample.com'; - $from_name = 'test_user'; - - $message = $this->getMessage(); - $message->setFrom($from, $from_name); - - $this->assertEquals(['email' => $from, 'name' => $from_name], $getFrom($message)); - } - - public function testReplyTo() - { - $getReplyTo = \Closure::bind(function ($message) { - return $this->getReplyTo($message); - }, $this->transport, SendgridTransport::class); - - $reply_to = 'test@exsample.com'; - $reply_to_name = 'test_user'; - - $message = $this->getMessage(); - $message->setReplyTo($reply_to, $reply_to_name); - - $this->assertEquals(['email' => $reply_to, 'name' => $reply_to_name], $getReplyTo($message)); - } - - public function testOverrideApiKey() - { - $container = []; - $history = GuzzleHttp\Middleware::history($container); - $stack = GuzzleHttp\HandlerStack::create(); - $stack->push($history); - $client = new GuzzleHttp\Client(['handler' => $stack]); - $transport = new SendgridTransport($client, 'This is the wrong value'); - - $message = new Message($this->getMessage()); - $message->from('from@google.com', 'test_from') - ->to('to@sink.sendgrid.net', 'test_to') - ->embedData([ - 'api_key' => $this->api_key, - 'custom_args' => [ - 'custom_args_key' => 'custom_args_value', + $email = (new Email()) + ->embed(self::sgEncode([ + 'personalizations' => [ + [ + 'to' => [ + ['email' => 'to1@sink.sendgrid.net', 'name' => 'test_to1'], + ['email' => 'to2@sink.sendgrid.net', 'name' => 'test_to2'], + ], + 'cc' => [ + ['email' => 'cc1@sink.sendgrid.net', 'name' => 'test_cc1'], + ['email' => 'cc2@sink.sendgrid.net', 'name' => 'test_cc2'], + ], + 'bcc' => [ + ['email' => 'bcc1@sink.sendgrid.net', 'name' => 'test_bcc1'], + ['email' => 'bcc2@sink.sendgrid.net', 'name' => 'test_bcc2'], + ], + ], ], - ], 'sendgrid/x-smtpapi'); - $transport->send($message->getSwiftMessage()); + 'categories' => ['test_category'] + ]), SendgridTransport::SMTP_API_NAME); - /** @var \GuzzleHttp\Psr7\Request $request */ - $request = Arr::get($container, '0.request'); - $this->assertEquals('Bearer ' . $this->api_key, $request->getHeaderLine('Authorization')); - $this->assertStringNotContainsString('"api_key":', (string)$request->getBody()); - } + $method = $this->reflection->getMethod('setParameters'); + $method->setAccessible(true); - /** - * @return Swift_Message - */ - private function getMessage() - { - return new Swift_Message('Test subject', 'Test body.'); + $data = []; + $result = $method->invoke($this->transport, $email, $data); + unset($result[0]['content_id']); + self::assertEquals([ + 'personalizations' => [ + [ + 'to' => [ + ['email' => 'to1@sink.sendgrid.net', 'name' => 'test_to1'], + ['email' => 'to2@sink.sendgrid.net', 'name' => 'test_to2'], + ], + 'cc' => [ + ['email' => 'cc1@sink.sendgrid.net', 'name' => 'test_cc1'], + ['email' => 'cc2@sink.sendgrid.net', 'name' => 'test_cc2'], + ], + 'bcc' => [ + ['email' => 'bcc1@sink.sendgrid.net', 'name' => 'test_bcc1'], + ['email' => 'bcc2@sink.sendgrid.net', 'name' => 'test_bcc2'], + ], + ], + ], + 'categories' => ['test_category'] + ], $result); } -} +} \ No newline at end of file