Install the Package
Add to composer.json under require-dev:
"tedivm/dovecottesting": "~1"
Run composer update.
Integrate with Laravel Testing
Place SetupEnvironment.sh in your project root (or a bin/ directory) and make it executable:
chmod +x vendor/tedivm/dovecottesting/SetupEnvironment.sh
Call it in your phpunit.xml or tests/CreatesApplication (for Laravel 8+) via beforeTestClass:
<phpunit>
<php>
<ini name="include_path" value="./vendor"/>
</php>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory>./tests</directory>
</whitelist>
</filter>
<listeners>
<listener class="\Tests\Listeners\SetupDovecotListener" file="vendor/tedivm/dovecottesting/SetupEnvironment.sh"/>
</listeners>
</phpunit>
Alternative: Run it manually before tests:
vendor/tedivm/dovecottesting/SetupEnvironment.sh && phpunit
First Test Case
Use Laravel’s Mail facade or a library like spatie/laravel-imap to connect to the test server:
use Illuminate\Support\Facades\Mail;
use Spatie\Imap\Connection;
public function test_imap_connection()
{
$connection = new Connection(
config('mail.imap.host', '127.0.0.1'), // Travis
// config('mail.imap.host', '172.31.1.2'), // Vagrant
config('mail.imap.port', 143),
config('mail.imap.encryption', null),
config('mail.username', 'testuser'),
config('mail.password', 'applesauce')
);
$this->assertTrue($connection->connect());
$this->assertEquals(3, $connection->getMailbox('INBOX')->count()); // Pre-seeded emails
}
Bootstrap the VM
Run SetupEnvironment.sh once to provision the Dovecot VM (takes ~5 mins on first run). Subsequent runs reset the mailbox.
vendor/tedivm/dovecottesting/SetupEnvironment.sh
Test IMAP/POP Locally
Configure Laravel’s .env for Vagrant:
MAIL_IMAP_HOST=172.31.1.2
MAIL_IMAP_PORT=143
MAIL_USERNAME=testuser
MAIL_PASSWORD=applesauce
Add Custom Emails
testuser@172.31.1.2./var/mail/vmail/testuser/ (inside VM) to vendor/tedivm/dovecottesting/resources/.Automate in phpunit.xml
<listeners>
<listener class="\Tests\Listeners\DovecotSetupListener">
<arguments>
<object class="\Symfony\Component\Process\Process">
<constructor>
<argument value="vendor/tedivm/dovecottesting/SetupEnvironment.sh"/>
</constructor>
</object>
</arguments>
</listener>
</listeners>
Configure .travis.yml
before_script:
- composer install --dev
- vendor/tedivm/dovecottesting/SetupEnvironment.sh
Use CI-Specific Host
Override .env in CI:
MAIL_IMAP_HOST=127.0.0.1 # Travis default
MAIL_IMAP_PORT=143
Test Parallelization Since the VM resets per test, parallelize tests safely:
phpunit --parallel
Seed Test Emails
Use Laravel’s Mail::raw() in a test setup method:
public function setUp(): void
{
Mail::raw('Test email body', function ($message) {
$message->to('testuser@127.0.0.1')
->subject('Test Subject');
});
}
Verify Delivery Assert emails exist in the IMAP inbox:
public function test_email_delivery()
{
$this->assertEquals(4, $this->connection->getMailbox('INBOX')->count());
}
VM Inactivity Timeout
SetupEnvironment.sh before tests.vagrant up manually if tests hang, then reset with SetupEnvironment.sh.Host Resolution Issues
127.0.0.1; Vagrant: Uses 172.31.1.2. Hardcode the correct host in tests or use environment variables.config/mail.php override for testing:
'imap' => [
'host' => env('MAIL_IMAP_HOST', config('mail.host')),
'port' => env('MAIL_IMAP_PORT', 143),
],
Email Seed Data Persistence
/var/mail/vmail/testuser/ inside the VM won’t persist across SetupEnvironment.sh runs unless copied to the package’s resources/ directory.SSL/TLS Configuration
143/110). For encrypted tests:
SetupEnvironment.sh to enable SSL in Dovecot’s config.993 (IMAPS) or 995 (POPS) in your tests.PHP-Specific Quirks
DovecotTesting\Helper). For Laravel, extend these in a trait:
use DovecotTesting\Helper as Dovecot;
public function test_with_helper()
{
$this->assertTrue(Dovecot::isMailboxReady());
}
Check VM Logs SSH into the VM to debug Dovecot:
vagrant ssh
tail -f /var/log/dovecot.log
Verify Email Count
Use telnet to manually check IMAP:
telnet 172.31.1.2 143
a login testuser applesauce
a select INBOX
a fetch 1 BODY[]
Reset Stuck VM If the VM hangs, destroy and recreate it:
vagrant destroy -f && vagrant up
Custom Email Templates
Add emails to vendor/tedivm/dovecottesting/resources/ and update SetupEnvironment.sh to copy them:
cp -r /path/to/your/emails/* /var/mail/vmail/testuser/
Dynamic Test Data
Use Laravel’s DatabaseMigrations or DatabaseTransactions to sync test data with IMAP:
public function setUp(): void
{
$this->artisan('migrate:fresh');
// Trigger email sends via Laravel events
}
Multi-Language Support
Fork the package and adapt SetupEnvironment.sh for other languages (e.g., Python’s imaplib). Key changes:
provision.sh).Docker Alternative Replace Vagrant with Docker for CI:
# docker-compose.yml
services:
dovecot:
image: tedivm/dovecot-testing:latest
ports:
- "143:143"
Note: Requires rebuilding the Docker image with your custom emails.
How can I help you explore Laravel packages today?