diff --git a/src/Illuminate/Mail/Message.php b/src/Illuminate/Mail/Message.php
index b9a4eb5352ca..e3eb8e1a8d1b 100755
--- a/src/Illuminate/Mail/Message.php
+++ b/src/Illuminate/Mail/Message.php
@@ -4,7 +4,6 @@
use Illuminate\Contracts\Mail\Attachable;
use Illuminate\Support\Collection;
-use Illuminate\Support\Str;
use Illuminate\Support\Traits\ForwardsCalls;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
@@ -344,31 +343,27 @@ public function embed($file)
if ($file instanceof Attachment) {
return $file->attachWith(
function ($path) use ($file) {
- $cid = $file->as ?? Str::random();
+ $part = (new DataPart(new File($path), $file->as, $file->mime))->asInline();
- $this->message->addPart(
- (new DataPart(new File($path), $cid, $file->mime))->asInline()
- );
+ $this->message->addPart($part);
- return "cid:{$cid}";
+ return "cid:{$part->getContentId()}";
},
function ($data) use ($file) {
- $this->message->addPart(
- (new DataPart($data(), $file->as, $file->mime))->asInline()
- );
+ $part = (new DataPart($data(), $file->as, $file->mime))->asInline();
+ $this->message->addPart($part);
- return "cid:{$file->as}";
+ return "cid:{$part->getContentId()}";
}
);
}
- $cid = Str::random(10);
+ $fileObject = new File($file);
+ $part = (new DataPart($fileObject, $fileObject->getFilename()))->asInline();
- $this->message->addPart(
- (new DataPart(new File($file), $cid))->asInline()
- );
+ $this->message->addPart($part);
- return "cid:$cid";
+ return "cid:{$part->getContentId()}";
}
/**
@@ -381,11 +376,11 @@ function ($data) use ($file) {
*/
public function embedData($data, $name, $contentType = null)
{
- $this->message->addPart(
- (new DataPart($data, $name, $contentType))->asInline()
- );
+ $part = (new DataPart($data, $name, $contentType))->asInline();
+
+ $this->message->addPart($part);
- return "cid:$name";
+ return "cid:{$part->getContentId()}";
}
/**
diff --git a/tests/Integration/Mail/Fixtures/embed-image.blade.php b/tests/Integration/Mail/Fixtures/embed-image.blade.php
new file mode 100644
index 000000000000..0be2b5242fea
--- /dev/null
+++ b/tests/Integration/Mail/Fixtures/embed-image.blade.php
@@ -0,0 +1 @@
+Embedded image:
diff --git a/tests/Integration/Mail/Fixtures/embed.blade.php b/tests/Integration/Mail/Fixtures/embed.blade.php
index 4a19e330d84e..7b3839aa472d 100644
--- a/tests/Integration/Mail/Fixtures/embed.blade.php
+++ b/tests/Integration/Mail/Fixtures/embed.blade.php
@@ -1 +1,3 @@
+Embed file: {{ basename(__FILE__) }}
+
Embed content: {{ $message->embed(__FILE__) }}
diff --git a/tests/Integration/Mail/Fixtures/empty_image.jpg b/tests/Integration/Mail/Fixtures/empty_image.jpg
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/tests/Integration/Mail/SendingMarkdownMailTest.php b/tests/Integration/Mail/SendingMarkdownMailTest.php
index 712fe0b7cecb..b4d3c474815e 100644
--- a/tests/Integration/Mail/SendingMarkdownMailTest.php
+++ b/tests/Integration/Mail/SendingMarkdownMailTest.php
@@ -52,13 +52,19 @@ public function testEmbed()
$email = app('mailer')->getSymfonyTransport()->messages()[0]->getOriginalMessage()->toString();
$cid = explode(' cid:', (new Stringable($email))->explode("\r\n")
- ->filter(fn ($line) => str_contains($line, 'Embed content: cid:'))
+ ->filter(fn ($line) => str_contains($line, ' content: cid:'))
+ ->first())[1];
+
+ $filename = explode('Embed file: ', (new Stringable($email))->explode("\r\n")
+ ->filter(fn ($line) => str_contains($line, ' file:'))
->first())[1];
$this->assertStringContainsString(<<\r
EOT, $email);
}
@@ -66,9 +72,8 @@ public function testEmbedData()
{
Mail::to('test@mail.com')->send($mailable = new EmbedDataMailable());
- $mailable->assertSeeInHtml('Embed data content: cid:foo.jpg');
$mailable->assertSeeInText('Embed data content: ');
- $mailable->assertDontSeeInText('Embed data content: cid:foo.jpg');
+ $mailable->assertSeeInHtml('Embed data content: cid:');
$email = app('mailer')->getSymfonyTransport()->messages()[0]->getOriginalMessage()->toString();
@@ -87,8 +92,7 @@ public function testEmbedMultilineImage()
$this->assertStringContainsString('Embed multiline content:
assertStringContainsString('alt="multiline image"', $html);
- $this->assertStringContainsString('data:image/png;base64', $html);
- $this->assertStringNotContainsString('cid:foo.jpg', $html);
+ $this->assertStringContainsString('
tag.
+ preg_match('/
]+src="cid:([^"]+)"/', $rawEmail, $htmlMatches);
+ $htmlImageCid = $htmlMatches[1] ?? null;
+
+ // Extract CID from MIME attachment Content-ID header.
+ preg_match('/Content-ID:\s*<([^>]+)>/', $rawEmail, $headerMatches);
+ $attachmentContentId = $headerMatches[1] ?? null;
+
+ return [$htmlImageCid, $attachmentContentId];
+ }
}
class BasicMailable extends Mailable
@@ -236,6 +283,26 @@ public function content()
}
}
+class EmbedImageMailable extends Mailable
+{
+ public function envelope()
+ {
+ return new Envelope(
+ subject: 'My basic title',
+ );
+ }
+
+ public function content()
+ {
+ return new Content(
+ markdown: 'embed-image',
+ with: [
+ 'image' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'empty_image.jpg',
+ ]
+ );
+ }
+}
+
class MessageAsPublicPropertyMailable extends Mailable
{
public $message = 'My message';
diff --git a/tests/Integration/Notifications/Fixtures/markdown.blade.php b/tests/Integration/Notifications/Fixtures/markdown.blade.php
index 4a19e330d84e..6e7b0a25097d 100644
--- a/tests/Integration/Notifications/Fixtures/markdown.blade.php
+++ b/tests/Integration/Notifications/Fixtures/markdown.blade.php
@@ -1 +1,2 @@
+Embed file: {{ basename(__FILE__) }}
Embed content: {{ $message->embed(__FILE__) }}
diff --git a/tests/Integration/Notifications/SendingMailableNotificationsTest.php b/tests/Integration/Notifications/SendingMailableNotificationsTest.php
index dd0f44a00186..f1307006a349 100644
--- a/tests/Integration/Notifications/SendingMailableNotificationsTest.php
+++ b/tests/Integration/Notifications/SendingMailableNotificationsTest.php
@@ -49,16 +49,24 @@ public function testMarkdownNotification()
$user->notify(new MarkdownNotification());
- $email = app('mailer')->getSymfonyTransport()->messages()[0]->getOriginalMessage()->toString();
+ $message = app('mailer')->getSymfonyTransport()->messages()[0]->getOriginalMessage();
+ $email = $message->toString();
+ $textBody = $message->getTextBody();
- $cid = explode(' cid:', (new Stringable($email))->explode("\r\n")
+ $cid = explode(' cid:', (new Stringable($textBody))->explode("\n")
->filter(fn ($line) => str_contains($line, 'Embed content: cid:'))
->first())[1];
+ $filename = explode(' file: ', (new Stringable($textBody))->explode("\n")
+ ->filter(fn ($line) => str_contains($line, 'Embed file: '))
+ ->first())[1];
+
$this->assertStringContainsString(<<\r
EOT, $email);
}
diff --git a/tests/Mail/MailMessageTest.php b/tests/Mail/MailMessageTest.php
index 330777cd674a..eff028ddadfe 100755
--- a/tests/Mail/MailMessageTest.php
+++ b/tests/Mail/MailMessageTest.php
@@ -165,13 +165,14 @@ public function testEmbedPath(): void
$cid = $this->message->embed($path);
$this->assertStringStartsWith('cid:', $cid);
- $name = Str::after($cid, 'cid:');
+ $contentId = Str::after($cid, 'cid:');
$attachment = $this->message->getSymfonyMessage()->getAttachments()[0];
$headers = $attachment->getPreparedHeaders()->toArray();
$this->assertSame('bar', $attachment->getBody());
- $this->assertSame("Content-Type: image/jpeg; name={$name}", $headers[0]);
+ $this->assertSame($contentId, $attachment->getContentId());
+ $this->assertStringContainsString('Content-Type: image/jpeg', $headers[0]);
$this->assertSame('Content-Transfer-Encoding: base64', $headers[1]);
- $this->assertSame("Content-Disposition: inline; name={$name}; filename={$name}", $headers[2]);
+ $this->assertStringContainsString('Content-Disposition: inline', $headers[2]);
unlink($path);
}
@@ -182,7 +183,9 @@ public function testDataEmbed(): void
$attachment = $this->message->getSymfonyMessage()->getAttachments()[0];
$headers = $attachment->getPreparedHeaders()->toArray();
- $this->assertSame('cid:foo.jpg', $cid);
+ $this->assertStringStartsWith('cid:', $cid);
+ $contentId = Str::after($cid, 'cid:');
+ $this->assertSame($contentId, $attachment->getContentId());
$this->assertSame('bar', $attachment->getBody());
$this->assertSame('Content-Type: image/png; name=foo.jpg', $headers[0]);
$this->assertSame('Content-Transfer-Encoding: base64', $headers[1]);
@@ -201,9 +204,11 @@ public function toMailAttachment()
}
});
- $this->assertSame('cid:baz', $cid);
+ $this->assertStringStartsWith('cid:', $cid);
+ $contentId = Str::after($cid, 'cid:');
$attachment = $this->message->getSymfonyMessage()->getAttachments()[0];
$headers = $attachment->getPreparedHeaders()->toArray();
+ $this->assertSame($contentId, $attachment->getContentId());
$this->assertSame('bar', $attachment->getBody());
$this->assertSame('Content-Type: image/png; name=baz', $headers[0]);
$this->assertSame('Content-Transfer-Encoding: base64', $headers[1]);
@@ -225,14 +230,14 @@ public function toMailAttachment()
});
$this->assertStringStartsWith('cid:', $cid);
- $name = Str::after($cid, 'cid:');
- $this->assertSame(16, mb_strlen($name));
+ $contentId = Str::after($cid, 'cid:');
$attachment = $this->message->getSymfonyMessage()->getAttachments()[0];
+ $this->assertSame($contentId, $attachment->getContentId());
$headers = $attachment->getPreparedHeaders()->toArray();
$this->assertSame('bar', $attachment->getBody());
- $this->assertSame("Content-Type: image/jpeg; name={$name}", $headers[0]);
+ $this->assertStringContainsString('Content-Type: image/jpeg', $headers[0]);
$this->assertSame('Content-Transfer-Encoding: base64', $headers[1]);
- $this->assertSame("Content-Disposition: inline; name={$name};\r\n filename={$name}", $headers[2]);
+ $this->assertStringContainsString('Content-Disposition: inline', $headers[2]);
unlink($path);
}