PHPackages                             zerodrop/zerodrop - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Testing &amp; Quality](/categories/testing)
4. /
5. zerodrop/zerodrop

ActiveLibrary[Testing &amp; Quality](/categories/testing)

zerodrop/zerodrop
=================

Disposable email inboxes for testing auth flows in CI — OTPs and magic links auto-extracted. PHPUnit, Pest, Laravel Dusk. No regex, no Docker, no signup.

v0.1.0(1mo ago)00MITPHPPHP &gt;=8.1CI passing

Since Jul 13Pushed 1mo agoCompare

[ Source](https://github.com/zerodrop-dev/zerodrop-php)[ Packagist](https://packagist.org/packages/zerodrop/zerodrop)[ Docs](https://zerodrop.dev)[ RSS](/packages/zerodrop-zerodrop/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependenciesVersions (2)Used By (0)

zerodrop-php
============

[](#zerodrop-php)

[![Packagist Version](https://camo.githubusercontent.com/e4021b4cae88d20dbd61fc165f6f4f09ead2b9beb1f7012fb58ee07412d81773/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7a65726f64726f702f7a65726f64726f702e737667)](https://packagist.org/packages/zerodrop/zerodrop)[![CI](https://github.com/zerodrop-dev/zerodrop-php/actions/workflows/ci.yml/badge.svg)](https://github.com/zerodrop-dev/zerodrop-php/actions/workflows/ci.yml)[![license](https://camo.githubusercontent.com/fb14474ab26fe2a9697f48ae062927d4b3d79698b5a19747396fe06a9fb6ae6e/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f7a65726f64726f702d6465762f7a65726f64726f702d7068702e737667)](LICENSE)

Email verification infrastructure for CI pipelines.

Send a verification email. Catch it at the edge. Get `$email->otp` and `$email->magicLink` back — auto-extracted, no regex, no Docker, no signup.

```
$email = $mail->waitForLatest($inbox, timeout: 15);

$email->otp;       // "123456" — auto-extracted
$email->magicLink; // "https://..." — no regex needed
```

**[Documentation](https://docs.zerodrop.dev)** · [GitHub](https://github.com/zerodrop-dev) · [Status](https://zerodrop.instatus.com)

Install
-------

[](#install)

```
composer require --dev zerodrop/zerodrop
```

PHP 8.1+ · ext-curl · ext-json — no other dependencies.

Quick start
-----------

[](#quick-start)

```
use ZeroDrop\Client;

$mail = new Client();
$inbox = $mail->generateInbox();
// => "swift-x7k29ab@zerodrop-sandbox.online"

// Trigger your app's email flow with the inbox address...

$email = $mail->waitForLatest($inbox, timeout: 15);

$email->subject;   // "Verify your email"
$email->otp;       // "123456" — auto-extracted, no regex
$email->magicLink; // "https://..." — auto-extracted
```

PHPUnit
-------

[](#phpunit)

```
use PHPUnit\Framework\TestCase;
use ZeroDrop\Client;

final class SignupTest extends TestCase
{
    public function testEmailVerification(): void
    {
        $mail = new Client();
        $inbox = $mail->generateInbox();

        // Trigger signup with $inbox...

        $email = $mail->waitForLatest($inbox, timeout: 15);

        $this->assertNotNull($email->otp);
        $this->assertMatchesRegularExpression('/^\d{6}$/', $email->otp);
    }
}
```

Pest
----

[](#pest)

```
use ZeroDrop\Client;

it('verifies the account via emailed OTP', function () {
    $mail = new Client();
    $inbox = $mail->generateInbox();

    // Trigger signup with $inbox...

    $email = $mail->waitForLatest($inbox, timeout: 15);

    expect($email->otp)->not->toBeNull()
        ->and($email->otp)->toMatch('/^\d{6}$/');
});
```

Laravel Dusk
------------

[](#laravel-dusk)

```
use Laravel\Dusk\Browser;
use ZeroDrop\Client;

public function testSignupEmailVerification(): void
{
    $mail = new Client();
    $inbox = $mail->generateInbox();

    $this->browse(function (Browser $browser) use ($mail, $inbox) {
        $browser->visit('/signup')
                ->type('email', $inbox)
                ->type('password', 'TestPassword123!')
                ->press('Create account');

        $email = $mail->waitForLatest($inbox, timeout: 15);

        $browser->type('otp', $email->otp)
                ->press('Verify')
                ->assertPathIs('/dashboard');
    });
}
```

Email filtering
---------------

[](#email-filtering)

```
use ZeroDrop\Filter;

$email = $mail->waitForLatest(
    $inbox,
    timeout: 15,
    filter: new Filter(
        from: 'noreply@yourapp.com',
        subject: 'Verify',
        hasOtp: true,
    ),
);
```

All string filters are case-insensitive partial matches.

Magic link flows
----------------

[](#magic-link-flows)

```
$email = $mail->waitForLatest(
    $inbox,
    timeout: 15,
    filter: new Filter(hasMagicLink: true),
);

$browser->visit($email->magicLink)
        ->assertPathIs('/dashboard');
```

Parallel test runs
------------------

[](#parallel-test-runs)

`generateInbox()` runs locally — no network request, no collisions. Safe with Paratest and parallel Dusk runs; every call returns a unique isolated inbox.

Error handling
--------------

[](#error-handling)

```
use ZeroDrop\Exception\TimeoutException;
use ZeroDrop\Exception\AuthException;
use ZeroDrop\Exception\NetworkException;

try {
    $email = $mail->waitForLatest($inbox, timeout: 15);
} catch (TimeoutException $e) {
    // No email arrived — check your app is sending correctly
} catch (AuthException $e) {
    // Invalid API key
} catch (NetworkException $e) {
    // Transport failure — message includes status page link
}
```

Workspaces
----------

[](#workspaces)

```
$mail = new Client(apiKey: getenv('ZERODROP_API_KEY'));
```

Self-hosted
-----------

[](#self-hosted)

```
$mail = new Client(baseUrl: 'https://your-instance.yourdomain.com');
```

API
---

[](#api)

MethodDescription`new Client(?string $apiKey, string $baseUrl)`Create a client. No args = free sandbox mode.`generateInbox(): string`Instant inbox address. No network request.`fetchLatest(string $inbox, ?Filter $filter): ?Email`Latest matching email or null.`waitForLatest(string $inbox, float $timeout, float $pollInterval, ?Filter $filter): Email`Block until email arrives.Free vs Workspace
-----------------

[](#free-vs-workspace)

FreeWorkspaceInbox generation✓✓OTP auto-extraction✓✓Magic link extraction✓✓Email filtering✓✓Email retention30 minExtendedCustom domains✗✓Get a Workspace at [zerodrop.dev](https://zerodrop.dev)

License
-------

[](#license)

MIT

###  Health Score

33

—

LowBetter than 72% of packages

Maintenance90

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity32

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

48d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/f09287de3bd93eb4404c59262ae8dd2e20f72278f0b6093c70f04f21c90edb8e?d=identicon)[zerodrop](/maintainers/zerodrop)

---

Top Contributors

[![devdoc83](https://avatars.githubusercontent.com/u/280086534?v=4)](https://github.com/devdoc83 "devdoc83 (1 commits)")

---

Tags

email-testinglaravellaravel-duskotppestphpphpunittesting-toolstestingphpunitpestotpemailcimagic-linke2eemail-verificationLaravel Dusk

### Embed Badge

![Health badge](/badges/zerodrop-zerodrop/health.svg)

```
[![Health](https://phpackages.com/badges/zerodrop-zerodrop/health.svg)](https://phpackages.com/packages/zerodrop-zerodrop)
```

###  Alternatives

[rregeer/phpunit-coverage-check

Check the code coverage using the clover report of phpunit

626.8M237](/packages/rregeer-phpunit-coverage-check)[code-distortion/adapt

A Laravel package that builds databases for your tests, improving their speed.

3039.7k](/packages/code-distortion-adapt)[shipmonk/phpunit-parallel-job-balancer

Balances PHPUnit test execution across parallel jobs based on JUnit XML timing data

103.7k](/packages/shipmonk-phpunit-parallel-job-balancer)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
