zbateson/mail-mime-parser
PSR-compliant, testable MIME email parser for PHP (RFC 822/2822/5322). A standards-based but forgiving alternative to imap* and Pear for reading and inspecting messages, headers, parts, and attachments. Requires PHP 8.1+.
Installation:
composer require zbateson/mail-mime-parser
Ensure your project uses PHP 8.1+ (required for v4.0+).
Basic Parsing: Parse a raw email string or file handle:
use ZBateson\MailMimeParser\MailMimeParser;
$parser = new MailMimeParser();
$message = $parser->parse(file_get_contents('email.eml'), false);
First Use Case: Extract core metadata (subject, sender, recipients) and text content:
echo $message->getSubject(); // "Meeting Notes"
echo $message->getHeaderValue(\ZBateson\MailMimeParser\Header\HeaderConsts::FROM);
echo $message->getTextContent(); // Plaintext body
MailMimeParser: Main class for parsing emails.Message: Interface for parsed emails (use Message::from() for static parsing).HeaderConsts: Predefined header constants (e.g., FROM, TO, SUBJECT).$handle = fopen('email.eml', 'r');
$message = $parser->parse($handle, true); // Auto-closes handle
$message = Message::from($rawEmailString, false);
$fromHeader = $message->getHeader(\ZBateson\MailMimeParser\Header\HeaderConsts::FROM);
$senderName = $fromHeader->getPersonName(); // "John Doe"
$senderEmail = $fromHeader->getEmail(); // "john@example.com"
foreach ($message->getAttachmentParts() as $attachment) {
$attachment->saveContent('downloads/' . $attachment->getFileName());
}
$htmlPart = $message->getHtmlPart();
$textPart = $message->getTextPart();
Install companion packages:
composer require zbateson/mmp-crypt-smime # S/MIME
composer require zbateson/mmp-crypt-gpg # PGP/MIME
The parser automatically decrypts encrypted emails during parsing.
Override default parsers via PHP-DI:
$parser = new MailMimeParser([
'parsers' => [
'custom_header_parser' => \App\CustomHeaderParser::class,
],
]);
Service Provider Binding:
// app/Providers/AppServiceProvider.php
public function register()
{
$this->app->singleton(MailMimeParser::class, function ($app) {
return new MailMimeParser();
});
}
Mail Parsing in Controllers:
use ZBateson\MailMimeParser\MailMimeParser;
public function parseEmail(Request $request)
{
$parser = app(MailMimeParser::class);
$message = $parser->parse($request->file('email')->getRealPath());
return response()->json([
'subject' => $message->getSubject(),
'attachments' => count($message->getAttachmentParts()),
]);
}
Queueing Parsing Jobs:
// app/Jobs/ParseEmailJob.php
public function handle()
{
$parser = new MailMimeParser();
$message = $parser->parse($this->emailContent);
// Process parsed data (e.g., save to DB)
}
parse($handle, true) to auto-close file handles and avoid leaks.$attachment->getContentStream()->rewind();
file_put_contents('large-file.pdf', $attachment->getContentStream());
Resource Leaks:
parse().true) to auto-close:
$parser->parse($handle, true); // Auto-closes
Encoding Issues:
getHeaderValue() with proper charset handling:
$subject = $message->getSubject(); // Auto-decodes
Multipart Parsing:
getHtmlPart()/getTextPart() may return null if no matching part exists.null and handle gracefully:
$html = $message->getHtmlPart()?->getContent() ?? 'No HTML content';
Custom Headers:
X-Custom-Header) may not parse correctly.getHeader() with raw names:
$customHeader = $message->getHeader('X-Custom-Header');
PHP 8.1+ Requirements:
ClassNotFound errors.Error Handling:
getErrors() on Message or headers to inspect parsing issues:
if ($message->getErrors()) {
foreach ($message->getErrors() as $error) {
Log::error($error);
}
}
Logging:
MailMimeParser constructor:
$parser = new MailMimeParser([
'logger' => new Monolog\Logger('mail_parser'),
]);
Validation:
getErrors(true):
$message->getErrors(true); // Includes additional validation
Custom Parsers:
AbstractParserService to handle proprietary email formats:
class CustomParserService extends AbstractParserService
{
public function parse($content): IPart
{
// Custom logic
}
}
$parser = new MailMimeParser(['parsers' => ['custom' => CustomParserService::class]]);
Header Extensions:
AbstractHeader:
class CustomHeader extends AbstractHeader
{
protected function parseHeaderValue($value): void
{
// Custom parsing logic
}
}
Attachment Processing:
AttachmentPart behavior:
$attachment = $message->getAttachmentPart(0);
$attachment->setContentDisposition('attachment; filename="custom.name"');
Default Parsers:
NonMimeParserService) for unknown MIME types. To disable:
$parser = new MailMimeParser(['parsers' => []]); // Empty array
Charset Handling:
$parser = new MailMimeParser(['charset' => 'UTF-8']);
Deprecations:
MailMimeParser::setGlobalLogger) may break. Use constructor injection instead.How can I help you explore Laravel packages today?