Skip to content

Django - 发送电子邮件

Django 提供了一个方便且健壮的 API 用于发送电子邮件,它抽象了 SMTP(简单邮件传输协议)的底层细节。

在发送电子邮件之前,你需要在项目的 settings.py 文件中配置电子邮件后端和连接详情:

settings.py
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.example.com' # 你的 SMTP 服务器地址(例如 smtp.gmail.com)
EMAIL_PORT = 587 # TLS 的常用端口
EMAIL_USE_TLS = True # 使用 TLS (Transport Layer Security) - 推荐
# EMAIL_USE_SSL = False # 使用 SSL (Secure Sockets Layer) - 现在不如 TLS 常用
EMAIL_HOST_USER = 'your_email@example.com' # 你的 SMTP 用户名
EMAIL_HOST_PASSWORD = 'your_app_password' # 你的 SMTP 密码或应用专用密码(例如用于 Gmail)
  • EMAIL_BACKEND: 指定要使用的后端。smtp.EmailBackend 是标准的。其他后端包括 console.EmailBackend(将电子邮件打印到控制台,非常适合开发)、filebased.EmailBackend(将电子邮件保存到文件)和 locmem.EmailBackend(将电子邮件存储在内存中用于测试)。
  • EMAIL_HOST: 你的 SMTP 服务器的主机名或 IP 地址。
  • EMAIL_PORT: SMTP 服务器监听的端口(例如,TLS 为 587,SSL 为 465,未加密为 25 - 不推荐)。
  • EMAIL_USE_TLS / EMAIL_USE_SSL: 布尔标志,指示是否使用安全连接(TLS 通常比 SSL 更受欢迎)。它们是互斥的。
  • EMAIL_HOST_USER: 用于 SMTP 认证的用户名。
  • EMAIL_HOST_PASSWORD: 用于 SMTP 认证的密码。安全注意: 避免直接在 settings.py 中硬编码凭据。使用环境变量或密钥管理工具。
  • DEFAULT_FROM_EMAIL: (可选) 如果发送邮件时未指定 ‘From’ 地址,则设置一个默认的 ‘From’ 地址。settings.py -> DEFAULT_FROM_EMAIL = 'webmaster@example.com'

send_mail 函数是发送基本电子邮件的最快方式。

# 在视图或管理命令中
from django.core.mail import send_mail
from django.http import HttpResponse
def send_simple_email_view(request):
try:
num_sent = send_mail(
'Test Subject',
'This is the email body message.',
'from@example.com', # 发件人邮箱(通常与 EMAIL_HOST_USER 或 DEFAULT_FROM_EMAIL 匹配)
['recipient1@example.com', 'recipient2@example.com'], # 收件人列表
fail_silently=False, # 如果是 False(默认),发生错误时会抛出 SMTPException
)
return HttpResponse(f'{num_sent} email(s) sent successfully.')
except Exception as e:
# 记录错误 e
return HttpResponse(f'Error sending email: {e}', status=500)
  • subject: 电子邮件主题行(字符串)。
  • message: 电子邮件的纯文本正文(字符串)。
  • from_email: 发件人邮箱地址(字符串)。
  • recipient_list: 收件人邮箱地址的列表或元组(字符串)。
  • fail_silently: 布尔值。如果为 False(默认),则抛出异常。如果为 True,则静默忽略错误(通常不推荐,除非你有特定的错误处理)。
  • auth_user, auth_password: 覆盖 settings.py 中的凭据。
  • connection: 使用特定的电子邮件后端连接。
  • html_message: 提供电子邮件正文的 HTML 版本。如果提供,电子邮件将变为 multipart/alternative,电子邮件客户端会尽可能显示 HTML 版本,然后回退到纯文本 message。

高效发送多封电子邮件 (send_mass_mail)

Section titled “高效发送多封电子邮件 (send_mass_mail)”

要使用单个连接发送多封电子邮件(更高效),请使用 send_mass_mail。

