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

Fetch Bundle Laravel Package

xotelia/fetch-bundle

Xotelia Fetch Bundle simplifies fetching and handling remote data in PHP applications. It offers a clean, configurable API for making requests, processing responses, and integrating reusable fetch workflows with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install with composer require xotelia/fetch-bundle. It is a Symfony bundle, so it expects Symfony's kernel/bundle registration; there is no Laravel service provider shipped.
  • In a Symfony app, register Xotelia\AbimusFetchBundle\AbimusFetchBundle in config/bundles.php, then look at the bundle's DependencyInjection/Configuration.php and Resources/config/services.* to see the exact config keys and service IDs it exposes. That is your ground truth — the README is thin and the API surface is small.
  • The bundle is a thin wrapper around a PHP IMAP client (the Fetch/IMAP library it depends on). Read the underlying library's docs first; the bundle mostly gives you configuration, a configured client service, and Symfony wiring.
  • Configure the mailbox connection (host, port, username, password, encryption/SSL, mailbox name) in config/packages/abimus_fetch.yaml (or whatever the extension alias resolves to — check getAlias()). Keep credentials in env vars, not the YAML.
  • First use case: a console command that logs into a mailbox, selects INBOX, fetches UNSEEN messages, and dumps subject/from/date to stdout. Get that working before you add persistence.
// src/Command/PeekMailboxCommand.php (Symfony)
#[AsCommand(name: 'mail:peek')]
class PeekMailboxCommand extends Command
{
    public function __construct(private MailFetcherInterface $fetcher) { parent::__construct(); }

    protected function execute(InputInterface $in, OutputInterface $out): int
    {
        foreach ($this->fetcher->fetchUnseen() as $message) {
            $out->writeln(sprintf('%s | %s', $message->getSubject(), $message->getFrom()));
        }
        return Command::SUCCESS;
    }
}

Implementation Patterns

Poll-and-persist command (the bread and butter). A scheduled console command is the natural shape: connect, select folder, fetch by criteria (UNSEEN, SINCE <date>, or a UID range), hand each message to a handler, then flag or move it.

foreach ($fetcher->fetchByCriteria('UNSEEN') as $msg) {
    $this->handler->handle($msg);      // persist / dispatch / store attachments
    $msg->markAsSeen();                // or move to "Processed"
}

Idempotency via UIDVALIDITY + UID. Store both, not just the UID. Use them as a unique key on your messages table so re-runs and crashes don't duplicate rows.

Message::firstOrCreate(
    ['mailbox' => $folder, 'uid_validity' => $uidValidity, 'uid' => $msg->getUid()],
    ['subject' => $msg->getSubject(), 'from' => $msg->getFrom(), 'received_at' => $msg->getDate()]
);

Don't process inline — dispatch. Fetch in the command, persist a lightweight record plus raw message (or attachment paths), then dispatch a job/event for parsing. This keeps the IMAP connection short-lived and lets you retry parsing without re-hitting the server.

Laravel adaptation. You cannot composer require a Symfony bundle into Laravel and expect it to boot. Two options:

  1. Install the underlying IMAP library directly and wire it in a MailboxServiceProvider:
// app/Providers/MailboxServiceProvider.php
public function register(): void
{
    $this->app->singleton(MailClient::class, fn () => new MailClient(
        config('mailbox.host'),
        config('mailbox.port'),
        config('mailbox.username'),
        config('mailbox.password'),
        config('mailbox.encryption'),
    ));
}
  1. If you must use the bundle, boot a minimal Symfony DI container inside a Laravel job — rarely worth it. Prefer option 1.

Queue + scheduler in Laravel:

// app/Console/Kernel.php
$schedule->job(new FetchMailboxJob('INBOX'))->everyFiveMinutes()->withoutOverlapping();

// app/Jobs/FetchMailboxJob.php
public function handle(MailClient $client): void
{
    $client->connect();
    foreach ($client->fetchUnseen() as $msg) {
        ProcessMessageJob::dispatch($msg->getUid(), $msg->getRawBody(), $msg->getAttachments());
    }
    $client->disconnect();
}

Folder strategy. Use a dedicated folder (INBOX/ToProcess) rather than INBOX directly, and move messages to Processed/Failed after handling. This gives you a real queue with replay semantics and keeps the mailbox tidy.

Testing. Abstract the client behind a small interface (fetchUnseen(): iterable) and fake it in tests. For integration tests, point at a disposable Dovecot/GreenMail container and seed .eml fixtures rather than hitting a real server.

Gotchas and Tips

  • It is a Symfony bundle, not a Laravel package. No auto-discovery, no config/fetch.php, no facade. Expect to write the wiring yourself or use the underlying library directly. Budget for that.
  • Low adoption / effectively unmaintained. Zero dependents and no stars means you are the maintainer in practice. Pin an exact version, vendor-fork it if needed, and read its source before relying on it in production. Check composer.json for the Symfony version constraint — it likely won't support Symfony 6/7 without a fork.
  • UIDVALIDITY changes are silent breakage. When the server changes UIDVALIDITY, all stored UIDs become invalid. Detect the change and re-sync rather than treating it as duplicates.
  • Always bound your fetch. UNSEEN on a 100k-message mailbox will exhaust memory and hit server timeouts. Use SINCE, UID ranges, or BODY.PEEK[] with limits. Fetch headers first, then bodies on demand.
  • Encoding is where IMAP bites. Folder names are UTF-7, subjects/addresses are MIME-encoded words, and bodies can be quoted-printable or base64. Use the library's decoders; don't utf8_decode your way through it.
  • SSL and self-signed certs. novalidate-cert is a common requirement for internal mail servers; exposing that as an env toggle saves you an incident. Also set connection/read timeouts — the default can hang a worker indefinitely.
  • Attachments and memory. Large attachments will blow memory_limit. Stream to disk if the library supports it; otherwise cap message size server-side and skip oversized ones explicitly.
  • Flagging vs. moving. markAsSeen() mutates state even if processing later throws. Prefer moving to a Processed folder only after successful handling, or track your own processed state and leave server flags alone.
  • Extension points are the real value. In Symfony, decorate the bundle's client service or override its service definition to inject logging, retry, and metrics. In Laravel, wrap the client in a decorator that adds retry(3, 1000) on connect and logs fetch counts.
  • Debugging: log raw IMAP commands/responses at debug level and capture the last server response on failure — IMAP errors are notoriously vague. Test against a real Dovecot, not just a mock, when you first wire it up.
  • Rate limits and connection churn. Some providers throttle concurrent IMAP logins. Keep one connection per worker, reuse it for the whole batch, and expunge()/disconnect() in a finally block.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings