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

IMAPEngine is a Laravel-friendly PHP package for working with IMAP mailboxes. Connect to servers, list folders, fetch messages and attachments, search and manage mail, and handle common IMAP operations through a clean, high-level API.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require directorytree/imapengine
    

    Requires PHP 8.1+ and dependencies like symfony/mime and nesbot/carbon.

  2. Basic Connection:

    use DirectoryTree\ImapEngine\Client;
    use DirectoryTree\ImapEngine\Connection;
    
    $connection = new Connection('imap.example.com', [
        'username' => 'user@example.com',
        'password' => 'password',
        'ssl' => true,
    ]);
    
    $client = new Client($connection);
    
  3. First Use Case: Fetching Emails

    $inbox = $client->getFolder('INBOX');
    $messages = $inbox->search()->all();
    
    foreach ($messages as $message) {
        echo $message->subject . "\n";
    }
    

Key Entry Points

  • Client: Main entry point for managing connections and folders.
  • Folder: Represents an IMAP folder (e.g., INBOX, Sent).
  • Message: Represents an email with lazy-loaded properties (headers, body, attachments).
  • QueryBuilder: For searching messages with criteria like unread(), from('sender@example.com').

Implementation Patterns

Core Workflows

1. Fetching and Processing Messages

  • Lazy Loading: Avoid fetching full message content upfront.
    $messages = $folder->search()->unread()->limit(10)->get();
    foreach ($messages as $message) {
        // Headers are loaded on-demand
        echo $message->subject; // Triggers lazy load of headers
        $message->text; // Triggers lazy load of text body
    }
    
  • Bulk Operations:
    $folder->flag(['uid' => [1, 2, 3]], 'read');
    $folder->delete(['uid' => [4, 5]]);
    

2. Searching with Criteria

  • Combine criteria for complex queries:
    $query = $folder->search()
        ->unread()
        ->from('sender@example.com')
        ->since('2023-01-01')
        ->largerThan(1024); // Messages > 1KB
    $messages = $query->get();
    

3. Handling Attachments

  • Stream attachments directly to storage:
    foreach ($message->attachments() as $attachment) {
        $attachment->saveTo(storage_path("attachments/{$attachment->filename}"));
    }
    

4. Long Polling for New Messages

  • Use poll() to wait for new messages in a folder:
    $folder->poll(function (Folder $folder) {
        $newMessages = $folder->search()->since(now()->subMinute())->get();
        // Process $newMessages
    }, 30); // Timeout in seconds
    

5. Server-Side Sorting

  • Leverage IMAP SORT capability for efficient sorting:
    $messages = $folder->search()
        ->unread()
        ->sort('date', 'desc')
        ->get();
    

Integration Tips

Laravel Integration

  • Service Provider: Bind Client to the container for dependency injection:

    $this->app->singleton(Client::class, function ($app) {
        $connection = new Connection(config('imap.host'), [
            'username' => config('imap.username'),
            'password' => config('imap.password'),
            'ssl' => config('imap.ssl', true),
        ]);
        return new Client($connection);
    });
    
  • Queued Processing: Use Laravel queues to process large batches of emails asynchronously:

    $messages = $folder->search()->unread()->limit(100)->get();
    foreach ($messages as $message) {
        ProcessEmail::dispatch($message);
    }
    

Event-Driven Architecture

  • Extend Folder to trigger events (e.g., MessageReceived):
    $folder->poll(function (Folder $folder) {
        $newMessages = $folder->search()->since(now()->subMinute())->get();
        event(new MessageReceived($newMessages));
    });
    

Testing

  • Use ImapEngine's mockable design to test email logic:
    $mockConnection = Mockery::mock(Connection::class);
    $client = new Client($mockConnection);
    

Gotchas and Tips

Pitfalls

  1. Connection Timeouts:

    • IMAP servers may disconnect idle connections. Use poll() with a timeout or reconnect logic:
      try {
          $folder->poll($callback, 60);
      } catch (ImapConnectionFailedException $e) {
          $client->reconnect();
      }
      
  2. Lazy Loading Overhead:

    • Avoid eager-loading large messages. Use withHeaders(), withText(), or withAttachments() explicitly:
      $messages = $folder->search()->withHeaders()->limit(50)->get();
      
  3. UTF-8 Encoding Issues:

    • Ensure headers (e.g., from names) are decoded properly. Use $message->from->name after lazy loading.
  4. Attachment Handling:

    • Some servers may return .eml attachments for nested messages. Use $attachment->isEml() to filter:
      $attachments = $message->attachments()->reject(fn ($a) => $a->isEml());
      
  5. Query Builder Quirks:

    • Server-side sorting (sort()) requires the IMAP server to support the SORT extension. Fallback to client-side sorting if needed:
      $messages = $folder->search()->sort('date', 'desc')->get()->sortByDesc('date');
      

Debugging Tips

  1. Enable Verbose Logging:

    $connection = new Connection('imap.example.com', [
        'log' => true,
        'logFile' => storage_path('logs/imap.log'),
    ]);
    
  2. Check Raw Responses:

    • Use Spatie\Ray (dev dependency) to inspect raw IMAP responses:
      Ray::dd($message->rawHeaders);
      
  3. Common Exceptions:

    • ImapConnectionFailedException: Handle reconnection logic.
    • ImapSearchException: Validate search criteria (e.g., since() dates).

Extension Points

  1. Custom Message Parsing:

    • Extend DirectoryTree\ImapEngine\Message to add domain-specific logic:
      class CustomMessage extends Message {
          public function isPromotion(): bool {
              return str_contains($this->subject, 'promo');
          }
      }
      
  2. Query Builder Extensions:

    • Add custom search criteria:
      $query->hasHeader('X-Custom-Header');
      
      Extend QueryBuilder to support this:
      public function hasHeader(string $header): self {
          $this->criteria[] = "HEADER {$header}";
          return $this;
      }
      
  3. Attachment Processing:

    • Override Attachment to add virus scanning or metadata extraction:
      class SecureAttachment extends Attachment {
          public function scanForViruses(): bool {
              // Integrate with ClamAV or similar
          }
      }
      
  4. Folder Events:

    • Listen for folder changes (e.g., new messages) via poll() callbacks or Laravel events.

Configuration Quirks

  1. SSL/TLS:

    • Some servers require explicit SSL/TLS settings:
      $connection = new Connection('imap.example.com', [
          'ssl' => true,
          'port' => 993, // Default IMAPS port
      ]);
      
  2. Authentication:

    • Test with authMechanism for OAuth2 or other auth methods:
      $connection = new Connection('imap.example.com', [
          'authMechanism' => 'XOAUTH2',
          'oauthToken' => $googleOAuthToken,
      ]);
      
  3. Namespace Handling:

    • Use getFolder() with full paths (e.g., 'INBOX.Sent') if the server uses hierarchical folders.

Performance Tips

  1. Batch Fetching:

    • Fetch messages in chunks to avoid memory issues:
      $messages = $folder->search()->limit(100)->get();
      while ($messages->count() > 0) {
          // Process batch
          $messages = $folder->search()->offset($messages->last()->uid)->limit(100)->get();
      }
      
  2. Lazy Load Selectively:

    • Only load necessary parts of messages:
      $messages = $folder->search()->withHeaders()->withText()->get();
      
  3. Use UID for Operations:

    • Pre
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport