Last updated on October 18, 2026
Sending Emails in Laravel 13: Mailables, Queuing, and Resend

January 19, 2024 · 6 min read

This lesson is part of our free Laravel tutorial for beginners. The code examples use Laravel 13.
Email communication with Laravel
Whether you're sending out newsletters, post notifications, or password reset links, email communication is a staple of any application. Laravel simplifies the process of sending emails with its clean, expressive API and support for a variety of mail services.
Understanding email configuration in Laravel
Before you start sending emails, you'll need to configure your mail service in Laravel. The framework supports several drivers out of the box, including SMTP, Mailgun, Postmark, Amazon SES, and Resend. You can set up your mail configuration in the config/mail.php file and your .env file with details like your mail server, port, username, and password.
Here's an example .env configuration for an SMTP server using Mailtrap:
// Other options
MAIL_MAILER=smtp
MAIL_HOST=sandbox.smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=your_mailtrap_username
MAIL_PASSWORD=your_mailtrap_password
// Other optionsLocal email testing with Mailpit
For local development, a popular choice is Mailpit. Mailpit is a lightweight local SMTP server that captures all outgoing emails from your application and displays them in a web interface, without actually delivering them to real inboxes.
If you use Laravel Sail, Mailpit is already included. The web interface is available at http://localhost:8025. A fresh Laravel 13 app sets MAIL_MAILER=log, which writes emails to the log file instead. To send them to Mailpit, update your .env file:
MAIL_MAILER=smtp
MAIL_SCHEME=null
MAIL_HOST=127.0.0.1
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=nullMailpit runs as a separate program. Install it on your machine, or use Laravel Sail, which starts it for you. Then run your app as usual, for example with php artisan serve. Any emails sent by your application will appear at http://localhost:8025 instead of being delivered.
Note: Mailpit replaces Mailhog, which was previously the standard local mail catcher. If you have older projects using Mailhog, switch the host/port to the Mailpit defaults above.
Creating Mailables
In Laravel, each type of email sent by your application is represented as a "Mailable" class. You can generate a new mailable using the command:
php artisan make:mail NewPostPublished
This command creates a new mailable class in the app/Mail directory. Within this class, you define the content and configuration of your email. Here's a simple example:
namespace App\Mail;
use App\Models\Post;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class NewPostPublished extends Mailable
{
use Queueable, SerializesModels;
public function __construct(public Post $post)
{
}
public function envelope(): Envelope
{
return new Envelope(
subject: 'A New Post Has Been Published',
);
}
public function content(): Content
{
return new Content(
view: 'emails.posts.published',
with: [
'title' => $this->post->title,
'content' => $this->post->content,
],
);
}
}In the envelope method, you set the subject. In the content method, you specify the view that will be used as the email's content and pass any necessary data to the view.
Markdown Mailables
Laravel supports Markdown-based email templates, which give you access to pre-built email components like buttons, panels, and tables that are already styled for email clients. Generate a Markdown mailable with:
php artisan make:mail NewPostPublished --markdown=emails.posts.published
This creates both the mailable class and a Blade view in resources/views/emails/posts/published.blade.php. The view uses Laravel's Markdown mail components:
<x-mail::message>
# A New Post Has Been Published
We wanted to let you know that **{{ $post->title }}** has just been published.
<x-mail::button :url="url('/posts/'.$post->id)">
Read the Post
</x-mail::button>
Thanks,
{{ config('app.name') }}
</x-mail::message>Sending emails
To send an email, you use the Mail facade with the send method, passing in the mailable instance:
namespace App\Http\Controllers;
use App\Mail\NewPostPublished;
use App\Models\Post;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
class PostController extends Controller
{
public function store(Request $request)
{
// Other stuff
// Store the blog post...
$post = Post::create($request->all());
// Send the email
Mail::to('email@example.com')->send(new NewPostPublished($post));
// Other stuff
}
}This code is placed in a part of your application where the email should be sent, such as after a new post is created.

Queueing Emails
Sending emails synchronously during a request can slow down your application. Laravel allows you to queue emails for background sending, improving response time for your users:
namespace App\Http\Controllers;
use App\Mail\NewPostPublished;
use App\Models\Post;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
class PostController extends Controller
{
public function store(Request $request)
{
// Other stuff
// Store the blog post...
$post = Post::create($request->all());
// Send the email
Mail::to('email@example.com')->queue(new NewPostPublished($post));
// Other stuff
}
}To process queued emails, make sure you have set up your queue driver and are running a queue worker as we explained in a previous article.
Queueing via ShouldQueue on the Mailable
An alternative to calling ->queue() on the Mail facade is to implement the ShouldQueue interface directly on the Mailable class. When you do this, calling Mail::to(...)->send() will automatically queue the email:
use Illuminate\Contracts\Queue\ShouldQueue;
class NewPostPublished extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;
// The rest of the class stays the same.
// Calling Mail::to(...)->send(new NewPostPublished($post))
// will now automatically queue the email.
}This approach is cleaner when you always want a particular email to be queued, regardless of how it is dispatched in your controllers.

Sending Emails via Resend in Laravel 13
Laravel 13 includes a Resend mail driver. Resend is a developer-focused transactional email service with a simple API, generous free tier, and strong deliverability. To use it, set the following in your .env:
MAIL_MAILER=resend
RESEND_API_KEY=re_your_api_key_hereThe driver needs Resend's PHP SDK, so install it first with composer require resend/resend-php. Then get your API key from resend.com and set it as the RESEND_API_KEY environment variable. Make sure your sending domain is verified in the Resend dashboard.
Laravel 11 and 12 include the same Resend driver. The resend/laravel package from Resend is another way to set it up.
Testing emails with Mail::fake()
Laravel provides a Mail::fake() helper that prevents emails from actually being sent during tests. You can then assert that specific mailables were sent:
use Illuminate\Support\Facades\Mail;
use App\Mail\NewPostPublished;
public function test_email_is_sent_on_post_creation(): void
{
Mail::fake();
// Trigger the action
$this->post('/posts', ['title' => 'Hello World', 'content' => 'Content here']);
// Assert a mailable was sent to the correct address
Mail::assertSent(NewPostPublished::class, function ($mail) {
return $mail->hasTo('email@example.com');
});
// Assert a mailable was NOT sent
Mail::assertNotSent(AnotherMailable::class);
}If you want to test that an email was queued rather than sent immediately, use Mail::assertQueued() instead.
Conclusion
Sending emails in Laravel is a straightforward process that can greatly enhance the functionality of your application. Whether it's for user registration, post notifications, or marketing campaigns, Laravel's built-in email capabilities provide you with the tools to communicate effectively with your readers.
More Lessons in the Series
This article is part of our series Laravel for Beginners: A Step-by-Step Guide to Learn the Concepts.
Bring Your Ideas to Life 🚀
If you need help with a Laravel project let's get in touch.
Lucky Media is proud to be recognized as a leading Laravel Development Agency
Frequently Asked Questions
What is the best mail driver for Laravel in production?
For transactional email in production, dedicated sending services like Resend, Mailgun, Postmark, or Amazon SES are strongly preferred over raw SMTP. They provide high deliverability, bounce and complaint handling, and detailed analytics. Laravel 13 includes a Resend driver: install resend/resend-php, set MAIL_MAILER=resend and add your RESEND_API_KEY to get started.
How do I test emails locally in Laravel?
Use Mailpit, which is the default local mail catcher shipped with Laravel Sail. Mailpit captures all outgoing emails and shows them in a browser UI at http://localhost:8025. No emails are actually delivered. Point your app at Mailpit with the SMTP settings shown above in .env. For automated tests, use Mail::fake() to assert mailables without sending anything.
How do I queue emails in Laravel?
You have two options. First, call Mail::to(...)->queue(new YourMailable()) instead of ->send(). Second, implement the ShouldQueue interface on the Mailable class itself, which makes ->send() queue automatically. Either way, make sure your QUEUE_CONNECTION is set to something other than sync and that a queue worker is running.
What is the difference between a Mailable and a Notification in Laravel?
A Mailable is a dedicated class for a single email, it gives you full control over the template, subject, attachments, and headers. A Notification is a higher-level abstraction that can send messages across multiple channels (email, SMS, Slack, database) from a single class. For email-only communication, Mailables are more straightforward. For multi-channel alerts tied to a user or model event (such as a password reset or order shipped), Notifications are the better choice.
Technologies

Stay up-to-date
Be updated with all news, products and tips we share!
