# php-mime-mail-parser: reading RFC 5322 mail through the mailparse extension

> php-mime-mail-parser is a PHP library that wraps the mailparse extension and gives you headers, addresses, text and HTML bodies and attachments from a raw message. It suits PHP applications that receive mail from Postfix or read .eml files, and its first requirement is a C extension that has to be present on the machine.

**php-mime-mail-parser/php-mime-mail-parser** — A fully tested email parser for PHP 8.0+ (mailparse extension wrapper).

- Repository: https://github.com/php-mime-mail-parser/php-mime-mail-parser
- Website: https://mailcare.io
- Stars: 995 · Forks: 193
- Language: PHP
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/php-mime-mail-parser-php-mime-mail-parser

## A wrapper around the mailparse extension, not a pure PHP parser

php-mime-mail-parser is described as a fully tested email parser for PHP, and the important word in that description is wrapper. The project is a thin, friendly layer over the mailparse PHP extension, which is itself a binding to a C implementation of the Internet Message Format. The README names the relevant standards directly, RFC 822, RFC 2822 and RFC 5322, which tells you what problem is being solved: turning a raw message into structured headers, bodies and attachments without writing a MIME walk by hand.

The project is maintained by the same organisation behind mailcare.io, and the repository layout matches the shape of a small, well-tested library: src/, tests/, composer.json, phpunit.xml.dist, and a mailparse-stubs.php file that gives static analysers something to read for the extension functions.

The listed uses are practical rather than abstract: parse and read email from Postfix, read messages saved as .eml files, create webmail, and store email information such as a subject, an HTML body and attachments into a database. The third and fourth of those are where the library earns its keep, because they are the cases where a naive string search over the raw message quietly breaks on a message with a quoted printable body or a nested multipart structure.

## Four ways to hand a message to the parser

The loading API is the part of the library you touch first, and it covers the four input shapes a PHP application actually has. The same parser object accepts a file path, the raw MIME text as a string, a file resource opened as a stream, or a stream connected to a mail server. The README shows all four in one snippet:

```php
require_once __DIR__.'/vendor/autoload.php';

$path = 'path/to/email.eml';
$parser = new PhpMimeMailParser\Parser();

// 1. Either specify a file path (string)
$parser->setPath($path); 

// 2. or specify the raw mime mail text (string)
$parser->setText(file_get_contents($path));

// 3. or specify a php file resource (stream)
$parser->setStream(fopen($path, "r"));

// 4. or specify a stream to work with a mail server (stream)
$parser->setStream(fopen("php://stdin", "r"));
```

The fourth option is the interesting one for a Postfix setup, where the message arrives on standard input from the MTA. The first three are the everyday cases: an archived .eml file, a message body already in memory, and a stream you want read lazily. Because the same object handles all of them, code that parses a file during development is the same code that parses a piped message in production, which removes a class of environment-only bug.

## Headers come in two shapes, raw and decoded

Reading metadata is a two-level API, and the distinction is easy to miss. A single header comes out as a string with getHeader, and the address headers have a structured counterpart in getAddresses, which returns an array of entries with a display name, an address and an is_group flag. The README shows both forms for the to and from headers:

```php
$rawHeaderTo = $parser->getHeader('to');
// return "test" <test@example.com>, "test2" <test2@example.com>

$arrayHeaderTo = $parser->getAddresses('to');
// return [["display"=>"test", "address"=>"test@example.com", false]]
```

The bulk accessors differ in one specific way, charset conversion. getHeadersRaw returns all headers as a string with no charset conversion, while getHeaders returns them as an array with charset conversion applied. That matters for international mail, where the subject and display names arrive in encoded form and a naive string comparison against a database value will not match.

For storage workflows, the pattern the README suggests is exactly what the library supports: pull the subject, the HTML body and the attachments and write them to a database, and use the raw and decoded accessors depending on whether you want to store the message as it arrived or the values your application will actually query.

## Pulling the text body, the HTML body and the attachments

The body accessors are called by the part you want, with text and html as the two documented keys. The text variant returns the text version of the message, the html variant returns the HTML version, and the README continues with a third accessor for HTML with embedded content.

What is worth knowing is the shape of the choice. A message that contains both a plain text and an HTML alternative has to be resolved by you: asking for one part does not give you both, and it does not tell you which one the sender preferred. A client that only renders HTML will want the html accessor; a notification that prefers plain text will want the text accessor; a client that wants to keep the original will want the whole message, which means the raw text you loaded rather than a reconstructed body.

The project also states that it handles foreign character encoding and attachment handling among the areas it focuses on, and the same list of use cases includes storing attachments in a database. The attachments are reached through the same parser object once the body has been located, so an application that stores an email as a record can keep the body and the file parts in the same pass over the message rather than reopening and reparsing it.

## Installing the extension before the Composer package

The order of installation matters here, and the README is explicit about it. The library is installed with Composer, and the command to install the latest version is:

```bash
composer require php-mime-mail-parser/php-mime-mail-parser
```

Before that works, the mailparse extension has to be present, and the check the project gives is a one-liner. Running php -m | grep mailparse needs to return mailparse, otherwise the library has nothing to wrap.

On Debian, Ubuntu and derivatives the extension comes from the distribution:

```bash
sudo apt install php-cli php-mailparse
```

On macOS the route is PECL:

```bash
brew install php
pecl install mailparse
```

On other platforms the PECL prerequisites are installed first:

