Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Mailmimedecode Bundle Laravel Package

ijanki/mailmimedecode-bundle

ijanki/mailmimedecode-bundle decodes MIME-encoded email content, helping PHP applications convert encoded headers, subjects, and message bodies into readable UTF-8 text. It simplifies handling quoted-printable and base64 mail parts so your app can display and process incoming messages reliably.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is a Symfony2 Bundle, not a Laravel package — there is no service provider, facade, config file, or config/app.php entry to register. Before you try to install it in a Laravel app, understand what it actually is: a thin Symfony wrapper around the legacy PEAR Mail_mimeDecode class for turning raw RFC 822 / MIME message strings into a parsed tree of headers, bodies, and attachments.

The realistic minimal steps for a Laravel developer:

  1. Do not composer require the bundle into a Laravel project. The bundle depends on Symfony 2 components and will drag in conflicting versions.
  2. Look at the bundle's source first, specifically MailMimeDecode::decode() usage and how it walks parts recursively — that is the entire value proposition, and it is ~50 lines of glue.
  3. Decide between two paths:
    • Use the underlying pear/mail_mime-decode directly if you truly need a lightweight parser and can tolerate its quirks.
    • Use zbateson/mail-mime-parser or php-mime-mail-parser instead, which are actively maintained and PSR-friendly.

First use case: parsing an inbound email. In a Laravel app the entry point is usually a webhook payload (Postmark, Mailgun, SendGrid) or an IMAP fetch (via webklex/laravel-imap). You receive a raw MIME string and need to answer: what is the plain-text body, what is the HTML body, what attachments came with it, and what were the headers? That is exactly the job Mail_mimeDecode does — the Symfony bundle just wraps it.

Implementation Patterns

Pattern 1 — Call the parser directly, skip the bundle.

If you go the Mail_mimeDecode route, install the PEAR class standalone and wrap it in a small service of your own:

namespace App\Services;

class MimeDecoder
{
    public function decode(string $raw): object
    {
        $decoder = new \Mail_mimeDecode($raw);
        $params = [
            'include_bodies'  => true,
            'decode_bodies'   => true,
            'decode_headers'  => true,
        ];
        return $decoder->decode($params);
    }
}

Bind it once in a MailServiceProvider (or just use the container autowiring) and inject it where needed.

Pattern 2 — Recursive part walking.

Mail_mimeDecode returns a nested parts array. The only reliable pattern is recursion — you cannot assume depth or ordering:

public function walk(object $part, array &$out): void
{
    $type = $part->ctype_primary . '/' . $part->ctype_secondary;

    if (!empty($part->parts)) {
        foreach ($part->parts as $child) {
            $this->walk($child, $out);
        }
        return;
    }

    $out[] = [
        'type'        => $type,
        'charset'     => $part->ctype_parameters['charset'] ?? null,
        'disposition' => $part->disposition ?? 'inline',
        'filename'    => $part->d_parameters['filename'] ?? null,
        'body'        => $part->body ?? '',
    ];
}

Use this for text bodies, HTML alternates, and attachments alike.

Pattern 3 — Queue the work, not the HTTP request.

Email parsing is CPU-heavy and can be slow for large attachments. Accept the webhook, store the raw payload, and dispatch a job:

class IngestInboundEmail implements ShouldQueue
{
    public function __construct(
        public string $raw,
        public string $messageId,
    ) {}

    public function handle(MimeDecoder $decoder): void
    {
        $parsed = $decoder->decode($this->raw);
        // extract text/html/attachments, persist, or dispatch further events
    }
}

This decouples you from webhook timeouts and matches how Postmark/Mailgun retry.

Pattern 4 — Normalize across providers.

Different inbound providers shape the raw payload differently. Always persist the raw string (LONGTEXT), then run your decoder in one place. That way if you swap Mail_mimeDecode for zbateson/mail-mime-parser later, nothing upstream changes.

Pattern 5 — Attachment handling.

Write attachment bytes to Laravel's storage driver rather than into your database:

if (str_starts_with($part['disposition'], 'attachment') || $part['filename']) {
    Storage::disk('local')->put(
        "inbound/{$messageId}/{$part['filename']}",
        $part['body']
    );
}

Keep the attachment metadata (filename, MIME type, size) in the DB and the bytes on disk.

Integration tip: if you're using webklex/laravel-imap for polling mailboxes, $message->getRawBody() gives you exactly the string Mail_mimeDecode expects — no adapter needed.

Gotchas and Tips

  • This is not a Laravel package. There is no MailMimeDecodeServiceProvider, no publishing, no facade. Anything you do in Laravel is your own wrapper around the PEAR class, not the bundle.
  • Symfony 2 is EOL. Trying to install the bundle will fail on modern PHP and modern Laravel's dependency graph. If you're reading the repo for inspiration, read it — don't require it.
  • pear/mail_mime-decode itself is unmaintained. The last releases predate PHP 8. Expect deprecation notices and possible fatal errors on modern PHP. Test in a scratch project first.
  • Charset and encoding bugs are the #1 problem. Mail_mimeDecode handles base64 and quoted-printable but mishandles some multi-byte encodings, RFC 2231 extended parameters (filename*=UTF-8''...), and malformed headers. Sanitize file names and re-check text bodies with mb_detect_encoding + mb_convert_encoding to UTF-8.
  • Memory blowups. Decoding a 25 MB attachment with decode_bodies => true holds the whole thing in memory. For anything over a few MB, prefer streaming parsers (zbateson/mail-mime-parser supports streams) or set decode_bodies => false and fetch the raw part yourself.
  • parts is not always present. A single-part text/plain message has no parts key at all — only body. Guard for it.
  • Header decoding is best-effort. decode_headers => true mangles some encoded words (=?UTF-8?B?...?=). For strict RFC 2047 decoding, use iconv_mime_decode() on the raw header value.
  • No error handling. Mail_mimeDecode::decode() can return null on malformed input without an exception. Always null-check the return value and log the raw payload for replay.
  • Debugging: dump the full parsed object with json_encode($parsed, JSON_PRETTY_PRINT) after a test decode. The ctype_primary, ctype_secondary, disposition, and d_parameters keys tell you everything about how a part was interpreted — this is the fastest way to diagnose "why did my attachment come through empty."
  • Better alternatives for Laravel day-to-day:
    • zbateson/mail-mime-parser — actively maintained, stream-friendly, handles RFC 2231 correctly. Best default.
    • php-mime-mail-parser/php-mime-mail-parser — also maintained, built on mailparse extension, very fast.
    • Both are drop-in replacements for the parse-then-walk pattern above with the same service shape. Swapping later is cheap if you keep the decode call behind your own class.
  • Extension point to note: the bundle's only real config in Symfony was selecting the underlying parser class. In Laravel, replicate this by injecting an interface (MimeDecoderContract) into your job and binding either the PEAR implementation or a zbateson implementation — that's your migration path without touching the rest of your codebase.

Bottom line for a Laravel developer: treat this repo as a reference implementation of the pattern, not a dependency. Write a 20-line MimeDecoder service, back it with zbateson/mail-mime-parser, queue the parsing, and store raw + parts separately. You'll get 90% of the value with none of the PEAR-era baggage.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core