Trong các bài trước, chúng ta đã đi qua:
Observer
Event & Listener
Queue
Đến Bài 36, chúng ta bắt đầu một chức năng rất quan trọng trong các ứng dụng web thực tế:
📧 Gửi Email bằng Laravel
Email có thể được sử dụng cho:
✉️ Xác nhận đăng ký tài khoản
🔐 Đặt lại mật khẩu
📩 Thông báo khi có bài viết mới
🛒 Xác nhận đơn hàng
💳 Thông báo thanh toán
👤 Thông báo tài khoản
📢 Gửi thông báo hệ thống
📎 Gửi email kèm file
⚙️ Kết hợp Email + Queue để gửi email ở background
Laravel cung cấp một API gửi mail thống nhất dựa trên Symfony Mailer, hỗ trợ nhiều mail transport như SMTP, Mailgun, Postmark, Amazon SES và sendmail. (Laravel)
📚 NỘI DUNG BÀI 36
Trong bài này chúng ta sẽ xây dựng hệ thống email theo mô hình:
Laravel
│
├── Mailable
│
├── Blade Email
│
├── Mail Configuration
│
├── SMTP
│
├── Send Email
│
├── Attachment
│
├── Markdown Email
│
├── Preview Email
│
└── Queue Email1. 📧 Mail trong Laravel là gì?
Trong Laravel, mỗi loại email thường được biểu diễn bởi một class gọi là Mailable.
Ví dụ:
app/
└── Mail/
├── WelcomeUser.php
├── OrderShipped.php
└── ResetPassword.phpMỗi Mailable chịu trách nhiệm mô tả một loại email.
Ví dụ:
WelcomeUser
↓
Email chào mừng
OrderShipped
↓
Email thông báo giao hàng
InvoicePaid
↓
Email thông báo thanh toánLaravel tạo Mailable bằng Artisan:
php artisan make:mail WelcomeUserSau khi chạy lệnh, Laravel tạo class trong:
app/Mail/WelcomeUser.phpĐây là cách chính thức Laravel sử dụng để tạo Mailable. (Laravel)
2. ⚙️ Cấu hình Mail
Thông tin mail của ứng dụng thường được cấu hình thông qua:
.envvà:
config/mail.phpVí dụ .env:
MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME="your@gmail.com"
MAIL_PASSWORD="your_app_password"
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="your@gmail.com"
MAIL_FROM_NAME="${APP_NAME}"Không nên viết trực tiếp username/password vào source code.
Thay vào đó:
.env
↓
config/mail.php
↓
Laravel Mail
↓
SMTP Server3. 📨 Tạo Mailable
Tạo email:
php artisan make:mail WelcomeUserLaravel sẽ tạo:
app/Mail/WelcomeUser.phpMột Mailable hiện đại có thể sử dụng:
envelope()
content()
attachments()Ví dụ:
<?php
namespace App\Mail;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
class WelcomeUser extends Mailable
{
public function envelope(): Envelope
{
return new Envelope(
subject: 'Chào mừng bạn đến với website',
);
}
public function content(): Content
{
return new Content(
view: 'emails.welcome',
);
}
}Trong đó:
envelope()dùng để cấu hình thông tin email.
content()dùng để xác định nội dung email.
Laravel hiện sử dụng Envelope và Content trong cấu trúc Mailable hiện đại. (Laravel)
4. 🎨 Tạo giao diện Email bằng Blade
Tạo file:
resources/views/emails/welcome.blade.phpVí dụ:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Chào mừng</title>
</head>
<body>
<h1>Chào mừng bạn!</h1>
<p>
Cảm ơn bạn đã đăng ký tài khoản.
</p>
</body>
</html>Laravel sử dụng Blade để render HTML email giống như các View thông thường. (Laravel)
5. 👤 Truyền dữ liệu vào Email
Giả sử chúng ta muốn gửi tên người dùng.
Mailable:
<?php
namespace App\Mail;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
class WelcomeUser extends Mailable
{
public function __construct(
public string $name
) {}
public function envelope(): Envelope
{
return new Envelope(
subject: 'Chào mừng bạn!',
);
}
public function content(): Content
{
return new Content(
view: 'emails.welcome',
);
}
}Blade:
<h1>
Xin chào {{ $name }}
</h1>
<p>
Chào mừng bạn đến với website.
</p>Khi Laravel render View:
$name
↓
Blade
↓
HTML Email6. 🚀 Gửi Email
Laravel cung cấp Mail facade.
use Illuminate\Support\Facades\Mail;
use App\Mail\WelcomeUser;Sau đó:
Mail::to($user->email)
->send(new WelcomeUser($user->name));Ví dụ trong Controller:
public function welcome()
{
$user = auth()->user();
Mail::to($user->email)
->send(
new WelcomeUser($user->name)
);
return back();
}Luồng hoạt động:
Controller
↓
Mail::to()
↓
WelcomeUser
↓
Blade
↓
SMTP
↓
Email người nhận7. 📮 Gửi cho nhiều người
Có thể gửi email tới nhiều địa chỉ.
Ví dụ:
Mail::to([
'user1@example.com',
'user2@example.com',
])
->send(new WelcomeUser('Các bạn'));Ngoài to(), hệ thống email còn có thể sử dụng các địa chỉ như:
->cc()và:
->bcc()Ví dụ:
Mail::to($user->email)
->cc('admin@example.com')
->send(
new WelcomeUser($user->name)
);8. 📎 Gửi Email kèm File
Một email thực tế đôi khi cần gửi:
PDF
Hóa đơn
Báo giá
Báo cáo
Hình ảnh
File Excel
Trong Mailable có thể định nghĩa:
public function attachments(): array
{
return [
Attachment::fromPath(
storage_path('app/invoices/invoice.pdf')
),
];
}Import:
use Illuminate\Mail\Mailables\Attachment;Laravel hỗ trợ cấu hình attachment trực tiếp trong Mailable. (Laravel)
9. 📝 Markdown Email
Laravel còn hỗ trợ Markdown Mailables.
Thay vì tự viết toàn bộ HTML:
<table>
<tr>
<td>
...chúng ta có thể sử dụng Markdown.
Tạo Mailable:
php artisan make:mail OrderShipped --markdown=emails.orders.shippedLaravel sẽ tạo template tương ứng.
Ví dụ:
resources/views/emails/orders/shipped.blade.phpNội dung:
<x-mail::message>
# Đơn hàng đã được giao
Xin chào {{ $user->name }},
Đơn hàng của bạn đã được giao thành công.
<x-mail::button :url="$url">
Xem đơn hàng
</x-mail::button>
Cảm ơn,<br>
{{ config('app.name') }}
</x-mail::message>Markdown Mailables rất phù hợp với:
Thông báo
Xác nhận đơn hàng
Reset Password
Thông báo hệ thống10. 👀 Preview Email
Một tính năng rất hữu ích khi thiết kế email là preview trực tiếp trên trình duyệt.
Có thể tạo Route:
use App\Mail\WelcomeUser;
use Illuminate\Support\Facades\Route;
Route::get('/preview-mail', function () {
return new WelcomeUser(
'Nguyễn Văn A'
);
});Sau đó truy cập:
/preview-mailLaravel sẽ render Mailable thành HTML để xem trước mà không cần gửi email thật. (Laravel)
Đây là cách rất tiện để thiết kế email.
Blade Email
↓
Mailable
↓
Browser Preview11. 🧪 Test Email
Khi test ứng dụng, chúng ta không muốn gửi email thật.
Laravel cung cấp:
Mail::fake();Ví dụ:
use Illuminate\Support\Facades\Mail;
Mail::fake();Sau đó thực hiện hành động gửi email.
Có thể kiểm tra:
Mail::assertSent(
WelcomeUser::class
);Hoặc kiểm tra email không được gửi:
Mail::assertNotSent(
WelcomeUser::class
);Laravel cũng hỗ trợ kiểm tra số lượng Mailable đã gửi. (Laravel)
12. ⚡ Kết hợp Mail với Queue
Đây là phần rất quan trọng.
Giả sử người dùng đăng ký:
Register
↓
Tạo User
↓
Gửi Email
↓
SMTP
↓
Chờ...
↓
ResponseNếu SMTP phản hồi chậm, người dùng có thể phải chờ.
Thay vào đó:
Register
↓
Tạo User
↓
Đưa Email vào Queue
↓
Response ngay
↓
Queue Worker
↓
Gửi EmailMục tiêu là:
Không bắt HTTP request phải chờ việc gửi email hoàn thành.
Mailable có thể được queue để Laravel xử lý việc gửi email ở background.
Ví dụ:
Mail::to($user->email)
->queue(
new WelcomeUser($user->name)
);Đây chính là lúc kiến thức Bài 35 — Queue được kết nối với Bài 36 — Mail.
13. 🔄 Mail + Queue trong dự án Blog CMS
Trong dự án Blog CMS của chúng ta, có thể xây dựng:
User đăng ký
│
▼
Register
│
▼
Create User
│
▼
WelcomeUser Mail
│
▼
Queue
│
▼
Queue Worker
│
▼
SMTP
│
▼
EmailHoặc:
Admin xuất bản bài viết
│
▼
PostPublished Event
│
▼
Listener
│
▼
SendNewPostMail
│
▼
Queue
│
▼
SubscribersĐây là cách các thành phần Laravel bắt đầu kết nối với nhau thành một hệ thống thực tế.
14. 🏠 Mail khi Development
Khi lập trình local, chúng ta không nên liên tục gửi email thật.
Một giải pháp rất tiện là sử dụng Mailpit để bắt email và xem chúng trên trình duyệt. Tài liệu Laravel/Sail hiện mô tả Mailpit cho môi trường development; giao diện mặc định có thể truy cập qua cổng 8025. (Laravel)
Mô hình:
Laravel
│
▼
Mailpit
│
▼
BrowserThay vì:
Laravel
│
▼
Email thật
│
▼
Khách hàngDevelopment nên dùng:
Local
↓
Mailpit
↓
PreviewProduction mới cấu hình:
Production
↓
SMTP / Mail Provider
↓
User15. 🧩 Mail trong kiến trúc Laravel
Sau bài này, chúng ta có thể hình dung Laravel Mail như sau:
┌───────────────┐
│ Controller │
└───────┬───────┘
│
▼
┌───────────────┐
│ Mail │
└───────┬───────┘
│
▼
┌───────────────┐
│ Mailable │
└───────┬───────┘
│
┌────────┴────────┐
▼ ▼
Blade View Attachment
│
▼
HTML Mail
│
▼
SMTP / Mailer
│
▼
Người nhậnNếu kết hợp Queue:
Mailable
│
▼
Queue
│
▼
Worker
│
▼
Mailer
│
▼
Email16. 🎯 Bài tập thực hành
Tạo hệ thống gửi email chào mừng người dùng.
Bước 1
Tạo Mailable:
php artisan make:mail WelcomeUserBước 2
Tạo View:
resources/views/emails/welcome.blade.phpBước 3
Truyền:
$uservào Mailable.
Bước 4
Thiết kế email:
Xin chào Nguyễn Văn A!
Chào mừng bạn đến với Blog CMS.
[Truy cập website]Bước 5
Tạo route preview:
/preview-mailBước 6
Test email bằng:
Mail::fake();Bước 7
Cuối cùng chuyển sang Queue:
Mail::to($user->email)
->queue(
new WelcomeUser($user)
);17. 🧠 Những kiến thức cần nhớ
| Thành phần | Vai trò |
|---|---|
Mail | Facade gửi email |
Mailable | Đại diện cho một loại email |
Envelope | Subject và metadata của email |
Content | Xác định nội dung/View |
Blade | Thiết kế email |
Attachment | File đính kèm |
| Markdown Mail | Tạo email bằng Markdown |
| SMTP | Giao thức/server gửi email |
| Queue | Gửi email background |
Mail::fake() | Fake email khi test |
| Mailpit | Xem email khi development |
18. 🔥 Tổng kết Bài 36
Sau bài này, chúng ta đã biết cách:
📧 MAIL
│
┌──────────────┼──────────────┐
▼ ▼ ▼
Mailable Blade SMTP
│ │ │
▼ ▼ ▼
Envelope Template Delivery
│
▼
Attachment
│
▼
Queue
│
▼
Background MailĐiểm quan trọng nhất cần nhớ:
Mailable là lớp đại diện cho email.
Blade là nơi xây dựng nội dung email.
Mail facade là nơi gửi email.
Queue giúp việc gửi email không làm chậm request của người dùng.
Và từ đây, chúng ta đã bắt đầu kết nối các kiến thức:
Event
↓
Listener
↓
Queue
↓
Mail
↓
UserĐây chính là kiểu kiến trúc thường gặp trong một ứng dụng Laravel thực tế.
📌 Liên hệ với các bài tiếp theo
Sau Bài 36 — Mail, bài tiếp theo sẽ là:
📘 Bài 37 — Notification
Trong bài đó chúng ta sẽ phân biệt:
Mail
Notification
Event
Listener
Queuevà tìm hiểu tại sao Notification có thể gửi thông báo qua nhiều kênh khác nhau thay vì chỉ gửi email.
Tài liệu Laravel 13 cũng tiếp tục hỗ trợ việc kết hợp Notification với Mailable khi cần các email phức tạp hơn. (Laravel)
Lưu ý: Danh sách ban đầu của bạn ghi Laravel 12 LTS, nhưng nếu mục tiêu là khóa học Laravel 2026, mình khuyên đổi toàn bộ tiêu đề thành Laravel 13. Laravel 13 hiện là phiên bản chính thức mới, còn Laravel 12 đã hết thời hạn bug fixes vào 13/08/2026 nhưng vẫn nhận security fixes đến 24/02/2027. (Laravel)




Không có nhận xét nào:
Đăng nhận xét