Django: gửi email bằng send_mail() trong 5 phút — cấu hình SMTP đúng cách
Django đã có sẵn hàm send_mail() để gửi email — chỉ cần cấu hình SMTP một lần trong settings.py rồi gọi một dòng là gửi được. Dùng cho mail chào mừng sau đăng ký, xác nhận đơn hàng, đặt lại mật khẩu hay thông báo hệ thống. Không cần cài thêm thư viện, cũng không cần tự viết code SMTP bằng smtplib.
Vấn đề thường gặp
Nhiều dự án mới gọi send_mail() ngay mà chưa cấu hình gì, vì nghĩ Django "tự biết" gửi mail đi đâu. Thực tế Django mặc định dùng SMTP backend trỏ về localhost:25 — máy dev thường không có mail server nên request treo rồi lỗi ConnectionRefusedError, người dùng đăng ký xong chờ mãi không thấy mail chào mừng.
Lỗi khác cũng hay gặp là hardcode mật khẩu email thẳng vào settings.py rồi vô tình commit lên Git — tài khoản mail bị lộ và bị dùng để gửi spam.
from django.core.mail import send_mail
send_mail(
"Chao mung ban den voi MyShop",
"Cam on ban da dang ky tai khoan.",
"noreply@example.com",
["khach@example.com"],
fail_silently=False,
)
# ConnectionRefusedError: [Errno 111] Connection refused (localhost:25)
Cấu hình SMTP đúng cách
Cách đúng là tách cấu hình ra biến môi trường và để Django lo phần SMTP. Trong settings.py, khai báo backend SMTP cùng host, cổng và tài khoản — mật khẩu lấy từ biến môi trường, tuyệt đối không ghi thẳng vào code. Khi phát triển local, đổi sang console backend để mail in ra terminal thay vì gửi thật.
import os
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = "smtp.gmail.com"
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = os.environ["EMAIL_HOST_USER"]
EMAIL_HOST_PASSWORD = os.environ["EMAIL_HOST_PASSWORD"]
DEFAULT_FROM_EMAIL = "MyShop <noreply@example.com>"
# Dev local: in mail ra terminal thay vi gui that
# EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
Sau đó, ở bất cứ đâu trong code — view, signal hay management command — chỉ cần một lời gọi send_mail() với 4 tham số: tiêu đề, nội dung text, địa chỉ người gửi và danh sách người nhận. Hàm trả về số mail gửi thành công, thường là 1. Cần bản HTML đẹp thì truyền thêm html_message, Django tự đính kèm bản text làm phương án dự phòng.
from django.core.mail import send_mail
sent = send_mail(
"Don hang #123 da duoc xac nhan",
"Don hang #123 cua ban da duoc xac nhan.",
"noreply@example.com",
["khach@example.com"],
html_message="<h1>Don hang #123</h1><p>Cam on ban da mua hang.</p>",
)
print(sent) # 1
Áp dụng vào dự án
Gắn send_mail() vào đúng điểm chạm: mail chào mừng sau khi user đăng ký (kết hợp signal post_save), mail xác nhận sau khi đơn hàng được tạo, mail đặt lại mật khẩu. Vì gửi qua SMTP thường mất 1–3 giây, đừng gọi trực tiếp trong view nếu không muốn người dùng chờ — đẩy sang background task hoặc chạy sau khi transaction commit thành công, và luôn log lại khi gửi thất bại để còn gửi bù.
Dùng Gmail thì host smtp.gmail.com, cổng 587, bật TLS và dùng App Password thay cho mật khẩu chính — Gmail đã chặn đăng nhập bằng mật khẩu thường từ 2022.
Đọc bản đầy đủ (tiếng Anh) tại: https://linhfish.dev/en/2026/11/07/django-send-email-with-send_mail-in-5-minutes-configure-smtp-the-right-way/
All rights reserved