php
52 lines · 9 steps
Parsing multipart emails with mailparse
Walk a raw MIME message into structured headers and decoded body parts using PHP's mailparse extension.
Explained by
highlit
1<?php
2
3function parseMultipartEmail(string $raw): array
4{
5 $resource = mailparse_msg_create();
6 mailparse_msg_parse($resource, $raw);
7
8 $structure = mailparse_msg_get_structure($resource);
9 $message = [
10 'headers' => [],
11 'parts' => [],
12 ];
13
14 $rootData = mailparse_msg_get_part_data($resource);
15 $message['headers'] = $rootData['headers'] ?? [];
16
17 foreach ($structure as $partId) {
18 $part = mailparse_msg_get_part($resource, $partId);
19 $data = mailparse_msg_get_part_data($part);
20
21 $contentType = $data['content-type'] ?? 'text/plain';
22 if (str_starts_with($contentType, 'multipart/')) {
23 continue;
24 }
25
26 $body = mailparse_msg_extract_part_file(
27 $part,
28 $raw,
29 null
30 );
31
32 $encoding = strtolower($data['transfer-encoding'] ?? '');
33 $body = match ($encoding) {
34 'base64' => base64_decode($body),
35 'quoted-printable' => quoted_printable_decode($body),
36 default => $body,
37 };
38
39 $message['parts'][] = [
40 'id' => $partId,
41 'content_type' => $contentType,
42 'charset' => $data['charset'] ?? 'us-ascii',
43 'disposition' => $data['content-disposition'] ?? 'inline',
44 'filename' => $data['disposition-filename'] ?? $data['content-name'] ?? null,
45 'body' => $body,
46 ];
47 }
48
49 mailparse_msg_free($resource);
50
51 return $message;
52}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1MIME messages are a tree, so skipping multipart container nodes leaves you with only the real leaf content.
- 2Transfer encodings like base64 and quoted-printable must be decoded before a body is usable.
- 3Extension resources need explicit cleanup — free them once you've extracted everything you need.
Related explainers
php
<?php namespace App\Http\Controllers;
Streaming a filtered CSV export in Laravel
streaming
csv-export
query-builder
Intermediate
9 steps
php
<?php namespace App\Http\Middleware;
Idempotent requests with Laravel middleware
idempotency
middleware
caching
Advanced
8 steps
php
<?php namespace App\Services;
Batch image resizing with PHP GD
image-processing
constructor-promotion
match-expression
Intermediate
10 steps
php
<?php namespace App\Cache;
A content-hashed fragment cache in PHP
caching
content-hashing
atomic-writes
Intermediate
10 steps
php
<?php namespace App\View\Composers;
How a Laravel view composer feeds the navigation
view-composer
caching
dependency-injection
Intermediate
5 steps
php
public function transaction(callable $callback, int $maxAttempts = 3): mixed { $attempt = 0;
Retrying database deadlocks in PHP
retry
transactions
deadlock
Intermediate
8 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/parsing-multipart-emails-with-mailparse-explained-php-8fa9/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.