ارسال ایمیل در Django: راهنمای کامل send_mail، EmailMessage و EmailMultiAlternatives

این مقاله یک راهنمای جامع برای ارسال ایمیل در Django ارائه می‌دهد. موضوعاتی مانند send_mail، ارسال انبوه با send_mass_mail، ساخت ایمیل‌های چندبخشی با EmailMessage و EmailMultiAlternatives، تنظیمات SMTP و بهترین روش‌های ارسال ایمیل بررسی می‌شوند.

Django send_mail, EmailMessageEmailMultiAlternativessend_mass_mail, SMTP settings, Django email backend

~9 دقیقه مطالعه • بروزرسانی ۲۴ اسفند ۱۴۰۴

مقدمه

Django یک API ساده و قدرتمند برای ارسال ایمیل ارائه می‌دهد که بر پایهٔ ماژول smtplib پایتون ساخته شده است. این ابزارها ارسال ایمیل را سریع‌تر، تست آن را آسان‌تر و استفاده از پلتفرم‌هایی که SMTP ندارند را ممکن می‌کنند.

تمام ابزارهای ارسال ایمیل در ماژول django.core.mail قرار دارند.


ارسال سریع ایمیل با send_mail()

ساده‌ترین روش ارسال ایمیل در Django استفاده از send_mail() است. این تابع برای ارسال پیام‌های متنی ساده بسیار مناسب است.


from django.core.mail import send_mail

send_mail(
    "Subject here",
    "Here is the message.",
    "[email protected]",
    ["[email protected]"],
    fail_silently=False,
)

پارامترهای ضروری

  • subject: موضوع ایمیل
  • message: متن سادهٔ ایمیل
  • from_email: آدرس فرستنده
  • recipient_list: لیست گیرندگان

پارامترهای اختیاری

  • fail_silently: جلوگیری از خطاهای SMTP
  • auth_user: نام کاربری SMTP
  • auth_password: رمز عبور SMTP
  • connection: بک‌اند ایمیل سفارشی
  • html_message: نسخهٔ HTML ایمیل

خروجی این تابع تعداد ایمیل‌های ارسال‌شده است (۰ یا ۱).


ایمیل‌های پیشرفته با EmailMessage و EmailMultiAlternatives

برای ارسال ایمیل‌های پیچیده‌تر—مثل ایمیل‌های HTML، ایمیل‌های چندبخشی یا ایمیل با هدرهای سفارشی—از EmailMessage یا EmailMultiAlternatives استفاده کنید.

ارسال ایمیل چندبخشی (HTML + متن)


from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string

text_content = render_to_string(
    "templates/emails/my_email.txt",
    {"my_variable": 42},
)

html_content = render_to_string(
    "templates/emails/my_email.html",
    {"my_variable": 42},
)

msg = EmailMultiAlternatives(
    subject="Subject here",
    body=text_content,
    from_email="[email protected]",
    to=["[email protected]"],
    headers={"List-Unsubscribe": ""},
)

msg.attach_alternative(html_content, "text/html")
msg.send()

این روش برای ارسال ایمیل‌های خبری، تراکنشی و قالب‌محور بسیار مناسب است.


تنظیمات SMTP

Django از تنظیمات زیر برای ارسال ایمیل استفاده می‌کند:

  • EMAIL_HOST: آدرس سرور SMTP
  • EMAIL_PORT: پورت SMTP
  • EMAIL_HOST_USER: نام کاربری
  • EMAIL_HOST_PASSWORD: رمز عبور
  • EMAIL_USE_TLS: فعال‌سازی TLS
  • EMAIL_USE_SSL: فعال‌سازی SSL

کدگذاری ایمیل‌ها برابر با مقدار DEFAULT_CHARSET خواهد بود.


ارسال انبوه ایمیل با send_mass_mail()

برای ارسال چند ایمیل مختلف با یک اتصال SMTP از send_mass_mail() استفاده کنید.

مثال


message1 = (
    "Subject here",
    "Here is the message",
    "[email protected]",
    ["[email protected]", "[email protected]"],
)

message2 = (
    "Another Subject",
    "Here is another message",
    "[email protected]",
    ["[email protected]"],
)

send_mass_mail((message1, message2), fail_silently=False)

هر عنصر از datatuple یک ایمیل جداگانه ارسال می‌کند. خروجی تعداد ایمیل‌های ارسال‌شده است.


