ddeboer/imap
A modern PHP IMAP library for reading mailboxes and messages. Connect to servers, list folders, fetch and search messages, inspect headers, bodies and attachments, flag or move mail, and work with UTF-8 folder names through a clean, object-oriented API.
Architecture fit. ddeboer/imap is a framework-agnostic, object-oriented IMAP client rather than a Laravel package: no service provider, no publishable config, no facade. It exposes a small domain model (Server → Mailbox → Message → Part/Attachment) that maps cleanly onto Laravel service classes, jobs, and events. For a product that must read arbitrary hosted mailboxes — shared inboxes, support@ accounts, customer-owned IMAP accounts — this is the right layer of abstraction. It is the wrong tool for greenfield inbound mail (webhook-based providers such as Postmark, Mailgun, or SES inbound are cheaper, lower-latency, and far less operationally brittle), so the build/buy decision should be settled before adopting it.
Integration feasibility. Straightforward. A thin adapter (~1–3 engineer-days) covers connection construction, mailbox enumeration, message retrieval, and attachment persistence via Flysystem. The substantive work is the polling pipeline around it: UID watermarking (UIDVALIDITY/UIDNEXT, never sequence numbers), Message-ID-based deduplication, idempotent processing, and an error taxonomy. Budget 1–2 weeks for a production-grade poller, not for the library integration itself.
Technical risk. Moderate and well-understood, concentrated in three areas:
winmail.dat, and inline images are routine. The library is well tested against Dovecot, but Exchange and Gmail label semantics (folders vs. labels, modified UTF-7 folder names) differ in ways that surface only in production.Key questions.
Stack fit. Good, with one wrapper. Bind a configured Server factory as a singleton in a service provider, inject it into jobs, and keep the library's types out of controllers and domain models — map to internal DTOs/entities so the dependency stays swappable. Attachments stream to S3 via Flysystem; never hold raw message bodies in memory beyond one message at a time.
Migration path. Adopt behind an internal MailboxReader interface. If the application already uses webklex/laravel-imap, migrate by feature rather than by rewrite: implement the interface against ddeboer/imap, run both in shadow mode against a test mailbox, diff parsed output, then cut over per-mailbox. The absence of Laravel-specific coupling makes this cheap; the absence of a facade means you own the wiring, which is arguably an advantage for testability.
Compatibility. Requires PHP 8.x and modern Composer; verify the constraint against the app's floor and against Laravel's supported PHP matrix. The strategic win is that v2 no longer depends on ext-imap, which is unbundled and deprecated in current PHP releases — this removes a PECL install from the container image and a recurring upgrade hazard. Note that any other package still using ext-imap will keep that dependency alive in the image regardless.
Sequencing.
Cache::lock per mailbox, and structured logging.Maintenance. Low code churn, but two ongoing obligations: tracking upstream releases (the v2 protocol rewrite is recent and will need patch releases), and owning provider-specific quirks yourself — there is no vendor to escalate to. Pin versions, review changelogs before upgrades, and keep the adapter small enough that forking is a weekend, not a quarter.
Support. Failures will be reported as "email didn't arrive in the app," not as IMAP errors. Invest early in a support-visible diagnostic: last successful poll per mailbox, last error, last processed UID. Without it, every ticket becomes an engineering investigation.
Scaling. IMAP is a polling protocol and scales linearly with mailbox count, not gracefully. Each mailbox is a stateful, latency-bound connection; providers impose hard limits (Gmail caps concurrent connections and daily bandwidth per account). Model capacity as mailboxes × poll frequency and expect to shard across queue workers. Laravel's long-lived queue workers are a real hazard here: stale connections, memory growth from leaked message objects, and timeouts mid-fetch. Enforce maxJobs/maxTime on the queue, set explicit socket timeouts, and reconnect per batch rather than holding sockets open.
Failure modes.
Ramp-up. One engineer familiar with Laravel queues and the IMAP model (UIDs, folders, MIME) can own this within a sprint; the library's test suite and clean API shorten the curve. The real ramp-up cost is domain knowledge — MIME edge cases and provider idiosyncrasies — which is durable, transferable, and worth the investment only if IMAP mailbox access is a genuine product requirement rather than an implementation shortcut around inbound webhooks.
How can I help you explore Laravel packages today?