|
217 | 217 | expect($attachments[0]->filename())->toBe('inline_image.png'); |
218 | 218 | }); |
219 | 219 |
|
220 | | -test('it can extract attachments from forwarded messages', function () { |
| 220 | +test('it merges attachments from an inline forwarded message', function () { |
221 | 221 | // Create a forwarded message that contains an attachment |
222 | 222 | $forwardedMessage = <<<'EOT' |
223 | 223 | From: "Original Sender" <[email protected]> |
|
243 | 243 | --ORIGINAL_BOUNDARY-- |
244 | 244 | EOT; |
245 | 245 |
|
246 | | - // Create the main message that forwards the above message |
| 246 | + // Create the main message that forwards the above message inline (no filename/disposition on message/rfc822) |
247 | 247 | $contents = <<<EOT |
248 | 248 | From: "Forwarder" <[email protected]> |
249 | 249 | To: "Final Recipient" <[email protected]> |
|
259 | 259 | Here is the forwarded message with its attachment. |
260 | 260 |
|
261 | 261 | --FORWARD_BOUNDARY |
262 | | - Content-Type: message/rfc822; name="forwarded-message.eml" |
263 | | - Content-Disposition: attachment; filename="forwarded-message.eml" |
| 262 | + Content-Type: message/rfc822 |
264 | 263 |
|
265 | 264 | $forwardedMessage |
266 | 265 | --FORWARD_BOUNDARY |
|
290 | 289 | expect($attachments[1]->contentType())->toBe('application/zip'); |
291 | 290 | }); |
292 | 291 |
|
| 292 | +test('it does not merge attached .eml files', function () { |
| 293 | + // Forwarded message that itself contains an attachment |
| 294 | + $forwardedMessage = <<<'EOT' |
| 295 | + From: "Original Sender" <[email protected]> |
| 296 | + To: "Original Recipient" <[email protected]> |
| 297 | + Subject: Original Message with Attachment |
| 298 | + Date: Tue, 18 Feb 2025 10:00:00 -0500 |
| 299 | + |
| 300 | + MIME-Version: 1.0 |
| 301 | + Content-Type: multipart/mixed; boundary="ORIGINAL_BOUNDARY" |
| 302 | +
|
| 303 | + --ORIGINAL_BOUNDARY |
| 304 | + Content-Type: text/plain; charset="UTF-8" |
| 305 | +
|
| 306 | + This is the original message with an attachment. |
| 307 | +
|
| 308 | + --ORIGINAL_BOUNDARY |
| 309 | + Content-Type: application/pdf; name="original-document.pdf" |
| 310 | + Content-Disposition: attachment; filename="original-document.pdf" |
| 311 | + Content-Transfer-Encoding: base64 |
| 312 | +
|
| 313 | + JVBERi0xLjUKJeLjz9MKMyAwIG9iago8PC9MZW5ndGggNCAgIC9GaWx0ZXIvQXNjaWlIYXgg |
| 314 | + ICAgPj5zdHJlYW0Kc3R1ZmYKZW5kc3RyZWFtCmVuZG9iajAK |
| 315 | + --ORIGINAL_BOUNDARY-- |
| 316 | + EOT; |
| 317 | + |
| 318 | + // Top-level message that attaches the forwarded message as an .eml (should not merge) |
| 319 | + $contents = <<<EOT |
| 320 | + From: "Forwarder" <[email protected]> |
| 321 | + To: "Final Recipient" <[email protected]> |
| 322 | + Subject: Fwd: Original Message with Attachment (as .eml) |
| 323 | + Date: Wed, 19 Feb 2025 12:34:56 -0500 |
| 324 | + |
| 325 | + MIME-Version: 1.0 |
| 326 | + Content-Type: multipart/mixed; boundary="FORWARD_BOUNDARY" |
| 327 | +
|
| 328 | + --FORWARD_BOUNDARY |
| 329 | + Content-Type: text/plain; charset="UTF-8" |
| 330 | +
|
| 331 | + Here is the forwarded message attached as an .eml file. |
| 332 | +
|
| 333 | + --FORWARD_BOUNDARY |
| 334 | + Content-Type: message/rfc822; name="forwarded-message.eml" |
| 335 | + Content-Disposition: attachment; filename="forwarded-message.eml" |
| 336 | +
|
| 337 | + $forwardedMessage |
| 338 | + --FORWARD_BOUNDARY |
| 339 | + Content-Type: application/zip; name="additional-file.zip" |
| 340 | + Content-Disposition: attachment; filename="additional-file.zip" |
| 341 | + Content-Transfer-Encoding: base64 |
| 342 | +
|
| 343 | + UEsDBAoAAAAAAKxVVVMAAAAAAAAAAAAAAAAJAAAAdGVzdC50eHRQSwECFAAKAAAAAACs |
| 344 | + VVVTAAAAAAAAAAAAAAAACQAAAAAAAAAAAAAAAAAAAHRlc3QudHh0UEsFBgAAAAABAAEA |
| 345 | + NwAAAB8AAAAAAA== |
| 346 | + --FORWARD_BOUNDARY-- |
| 347 | + EOT; |
| 348 | + |
| 349 | + $message = new FileMessage($contents); |
| 350 | + |
| 351 | + $attachments = $message->attachments(); |
| 352 | + |
| 353 | + // Expect exactly two top-level attachments: the attached .eml itself and the zip |
| 354 | + expect($attachments)->toHaveCount(2); |
| 355 | + |
| 356 | + // .eml is preserved as-is (no merging of its inner PDF) |
| 357 | + expect($attachments[0]->contentType())->toBe('message/rfc822'); |
| 358 | + expect($attachments[0]->filename())->toBe('forwarded-message.eml'); |
| 359 | + |
| 360 | + // The top-level zip attachment remains |
| 361 | + expect($attachments[1]->contentType())->toBe('application/zip'); |
| 362 | + expect($attachments[1]->filename())->toBe('additional-file.zip'); |
| 363 | +}); |
| 364 | + |
293 | 365 | test('it can handle multiple levels of forwarded messages with attachments', function () { |
294 | 366 | // Create the deepest nested message with an attachment |
295 | 367 | $deepestMessage = <<<'EOT' |
|
0 commit comments