From 9b077395ff8bc2a84ad59e97a4542b99240b9bb0 Mon Sep 17 00:00:00 2001 From: Bjarn Bronsveld Date: Tue, 7 Oct 2025 21:26:57 +0200 Subject: [PATCH] feat: add inline attachment support to EmailEndpoint Introduced optional `contentId` for inline email attachments, enabling embedding images or files directly in HTML emails. Updated tests to validate the new functionality, ensuring correct handling of `contentId`. Enhanced the README with examples demonstrating usage of inline attachments. --- README.md | 15 ++++++++++++++ src/Endpoints/EmailEndpoint.php | 11 +++++++++-- tests/Endpoints/EmailEndpointTest.php | 28 +++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 009d554..65306ee 100644 --- a/README.md +++ b/README.md @@ -56,11 +56,26 @@ $lettermint->email ->text('Hello!') ->headers(['X-Custom-Header' => 'Value']) ->attach('document.pdf', base64_encode($fileContent)) + ->attach('logo.png', base64_encode($logoContent), 'logo@example.com') ->route('my-route-id') ->idempotencyKey('unique-request-id-123') ->send(); ``` +#### Inline Attachments + +You can embed images and other content in your HTML emails using content IDs: + +```php +$lettermint->email + ->from('sender@example.com') + ->to('recipient@example.com') + ->subject('Email with inline image') + ->html('

Here is an image:

') + ->attach('logo.png', base64_encode($imageContent), 'logo@example.com') + ->send(); +``` + ### Idempotency To ensure that duplicate requests are not processed, you can use an idempotency key: diff --git a/src/Endpoints/EmailEndpoint.php b/src/Endpoints/EmailEndpoint.php index 53af4d0..966bd56 100644 --- a/src/Endpoints/EmailEndpoint.php +++ b/src/Endpoints/EmailEndpoint.php @@ -134,14 +134,21 @@ public function replyTo(string ...$emails): self * * @param string $filename The attachment filename. * @param string $base64Content The base64-encoded file content. + * @param string|null $contentId Optional content ID for inline attachments. */ - public function attach(string $filename, string $base64Content): self + public function attach(string $filename, string $base64Content, ?string $contentId = null): self { - $this->payload['attachments'][] = [ + $attachment = [ 'filename' => $filename, 'content' => $base64Content, ]; + if ($contentId !== null) { + $attachment['content_id'] = $contentId; + } + + $this->payload['attachments'][] = $attachment; + return $this; } diff --git a/tests/Endpoints/EmailEndpointTest.php b/tests/Endpoints/EmailEndpointTest.php index 92f83a4..ace7eca 100644 --- a/tests/Endpoints/EmailEndpointTest.php +++ b/tests/Endpoints/EmailEndpointTest.php @@ -157,6 +157,34 @@ ->send(); }); +test('it handles attachments with content_id', function () { + $attachment = [ + 'filename' => 'logo.png', + 'content' => 'base64encodedimage', + 'content_id' => 'logo@example.com', + ]; + + $this->httpClient + ->shouldReceive('post') + ->once() + ->with('/v1/send', [ + 'from' => 'sender@example.com', + 'to' => ['recipient@example.com'], + 'subject' => 'Test Subject', + 'html' => '', + 'attachments' => [$attachment], + ], []) + ->andReturn(['message_id' => '123', 'status' => 'pending']); + + $this->endpoint + ->from('sender@example.com') + ->to('recipient@example.com') + ->subject('Test Subject') + ->html('') + ->attach('logo.png', 'base64encodedimage', 'logo@example.com') + ->send(); +}); + test('it handles custom headers', function () { $this->httpClient ->shouldReceive('post')