Skip to content

Commit c1a5c50

Browse files
committed
Fix DataPart API misuse in email embed methods - second parameter is filename, not cid
1 parent ddc3977 commit c1a5c50

File tree

6 files changed

+54
-39
lines changed

6 files changed

+54
-39
lines changed

src/Illuminate/Mail/Message.php

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
use Illuminate\Contracts\Mail\Attachable;
66
use Illuminate\Support\Collection;
7-
use Illuminate\Support\Str;
87
use Illuminate\Support\Traits\ForwardsCalls;
98
use Symfony\Component\Mime\Address;
109
use Symfony\Component\Mime\Email;
@@ -344,31 +343,27 @@ public function embed($file)
344343
if ($file instanceof Attachment) {
345344
return $file->attachWith(
346345
function ($path) use ($file) {
347-
$cid = $file->as ?? Str::random();
346+
$part = (new DataPart(new File($path), $file->as, $file->mime))->asInline();
348347

349-
$this->message->addPart(
350-
(new DataPart(new File($path), $cid, $file->mime))->asInline()
351-
);
348+
$this->message->addPart($part);
352349

353-
return "cid:{$cid}";
350+
return "cid:{$part->getContentId()}";
354351
},
355352
function ($data) use ($file) {
356-
$this->message->addPart(
357-
(new DataPart($data(), $file->as, $file->mime))->asInline()
358-
);
353+
$part = (new DataPart($data(), $file->as, $file->mime))->asInline();
354+
$this->message->addPart($part);
359355

360-
return "cid:{$file->as}";
356+
return "cid:{$part->getContentId()}";
361357
}
362358
);
363359
}
364360

365-
$cid = Str::random(10);
361+
$fileObject = new File($file);
362+
$part = (new DataPart($fileObject, $fileObject->getFilename()))->asInline();
366363

367-
$this->message->addPart(
368-
(new DataPart(new File($file), $cid))->asInline()
369-
);
364+
$this->message->addPart($part);
370365

371-
return "cid:$cid";
366+
return "cid:{$part->getContentId()}";
372367
}
373368

374369
/**
@@ -381,11 +376,11 @@ function ($data) use ($file) {
381376
*/
382377
public function embedData($data, $name, $contentType = null)
383378
{
384-
$this->message->addPart(
385-
(new DataPart($data, $name, $contentType))->asInline()
386-
);
379+
$part = (new DataPart($data, $name, $contentType))->asInline();
380+
381+
$this->message->addPart($part);
387382

388-
return "cid:$name";
383+
return "cid:{$part->getContentId()}";
389384
}
390385

