├── .github ├── CODEOWNERS └── workflows │ └── php.yml ├── renovate.json ├── .gitignore ├── config └── mailersend-driver.php ├── .editorconfig ├── phpunit.xml.dist ├── tests ├── TestCase.php └── MailerSendTransportTest.php ├── LICENSE.md ├── src ├── LaravelDriverServiceProvider.php ├── MailerSendTrait.php └── MailerSendTransport.php ├── composer.json └── README.md /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @mailersend/php-sdk-maintainers 2 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["github>mailerlite/renovate-config:base"] 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | composer.phar 2 | composer.lock 3 | vendor 4 | .idea 5 | .phpunit.result.cache 6 | -------------------------------------------------------------------------------- /config/mailersend-driver.php: -------------------------------------------------------------------------------- 1 | env('MAILERSEND_API_KEY'), 5 | 'host' => env('MAILERSEND_API_HOST', 'api.mailersend.com'), 6 | 'protocol' => env('MAILERSEND_API_PROTO', 'https'), 7 | 'api_path' => env('MAILERSEND_API_PATH', 'v1'), 8 | ]; -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | ; This file is for unifying the coding style for different editors and IDEs. 2 | ; More information at http://editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | indent_size = 4 9 | indent_style = space 10 | end_of_line = lf 11 | insert_final_newline = true 12 | trim_trailing_whitespace = true 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | tests 15 | 16 | 17 | 18 | 19 | src/ 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /.github/workflows/php.yml: -------------------------------------------------------------------------------- 1 | name: PHP Composer 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | run: 11 | 12 | runs-on: ubuntu-latest 13 | strategy: 14 | matrix: 15 | operating-system: [ubuntu-latest] 16 | php-versions: ['8.0', '8.1', '8.4'] 17 | name: PHP ${{ matrix.php-versions }} Test on ${{ matrix.operating-system }} 18 | 19 | steps: 20 | - uses: actions/checkout@v5 21 | 22 | - name: Setup PHP 23 | uses: shivammathur/setup-php@v2 24 | with: 25 | php-version: ${{ matrix.php-versions }} 26 | extensions: mbstring, pdo, pdo_mysql, intl, zip 27 | coverage: none 28 | - name: Install dependencies 29 | run: composer install --prefer-dist --no-progress --no-suggest 30 | 31 | - name: Run test suite 32 | run: composer run-script test 33 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | getMessage()); 25 | } 26 | 27 | $method = $reflection->getMethod($method); 28 | $method->setAccessible(true); 29 | 30 | return $method->invokeArgs($object, $parameters); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 MailerSend 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /src/LaravelDriverServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->make(MailManager::class)->extend('mailersend', function (array $config) { 15 | $config = array_merge($this->app['config']->get('mailersend-driver', []), $config); 16 | 17 | $mailersend = new MailerSend([ 18 | 'api_key' => Arr::get($config, 'api_key'), 19 | 'host' => Arr::get($config, 'host'), 20 | 'protocol' => Arr::get($config, 'protocol'), 21 | 'api_path' => Arr::get($config, 'api_path'), 22 | ]); 23 | 24 | return new MailerSendTransport($mailersend); 25 | }); 26 | 27 | if ($this->app->runningInConsole()) { 28 | $this->publishes([ 29 | __DIR__.'/../config/config.php' => config_path('laravel-driver.php'), 30 | ], 'config'); 31 | } 32 | } 33 | 34 | public function register() 35 | { 36 | $this->mergeConfigFrom(__DIR__.'/../config/mailersend-driver.php', 'mailersend-driver'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mailersend/laravel-driver", 3 | "description": "MailerSend Laravel Driver", 4 | "keywords": [ 5 | "MailerSend", 6 | "mailersend", 7 | "email", 8 | "transactional", 9 | "laravel-driver" 10 | ], 11 | "homepage": "https://github.com/mailersend/mailersend-laravel-driver", 12 | "license": "MIT", 13 | "type": "library", 14 | "authors": [ 15 | { 16 | "name": "Tautvydas Tijūnaitis", 17 | "email": "tautvydas@mailersend.com", 18 | "homepage": "https://mailersend.com", 19 | "role": "Developer" 20 | } 21 | ], 22 | "require": { 23 | "php": ">=8.0", 24 | "ext-json": "*", 25 | "illuminate/support": "^9.0 || ^10.0 || ^11.0 || ^12.0", 26 | "mailersend/mailersend": "^0.35.0", 27 | "nyholm/psr7": "^1.5", 28 | "php-http/guzzle7-adapter": "^1.0", 29 | "symfony/mailer": "^6.0 || ^7.0" 30 | }, 31 | "require-dev": { 32 | "phpunit/phpunit": "^9.0 || ^10.5 || ^12.0", 33 | "orchestra/testbench": "^7.0 || ^9.0 || ^10.0" 34 | }, 35 | "autoload": { 36 | "psr-4": { 37 | "MailerSend\\LaravelDriver\\": "src" 38 | } 39 | }, 40 | "autoload-dev": { 41 | "psr-4": { 42 | "MailerSend\\LaravelDriver\\Tests\\": "tests" 43 | } 44 | }, 45 | "scripts": { 46 | "test": "vendor/bin/phpunit" 47 | }, 48 | "config": { 49 | "sort-packages": true, 50 | "allow-plugins": { 51 | "php-http/discovery": false 52 | } 53 | }, 54 | "extra": { 55 | "laravel": { 56 | "providers": [ 57 | "MailerSend\\LaravelDriver\\LaravelDriverServiceProvider" 58 | ], 59 | "aliases": { 60 | "LaravelDriver": "MailerSend\\LaravelDriver\\LaravelDriverFacade" 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/MailerSendTrait.php: -------------------------------------------------------------------------------- 1 | driver() === 'mailersend') { 21 | $this->withSymfonyMessage(function (Email $message) use ( 22 | $tags, 23 | $template_id, 24 | $personalization, 25 | $sendAt, 26 | $precedenceBulkHeader 27 | ) { 28 | $mailersendData = []; 29 | 30 | Arr::set($mailersendData, MailerSendTransport::MAILERSEND_DATA_TEMPLATE_ID, $template_id); 31 | Arr::set($mailersendData, MailerSendTransport::MAILERSEND_DATA_TAGS, $tags); 32 | Arr::set($mailersendData, MailerSendTransport::MAILERSEND_DATA_PERSONALIZATION, $personalization); 33 | Arr::set($mailersendData, MailerSendTransport::MAILERSEND_DATA_PRECENDECE_BULK_HEADER, $precedenceBulkHeader); 34 | Arr::set($mailersendData, MailerSendTransport::MAILERSEND_DATA_SEND_AT, $sendAt?->timestamp); 35 | 36 | $message->addPart(new DataPart( 37 | json_encode($mailersendData, JSON_THROW_ON_ERROR), 38 | MailerSendTransport::MAILERSEND_DATA_SUBTYPE.'.json', 39 | MailerSendTransport::MAILERSEND_DATA_TYPE.'/'.MailerSendTransport::MAILERSEND_DATA_SUBTYPE 40 | )); 41 | }); 42 | 43 | if ($template_id !== null) { 44 | $this->html(''); 45 | } 46 | } 47 | 48 | return $this; 49 | } 50 | 51 | protected function driver(): string 52 | { 53 | return function_exists('config') ? config('mail.default') : env('MAIL_MAILER'); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /tests/MailerSendTransportTest.php: -------------------------------------------------------------------------------- 1 | mailersend = new MailerSend([ 26 | 'api_key' => 'key', 27 | 'host' => '', 28 | 'protocol' => '', 29 | 'api_path' => '', 30 | ]); 31 | 32 | 33 | $this->transport = new MailerSendTransport($this->mailersend); 34 | } 35 | 36 | public function test_basic_message_is_sent(): void 37 | { 38 | $response = [ 39 | 'response' => $this->mock(ResponseInterface::class, function (MockInterface $mock) { 40 | $mock->expects('getHeaderLine')->withArgs(['X-Message-Id'])->andReturn('messageId'); 41 | 42 | $stream = $this->mock(StreamInterface::class, function (MockInterface $mock) { 43 | $mock->expects('getContents')->withNoArgs()->andReturn('{"json":"value"}'); 44 | }); 45 | 46 | $mock->expects('getBody')->withNoArgs()->andReturn($stream); 47 | }), 48 | ]; 49 | 50 | $emailParams = $this->partialMock(EmailParams::class, function (MockInterface $mock) { 51 | $mock->expects('setFrom')->withArgs(['test@mailersend.com'])->andReturnSelf(); 52 | $mock->expects('setFromName')->withArgs(['John Doe'])->andReturnSelf(); 53 | $mock->expects('setRecipients')->withAnyArgs()->andReturnSelf(); 54 | $mock->expects('setSubject')->withArgs(['Subject'])->andReturnSelf(); 55 | $mock->expects('setText')->withArgs(['Here is the text message'])->andReturnSelf(); 56 | }); 57 | 58 | /** @noinspection PhpFieldAssignmentTypeMismatchInspection */ 59 | $this->mailersend->email = $this->mock(Email::class, 60 | function (MockInterface $mock) use ($emailParams, $response) { 61 | $mock->allows('send')->withArgs([$emailParams])->andReturn($response); 62 | }); 63 | 64 | $message = (new \Symfony\Component\Mime\Email()) 65 | ->subject('Subject') 66 | ->from('John Doe ') 67 | ->to('test-receive@mailersend.com') 68 | ->text('Here is the text message'); 69 | 70 | $transport = new MailerSendTransport($this->mailersend); 71 | $sentMessage = $transport->send($message, Envelope::create($message)); 72 | 73 | self::assertNotNull($sentMessage); 74 | 75 | $sentMessageString = $sentMessage->getMessage()->toString(); 76 | 77 | self::assertStringContainsString('X-MailerSend-Message-Id: messageId', $sentMessageString); 78 | self::assertStringContainsString('X-MailerSend-Body: {"json":"value"}', $sentMessageString); 79 | } 80 | 81 | public function test_get_from(): void 82 | { 83 | $message = (new \Symfony\Component\Mime\Email()) 84 | ->from('John Doe '); 85 | 86 | $getFrom = $this->callMethod($this->transport, 'getFrom', [$message]); 87 | 88 | self::assertEquals(['email' => 'test@mailersend.com', 'name' => 'John Doe'], $getFrom); 89 | } 90 | 91 | public function test_get_reply_to(): void 92 | { 93 | $message = (new \Symfony\Component\Mime\Email()) 94 | ->replyTo('John Doe '); 95 | 96 | $getReplyTo = $this->callMethod($this->transport, 'getReplyTo', [$message]); 97 | 98 | self::assertEquals(['email' => 'test@mailersend.com', 'name' => 'John Doe'], $getReplyTo); 99 | } 100 | 101 | public function test_get_recipients(): void 102 | { 103 | $message = (new \Symfony\Component\Mime\Email()) 104 | ->to('test-receive@mailersend.com'); 105 | 106 | $getTo = $this->callMethod($this->transport, 'getRecipients', ['to', $message]); 107 | 108 | self::assertEquals('test-receive@mailersend.com', Arr::get(reset($getTo)->toArray(), 109 | 'email')); 110 | } 111 | 112 | public function test_get_attachments(): void 113 | { 114 | $attachment = new DataPart('data', 'filename', 'image/jpeg'); 115 | 116 | if (method_exists(new \Symfony\Component\Mime\Email(), 'attachPart')) { 117 | $message = (new \Symfony\Component\Mime\Email()) 118 | ->attachPart($attachment); 119 | } else { 120 | $message = (new \Symfony\Component\Mime\Email()) 121 | ->addPart($attachment); 122 | } 123 | 124 | $getAttachments = $this->callMethod($this->transport, 'getAttachments', [$message]); 125 | 126 | $attachmentResult = reset($getAttachments)->toArray(); 127 | 128 | self::assertEquals('data', Arr::get($attachmentResult, 129 | 'content')); 130 | self::assertEquals('filename', Arr::get($attachmentResult, 131 | 'filename')); 132 | self::assertEquals('attachment', Arr::get($attachmentResult, 133 | 'disposition')); 134 | } 135 | 136 | public function test_get_additional_data(): void 137 | { 138 | if (method_exists(new \Symfony\Component\Mime\Email(), 'attachPart')) { 139 | $message = (new \Symfony\Component\Mime\Email()) 140 | ->attachPart(new DataPart( 141 | json_encode([ 142 | 'template_id' => 'id' 143 | ], JSON_THROW_ON_ERROR), 144 | MailerSendTransport::MAILERSEND_DATA_SUBTYPE.'.json', 145 | MailerSendTransport::MAILERSEND_DATA_TYPE.'/'.MailerSendTransport::MAILERSEND_DATA_SUBTYPE 146 | )); 147 | } else { 148 | $message = (new \Symfony\Component\Mime\Email()) 149 | ->addPart(new DataPart( 150 | json_encode([ 151 | 'template_id' => 'id' 152 | ], JSON_THROW_ON_ERROR), 153 | MailerSendTransport::MAILERSEND_DATA_SUBTYPE.'.json', 154 | MailerSendTransport::MAILERSEND_DATA_TYPE.'/'.MailerSendTransport::MAILERSEND_DATA_SUBTYPE 155 | )); 156 | } 157 | 158 | 159 | $getAdditionalData = $this->callMethod($this->transport, 'getAdditionalData', [$message]); 160 | 161 | self::assertEquals('id', Arr::get($getAdditionalData, 162 | 'template_id')); 163 | self::assertEquals([], Arr::get($getAdditionalData, 164 | 'tags')); 165 | self::assertEquals([], Arr::get($getAdditionalData, 166 | 'personalization')); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | MailerSend Laravel Driver 4 | 5 | [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE.md) 6 | 7 | # Table of Contents 8 | 9 | * [Installation](#installation) 10 | * [Usage](#usage) 11 | * [Support and Feedback](#support-and-feedback) 12 | * [License](#license) 13 | 14 | 15 | # Installation 16 | 17 | ## Requirements 18 | 19 | - Laravel 9.0+ 20 | - PHP 8.0+ 21 | - Guzzle 7.0+ 22 | - An API Key from [mailersend.com](https://www.mailersend.com) 23 | 24 | **For Laravel 7.x - 8.x support see [1.x branch](https://github.com/mailersend/mailersend-laravel-driver/tree/1.x)** 25 | 26 | ## Setup 27 | 28 | You can install the package via composer: 29 | 30 | ```bash 31 | composer require mailersend/laravel-driver 32 | ``` 33 | 34 | After that, you need to set `MAILERSEND_API_KEY` in your `.env` file: 35 | 36 | ```dotenv 37 | MAILERSEND_API_KEY= 38 | ``` 39 | 40 | Add MailerSend as a Laravel Mailer in `config/mail.php` in `mailers` array: 41 | 42 | ```php 43 | 'mailersend' => [ 44 | 'transport' => 'mailersend', 45 | ], 46 | ``` 47 | 48 | And set environment variable `MAIL_MAILER` in your `.env` file 49 | 50 | ```dotenv 51 | MAIL_MAILER=mailersend 52 | ``` 53 | 54 | Also, double check that your `FROM` data is filled in `.env`: 55 | 56 | ```dotenv 57 | MAIL_FROM_ADDRESS=app@yourdomain.com 58 | MAIL_FROM_NAME="App Name" 59 | ``` 60 | 61 | 62 | # Usage 63 | 64 | ### Old Syntax: 65 | This is an example using the build [mailable](https://laravel.com/docs/8.x/mail#writing-mailables) that you can use to send an email with. 66 | 67 | `app/Mail/TestEmail.php` 68 | 69 | ```php 70 | namespace App\Mail; 71 | 72 | use Illuminate\Bus\Queueable; 73 | use Illuminate\Mail\Mailable; 74 | use Illuminate\Queue\SerializesModels; 75 | use Illuminate\Support\Arr; 76 | use MailerSend\Helpers\Builder\Variable; 77 | use MailerSend\Helpers\Builder\Personalization; 78 | use MailerSend\LaravelDriver\MailerSendTrait; 79 | 80 | class TestEmail extends Mailable 81 | { 82 | use Queueable, SerializesModels, MailerSendTrait; 83 | 84 | public function build() 85 | { 86 | // Recipient for use with variables and/or personalization 87 | $to = Arr::get($this->to, '0.address'); 88 | 89 | return $this 90 | ->view('emails.test_html') 91 | ->text('emails.test_text') 92 | ->attachFromStorageDisk('public', 'example.png') 93 | // Additional options for MailerSend API features 94 | ->mailersend( 95 | template_id: null, 96 | tags: ['tag'], 97 | personalization: [ 98 | new Personalization($to, [ 99 | 'var' => 'variable', 100 | 'number' => 123, 101 | 'object' => [ 102 | 'key' => 'object-value' 103 | ], 104 | 'objectCollection' => [ 105 | [ 106 | 'name' => 'John' 107 | ], 108 | [ 109 | 'name' => 'Patrick' 110 | ] 111 | ], 112 | ]) 113 | ], 114 | precedenceBulkHeader: true, 115 | sendAt: new Carbon('2022-01-28 11:53:20'), 116 | ); 117 | } 118 | } 119 | ``` 120 | 121 | ### New Syntax: 122 | This is an example using the new [mailable](https://laravel.com/docs/9.x/mail#writing-mailables) syntax that you can use to send an email with. 123 | 124 | `app/Mail/TestEmail.php` 125 | 126 | ```php 127 | to, '0.address'); 171 | 172 | // Additional options for MailerSend API features 173 | $this->mailersend( 174 | template_id: null, 175 | tags: ['tag'], 176 | personalization: [ 177 | new Personalization($to, [ 178 | 'var' => 'variable', 179 | 'number' => 123, 180 | 'object' => [ 181 | 'key' => 'object-value' 182 | ], 183 | 'objectCollection' => [ 184 | [ 185 | 'name' => 'John' 186 | ], 187 | [ 188 | 'name' => 'Patrick' 189 | ] 190 | ], 191 | ]) 192 | ], 193 | precedenceBulkHeader: true, 194 | sendAt: new Carbon('2022-01-28 11:53:20'), 195 | ); 196 | 197 | return new Content( 198 | view: 'emails.test_html', 199 | text: 'emails.test_text' 200 | ); 201 | } 202 | 203 | /** 204 | * Get the attachments for the message. 205 | * 206 | * @return array 207 | */ 208 | public function attachments(): array 209 | { 210 | return [ 211 | Attachment::fromStorageDisk('public', 'example.png') 212 | ]; 213 | } 214 | } 215 | ``` 216 | 217 | We provide a `MailerSendTrait` trait that adds a `mailersend` method to the mailable and allows you to use additional options that are available through our API. 218 | 219 | After creating the mailable, you can send it using: 220 | 221 | ```php 222 | use App\Mail\TestEmail; 223 | use Illuminate\Support\Facades\Mail; 224 | 225 | Mail::to('recipient@domain.com') 226 | ->cc('cc@domain.com') 227 | ->bcc('bcc@domain.com') 228 | ->send(new TestEmail()); 229 | ``` 230 | 231 | Please refer to [Laravel Mail documenation](https://laravel.com/docs/9.x/mail) and [MailerSend API documentation](https://developers.mailersend.com) for more information. 232 | 233 | 234 | # Support and Feedback 235 | 236 | In case you find any bugs, submit an issue directly here in GitHub. 237 | 238 | If you have any troubles using our driver, feel free to contact our support by email [info@mailersend.com](mailto:info@mailersend.com) 239 | 240 | Official API documentation is at [https://developers.mailersend.com](https://developers.mailersend.com) 241 | 242 | 243 | # License 244 | 245 | [The MIT License (MIT)](LICENSE.md) 246 | -------------------------------------------------------------------------------- /src/MailerSendTransport.php: -------------------------------------------------------------------------------- 1 | mailersend = $mailersend; 36 | } 37 | 38 | /** 39 | * @throws \Assert\AssertionFailedException 40 | * @throws \JsonException 41 | * @throws \Psr\Http\Client\ClientExceptionInterface 42 | * @throws TransportExceptionInterface 43 | * @throws \MailerSend\Exceptions\MailerSendAssertException 44 | */ 45 | public function send(RawMessage $message, ?Envelope $envelope = null): ?SentMessage 46 | { 47 | try{ 48 | ['email' => $fromEmail, 'name' => $fromName] = $this->getFrom($message); 49 | ['email' => $replyToEmail, 'name' => $replyToName] = $this->getReplyTo($message); 50 | 51 | $text = $message->getTextBody(); 52 | $html = $message->getHtmlBody(); 53 | 54 | $to = $this->getRecipients('to', $message); 55 | $cc = $this->getRecipients('cc', $message); 56 | $bcc = $this->getRecipients('bcc', $message); 57 | 58 | $subject = $message->getSubject(); 59 | 60 | $attachments = $this->getAttachments($message); 61 | 62 | [ 63 | 'template_id' => $template_id, 64 | 'tags' => $tags, 65 | 'personalization' => $personalization, 66 | 'precedence_bulk_header' => $precedenceBulkHeader, 67 | 'send_at' => $sendAt, 68 | ] = $this->getAdditionalData($message); 69 | 70 | $emailParams = app(EmailParams::class) 71 | ->setFrom($fromEmail) 72 | ->setFromName($fromName) 73 | ->setReplyTo($replyToEmail) 74 | ->setReplyToName(strval($replyToName)) 75 | ->setRecipients($to) 76 | ->setCc($cc) 77 | ->setBcc($bcc) 78 | ->setSubject($subject) 79 | ->setHtml($html) 80 | ->setText($text) 81 | ->setTemplateId($template_id) 82 | ->setPersonalization($personalization) 83 | ->setAttachments($attachments) 84 | ->setTags($tags) 85 | ->setPrecedenceBulkHeader($precedenceBulkHeader) 86 | ->setSendAt($sendAt); 87 | 88 | $listUnsubscribeHeader = $message->getHeaders()->get('List-Unsubscribe'); 89 | $listUnsubscribe = $listUnsubscribeHeader ? $listUnsubscribeHeader->getBodyAsString() : null; 90 | if (!empty($listUnsubscribe)) { 91 | $emailParams->setListUnsubscribe($listUnsubscribe); 92 | } 93 | 94 | $response = $this->mailersend->email->send($emailParams); 95 | 96 | /** @var ResponseInterface $respInterface */ 97 | $respInterface = $response['response']; 98 | 99 | if ($messageId = $respInterface->getHeaderLine('X-Message-Id')) { 100 | $message->getHeaders()?->addTextHeader('X-MailerSend-Message-Id', $messageId); 101 | } 102 | 103 | if ($body = $respInterface->getBody()->getContents()) { 104 | $message->getHeaders()?->addTextHeader('X-MailerSend-Body', $body); 105 | } 106 | 107 | return new SentMessage($message, $envelope); 108 | }catch (MailerSendHttpException $exception){ 109 | throw new TransportException($exception->getMessage(), $exception->getCode()); 110 | } 111 | } 112 | 113 | protected function getFrom(RawMessage $message): array 114 | { 115 | $from = $message->getFrom(); 116 | 117 | if (count($from) > 0) { 118 | return ['name' => $from[0]->getName(), 'email' => $from[0]->getAddress()]; 119 | } 120 | 121 | return ['email' => '', 'name' => '']; 122 | } 123 | 124 | protected function getReplyTo(RawMessage $message): array 125 | { 126 | $from = $message->getReplyTo(); 127 | 128 | if (count($from) > 0) { 129 | return ['name' => $from[0]->getName(), 'email' => $from[0]->getAddress()]; 130 | } 131 | 132 | return ['email' => '', 'name' => '']; 133 | } 134 | 135 | /** 136 | * @throws \MailerSend\Exceptions\MailerSendAssertException 137 | */ 138 | protected function getRecipients(string $type, RawMessage $message): array 139 | { 140 | $recipients = []; 141 | 142 | if ($addresses = $message->{'get'.ucfirst($type)}()) { 143 | foreach ($addresses as $address) { 144 | $recipients[] = new Recipient($address->getAddress(), $address->getName()); 145 | } 146 | } 147 | 148 | return $recipients; 149 | } 150 | 151 | protected function getAttachments(RawMessage $message): array 152 | { 153 | $attachments = []; 154 | 155 | foreach ($message->getAttachments() as $attachment) { 156 | /** @var DataPart $attachment */ 157 | 158 | if ($attachment->getMediaSubtype() === self::MAILERSEND_DATA_SUBTYPE) { 159 | continue; 160 | } 161 | 162 | $attachments[] = new Attachment( 163 | $attachment->getBody(), 164 | $attachment->getPreparedHeaders()->get('content-disposition')?->getParameter('filename'), 165 | $attachment->getPreparedHeaders()->get('content-disposition')?->getBody(), 166 | $attachment->getPreparedHeaders()->get('content-id')?->getBodyAsString() 167 | ); 168 | } 169 | 170 | return $attachments; 171 | } 172 | 173 | /** 174 | * @param RawMessage $message 175 | * @param array $payload 176 | * @throws \JsonException 177 | */ 178 | protected function getAdditionalData(RawMessage $message): array 179 | { 180 | $defaultValues = [ 181 | 'template_id' => null, 182 | 'personalization' => [], 183 | 'tags' => [], 184 | 'precedence_bulk_header' => null, 185 | 'send_at' => null, 186 | ]; 187 | 188 | foreach ($message->getAttachments() as $attachment) { 189 | /** @var DataPart $attachment */ 190 | 191 | if ($attachment->getMediaSubtype() !== self::MAILERSEND_DATA_SUBTYPE) { 192 | continue; 193 | } 194 | 195 | return array_merge($defaultValues, 196 | json_decode($attachment->getBody(), true, 512, JSON_THROW_ON_ERROR)); 197 | } 198 | 199 | return $defaultValues; 200 | } 201 | 202 | public function __toString(): string 203 | { 204 | return 'mailersend'; 205 | } 206 | } 207 | --------------------------------------------------------------------------------