```bash
sudo apt install php-cli php-pear php-dev
pecl install mailparse
```

Building from source is documented too, with the placeholder for the extension directory spelled out. AAAAMMDD should be the output of php-config --extension-dir, and the sequence is clone, phpize, configure, make, then move the built module and enable it:

```bash
git clone https://github.com/php/pecl-mail-mailparse.git
cd pecl-mail-mailparse
phpize
./configure
make
```

On Windows the project points at the PECL package page for the DLL and asks you to add extension=php_mailparse.dll to php.ini. In every case the acceptance test is the same: the extension has to appear in the module list before the Composer package is useful.

## PHP version support and the older release lines

The requirements section lists PHP 8.2, 8.3, 8.4 and 8.5 as supported, and the project description on the package page says PHP 8.0+, which is a discrepancy worth resolving before you pin a version. The table of previous versions is the more precise document, because it maps every PHP line to the release that served it. PHP 8.0 and 8.1 are covered by 9.0.1, PHP 7.2 through 7.4 by 7.1.2, PHP 7.1 by 5.0.5, PHP 7.0 by 3.0.4, and PHP 5.4 through 5.6 by 2.11.1, with an HHVM entry pointing at the same 2.11.1 release. There are no rows for the intermediate 5.x-to-7.x versions beyond those, so a legacy application on PHP 5.6 is pinned to a release from years ago while a current application on 8.2 or newer takes the newest line.

The current release is 10.0.0, published on 2026-04-22, and the last push to the repository was on 2026-05-14. The project is not archived, and the previous two releases, 9.0.1 and 9.0.0, both landed in December 2024, so the 10.0.0 line is a step up from a long quiet period rather than a fast-moving stream of patch releases.

The licence is MIT, with the licence file at the root of the repository, which is the permissive end of the spectrum for a library you are likely to embed in a commercial application.

## Where the wrapper is the right call, and where it is not

The trade-off in this project is visible in its dependency direction. You get correct handling of encoded words, nested multipart bodies and attachments, plus a small readable API, in exchange for a C extension that has to exist on the machine and a second thing to install when you deploy. For a PHP team already running PECL extensions, that is a reasonable trade. For a container image built from a minimal PHP base with no compiler, it is an extra build step, and for a platform where you cannot install extensions at all it is a dead end.

The alternative approach is to parse the message yourself with PHP string functions, which costs nothing to install and gives you full control, and it is what this library exists to replace. The argument for the library is correctness on real-world mail, not speed: quoted printable encoding, base64 transfer encoding, multiple content types and nested alternative parts are exactly where hand-written parsing fails quietly, and a mail parsing bug usually shows up as missing or mangled content rather than as an exception. A third option is to treat the message as opaque and store the raw bytes, which is the right call when you only need to archive mail and never to read it.

The library does not document how it behaves on a malformed message that the underlying extension rejects, and the README does not cover error handling for that case. If you are feeding it mail from unknown senders, that is the gap to test before you rely on it.

## Conclusion

php-mime-mail-parser fits a PHP 8.2 to 8.5 application that receives mail through Postfix, reads .eml archives or stores message metadata and attachments in a database, and it removes the work of handling RFC 822, 2822 and 5322 structures by hand. It does not fit a deployment where you cannot install a PHP extension, and it is heavier than needed for a service that only ever reads a subject line. Before adopting it, confirm that php -m lists mailparse on the target machine, decide whether the Composer package or the PECL extension suits your build, and check the version table, since PHP 8.0 and 8.1 are served by the older 9.0.1 line rather than by 10.0.0. The last push was on 2026-05-14 and the current release is 10.0.0.

## FAQ

### How do I install php-mime-mail-parser?

Install the library with composer require php-mime-mail-parser/php-mime-mail-parser, but make sure the mailparse extension is present first. The project gives the check php -m | grep mailparse, which needs to return mailparse.

### Which PHP versions does php-mime-mail-parser support?

The requirements section lists PHP 8.2, 8.3, 8.4 and 8.5. The version table maps older lines to older releases, with PHP 8.0 and 8.1 served by 9.0.1 and PHP 7.2 to 7.4 by 7.1.2.

### How do I parse an email file in PHP with php-mime-mail-parser?

Create the parser with new PhpMimeMailParser\Parser() and call setPath with the file path, or use setText for raw message text or setStream for a file resource or a stream such as php://stdin.

### What is the difference between getHeaders and getHeadersRaw?

getHeadersRaw returns all headers as a string with no charset conversion, while getHeaders returns them as an array with charset conversion applied. The same distinction applies to a single header, which is read with getHeader.

### Can I read mail piped in from Postfix with php-mime-mail-parser?

Yes. One of the four loading options in the README is a stream connected to a mail server, shown as fopen("php://stdin", "r"), and reading email from Postfix is one of the listed use cases for the library.

### What license is php-mime-mail-parser released under?

The project is released under the MIT License, with the licence file at the root of the repository.

## Sources

- [License: MIT](https://github.com/php-mime-mail-parser/php-mime-mail-parser/blob/main/LICENSE)
- [php-mime-mail-parser/php-mime-mail-parser on GitHub](https://github.com/php-mime-mail-parser/php-mime-mail-parser)
- [Project website](https://mailcare.io)
- [README](https://github.com/php-mime-mail-parser/php-mime-mail-parser/blob/main/README.md)
- [Releases](https://github.com/php-mime-mail-parser/php-mime-mail-parser/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/php-mime-mail-parser-php-mime-mail-parser