391386
/**
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
Embed file: {{ basename(__FILE__) }}
2+
13
Embed content: {{ $message->embed(__FILE__) }}

tests/Integration/Mail/SendingMarkdownMailTest.php

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,23 +52,28 @@ public function testEmbed()
5252
$email = app('mailer')->getSymfonyTransport()->messages()[0]->getOriginalMessage()->toString();
5353

5454
$cid = explode(' cid:', (new Stringable($email))->explode("\r\n")
55-
->filter(fn ($line) => str_contains($line, 'Embed content: cid:'))
55+
->filter(fn ($line) => str_contains($line, ' content: cid:'))
56+
->first())[1];
57+
58+
$filename = explode('Embed file: ', (new Stringable($email))->explode("\r\n")
59+
->filter(fn ($line) => str_contains($line, ' file:'))
5660
->first())[1];
5761

5862
$this->assertStringContainsString(<<<EOT
59-
Content-Type: application/x-php; name=$cid\r
63+
Content-Type: application/x-php; name=$filename\r
6064
Content-Transfer-Encoding: base64\r
61-
Content-Disposition: inline; name=$cid; filename=$cid\r
65+
Content-Disposition: inline; name=$filename;\r
66+
filename=$filename\r
67+
Content-ID: <$cid>\r
6268
EOT, $email);
6369
}
6470

6571
public function testEmbedData()
6672
{
6773
Mail::to('[email protected]')->send($mailable = new EmbedDataMailable());
6874

69-
$mailable->assertSeeInHtml('Embed data content: cid:foo.jpg');
7075
$mailable->assertSeeInText('Embed data content: ');
71-
$mailable->assertDontSeeInText('Embed data content: cid:foo.jpg');
76+
$mailable->assertSeeInHtml('Embed data content: cid:');
7277

7378
$email = app('mailer')->getSymfonyTransport()->messages()[0]->getOriginalMessage()->toString();
7479

@@ -87,8 +92,7 @@ public function testEmbedMultilineImage()
8792

8893
$this->assertStringContainsString('Embed multiline content: <img', $html);
8994
$this->assertStringContainsString('alt="multiline image"', $html);
90-
$this->assertStringContainsString('data:image/png;base64', $html);
91-
$this->assertStringNotContainsString('cid:foo.jpg', $html);
95+
$this->assertStringContainsString('<img src="cid:', $html);
9296
}
9397

9498
public function testMessageAsPublicPropertyMayBeDefinedAsViewData()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
Embed file: {{ basename(__FILE__) }}
12
Embed content: {{ $message->embed(__FILE__) }}

tests/Integration/Notifications/SendingMailableNotificationsTest.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,24 @@ public function testMarkdownNotification()
4949

5050
$user->notify(new MarkdownNotification());
5151

52-
$email = app('mailer')->getSymfonyTransport()->messages()[0]->getOriginalMessage()->toString();
52+
$message = app('mailer')->getSymfonyTransport()->messages()[0]->getOriginalMessage();
53+
$email = $message->toString();
54+
$textBody = $message->getTextBody();
5355

54-
$cid = explode(' cid:', (new Stringable($email))->explode("\r\n")
56+
$cid = explode(' cid:', (new Stringable($textBody))->explode("\n")
5557
->filter(fn ($line) => str_contains($line, 'Embed content: cid:'))
5658
->first())[1];
5759

60+
$filename = explode(' file: ', (new Stringable($textBody))->explode("\n")
61+
->filter(fn ($line) => str_contains($line, 'Embed file: '))
62+
->first())[1];
63+
5864
$this->assertStringContainsString(<<<EOT
59-
Content-Type: application/x-php; name=$cid\r
65+
Content-Type: application/x-php; name=$filename\r
6066
Content-Transfer-Encoding: base64\r
61-
Content-Disposition: inline; name=$cid; filename=$cid\r
67+
Content-Disposition: inline; name=$filename;\r
68+
filename=$filename\r
69+
Content-ID: <$cid>\r
6270
EOT, $email);
6371
}
6472

tests/Mail/MailMessageTest.php

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,14 @@ public function testEmbedPath(): void
165165
$cid = $this->message->embed($path);
166166

167167
$this->assertStringStartsWith('cid:', $cid);
168-
$name = Str::after($cid, 'cid:');
168+
$contentId = Str::after($cid, 'cid:');
169169
$attachment = $this->message->getSymfonyMessage()->getAttachments()[0];
170170
$headers = $attachment->getPreparedHeaders()->toArray();
171171
$this->assertSame('bar', $attachment->getBody());
172-
$this->assertSame("Content-Type: image/jpeg; name={$name}", $headers[0]);
172+
$this->assertSame($contentId, $attachment->getContentId());
173+
$this->assertStringContainsString('Content-Type: image/jpeg', $headers[0]);
173174
$this->assertSame('Content-Transfer-Encoding: base64', $headers[1]);
174-
$this->assertSame("Content-Disposition: inline; name={$name}; filename={$name}", $headers[2]);
175+
$this->assertStringContainsString('Content-Disposition: inline', $headers[2]);
175176

176177
unlink($path);
177178
}
@@ -182,7 +183,9 @@ public function testDataEmbed(): void
182183

183184
$attachment = $this->message->getSymfonyMessage()->getAttachments()[0];
184185
$headers = $attachment->getPreparedHeaders()->toArray();
185-
$this->assertSame('cid:foo.jpg', $cid);
186+
$this->assertStringStartsWith('cid:', $cid);
187+
$contentId = Str::after($cid, 'cid:');
188+
$this->assertSame($contentId, $attachment->getContentId());
186189
$this->assertSame('bar', $attachment->getBody());
187190
$this->assertSame('Content-Type: image/png; name=foo.jpg', $headers[0]);
188191
$this->assertSame('Content-Transfer-Encoding: base64', $headers[1]);
@@ -201,9 +204,11 @@ public function toMailAttachment()
201204
}
202205
});
203206

204-
$this->assertSame('cid:baz', $cid);
207+
$this->assertStringStartsWith('cid:', $cid);
208+
$contentId = Str::after($cid, 'cid:');
205209
$attachment = $this->message->getSymfonyMessage()->getAttachments()[0];
206210
$headers = $attachment->getPreparedHeaders()->toArray();
211+
$this->assertSame($contentId, $attachment->getContentId());
207212
$this->assertSame('bar', $attachment->getBody());
208213
$this->assertSame('Content-Type: image/png; name=baz', $headers[0]);
209214
$this->assertSame('Content-Transfer-Encoding: base64', $headers[1]);
@@ -225,14 +230,14 @@ public function toMailAttachment()
225230
});
226231

227232
$this->assertStringStartsWith('cid:', $cid);
228-
$name = Str::after($cid, 'cid:');
229-
$this->assertSame(16, mb_strlen($name));
233+
$contentId = Str::after($cid, 'cid:');
230234
$attachment = $this->message->getSymfonyMessage()->getAttachments()[0];
235+
$this->assertSame($contentId, $attachment->getContentId());
231236
$headers = $attachment->getPreparedHeaders()->toArray();
232237
$this->assertSame('bar', $attachment->getBody());
233-
$this->assertSame("Content-Type: image/jpeg; name={$name}", $headers[0]);
238+
$this->assertStringContainsString('Content-Type: image/jpeg', $headers[0]);
234239
$this->assertSame('Content-Transfer-Encoding: base64', $headers[1]);
235-
$this->assertSame("Content-Disposition: inline; name={$name};\r\n filename={$name}", $headers[2]);
240+
$this->assertStringContainsString('Content-Disposition: inline', $headers[2]);
236241

237242
unlink($path);
238243
}

0 commit comments

Comments
 (0)