NTM Solutions

Thứ Ba, 8 tháng 9, 2026

📘LARAVEL 13 — BÀI 36 — MAIL

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 Email

1. 📧 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.php

Mỗ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án

Laravel tạo Mailable bằng Artisan:

php artisan make:mail WelcomeUser

Sau 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:

.env

và:

config/mail.php

Ví 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 Server

3. 📨 Tạo Mailable

Tạo email:

php artisan make:mail WelcomeUser

Laravel sẽ tạo:

app/Mail/WelcomeUser.php

Mộ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 EnvelopeContent 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.php

Ví 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 Email

6. 🚀 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ận

7. 📮 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.shipped

Laravel sẽ tạo template tương ứng.

Ví dụ:

resources/views/emails/orders/shipped.blade.php

Nộ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ống

10. 👀 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-mail

Laravel 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 Preview

11. 🧪 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ờ...
   ↓
Response

Nế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 Email

Mụ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
     │
     ▼
Email

Hoặ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
   │
   ▼
Browser

Thay vì:

Laravel
   │
   ▼
Email thật
   │
   ▼
Khách hàng

Development nên dùng:

Local
  ↓
Mailpit
  ↓
Preview

Production mới cấu hình:

Production
    ↓
SMTP / Mail Provider
    ↓
User

15. 🧩 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ận

Nếu kết hợp Queue:

Mailable
   │
   ▼
Queue
   │
   ▼
Worker
   │
   ▼
Mailer
   │
   ▼
Email

16. 🎯 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 WelcomeUser

Bước 2

Tạo View:

resources/views/emails/welcome.blade.php

Bước 3

Truyền:

$user

và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-mail

Bướ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ầnVai trò
MailFacade gửi email
MailableĐại diện cho một loại email
EnvelopeSubject và metadata của email
ContentXác định nội dung/View
BladeThiết kế email
AttachmentFile đính kèm
Markdown MailTạo email bằng Markdown
SMTPGiao thức/server gửi email
QueueGửi email background
Mail::fake()Fake email khi test
MailpitXem 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
Queue

và 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

Facebook Youtube RSS