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

Mailtrap Php Laravel Package

railsware/mailtrap-php

Official Mailtrap PHP SDK for Laravel and plain PHP apps. Send transactional email, manage templates and contacts, and integrate Mailtrap’s testing sandbox and email API workflows through a lightweight, framework-agnostic client.

View on GitHub
Deep Wiki
Context7

Getting Started

mailtrap/mailtrap-php is the official Mailtrap API SDK, not a full Laravel mail transport. In a Laravel app it lives alongside your normal mailer and covers what SMTP can't: sandbox inspection, bulk/batch sending, contacts, templates, and now inbound email (rules + threads).

  1. composer require mailtrap/mailtrap-php (3.16.0 is additive — safe bump from 3.15.x).
  2. Grab a token from the Mailtrap dashboard: a sandbox token and an inbox ID for local/staging, and a sending token tied to a verified domain for production.
  3. Register the client as a singleton in a service provider, reading credentials from config/services.php:
$this->app->singleton(MailtrapClient::class, fn () => MailtrapSdk::client(
    new Config(
        app()->environment('production')
            ? new BearerAuthCredentials(config('services.mailtrap.api_token'))
            : new BearerAuthCredentials(config('services.mailtrap.sandbox_token')),
        app()->environment('production') ? null : (int) config('services.mailtrap.inbox_id'),
    )
));

First use case: send one templated transactional email from a tinker session or an artisan command against the sandbox, then confirm it appears in the sandbox inbox. That single loop validates credentials, inbox ID, and template UUID wiring before you build anything else. Look first at the Email builder (Email::buildWithTemplate/buildWithHtml/buildWithText) and the sandbox/sending split — almost every early bug is one of those two.

Implementation Patterns

Environment-driven client. Bind one singleton that switches sandbox vs. sending by environment, so controllers and jobs never know which one they're talking to. Keeps test code identical to production code.

Transactional mail via templates. Build the message, don't hand-assemble HTML:

$email = Email::buildWithTemplate($templateUuid)
    ->subject('Your receipt')
    ->from(new Address('[email protected]', 'Billing'))
    ->to(new Address($user->email, $user->name))
    ->customVariables(['order_id' => $order->id, 'total' => $order->formatted_total]);

$mailtrap->send($email);

Wrap this in a queued job with $tries/backoff so a Mailtrap 5xx or 429 doesn't fail the user request.

Bulk/batch sending. For digests and newsletters, use the batch builder to send up to 500 personalised messages in one API call rather than looping send() — dramatically fewer round trips and cleaner rate-limit behaviour. Chunk larger audiences into batches.

Template API (new in 3.16.0). The paginated /api/templates endpoints are the interesting part for Laravel teams: you can now treat Mailtrap templates as versioned artefacts. Two patterns worth adopting:

  • Provisioning: a deploy/artisan command that pushes templates from resources/mailtrap/*.html and stores the returned UUIDs in config or DB.
  • Discovery: list templates once and cache the name→UUID map, instead of hardcoding UUIDs per environment (sandbox UUIDs differ from production).

Because the endpoints are paginated, always iterate pages rather than assuming a single call returns everything:

foreach ($mailtrap->templates()->list() as $template) { /* first page */ }
// iterate subsequent pages until exhausted; cache the result

Check the generated API reference for the exact paginator/iterator method names on these endpoints before wiring them in.

Inbound email (new in 3.16.0). Forward rules let you route inbound mail to an HTTP endpoint or address; threads search lets you pull a conversation by participants/subject. That's a credible path to a support-inbox feature without a second ESP: receive via Mailtrap, persist the thread ID, and reply through the sending API so the thread stays coherent.

Integration tip: keep the SDK behind a thin MailtrapMailer-style wrapper class in your app. Every call site then goes through one place you can stub, log, and later swap — the SDK's objects are otherwise easy to leak into controllers.

Gotchas and Tips

  • Mail::fake() will not see these sends. The SDK talks to the HTTP API directly, bypassing Laravel's mail manager, so mail events, Mail::assertSent, and log-based assertions don't apply. Test by faking your wrapper class, or point tests at the sandbox and assert on the sandbox API.
  • Sandbox vs. sending tokens are not interchangeable, and sandbox calls need an inbox ID. A missing inbox ID in non-prod is the single most common "it silently does nothing" cause.
  • The from domain must be verified on the sending domain, or the request fails validation regardless of token scope.
  • Rate limits are per-account. Catch the API exception, inspect the status code, and retry with backoff on 429/5xx only. Don't blanket-retry 4xx — validation errors will never succeed.
  • Attachments: prefer the file-path or base64 helpers over raw content; large base64 payloads hit request-size limits before they hit Mailtrap's attachment limit.
  • customVariables vs template merge fields are distinct concepts — a variable that renders as blank in the delivered mail is usually the wrong one of the two.
  • Pagination: the new template endpoints are paginated; a naive single call gives you a partial list and intermittent "template not found" in fresh environments. Assert on page counts in your provisioning command.
  • Debugging: keep the SDK's HTTP client configurable (timeouts, retries, and a PSR-18 client you can decorate with logging middleware). Log request IDs from failed responses — Mailtrap support will ask for them.
  • Extension points: the Config object and the injectable HTTP client are the two seams worth using; wrap them in your own container bindings so you can swap transports in tests without touching call sites.
  • Version pinning: 3.16.0 is additive over 3.15.0 with no deprecations, so ^3.16 is a comfortable constraint — but pin the minor if you're adopting the new template/inbound endpoints in a deploy pipeline, since their surface is still young.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
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