abimus/fetch-bundle
Laravel package for fetching and bundling remote assets (CSS/JS/images) into a single, cacheable build. Helps reduce HTTP requests, manage dependencies, and serve optimized files in production with simple configuration.
Installation
composer require abimus/fetch-bundle
Add to config/bundles.php:
return [
// ...
Abimus\FetchBundle\AbimusFetchBundle::class => ['all' => true],
];
Configuration Publish the default config:
php bin/console config:dump-reference AbimusFetchBundle
Update config/packages/abimus_fetch.yaml with your IMAP credentials:
abimus_fetch:
imap:
host: 'imap.example.com'
port: 993
username: '[email protected]'
password: 'your_password'
ssl: true
validate_cert: false # Disable if using self-signed certs
First Use Case: Fetching Emails
Inject the AbimusFetchBundle\Service\FetchService into a controller or command:
use Abimus\FetchBundle\Service\FetchService;
class MailController extends AbstractController
{
public function __construct(private FetchService $fetchService) {}
public function fetchMails(): Response
{
$emails = $this->fetchService->fetch();
// Process $emails (array of \Abimus\FetchBundle\Entity\Email)
return $this->json($emails);
}
}
Periodic Fetching
Use Symfony’s CronExpression to schedule mail checks (e.g., every 5 minutes):
# config/packages/abimus_fetch.yaml
abimus_fetch:
cron: '*/5 * * * * *' # Every 5 minutes
Create a command to process fetched emails:
use Abimus\FetchBundle\Service\FetchService;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class ProcessMailsCommand extends Command
{
protected static $defaultName = 'app:process-mails';
public function __construct(private FetchService $fetchService) {}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$emails = $this->fetchService->fetch();
foreach ($emails as $email) {
// Save to DB, trigger events, etc.
}
return Command::SUCCESS;
}
}
Filtering Emails
Use the FetchService to filter by criteria (e.g., unread emails):
$unreadEmails = $this->fetchService->fetch(['unread' => true]);
Attachment Handling Stream attachments directly to storage:
foreach ($emails as $email) {
foreach ($email->getAttachments() as $attachment) {
file_put_contents(
"/path/to/storage/{$attachment->getFilename()}",
$attachment->getContent()
);
}
}
Email entities to a database table for persistence:
// src/Entity/Mail.php
use Abimus\FetchBundle\Entity\Email;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
class Mail
{
#[ORM\OneToOne(targetEntity: Email::class, mappedBy: 'mail')]
private ?Email $emailData = null;
}
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
class FetchService
{
public function __construct(
private EventDispatcherInterface $dispatcher
) {}
public function fetch(array $criteria = []): array
{
$emails = $this->imapClient->fetch($criteria);
$this->dispatcher->dispatch(new EmailsFetchedEvent($emails));
return $emails;
}
}
SSL Validation Errors If using self-signed certificates, disable validation in config:
abimus_fetch:
imap:
validate_cert: false
Warning: This exposes you to MITM attacks. Use only in development.
Memory Limits
Fetching large mailboxes may hit PHP’s memory limit. Use fetchLimit to paginate:
abimus_fetch:
imap:
fetch_limit: 50 # Fetch 50 emails at a time
Connection Timeouts IMAP servers may drop idle connections. Implement reconnection logic:
try {
$emails = $this->fetchService->fetch();
} catch (\Abimus\FetchBundle\Exception\ConnectionException $e) {
$this->fetchService->reconnect();
$emails = $this->fetchService->fetch();
}
UTF-8 Encoding Issues Some IMAP servers return emails in non-UTF-8 encodings. Normalize content:
$email->setSubject(mb_convert_encoding($email->getSubject(), 'UTF-8'));
Enable Verbose Logging
Add to config/packages/monolog.yaml:
handlers:
imap:
type: stream
path: "%kernel.logs_dir%/imap.log"
level: debug
channels: ["abimus_fetch"]
Then enable the channel in AbimusFetchBundle config:
abimus_fetch:
debug: true
Check IMAP Server Logs Many IMAP servers (e.g., Dovecot) log connection attempts. Verify credentials and permissions.
Custom Email Parsing
Override the default Email entity or parser:
use Abimus\FetchBundle\Parser\EmailParserInterface;
class CustomEmailParser implements EmailParserInterface
{
public function parse(\Imap\Message $message): Email
{
// Custom logic (e.g., extract metadata from headers)
return new Email(...);
}
}
Register the service:
services:
Abimus\FetchBundle\Parser\EmailParserInterface: '@custom_email_parser'
Adding Custom Headers
Extend the Email entity to include additional headers:
use Abimus\FetchBundle\Entity\Email;
class ExtendedEmail extends Email
{
private ?string $customHeader = null;
public function setCustomHeader(?string $header): self
{
$this->customHeader = $header;
return $this;
}
}
Update the parser to populate the new field.
Batch Processing
Use Symfony’s Messenger component to process emails asynchronously:
use Symfony\Component\Messenger\MessageBusInterface;
class FetchService
{
public function __construct(
private MessageBusInterface $bus
) {}
public function fetch(array $criteria = []): void
{
$emails = $this->imapClient->fetch($criteria);
foreach ($emails as $email) {
$this->bus->dispatch(new ProcessEmailMessage($email));
}
}
}
How can I help you explore Laravel packages today?