Weave Code
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

Imapengine Laravel Package

directorytree/imapengine

IMAP Engine is a Laravel-friendly PHP package for working with IMAP mailboxes. It simplifies connecting to mail servers, browsing folders, fetching and searching messages, and handling attachments with a clean, developer-focused API for email workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Package:
    composer require directorytree/imapengine
    
  2. Configure Connection:
    use DirectoryTree\ImapEngine\Client;
    
    $client = new Client([
        'host' => 'imap.example.com',
        'port' => 993,
        'encryption' => 'ssl',
        'username' => 'user@example.com',
        'password' => 'password',
    ]);
    
  3. First Use Case: Fetch Inbox Messages
    $inbox = $client->getFolder('INBOX');
    $messages = $inbox->search(['UNSEEN'])->fetch(['headers', 'body']);
    foreach ($messages as $message) {
        echo $message->subject . "\n";
    }
    

Where to Look First

  • Documentation (Official guide with Laravel-specific examples).
  • Client Class: Entry point for connections and folder operations.
  • Folder Methods: search(), fetch(), poll(), and idle() for real-time updates.
  • Message Properties: headers, body, attachments, and flags for parsing.

Implementation Patterns

Core Workflows

1. Connecting and Authenticating

$client = new Client(config('imap'));
$client->connect(); // Throws `ImapConnectionFailedException` on failure
  • Laravel Integration: Store credentials in .env and bind Client to the container:
    $this->app->singleton(Client::class, function ($app) {
        return new Client($app['config']['imap']);
    });
    

2. Searching and Fetching Messages

$folder = $client->getFolder('INBOX');
$messages = $folder->search([
    'FROM' => 'support@example.com',
    'SINCE' => '2023-01-01',
    'UNSEEN',
])->fetch(['headers', 'body']);
  • Lazy Loading: Use with() to defer fetching:
    $messages = $folder->search(['UNSEEN'])->with(['headers']);
    foreach ($messages as $message) {
        if ($message->hasBody()) {
            $message->fetchBody(); // Load on demand
        }
    }
    

3. Bulk Operations

$folder->bulkQuery()
    ->flag(['\Seen'], [1, 2, 3]) // Mark messages 1, 2, 3 as read
    ->delete([4, 5, 6]) // Delete messages 4, 5, 6
    ->execute();
  • Use Case: Process thousands of emails efficiently (e.g., archiving old messages).

4. Real-Time Polling

$folder->poll(30, function ($messages) { // Poll every 30 seconds
    foreach ($messages as $message) {
        // Process new messages
    }
});
  • Laravel Queues: Dispatch polling to a queue for background processing:
    PollingJob::dispatch($folder, 30);
    

5. Attachment Handling

$message = $folder->search(['FROM' => 'user@example.com'])->first();
foreach ($message->attachments() as $attachment) {
    $attachment->saveTo(storage_path('app/attachments/' . $attachment->filename));
}
  • Content-Disposition: Access metadata like filename or disposition:
    $attachment->contentDisposition; // e.g., 'attachment; filename="report.pdf"'
    

6. Server-Side Sorting

$messages = $folder->search(['UNSEEN'])
    ->sort('DATE', 'DESC') // Sort by date (server-side)
    ->fetch(['headers']);

Integration Tips

  • Laravel Events: Trigger events for new messages:
    $folder->poll(60, function ($messages) {
        event(new NewMessagesReceived($messages));
    });
    
  • Eloquent Models: Store parsed messages in a database:
    foreach ($messages as $message) {
        Email::create([
            'subject' => $message->subject,
            'body' => $message->text,
            'folder' => $folder->name,
        ]);
    }
    
  • Error Handling: Catch exceptions and retry:
    try {
        $folder->fetch(['body']);
    } catch (ImapException $e) {
        $this->retryLater();
    }
    

Gotchas and Tips

Pitfalls

  1. Connection Timeouts:

    • Issue: Long-running operations (e.g., fetching large attachments) may time out.
    • Fix: Use setTimeout() on the Client or implement chunked fetching:
      $client->setTimeout(120); // 2 minutes
      
  2. Lazy Loading Overhead:

    • Issue: Overusing with() or fetchBody() can lead to N+1 queries.
    • Fix: Fetch only what you need upfront:
      // Bad: Fetch all headers first, then bodies
      $messages = $folder->search([])->with(['headers']);
      foreach ($messages as $message) {
          $message->fetchBody(); // Separate call per message
      }
      
      // Good: Fetch headers + bodies in one go
      $messages = $folder->search([])->fetch(['headers', 'body']);
      
  3. UTF-8 Decoding:

    • Issue: Some email headers may not decode properly (e.g., From names).
    • Fix: Explicitly decode headers:
      $from = mb_convert_encoding($message->from, 'UTF-8', 'auto');
      
  4. Attachment Corruption:

    • Issue: Attachments may be malformed if the server sends partial data.
    • Fix: Validate attachments before processing:
      if ($attachment->isValid()) {
          $attachment->saveTo(...);
      }
      
  5. IDLE Mode Quirks:

    • Issue: $folder->idle() may hang or fail silently.
    • Fix: Use a timeout callback:
      $folder->idle(300, function () { // Timeout after 5 minutes
          return true; // Break idle
      });
      
  6. Bulk Operations Limits:

    • Issue: Some IMAP servers limit bulk operations (e.g., max 100 messages at once).
    • Fix: Chunk operations:
      $batchSize = 50;
      $uids = range(1, 1000);
      foreach (array_chunk($uids, $batchSize) as $chunk) {
          $folder->bulkQuery()->delete($chunk)->execute();
      }
      

Debugging Tips

  • Enable Logging:
    $client->setLogger(new MonologLogger(Logger::create('imap')));
    
  • Check Raw Responses:
    $client->setDebug(true); // Logs raw IMAP commands/responses
    
  • Validate UIDs:
    • Always use UIDs (not sequential numbers) for operations to avoid issues with moved messages:
      $uids = $folder->search([])->uids(); // Get UIDs first
      $folder->bulkQuery()->delete($uids)->execute();
      

Extension Points

  1. Custom Message Parsing:

    • Extend the Message class to add domain-specific logic:
      class CustomMessage extends \DirectoryTree\ImapEngine\Message
      {
          public function isSupportTicket(): bool
          {
              return str_contains($this->subject, '[Support]');
          }
      }
      
    • Override the fetch() method in your Folder class to use the custom parser.
  2. Attachment Storage:

    • Create a service to handle attachment storage (e.g., S3, local filesystem):
      class AttachmentStorage
      {
          public function store(Attachment $attachment): string
          {
              return Storage::disk('s3')->put(
                  'attachments/' . $attachment->filename,
                  $attachment->content
              );
          }
      }
      
  3. Query Builder Extensions:

    • Add custom search criteria:
      $folder->search(['CUSTOM_CRITERIA' => 'value']);
      
    • Implement a CustomCriteria class extending SearchCriteria.
  4. Event Dispatching:

    • Listen for MessageFetched or FolderPolled events to trigger actions:
      $folder->search([])->fetch(['headers'])->each(function ($message) {
          event(new MessageProcessed($message));
      });
      

Configuration Quirks

  • SSL/TLS:
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.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata