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

Resend Laravel Laravel Package

resend/resend-laravel

Provides Resend integration for Laravel and Symfony Mailer, including a Resend facade and a ready-to-use Laravel mail transport. Install via Composer, set RESEND_API_KEY, and send emails through Resend with minimal configuration.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and set the API key:

composer require resend/resend-laravel
RESEND_API_KEY=re_123456789
MAIL_MAILER=resend

Add a Resend mailer to config/mail.php:

'resend' => [
    'transport' => 'resend',
],

The first place to look is the README’s two integration paths: the Laravel mailer and the Resend facade. For day-to-day work, start with the mailer because it preserves Laravel’s normal Mailable, queue, and mail-event workflow. Use the facade when you need Resend-specific API operations such as contacts, domains, topics, usage, or fine-grained email payloads.

A good first use case is a queued transactional email:

use App\Mail\WelcomeEmail;
use Illuminate\Support\Facades\Mail;

Mail::to($user->email)->queue(new WelcomeEmail($user));

Ensure the from address uses a verified Resend domain. For local experiments, Resend’s onboarding address may be useful, but production should use your own verified domain.

Implementation Patterns

Use the Laravel mailer for application email. Keep using Mailable, Blade/Markdown templates, Mail::to(), and ShouldQueue. The Resend transport sits behind Laravel’s mailer, so existing mail workflows mostly continue to work. This is the lowest-friction pattern for password resets, receipts, notifications, and onboarding sequences.

Use the facade for Resend-native operations. The facade is the escape hatch for operations that do not map cleanly to Laravel’s mailer:

use Resend\Laravel\Facades\Resend;

Resend::emails()->send([
    'from' => '[email protected]',
    'to' => '[email protected]',
    'subject' => 'hello world',
    'text' => 'it works!',
]);

Use this pattern for API-level features such as tags, idempotency keys, contacts, domains, topics, and usage checks. Keep these calls in small service classes or jobs rather than scattering facade calls through controllers.

Treat webhooks as the event backbone. The package includes webhook signature verification middleware and webhook processing support. A practical pattern is:

  • Register a POST webhook route.
  • Protect it with the package’s VerifyWebhookSignature middleware.
  • Validate the event type.
  • Dispatch a queued job for each event.
  • Deduplicate by event ID because webhook deliveries can be retried.

Supported event coverage has expanded over time: contact events, domain events, email.suppressed, contact-topic events, and topic created/updated/deleted events. Model your handlers around event type rather than around a single “webhook received” action.

Capture the Resend email ID. The package exposes X-Resend-Email-ID on the SentMessage instance after API sends. If your flow captures the sent message, store that ID against your application’s email log. It makes support, webhook correlation, and delivery debugging much easier.

Use tags and idempotency keys deliberately. Tags are useful for categorizing mail by product area, tenant, or campaign. Idempotency keys are useful for retryable sends: generate the key once per logical send and reuse it across retries. Do not generate a fresh key inside a retry loop, or you lose the protection.

Handle attachments through the mailer where possible. The package supports attachments, inline attachments, attachment MIME types, and inline content IDs. Prefer Laravel’s normal attachment APIs inside a Mailable; reserve direct facade payloads for cases where you need precise control over the Resend request body.

Separate “send mail” from “manage Resend resources.” A clean integration usually has:

  • Mailables for user-facing email.
  • Jobs for queued sending.
  • A small Resend service for contacts, domains, topics, and usage.
  • Webhook jobs for delivery/contact/domain events.

This keeps the package usage testable and avoids coupling domain logic to the facade.

Gotchas and Tips

Verify the sending domain first. Most “it sends in local but fails in production” issues are domain/from-address problems. Use a verified domain for production and keep the test/onboarding sender out of real customer flows.

The mailer and facade share the same API key. RESEND_API_KEY is used by both paths. If you use restricted API keys, confirm the key has the permissions needed for the operations you call through the facade, not just sending.

Clear config cache after environment changes. If MAIL_MAILER or RESEND_API_KEY changes do not appear to take effect, run:

php artisan config:clear

In deployed environments, rebuild the config cache after updating environment variables.

Webhook verification depends on the raw request body. Do not let middleware or custom parsing mutate the payload before signature verification. Keep the verification middleware early in the route stack, exclude the route from CSRF, and use the package’s webhook secret configuration consistently across environments. Log signature failures distinctly from handler failures.

Make webhook handlers idempotent. Resend webhooks can be retried. Store processed event IDs or use an upsert pattern so duplicate contact.updated, email.suppressed, or topic events do not double-apply side effects.

Do not confuse facade sends with Laravel mailer sends. The facade bypasses Laravel’s Mailable rendering and some of Laravel’s mail pipeline behavior. That is fine for API-style sends, but for normal application email prefer Mail::to()->send() or queue() so templates, localization, and mail events behave as expected.

Watch package and resend-php version alignment. The Laravel package is a thin adapter over resend/resend-php; minor releases often bump that dependency. Pin versions in production, read the changelog, and smoke-test sending plus webhooks after upgrades. Pay attention to changes such as inline attachment content ID naming and attachment/header fixes.

Catch transport failures around mail sends. The package’s transport factory uses Symfony mailer exceptions. If you need retry or fallback behavior, catch TransportExceptionInterface around the send or rely on queued job retries with a bounded attempt count.

Use Laravel’s testing tools at the right boundary. Mail::fake() is appropriate for mailables and queued mail assertions. For facade calls, isolate them behind your own service and fake/mock that service, or fake the HTTP boundary. Avoid hitting the real Resend API in the default test suite.

Use usage() and domain/contact APIs for operations, not just sending. The package is not only a transport. Day-to-day leverage comes from combining mail sending with contact/topic management, domain checks, webhook-driven suppression handling, and account usage visibility.

Keep webhook processing queued. Verify the signature in the request, then dispatch a job. This keeps the webhook endpoint fast and prevents Resend retries from turning into long-running request timeouts.

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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin