Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Mailtrap Driver Laravel Package

manageitwa/laravel-mailtrap-driver

A Laravel mail driver for Mailtrap that plugs into Laravel's native mail system, letting you send mail through Mailtrap's service with simple config changes. Useful for testing, staging, and transactional email delivery.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is a thin, first-party-feeling transport driver: it teaches Laravel's Mail manager a new mailtrap mailer that talks to Mailtrap's HTTP API instead of SMTP. You do not change your Mailable classes at all — everything below is config plus one or two env vars.

Minimal setup:

  1. composer require laravel/mailtrap (pull it into require, not require-dev — you will likely want it in staging too).
  2. Add a mailtrap block to config/services.php holding your API token and the sandbox flag, e.g. api_key, sandbox, and the sandbox inbox id. Read the token from MAILTRAP_API_KEY rather than committing it.
  3. Add (or repoint) a mailer in config/mail.php with 'transport' => 'mailtrap', then set MAIL_MAILER=mailtrap in the environment you want to intercept.
  4. php artisan config:clear and send something — Mail::raw(...) from php artisan tinker is the fastest smoke test, because it exercises the transport without any Mailable or view rendering in the way.

Where to look first: the package's service provider (to see the exact config keys it reads and how the transport is resolved) and the underlying railsware/mailtrap-php client it wraps. Those two files tell you more about real-world behaviour than the release note does. Treat the key names as authoritative only once you've confirmed them in the provider — most first-run failures are a key that exists but is spelled differently than you assumed.

The canonical first use case is CI/local mail interception: sandbox mode swallows everything, gives you rendered HTML, plain text, spam score, and a shareable URL per message. That is a genuinely better workflow than Mailhog/Mailpit for anything you want a designer or PM to review.

Implementation Patterns

Two mailers, not one switch. Rather than flipping a boolean in one mailer definition, define both mailtrap (sandbox) and your production mailer side by side and choose per environment via MAIL_MAILER. It makes the intent readable in config/mail.php and makes an accidental production send require two mistakes instead of one.

Per-mailer overrides for edge cases. Mail::mailer('mailtrap')->to(...)->send(...) and $mailable->mailer('mailtrap') both work unchanged, so you can route only, say, transactional receipts to the sandbox during a migration while everything else goes live.

Keep Mail::fake() for logic tests, add one real transport test. Fake asserts the decision to send; it never touches credentials, host, or payload shape. A nightly job (or a single @group external test) that sends one real message to a sandbox inbox and asserts a 2xx/queued response is the cheapest possible guard against a silently broken token.

Queue your mailables and let the transport fail loudly. Because this is an HTTP call, not a socket, failures arrive as exceptions with a status code rather than a timeout. That is a feature: wrap the send in a job with $tries/backoff, and 429s become automatic retry pressure instead of lost mail.

Reach for the SDK for anything template-shaped. The transport only covers "send this MIME message." Mailtrap-side concerns — templates, bulk/batch sends, reading a sandbox inbox, cleaning it between test runs — belong to the underlying client. In CI, send → poll inbox → assert → delete is a legitimate end-to-end test pattern and is the main reason to prefer this driver over plain SMTP.

Dynamic credentials in multi-tenant apps. config(['services.mailtrap.api_key' => $tenant->token]) before the send works, but only in a request-scoped process. In a long-running queue worker, remember to reset it — a leaked token across tenants is the kind of bug that only shows up in production.

Decorator for observability. Since it implements the standard transport contract, you can wrap it with your own logging/metrics transport that delegates to the real one. That gives you per-message timing and provider response codes without forking the package.

Gotchas and Tips

  • Sandbox and live sending are different hosts and different APIs, not a debug flag. A misconfigured sandbox value on a production box sends real mail to real addresses. Add a hard guard (abort_unless(app()->isProduction() === false, ...) or an explicit allowlist) around any code path that lets a non-production env fall through to the live endpoint.
  • Sender domain verification is required for the sending API and not for the sandbox. The asymmetry means everything works locally and then 4xx's on deploy with an error that looks like an auth problem but is a DNS/SPF/DKIM problem on MAIL_FROM_ADDRESS's domain.
  • Config caching silently defeats you. config:cache during deploy means editing .env afterwards changes nothing. Same for queue workers: queue:restart after any credential or mailer change.
  • Exceptions bubble. A Mailtrap 5xx or a malformed address will throw out of Mail::send(). In a signup flow that means a 500 for an otherwise successful registration — queue the mail, or catch and log when delivery is not load-bearing.
  • Limits are real and arrive as 429. The free tier's throughput is low, and the per-message size cap counts encoded attachments. Base64 in a JSON payload also means a 20MB attachment is a 27MB string in memory; store large files and email a link.
  • Sandbox inbox state is shared and sticky. Tests that assert "the inbox has one message" fail the moment a colleague sends something through the same inbox. Scope by a unique subject tag and clean up after yourself, or use a dedicated inbox per pipeline.
  • Extension points worth knowing: Mail::extend('mailtrap', ...) lets you register the transport yourself if you need custom host resolution or a token provider, and you can always fall back to SMTP credentials in config/mail.php — the driver is a convenience, not a lock-in, so keep the SMTP path documented as an escape hatch.
  • Debug order for "mail isn't arriving": (1) php artisan about to confirm the effective mailer, (2) check config:cache staleness, (3) confirm you're pointed at the sandbox inbox you're actually looking at, (4) only then inspect the exception. Steps 1–3 explain the large majority of reports.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource