webteractive/mailulator
Composer 安装命令:
composer require --dev webteractive/mailulator
包简介
Self-hosted Laravel-native email testing service. Captures outbound email for inspection — installable into any Laravel app.
README 文档
README
Self-hosted, Laravel-native email testing. One package ships both sides:
- Receiver — stores ingested email in an isolated database (default SQLite; any Laravel-supported driver works), serves a Vue 3 inbox UI at
/mailulator. - Driver — a Symfony Mailer transport registered as
mailulator. SetMAIL_MAILER=mailulatorand outbound mail flows to the receiver — over HTTP for standalone deployments, in-process for in-app ones.
Requirements
- PHP
^8.3 - Laravel
^11 || ^12 || ^13
Install
composer require webteractive/mailulator php artisan mailulator:install
mailulator:install publishes:
app/Providers/MailulatorServiceProvider.php— customize the auth gate here.config/mailulator.php— receiver + driver config.
It then runs migrations against the isolated mailulator connection and creates a protected Default inbox (it cannot be renamed or deleted; at least one inbox must always exist).
The install prints the Default inbox's bearer token. In-app deployments don't need it for delivery, but save it anyway — any sender app you later point at this receiver will need it, and it isn't shown again.
Publish compiled UI assets:
php artisan vendor:publish --tag=mailulator-assets
Re-run this tag after each composer update.
Deployment modes
Two shapes, distinguished by where the inbox UI lives.
1. In-app — UI lives with the app it captures
The app sending the mail is also the app you read it from. Install Mailulator there, set MAIL_MAILER=mailulator, and the captured mail shows up at /mailulator on the same host. One app, one inbox, no plumbing.
# .env
MAIL_MAILER=mailulator
No URL, no token. The transport detects in-app mode (driver enabled + receiver enabled + no MAILULATOR_URL) and writes directly to the Default inbox via StoreIncomingEmail, bypassing HTTP entirely. Open /mailulator on the same app to read the captured mail.
Best for: local development, staging, demo environments — any app that just wants to "swallow" its own outbound mail and read it back in place.
2. Standalone — UI lives in a dedicated app, shared by many senders
A single Laravel app exists just to host inboxes and the UI. Any number of other apps point at it via MAILULATOR_URL and route to the right inbox via MAILULATOR_TOKEN. One UI, many senders.
On the standalone receiver — install the package as receiver-only:
# .env
MAILULATOR_RECEIVER_ENABLED=true
MAILULATOR_DRIVER_ENABLED=false
Create one inbox per sender app from the UI (or reuse the seeded Default). Each inbox has its own bearer token; that token is the only thing that ties a sender to its inbox.
On each sender app — install the package as driver-only and point it at the receiver with the inbox's token:
# .env MAIL_MAILER=mailulator MAILULATOR_URL=https://mailulator.your-domain.test MAILULATOR_TOKEN=<token for this app's inbox> MAILULATOR_RECEIVER_ENABLED=false MAILULATOR_DRIVER_ENABLED=true
To onboard another sender app, repeat the sender-side .env with a different inbox token. The receiver doesn't care how many apps point at it. Open /mailulator on the receiver to read mail across all inboxes.
Gate
The SPA is gated. Edit app/Providers/MailulatorServiceProvider.php:
protected function gate(): void { Gate::define('viewMailulator', fn ($user) => in_array(optional($user)->email, [ 'you@example.com', ]) ); }
Default: local environment only. Non-local without a customized gate → 403.
Optional hooks in the same provider:
public function boot(): void { parent::boot(); Mailulator::canViewInbox(fn ($user, $inboxId) => $user->inboxes()->where('inboxes.id', $inboxId)->exists() ); Mailulator::manage(fn ($user) => $user->is_admin ?? false); }
Sender-side (.env)
| Variable | Default | Purpose |
|---|---|---|
MAIL_MAILER |
— | Set to mailulator to route outbound email through this driver. |
MAILULATOR_URL |
— | Base URL of the receiver. |
MAILULATOR_TOKEN |
— | Per-inbox bearer token printed by mailulator:install or the admin UI. |
MAILULATOR_TIMEOUT |
5 |
HTTP timeout (seconds) for ingest calls. |
MAILULATOR_ON_FAILURE |
log |
log (warn + return), silent (return), or throw (raise TransportException). |
MAILULATOR_DRIVER_ENABLED |
true |
Set false to install as receiver-only. |
A receiver outage will not break the sender app's request unless MAILULATOR_ON_FAILURE=throw.
Receiver-side (.env)
| Variable | Default | Purpose |
|---|---|---|
MAILULATOR_RECEIVER_ENABLED |
true |
Turn receiver off to install as driver-only. |
MAILULATOR_DB_CONNECTION |
mailulator |
Connection name to use. Set to any connection defined in your host app's config/database.php (e.g. mysql) to share that DB; leave as mailulator for an isolated, package-managed connection. |
MAILULATOR_DB_DRIVER |
sqlite |
Driver for the auto-managed connection — only used when MAILULATOR_DB_CONNECTION=mailulator and the host hasn't pre-defined it. |
MAILULATOR_SQLITE_PATH |
database_path('mailulator.sqlite') |
SQLite file, auto-touched. |
MAILULATOR_DB_HOST / _PORT / _DATABASE / _USERNAME / _PASSWORD / _CHARSET |
— | Credentials for the auto-managed connection (non-SQLite drivers). |
MAILULATOR_ATTACHMENTS_DISK |
local |
Filesystem disk for attachment bytes. |
MAILULATOR_RATE_LIMIT |
600 |
Ingest requests/min per inbox. |
MAILULATOR_RETENTION_DAYS |
30 |
Default retention for newly created inboxes. Per-inbox override available; null keeps forever. |
MAILULATOR_UI_PATH |
mailulator |
SPA path prefix. |
MAILULATOR_UI_DOMAIN |
— | Optional subdomain (e.g. mail.your-staging.com). |
MAILULATOR_REALTIME_ENABLED |
true |
Master switch for realtime updates. |
MAILULATOR_REALTIME |
polling |
polling or broadcast. |
MAILULATOR_POLL_INTERVAL |
3 |
Polling interval (seconds). |
MAILULATOR_BROADCASTER |
reverb |
reverb or pusher when MAILULATOR_REALTIME=broadcast. |
Ingest API
POST /api/emails — bearer-token authenticated, rate-limited per inbox.
Accepts JSON (base64 attachments) or multipart/form-data (UploadedFile attachments). Returns 201 { "id": <email_id> }.
Realtime
Three states, controlled by two env vars:
MAILULATOR_REALTIME_ENABLED |
MAILULATOR_REALTIME |
Behavior |
|---|---|---|
true (default) |
polling (default) |
UI polls every MAILULATOR_POLL_INTERVAL seconds. Zero extra deps. |
true |
broadcast |
Echo subscribes to mailulator.inbox.{id} private channels. |
false |
— | Static UI. No polling, no broadcast. |
To enable broadcasting, install Reverb / Pusher in the host app, then:
MAILULATOR_REALTIME=broadcast
MAILULATOR_BROADCASTER=reverb
MAILULATOR_ECHO_KEY=...
MAILULATOR_ECHO_CLUSTER=... # Pusher only
MAILULATOR_ECHO_HOST=... # Reverb only
MAILULATOR_ECHO_PORT=...
MAILULATOR_ECHO_SCHEME=https
EmailReceived dispatches to mailulator.inbox.{id} on every ingest. Channel authorization routes through Mailulator::canViewInbox. If MAILULATOR_REALTIME=broadcast is set without a configured MAILULATOR_ECHO_KEY, the client logs a warning and falls back to polling.
Inboxes
- Each inbox has a name, optional retention period, optional color (UI accent), and a hashed bearer token.
- The seeded
Defaultinbox is protected — it cannot be renamed or deleted. - The last remaining inbox cannot be deleted regardless of name.
- Regenerating a key invalidates the previous token immediately at the ingest boundary.
Retention
Set retention_days per inbox; the daily PruneEmails job deletes older emails and cleans their attachment files. null = keep forever.
The job is auto-scheduled. Ensure your host app runs schedule:run via cron or schedule:work.
Upgrade
composer update webteractive/mailulator php artisan vendor:publish --tag=mailulator-assets --force php artisan migrate --database=mailulator
License
MIT.
webteractive/mailulator 适用场景与选型建议
webteractive/mailulator 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 0 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 04 月 25 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「mail」 「testing」 「email」 「laravel」 「staging」 「mailtrap」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 webteractive/mailulator 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 webteractive/mailulator 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 webteractive/mailulator 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Testing Suite For Lumen like Laravel does.
Courier offers a convenient and painless solution for creating emails tailored for your Kirby website.
The PHP SDK for Checkmango
Mail libraries used by Zimbra Api
Extensible library for building notifications and sending them via different delivery channels.
Email+ extends Kirby's email capabilities by adding support for multiple email services using the same Kirby email API.
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 38
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-04-25