resend/resend-php
Official Resend PHP SDK (PHP 8.1+) for sending emails via the Resend API. Install with Composer, create a client with your API key, and send emails with a simple emails->send() call. Inspired by openai-php.
Install the package:
composer require resend/resend-php
Initialize the client in your Laravel service provider or a dedicated config file:
use Resend\ResendClient;
$resend = new ResendClient('re_your_api_key_here');
Store the API key in Laravel’s .env for security:
RESEND_API_KEY=re_your_api_key_here
First use case: Send a transactional email (e.g., password reset):
$resend->emails->send([
'from' => 'no-reply@yourdomain.com',
'to' => ['user@example.com'],
'subject' => 'Reset Your Password',
'html' => '<p>Click <a href="...">here</a> to reset.</p>',
]);
Mail facade).ResendClient (root client)Emails (for sending/retrieving emails)Contacts (for managing subscribers)Templates (for reusable email designs).Bind the client to Laravel’s container in AppServiceProvider:
public function register()
{
$this->app->singleton(ResendClient::class, function ($app) {
return new ResendClient(config('services.resend.key'));
});
}
Configure in config/services.php:
'resend' => [
'key' => env('RESEND_API_KEY'),
'api_url' => env('RESEND_API_URL', 'https://api.resend.com'), // Optional override
],
Extend Laravel’s Mailable to use Resend:
use Resend\ResendClient;
use Illuminate\Mail\Mailable;
class ResetPasswordMail extends Mailable
{
public function build()
{
$resend = app(ResendClient::class);
return $this->markdown('emails.reset')
->with(['url' => $this->url])
->to($this->user->email)
->subject('Reset Your Password');
}
// Override send() to use Resend
public function send($failOnFailure = true)
{
$resend = app(ResendClient::class);
$resend->emails->send([
'from' => config('mail.from.address'),
'to' => [$this->user->email],
'subject' => $this->subject,
'html' => $this->buildView($this->view),
]);
}
}
Use Laravel Queues with Resend:
// Dispatch a queued job
ResetPasswordJob::dispatch($user);
// Job implementation
public function handle()
{
$resend = app(ResendClient::class);
$resend->emails->send([
'from' => 'no-reply@yourdomain.com',
'to' => [$this->user->email],
'subject' => 'Your Password Reset Link',
'html' => $this->generateHtml(),
]);
}
$resend->emails->send([
'from' => 'support@yourdomain.com',
'to' => ['user@example.com'],
'subject' => 'Your Invoice',
'html' => '<p>Please find attached...</p>',
'attachments' => [
[
'filename' => 'invoice.pdf',
'content' => file_get_contents('path/to/invoice.pdf'),
'type' => 'application/pdf',
],
],
]);
// Create a template (one-time setup)
$resend->templates->create([
'name' => 'Welcome Email',
'subject' => 'Welcome to {{company}}!',
'html' => '<p>Hello {{name}}!</p>',
]);
// Send using the template
$resend->emails->send([
'from' => 'welcome@yourdomain.com',
'to' => ['user@example.com'],
'template_id' => 'template_id_here',
'template_data' => [
'name' => 'John Doe',
'company' => 'Acme Inc.',
],
]);
// Add a contact
$resend->contacts->create([
'email' => 'user@example.com',
'first_name' => 'John',
'last_name' => 'Doe',
]);
// Update contact properties
$resend->contacts->updateProperties('user@example.com', [
'custom_properties' => [
'tier' => 'premium',
],
]);
// List contacts in a segment
$contacts = $resend->contacts->list(['segment_id' => 'segment_123']);
$resend->emails->batch([
'emails' => [
[
'from' => 'newsletter@yourdomain.com',
'to' => ['user1@example.com'],
'subject' => 'Weekly News',
'html' => '<p>Newsletter content...</p>',
],
[
'from' => 'newsletter@yourdomain.com',
'to' => ['user2@example.com'],
'subject' => 'Weekly News',
'html' => '<p>Newsletter content...</p>',
],
],
'batch_validation' => true, // Validate before sending
]);
$resend->emails->send([
'from' => 'reminders@yourdomain.com',
'to' => ['user@example.com'],
'subject' => 'Your Scheduled Reminder',
'html' => '<p>This email is scheduled!</p>',
'schedule' => [
'time' => '2024-12-31T12:00:00Z', // ISO 8601 format
],
]);
Wrap Resend calls in try-catch blocks:
try {
$resend->emails->send([...]);
} catch (ResendException $e) {
Log::error('Resend error: ' . $e->getMessage(), [
'code' => $e->getCode(),
'response' => $e->getResponse(),
]);
// Retry logic or fallback (e.g., queue the email again)
$this->retryEmail($emailData);
}
Verify and handle Resend webhooks in Laravel:
// In routes/web.php
Route::post('/resend-webhook', function (Request $request) {
$resend = app(ResendClient::class);
$payload = $request->getContent();
$signature = $request->header('X-Resend-Signature');
try {
$resend->webhooks->verify($payload, $signature);
// Process the webhook event
$event = json_decode($payload, true);
// Handle $event (e.g., email opened, bounced)
} catch (ResendException $e) {
abort(401, 'Invalid webhook signature');
}
});
.env and config/services.php.429 Too Many Requests errors gracefully:
try {
$resend->emails->send([...]);
} catch (ResendException $e) {
if ($e->getCode() === 429) {
sleep($e->getRetryAfter()); // Respect Retry-After header
retry();
}
}
batch_validation: true for batch emails to catch invalid addresses upfront.invalid_to_address errors:
catch (ResendException $e) {
if ($e->getCode() === 4
How can I help you explore Laravel packages today?