承接 mailcapture/mailcapture-php 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

mailcapture/mailcapture-php

Composer 安装命令:

composer require --dev mailcapture/mailcapture-php

包简介

Official PHP SDK for the MailCapture email testing API

README 文档

README

Official PHP SDK for MailCapture — a real email capture API for integration testing OTP codes, verification links, and other transactional emails.

Requirements

  • PHP 8.1+
  • Guzzle 7 (guzzlehttp/guzzle)

Installation

composer require mailcapture/mailcapture-php

Quick start

use MailCapture\MailCapture;

$mc = new MailCapture($_ENV['MAILCAPTURE_API_KEY']);
$mc->ping();  // validates key, caches username

// In your test:
$mc->delete('signup');
$yourApp->register($mc->address('signup'));   // e.g. "alice-signup@mailcapture.app"
$email = $mc->waitFor('signup', timeout: 15.0);

echo $email->subject;   // "Verify your account"
echo $email->otp;       // "123456" — extracted automatically

The pattern for integration tests

use MailCapture\MailCapture;
use MailCapture\Model\Capture;
use PHPUnit\Framework\TestCase;

class UserRegistrationTest extends TestCase
{
    private static MailCapture $mc;

    public static function setUpBeforeClass(): void
    {
        self::$mc = new MailCapture($_ENV['MAILCAPTURE_API_KEY']);
        self::$mc->ping();
    }

    protected function setUp(): void
    {
        self::$mc->delete('signup');   // clean inbox before every test
    }

    public function testUserReceivesVerificationEmail(): void
    {
        $inbox = self::$mc->inbox('signup');

        $this->app->register($inbox->getAddress()); // "alice-signup@mailcapture.app"

        $email = $inbox->waitFor(timeout: 10.0);

        $this->assertSame('Verify your account', $email->subject);
        $this->assertMatchesRegularExpression('/^\d{6}$/', $email->otp);
        $this->assertLessThan(5000, $email->latencyMs);
    }
}

API reference

new MailCapture($apiKey, ...)

$mc = new MailCapture(
    apiKey: $_ENV['MAILCAPTURE_API_KEY'],
    baseUrl: 'http://localhost:3002',   // override for local dev (default: https://mailcapture.app)
    requestTimeout: 15.0,              // seconds, default 10.0
    username: 'alice',                 // pre-set to skip ping() (optional)
);

ping()PingResult

Validates your API key and returns your address template. Caches your username so address() works without a network call.

$result = $mc->ping();
echo $result->username;          // "alice"
echo $result->addressTemplate;   // "alice-{tag}@mailcapture.app"
echo $result->example;           // "alice-signup@mailcapture.app"

waitFor(tag, timeout, pollTimeout, after)Capture

Long-polls the API and returns the first email captured for the given tag. The server holds the connection open — no busy-waiting.

// Named arguments (recommended)
$email = $mc->waitFor('signup', timeout: 15.0);

// Full options
$email = $mc->waitFor(
    tag: 'signup',
    timeout: 15.0,           // total seconds to wait (default 30)
    pollTimeout: 5,           // per-poll server timeout in seconds, max 30 (default 10)
    after: new DateTime('-30 seconds'),  // only captures after this time
);

Throws MailCaptureTimeoutException if no email arrives in time.

inbox(tag)Inbox

Returns a scoped Inbox for a tag. Keeps test code clean.

$inbox = $mc->inbox('password-reset');

$inbox->getAddress()                    // "alice-password-reset@mailcapture.app"
$inbox->waitFor(timeout: 10.0)          // Capture
$inbox->list(limit: 5)                  // CaptureList
$inbox->clear()                         // deletes all captures for this tag

address(tag)string

Generates the capture email address synchronously. Requires ping() first (or username in the constructor).

$mc->ping();
echo $mc->address('signup');  // "alice-signup@mailcapture.app"

list(tag, limit, after)CaptureList

Lists recent captures (newest first).

$result = $mc->list(tag: 'signup', limit: 10);
foreach ($result->items as $email) {
    echo $email->subject . PHP_EOL;
}

get(captureId)Capture

Get a single capture by ID. Throws MailCaptureNotFoundException if not found.

delete(tag)void

Deletes all captures for a tag. Use in setUp() for test isolation.

The Capture object

$email->id          // string — UUID
$email->tag         // string — e.g. "signup"
$email->subject     // string — email subject line
$email->otp         // ?string — extracted code, null if none detected
$email->bodyText    // ?string — plain-text body
$email->bodyHtml    // ?string — HTML body
$email->latencyMs   // int — send-to-capture time in ms
$email->status      // string — e.g. "captured"
$email->receivedAt  // string — ISO 8601 timestamp

The otp field is extracted automatically. If your OTP is embedded in a sentence, the service finds it for you.

Exception handling

All exceptions extend MailCaptureException extends \RuntimeException and have getErrorCode().

use MailCapture\Exception\{
    MailCaptureAuthException,
    MailCaptureTimeoutException,
    MailCaptureNotFoundException,
    MailCaptureNetworkException,
};

try {
    $email = $mc->waitFor('signup', timeout: 10.0);
} catch (MailCaptureTimeoutException $e) {
    echo "Waited {$e->getWaitedSeconds()}s for tag: {$e->getTag()}" . PHP_EOL;
    echo "Did the email send? Check your email service logs." . PHP_EOL;
} catch (MailCaptureAuthException $e) {
    echo "Check your MAILCAPTURE_API_KEY environment variable." . PHP_EOL;
} catch (MailCaptureNetworkException $e) {
    echo "Network error: " . $e->getPrevious()?->getMessage() . PHP_EOL;
}
Exception getErrorCode() When
MailCaptureAuthException UNAUTHORIZED Invalid or revoked API key
MailCaptureTimeoutException TIMEOUT waitFor exceeded timeout
MailCaptureNotFoundException NOT_FOUND get() — capture not found
MailCaptureNetworkException NETWORK_ERROR Could not reach the API
MailCaptureApiException varies Unexpected API error

Testing with a mock HTTP client

Inject a Guzzle mock client to test your code without hitting the real API:

use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
use MailCapture\MailCapture;

$mock  = new MockHandler([
    new Response(200, ['Content-Type' => 'application/json'], json_encode([
        'items' => [[
            'id' => 'test-id', 'tag' => 'signup', 'subject' => 'Welcome',
            'otp' => '123456', 'body_text' => null, 'body_html' => null,
            'latency_ms' => 50, 'status' => 'captured',
            'received_at' => '2024-01-01T00:00:00+00:00',
        ]],
        'count' => 1,
        'next_after' => '2024-01-01T00:00:01+00:00',
    ])),
]);
$stack = HandlerStack::create($mock);
$mc    = new MailCapture('mc_testkey', httpClient: new Client(['handler' => $stack]));

$email = $mc->waitFor('signup', timeout: 5.0);
assert($email->otp === '123456');

Laravel / Symfony integration

// Laravel: AppServiceProvider
$this->app->singleton(MailCapture::class, fn() =>
    new MailCapture(config('services.mailcapture.key'))
);

// Symfony: services.yaml
services:
  MailCapture\MailCapture:
    arguments:
      $apiKey: '%env(MAILCAPTURE_API_KEY)%'

Local development

$mc = new MailCapture($_ENV['MAILCAPTURE_API_KEY'], baseUrl: 'http://localhost:3002');

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 2
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-22