from django.core.mail import send_mass_mail
from django.http import HttpResponse
def send_mass_email_view(request):
message1 = ('Subject 1', 'Message body 1', 'from@example.com', ['recipient1@example.com'])
message2 = ('Subject 2', 'Message body 2', 'from@example.com', ['recipient_other@example.com'])
datatuple = (message1, message2)
try:
num_sent = send_mass_mail(datatuple, fail_silently=False)
return HttpResponse(f'{num_sent} email(s) sent successfully using mass mail.')
except Exception as e:
# 记录错误 e
return HttpResponse(f'Error sending mass email: {e}', status=500)

send_mass_mail 接受一个元组(datatuple),其中每个元素都是一个格式为 (subject, message, from_email, recipient_list) 的元组。其他参数(fail_silently、auth_user 等)与 send_mail 类似。

发送 HTML 电子邮件和附件 (EmailMessage)

Section titled “发送 HTML 电子邮件和附件 (EmailMessage)”

为了获得更多控制,包括 HTML 内容、附件和标头,请使用 EmailMessage 类。

from django.core.mail import EmailMessage
from django.http import HttpResponse
import os
from django.conf import settings # 用于访问附件的 BASE_DIR
def send_html_email_with_attachment_view(request):
subject = 'Email with HTML and Attachment'
text_content = 'This is an important message.' # 纯文本回退
html_content = '<p>This is an **important** message in HTML.</p>'
from_email = 'from@example.com'
to = ['recipient@example.com']
try:
email = EmailMessage(subject, text_content, from_email, to)
email.attach_alternative(html_content, "text/html")
# 可选:附加文件
# attachment_path = os.path.join(settings.BASE_DIR, 'path/to/your/file.pdf')
# if os.path.exists(attachment_path):
# email.attach_file(attachment_path)
# 或者直接附加内容:
# email.attach('filename.txt', 'File content here', 'text/plain')
num_sent = email.send()
return HttpResponse(f'{num_sent} HTML email(s) sent.')
except Exception as e:
# 记录错误 e
return HttpResponse(f'Error sending HTML email: {e}', status=500)
  • 初始化: EmailMessage(subject, body, from_email, to, bcc=None, connection=None, attachments=None, headers=None, cc=None, reply_to=None)
  • send(fail_silently=False): 发送电子邮件。
  • attach(filename, content, mimetype): 附加代码中生成的内容。
  • attach_file(path, mimetype=None): 从文件系统附加文件。
  • attach_alternative(content, mimetype): 添加替代内容类型(常用于 text/html)。

发送电子邮件给管理员和经理 (mail_admins, mail_managers)

Section titled “发送电子邮件给管理员和经理 (mail_admins, mail_managers)”

Django 提供了快捷方式,可以发送电子邮件给在 settings.py 中定义的管理员和经理:

settings.py
ADMINS = [('Admin Name', 'admin@example.com'),]
MANAGERS = [('Manager Name', 'manager@example.com'),]
from django.core.mail import mail_admins, mail_managers
from django.http import HttpResponse
def notify_admins_view(request):
try:
mail_admins('Site Critical Alert', 'The site needs immediate attention!', fail_silently=False)
# mail_managers('网站更新', '内容需要审核。', fail_silently=False)
return HttpResponse('Notification email sent.')
except Exception as e:
return HttpResponse(f'Error sending admin/manager email: {e}', status=500)

这些函数会在主题前加上 EMAIL_SUBJECT_PREFIX 设置的值(默认值:[Django] )。

在开发过程中,避免发送真实的电子邮件。使用控制台或文件后端:

# settings.py(用于开发环境)
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

或者,使用 MailHog 或 Mailtrap 等工具,它们会设置一个本地的伪造 SMTP 服务器来捕获发送的电子邮件进行检查,而不会真正发送它们。

发送电子邮件有时会很慢并阻塞 Web 请求。对于生产应用程序,特别是那些频繁发送电子邮件或在用户请求期间发送电子邮件的应用,强烈建议使用任务队列(例如带有 Redis 或 RabbitMQ 的 Celery)异步发送电子邮件。这将电子邮件发送任务卸载到后台工作进程,使你的 Web 应用程序保持响应。