بهترین روش‌ها

  • برای ایمیل‌های HTML از EmailMultiAlternatives استفاده کنید.
  • برای ارسال انبوه از send_mass_mail() بهره ببرید.
  • اطلاعات SMTP را در متغیرهای محیطی ذخیره کنید.
  • در محیط توسعه از console backend یا file backend استفاده کنید.
  • در محیط واقعی fail_silently=False قرار دهید تا خطاها مشخص شوند.

جمع‌بندی

ابزارهای ارسال ایمیل در Django یک رابط ساده و قدرتمند برای ارسال انواع ایمیل‌ها فراهم می‌کنند—از پیام‌های ساده تا ایمیل‌های HTML پیچیده. با استفاده از send_mail()، EmailMessage و EmailMultiAlternatives می‌توانید سیستم‌های ایمیلی قابل‌اعتماد، انعطاف‌پذیر و حرفه‌ای بسازید.

تفاوت send_mail و send_mass_mail

مهم‌ترین تفاوت این دو تابع در نحوهٔ اتصال به سرور SMTP است:

  • send_mail() برای هر ایمیل یک اتصال جدید به سرور باز می‌کند.
  • send_mass_mail() فقط یک اتصال باز می‌کند و تمام ایمیل‌ها را از همان اتصال ارسال می‌کند.

بنابراین send_mass_mail() در ارسال تعداد زیاد ایمیل کارآمدتر است.


ارسال ایمیل به مدیران سایت با mail_admins()

تابع mail_admins() یک میان‌بُر برای ارسال ایمیل به مدیران سایت است که در تنظیمات ADMINS تعریف شده‌اند.

ویژگی‌ها

  • موضوع ایمیل با مقدار EMAIL_SUBJECT_PREFIX پیشوندگذاری می‌شود (پیش‌فرض: "[Django] ").
  • فرستندهٔ ایمیل برابر SERVER_EMAIL است.
  • از html_message برای ارسال نسخهٔ HTML پشتیبانی می‌کند.

ارسال ایمیل به مدیران فنی با mail_managers()

تابع mail_managers() مشابه mail_admins است، اما ایمیل را به افرادی ارسال می‌کند که در تنظیمات MANAGERS تعریف شده‌اند.


نمونه‌های کاربردی

ارسال یک ایمیل به چند گیرنده (همه در یک پیام)


send_mail(
    "Subject",
    "Message.",
    "[email protected]",
    ["[email protected]", "[email protected]"],
)

ارسال ایمیل جداگانه به هر گیرنده


datatuple = (
    ("Subject", "Message.", "[email protected]", ["[email protected]"]),
    ("Subject", "Message.", "[email protected]", ["[email protected]"]),
)
send_mass_mail(datatuple)

جلوگیری از Header Injection

Header Injection یک حملهٔ امنیتی است که مهاجم با وارد کردن newline در فیلدهای ایمیل، هدرهای جدید اضافه می‌کند.

Django از این حمله جلوگیری می‌کند:

  • اگر subject، from_email یا recipient_list شامل newline باشد → ValueError پرتاب می‌شود.

نمونهٔ امن


def send_email(request):
    subject = request.POST.get("subject", "")
    message = request.POST.get("message", "")
    from_email = request.POST.get("from_email", "")
    if subject and message and from_email:
        try:
            send_mail(subject, message, from_email, ["[email protected]"])
        except ValueError:
            return HttpResponse("Invalid header found.")
        return HttpResponseRedirect("/contact/thanks/")
    return HttpResponse("Make sure all fields are entered and valid.")

کلاس EmailMessage

توابع send_mail() و send_mass_mail() در واقع wrapperهایی هستند که از EmailMessage استفاده می‌کنند.

برای امکانات پیشرفته مثل:

  • BCC
  • CC
  • Reply-To
  • فایل‌های پیوست
  • ایمیل چندبخشی

باید مستقیماً از EmailMessage استفاده کنید.

نمونهٔ EmailMessage


from django.core.mail import EmailMessage

email = EmailMessage(
    subject="Hello",
    body="Body goes here",
    from_email="[email protected]",
    to=["[email protected]", "[email protected]"],
    bcc=["[email protected]"],
    reply_to=["[email protected]"],
    headers={"Message-ID": "foo"},
)

برای ارسال:


email.send()

جمع‌بندی

Django ابزارهای متنوعی برای ارسال ایمیل ارائه می‌دهد. برای ارسال ساده از send_mail()، برای ارسال انبوه از send_mass_mail() و برای ایمیل‌های حرفه‌ای از EmailMessage و EmailMultiAlternatives استفاده کنید. همچنین mail_admins() و mail_managers() ارسال پیام‌های سیستمی را ساده‌تر می‌کنند.

مقدمه

