directorytree/imapengine-laravel
Laravel integration for ImapEngine, a PHP IMAP client that manages mailboxes without the PHP imap extension. Configure connections, access mailboxes and messages, and use a clean API to work with IMAP servers in your Laravel apps.
Installation:
composer require directorytree/imapengine-laravel
php artisan vendor:publish --provider="DirectoryTree\ImapEngine\ImapEngineServiceProvider"
Configure IMAP Credentials:
Add to .env:
IMAP_HOST=imap.example.com
IMAP_PORT=993
IMAP_USERNAME=user@example.com
IMAP_PASSWORD=yourpassword
IMAP_SSL=true
First Command: Test connection with:
php artisan imap:watch --mailbox=INBOX --method=idle
Basic Usage in Code:
use DirectoryTree\ImapEngine\Facades\ImapEngine;
$mailbox = ImapEngine::mailbox('INBOX');
$messages = $mailbox->messages()->unread()->limit(10)->get();
config/imap.php – Centralize IMAP settings (host, credentials, timeouts).php artisan list → Look for imap:* commands (e.g., imap:watch).MailboxSynced, MailboxWatchAttemptsExceeded – Hook into these for reactivity.ImapEngine – Primary entry point for mailbox operations.// Fetch unread emails from INBOX
$unreadEmails = ImapEngine::mailbox('INBOX')
->messages()
->unread()
->limit(50)
->get();
// Process each email (e.g., store in DB or dispatch jobs)
foreach ($unreadEmails as $email) {
ProcessEmail::dispatch($email);
}
// Get all messages in a mailbox
$messages = ImapEngine::mailbox('INBOX')->messages()->get();
// Filter by flags (e.g., unread, seen)
$unread = ImapEngine::mailbox('INBOX')->messages()->unread()->get();
// Limit results
$recent = ImapEngine::mailbox('INBOX')->messages()->limit(10)->get();
// Search by subject
$messages = ImapEngine::mailbox('INBOX')
->messages()
->where('subject', 'like', '%invoice%')
->get();
// Search by sender
$messages = ImapEngine::mailbox('INBOX')
->messages()
->from('support@example.com')
->get();
imap:watchphp artisan imap:watch --mailbox=INBOX --method=idle
--method: Use idle (low-resource) or long-polling (fallback for restrictive environments).app/Console/Kernel.php:
$schedule->command('imap:watch --mailbox=INBOX --method=idle')->everyMinute();
Listen for MailboxSynced to react to new emails:
use DirectoryTree\ImapEngine\Events\MailboxSynced;
public function handle(MailboxSynced $event) {
foreach ($event->emails as $email) {
// Process new email (e.g., store in DB, send notification)
NewEmailReceived::dispatch($email);
}
}
Combine with Laravel Queues for background processing:
// In your event listener
public function handle(MailboxSynced $event) {
foreach ($event->emails as $email) {
ProcessEmailJob::dispatch($email);
}
}
Define the job:
class ProcessEmailJob implements ShouldQueue {
public function handle() {
// Parse email, store attachments, etc.
}
}
use DirectoryTree\ImapEngine\Mailbox;
class SupportMailbox extends Mailbox {
public function __construct() {
parent::__construct('Support');
}
public function getTickets() {
return $this->messages()
->where('subject', 'like', '%ticket%')
->orderBy('date', 'desc')
->get();
}
}
Register in AppServiceProvider:
$this->app->bind(SupportMailbox::class, function () {
return new SupportMailbox();
});
Usage:
$tickets = app(SupportMailbox::class)->getTickets();
Handle MailboxWatchAttemptsExceeded:
use DirectoryTree\ImapEngine\Events\MailboxWatchAttemptsExceeded;
public function handle(MailboxWatchAttemptsExceeded $event) {
Log::error("Failed to watch mailbox {$event->mailbox} after {$event->attempts} attempts.");
// Optionally: Notify admin or switch to long-polling
}
Use imapengine's test utilities or mock the facade:
// Example using Mockery
$mailboxMock = Mockery::mock(Mailbox::class);
$mailboxMock->shouldReceive('messages')
->andReturnSelf();
$mailboxMock->shouldReceive('unread')
->andReturnSelf();
$mailboxMock->shouldReceive('get')
->andReturn([new Message()]);
$mailboxMock->makePartial();
Connection Timeouts:
long-polling as a fallback:
php artisan imap:watch --mailbox=INBOX --method=long-polling --interval=30
Credential Exposure:
.env or a secrets manager (e.g., Vault).Rate Limiting:
Email Parsing Limits:
try-catch:
try {
$body = $email->body();
} catch (\Exception $e) {
Log::error("Failed to parse email body: " . $e->getMessage());
}
Time Zone Issues:
$localDate = $email->date->setTimezone('America/New_York');
Message ID Collisions:
message_id may not be unique across mailboxes. Use a composite key (e.g., mailbox + message_id) in your database.Enable Verbose Logging:
Add to config/imap.php:
'debug' => env('IMAP_DEBUG', false),
Check IMAP Server Logs:
tail -f /var/log/mail.log
Test with a Dummy Mailbox:
TestMailbox) to avoid affecting production data during development.Use Spatie Ray:
spatie/laravel-ray to inspect IMAP operations in real-time:
composer require spatie/laravel-ray
Validate IMAP Credentials:
imap_open:
$connection = imap_open(
"{imap.example.com:993/imap/ssl}INBOX",
"user@example.com",
"password"
);
if (!$connection) {
die("IMAP connection failed: " . imap_last_error());
}
SSL/TLS Settings:
IMAP_SSL is true for secure connections. For STARTTLS, use:
IMAP_PORT=143
IMAP_SSL=false
IMAP_STARTTLS=true
Port Conflicts:
ImapEngine::setMaxConnections(5); // Default is 10
Character Encoding:
$subject = mb_convert_
How can I help you explore Laravel packages today?