resend/resend-php
Resend PHP is an official PHP 8.1+ client for the Resend email API. Install via Composer and send transactional emails with a clean, simple interface (e.g., $resend->emails->send) in PHP or Laravel.
Install the package:
composer require resend/resend-php
Initialize the client (e.g., in config/services.php):
'resend' => [
'api_key' => env('RESEND_API_KEY'),
'api_url' => env('RESEND_API_URL', 'https://api.resend.com'),
],
Then create a helper in app/Providers/AppServiceProvider.php:
public function boot()
{
$this->app->singleton(Resend::class, function ($app) {
return Resend::client($app['config']['services.resend.api_key'], [
'api_url' => $app['config']['services.resend.api_url'],
]);
});
}
First email send (e.g., in a controller):
use Resend\Resend;
public function sendWelcomeEmail()
{
$resend = app(Resend::class);
$response = $resend->emails->send([
'from' => 'onboarding@example.com',
'to' => 'user@example.com',
'subject' => 'Welcome!',
'html' => '<strong>Welcome to our platform!</strong>',
]);
return response()->json($response);
}
events or logs endpoints.Email Sending
emails->send() with from, to, subject, and html/text.$resend->emails->send([
'from' => 'team@example.com',
'to' => 'user@example.com',
'template_id' => 'abc123',
'template_data' => ['name' => 'John'],
]);
$resend->emails->batch([
'emails' => [
['to' => 'user1@example.com', 'subject' => 'Hello'],
['to' => 'user2@example.com', 'subject' => 'Hi'],
],
'options' => ['batch_validation' => true],
]);
Contacts Management
contacts->create(), contacts->get(), etc.$resend->contacts->segments->add([
'segment_id' => 'segment_123',
'contact_ids' => ['contact_456'],
]);
Webhooks & Events
WebhookSignature verifier:
$verifier = new \Resend\WebhookSignature($this->request->header('X-Resend-Signature'));
if ($verifier->verify($this->request->getContent(), env('RESEND_WEBHOOK_SECRET'))) {
// Process event
}
events->list() or subscribe to topics.Templates & Domains
templates->create().$resend->domains->verify([
'domain' => 'example.com',
'dns_records' => ['type' => 'TXT', 'value' => 'resend=...'],
]);
Mailable to use Resend:
use Resend\Resend;
public function build()
{
$resend = app(Resend::class);
$this->withSwiftMessage(function ($message) use ($resend) {
$message->setFrom('onboarding@example.com');
$message->setTo('user@example.com');
// Use Resend’s API for advanced features like templates
});
}
use Resend\Resend;
use Illuminate\Bus\Queueable;
class SendEmailJob implements Queueable
{
public function handle(Resend $resend)
{
$resend->emails->send([...]);
}
}
API Key Exposure
RESEND_API_KEY in source. Use Laravel’s .env and config/services.php.Idempotency Keys
idempotency_key for critical emails (e.g., payments) to avoid duplicates:
$resend->emails->send([
'from' => 'payments@example.com',
'to' => 'user@example.com',
'subject' => 'Payment Received',
'headers' => ['Idempotency-Key' => 'unique_key_123'],
]);
Template Data Validation
template_data keys. Validate against the template’s schema before sending.Rate Limits
429 Too Many Requests errors. Implement exponential backoff:
try {
$resend->emails->send([...]);
} catch (\Resend\Exception\RateLimitException $e) {
sleep($e->getRetryAfter());
retry();
}
Webhook Delays
events->list() for critical syncs.debug: true in the client config to log requests/responses.4xx for client errors (e.g., 400 for invalid emails). Use:
try {
$resend->emails->send([...]);
} catch (\Resend\Exception\ResendException $e) {
Log::error('Resend error: ' . $e->getMessage());
}
TXT records are correctly propagated (use dig or nslookup).Custom HTTP Client Override the default Guzzle client for retries or middleware:
$client = new \Resend\Client($apiKey, [
'http_client' => new \GuzzleHttp\Client([
'timeout' => 30,
'headers' => ['User-Agent' => 'MyApp/1.0'],
]),
]);
Event Handlers
Extend the Event class to add custom logic:
class CustomEvent extends \Resend\Event
{
public function handle()
{
if ($this->event === 'email.bounce') {
// Custom bounce logic
}
}
}
Mocking for Tests
Use Laravel’s Mockery to stub the client:
$mock = Mockery::mock(Resend::class);
$mock->shouldReceive('emails->send')->once()->andReturn(['success' => true]);
$this->app->instance(Resend::class, $mock);
Laravel Notifications
Create a custom ResendChannel:
use Resend\Resend;
class ResendChannel implements ShouldQueue
{
public function __construct(protected Resend $resend) {}
public function send($notifiable, Notification $notification)
{
$this->resend->emails->send([
'from' => config('mail.from.address'),
'to' => $notifiable->getEmailForNotification($notification),
'subject' => $notification->subject(),
'html' => $notification->toHtml($notifiable),
]);
}
}
emails->list() to audit sent emails (filter by created_at).contacts->upsert() to update user properties in bulk.schedule option for time-based sends:
$resend->emails->send([
'from' => 'reminders@example.com',
'to' => 'user@example.com',
'subject' => 'Your Reminder',
'schedule' => ['send_at' => '2023-12-31T12:00:00Z'],
]);
How can I help you explore Laravel packages today?