سیستم ایمیل Django بسیار فراتر از send_mail() عمل می‌کند. برای ارسال ایمیل‌های حرفه‌ای—شامل پیوست‌ها، تصاویر inline، نسخه‌های HTML، هدرهای سفارشی و مدیریت اتصال SMTP—کلاس‌های EmailMessage و EmailMultiAlternatives ابزارهای اصلی شما هستند.


متدهای EmailMessage

send(fail_silently=False)

این متد ایمیل را ارسال می‌کند. اگر connection مشخص شده باشد، از همان استفاده می‌شود؛ در غیر این صورت Django یک اتصال جدید ایجاد می‌کند.

خروجی:

  • 1 → ارسال موفق
  • 0 → ارسال ناموفق

اگر fail_silently=True باشد، خطاهای SMTP نادیده گرفته می‌شوند.


message(policy=email.policy.default)

یک شیء email.message.EmailMessage پایتون می‌سازد و برمی‌گرداند. پارامتر policy قوانین serialization را کنترل می‌کند (مثلاً خط‌های \r\n برای SMTP).

اگر کلاس EmailMessage را توسعه می‌دهید، معمولاً باید این متد را override کنید.


recipients()

لیست کامل گیرندگان را از فیلدهای زیر برمی‌گرداند:

  • to
  • cc
  • bcc

اگر روش جدیدی برای تعیین گیرنده اضافه کنید، باید این متد را نیز override کنید.


مدیریت پیوست‌ها

attach(filename, content, mimetype)

دو روش برای استفاده:

۱. پیوست استاندارد


message.attach("design.png", img_data, "image/png")

۲. پیوست MIMEPart (از Django 6.0 به بعد)

برای تصاویر inline یا پیوست‌هایی با هدرهای سفارشی.


import email.utils
from email.message import MIMEPart

cid = email.utils.make_msgid()
inline_image = MIMEPart()
inline_image.set_content(
    image_data_bytes,
    maintype="image",
    subtype="png",
    disposition="inline",
    cid=cid,
)
message.attach(inline_image)
message.attach_alternative(f'', "text/html")

پشتیبانی از MIMEBase قدیمی منسوخ شده است.


attach_file(path, mimetype=None)

برای پیوست کردن فایل از سیستم فایل:


message.attach_file("/images/weather_map.png")

EmailAttachment (جدید در Django 5.2)

یک named tuple شامل:

  • filename
  • content
  • mimetype

ارسال چند نسخه از محتوا

EmailMultiAlternatives

این کلاس امکان ارسال نسخه‌های مختلف محتوا (مثلاً متن + HTML) را فراهم می‌کند.

مثال


from django.core.mail import EmailMultiAlternatives

msg = EmailMultiAlternatives(
    "hello",
    "This is an important message.",
    "[email protected]",
    ["[email protected]"],
)
msg.attach_alternative("

This is an important message.

", "text/html") msg.send()

alternatives

لیستی از EmailAlternative (content، mimetype) است.


body_contains(text)

بررسی می‌کند که آیا متن داده‌شده در:

  • بدنهٔ اصلی
  • تمام نسخه‌های text/*

وجود دارد یا نه. برای تست بسیار مفید است.


تغییر نوع محتوای پیش‌فرض

نوع پیش‌فرض text/plain است. برای ارسال HTML به‌عنوان بدنهٔ اصلی:


msg = EmailMessage(subject, html_content, from_email, [to])
msg.content_subtype = "html"
msg.send()

Email Backends

Backend مسئول ارسال واقعی ایمیل است.

متدهای Backend

  • open() → باز کردن اتصال
  • close() → بستن اتصال
  • send_messages() → ارسال لیستی از EmailMessage

استفاده به‌صورت context manager


from django.core import mail

with mail.get_connection() as connection:
    mail.EmailMessage(subject1, body1, from1, [to1], connection=connection).send()
    mail.EmailMessage(subject2, body2, from2, [to2], connection=connection).send()

این روش باعث استفادهٔ بهینه از یک اتصال SMTP می‌شود.


جمع‌بندی

سیستم ایمیل Django امکانات حرفه‌ای برای ارسال ایمیل‌های پیچیده فراهم می‌کند: پیوست‌ها، تصاویر inline، نسخه‌های HTML، هدرهای سفارشی و مدیریت اتصال SMTP. با EmailMessage، EmailMultiAlternatives و Email Backend می‌توانید سیستم‌های ایمیلی قدرتمند، مقیاس‌پذیر و قابل‌اعتماد بسازید.

دریافت یک نمونه از Email Backend

تابع get_connection() در django.core.mail یک نمونه از بک‌اند ایمیل را برمی‌گرداند.


from django.core.mail import get_connection

connection = get_connection()

پارامترها

  • backend: مسیر ایمپورت بک‌اند (اختیاری)
  • fail_silently: اگر True باشد، خطاهای ارسال ایمیل نادیده گرفته می‌شوند
  • سایر keyword arguments → مستقیماً به سازندهٔ بک‌اند ارسال می‌شوند

اگر backend مشخص نشود، Django از مقدار EMAIL_BACKEND استفاده می‌کند.


انواع Email Backendهای Django

۱. SMTP Backend (پیش‌فرض)

ایمیل‌ها از طریق یک سرور SMTP واقعی ارسال می‌شوند.

تنظیمات مرتبط:

  • EMAIL_HOST
  • EMAIL_PORT
  • EMAIL_HOST_USER
  • EMAIL_HOST_PASSWORD
  • EMAIL_USE_TLS
  • EMAIL_USE_SSL
  • EMAIL_TIMEOUT
  • EMAIL_SSL_KEYFILE
  • EMAIL_SSL_CERTFILE

برای استفادهٔ صریح:


EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"

۲. Console Backend

ایمیل‌ها را به خروجی استاندارد (stdout) چاپ می‌کند. مناسب برای توسعه.


EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"

۳. File Backend

ایمیل‌ها را در فایل ذخیره می‌کند.


EMAIL_BACKEND = "django.core.mail.backends.filebased.EmailBackend"
EMAIL_FILE_PATH = "/tmp/app-messages"

۴. In-Memory Backend (locmem)

ایمیل‌ها را در django.core.mail.outbox ذخیره می‌کند. مناسب برای تست.


EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"

۵. Dummy Backend

هیچ ایمیلی ارسال نمی‌کند. فقط برای توسعه.


EMAIL_BACKEND = "django.core.mail.backends.dummy.EmailBackend"

ساخت Email Backend سفارشی

اگر نیاز به رفتار خاصی دارید، می‌توانید بک‌اند خود را بسازید.

بک‌اند سفارشی باید از BaseEmailBackend ارث‌بری کند و متد زیر را پیاده‌سازی کند:

  • send_messages(email_messages) → تعداد ایمیل‌های ارسال‌شده را برمی‌گرداند

اگر بک‌اند شما اتصال پایدار دارد، باید open() و close() را نیز پیاده‌سازی کنید.


ارسال چند ایمیل با یک اتصال

باز و بسته کردن اتصال SMTP هزینه‌بر است. Django دو روش برای استفادهٔ مجدد از اتصال ارائه می‌دهد.

روش اول: send_messages()

یک لیست از EmailMessage را با یک اتصال ارسال می‌کند.


from django.core import mail

connection = mail.get_connection()
messages = get_notification_email()
connection.send_messages(messages)

روش دوم: مدیریت دستی اتصال


from django.core import mail

connection = mail.get_connection()
connection.open()

email1 = mail.EmailMessage("Hello", "Body", "[email protected]", ["to1"], connection=connection)
email1.send()

email2 = mail.EmailMessage("Hello", "Body", "[email protected]", ["to2"])
email3 = mail.EmailMessage("Hello", "Body", "[email protected]", ["to3"])

connection.send_messages([email2, email3])
connection.close()

پیکربندی ایمیل برای توسعه

در محیط توسعه معمولاً نمی‌خواهید ایمیل واقعی ارسال شود. Django چند گزینهٔ عالی ارائه می‌دهد:

۱. Console Backend

ایمیل‌ها در ترمینال چاپ می‌شوند.

۲. File Backend

ایمیل‌ها در فایل ذخیره می‌شوند.

۳. LocMem Backend

ایمیل‌ها در حافظه ذخیره می‌شوند (برای تست عالی است).

۴. استفاده از SMTP محلی با aiosmtpd


python -m pip install "aiosmtpd >= 1.4.5"
python -m aiosmtpd -n -l localhost:8025

سپس EMAIL_HOST و EMAIL_PORT را تنظیم کنید.


جمع‌بندی

Email Backendها در Django انعطاف‌پذیری فوق‌العاده‌ای برای ارسال ایمیل فراهم می‌کنند. چه در حال توسعه باشید، چه در حال ارسال ایمیل‌های واقعی، چه نیاز به بک‌اند سفارشی داشته باشید، Django ابزارهای قدرتمندی برای مدیریت اتصال، ارسال چند ایمیل، تست و توسعه ارائه می‌دهد.

نوشته و پژوهش شده توسط دکتر شاهین صیامی