发送电子邮件

虽然Python通过 smtplib 模块上,Django提供了两个光包装。提供这些包装器是为了使发送电子邮件更加快速,帮助在开发期间测试电子邮件发送,并为不能使用SMTP的平台提供支持。

代码存在于 django.core.mail 模块。

快速实例

两条线:

from django.core.mail import send_mail

send_mail(
    "Subject here",
    "Here is the message.",
    "from@example.com",
    ["to@example.com"],
    fail_silently=False,
)

使用中指定的SMTP主机和端口发送邮件 EMAIL_HOSTEMAIL_PORT 设置。这个 EMAIL_HOST_USEREMAIL_HOST_PASSWORD 设置(如果设置)用于对SMTP服务器进行身份验证,并且 EMAIL_USE_TLSEMAIL_USE_SSL 设置控制是否使用安全连接。

备注

与一起发送的电子邮件的字符集 django.core.mail 将被设置为 DEFAULT_CHARSET 设置。

send_mail()

send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None, connection=None, html_message=None)[源代码]

在大多数情况下,您可以使用 django.core.mail.send_mail() .

这个 subjectmessagefrom_emailrecipient_list 参数是必需的。

  • subject 一个字符串。

  • message 一个字符串。

  • from_email :字符串。如果 None ,Django将使用 DEFAULT_FROM_EMAIL 设置。

  • recipient_list :字符串列表,每个字符串都是电子邮件地址。每个成员 recipient_list 将在电子邮件的“收件人”字段中看到其他收件人。

  • fail_silently 一个布尔值。当它的时候 Falsesend_mail() 将提高 smtplib.SMTPException 如果发生错误。见 smtplib 用于列出可能的异常的文档,所有这些异常都是 SMTPException .

  • auth_user :用于对SMTP服务器进行身份验证的可选用户名。如果没有提供,Django将使用 EMAIL_HOST_USER 设置。

  • auth_password :用于对SMTP服务器进行身份验证的可选密码。如果没有提供,Django将使用 EMAIL_HOST_PASSWORD 设置。

  • connection :用于发送邮件的可选电子邮件后端。如果未指定,将使用默认后端的实例。请参阅上的文档 Email backends 了解更多详细信息。

  • html_message 如果 html_message 如果提供,则生成的电子邮件将是 multipart/alternative 电子邮件与 message 作为 text/plain 内容类型和 html_message 作为 text/html 内容类型。

返回值将是成功传递的消息数(可以是 01 因为它只能发送一条消息)。

send_mass_mail()

send_mass_mail(datatuple, fail_silently=False, auth_user=None, auth_password=None, connection=None)[源代码]

django.core.mail.send_mass_mail() 旨在处理大量电子邮件。

datatuple 是一个元组,其中每个元素的格式如下:

(subject, message, from_email, recipient_list)

fail_silentlyauth_userauth_password 具有与中相同的功能 send_mail() .

每个单独的元素 datatuple 生成单独的电子邮件。如在 send_mail() ,收件人相同 recipient_list 将在电子邮件的“收件人:”字段中看到其他地址。

例如,以下代码将向两组不同的收件人发送两条不同的邮件;但是,只打开一个到邮件服务器的连接::

message1 = (
    "Subject here",
    "Here is the message",
    "from@example.com",
    ["first@example.com", "other@example.com"],
)
message2 = (
    "Another Subject",
    "Here is another message",
    "from@example.com",
    ["second@test.com"],
)
send_mass_mail((message1, message2), fail_silently=False)

返回值将是成功传递的消息数。

send_mass_mail() vs. send_mail()

两者的主要区别 send_mass_mail()send_mail() 那是 send_mail() 每次执行邮件服务器时都打开与邮件服务器的连接,同时 send_mass_mail() 对其所有消息使用单个连接。这使得 send_mass_mail() 效率略高。

mail_admins()

mail_admins(subject, message, fail_silently=False, connection=None, html_message=None)[源代码]

django.core.mail.mail_admins() 是向网站管理员发送电子邮件的快捷方式,如中定义的 ADMINS 设置。

mail_admins() 在主题前面加上 EMAIL_SUBJECT_PREFIX 设置,即 "[Django] " 默认情况下。

电子邮件的“发件人:”标题将是 SERVER_EMAIL 设置。

这种方法的存在是为了方便和可读性。

如果 html_message 如果提供,则生成的电子邮件将是 multipart/alternative 电子邮件与 message 作为 text/plain 内容类型和 html_message 作为 text/html 内容类型。

mail_managers()

mail_managers(subject, message, fail_silently=False, connection=None, html_message=None)[源代码]

django.core.mail.mail_managers() 就像是 mail_admins() ,除非它向站点经理发送电子邮件,如 MANAGERS 设置。

实例

这将向john@example.com和jane@example.com发送一封电子邮件,两封邮件都显示在“收件人:”中:

send_mail(
    "Subject",
    "Message.",
    "from@example.com",
    ["john@example.com", "jane@example.com"],
)

这会向john@example.com和jane@example.com发送一条消息,两人都会收到一封单独的电子邮件:

datatuple = (
    ("Subject", "Message.", "from@example.com", ["john@example.com"]),
    ("Subject", "Message.", "from@example.com", ["jane@example.com"]),
)
send_mass_mail(datatuple)

防止集管喷射

Header injection 是一种安全漏洞,攻击者在其中插入额外的电子邮件头来控制脚本生成的电子邮件消息中的“to:”和“from:”。

上面概述的django电子邮件功能通过禁止在头值中添加新行来防止头注入。如果有的话 subjectfrom_emailrecipient_list 包含新行(Unix、Windows或Mac样式)、电子邮件功能(例如 send_mail() 将提高 django.core.mail.BadHeaderError (子类) ValueError )因此,不会发送电子邮件。您有责任在将所有数据传递给电子邮件功能之前对其进行验证。

如果A message 在字符串的开头包含标头,则标头将作为电子邮件的第一位打印。

下面是一个示例视图, subjectmessagefrom_email 从请求的post数据发送到admin@example.com,完成后重定向到“/contact/thanks/”:

from django.core.mail import BadHeaderError, send_mail
from django.http import HttpResponse, HttpResponseRedirect


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, ["admin@example.com"])
        except BadHeaderError:
            return HttpResponse("Invalid header found.")
        return HttpResponseRedirect("/contact/thanks/")
    else:
        # In reality we'd use a form class
        # to get proper validation errors.
        return HttpResponse("Make sure all fields are entered and valid.")

这个 EmailMessage

Django send_mail()send_mass_mail() 函数实际上是利用 EmailMessage 类。

不是所有的功能 EmailMessage 课程可通过 send_mail() 以及相关的包装函数。如果要使用高级功能,如密件抄送收件人、文件附件或多部分电子邮件,则需要创建 EmailMessage 直接引用实例。

备注

这是一个设计特点。 send_mail() 相关函数最初是Django提供的唯一接口。然而,他们接受的参数列表随着时间的推移而缓慢增长。对于电子邮件来说,转向更面向对象的设计是有意义的,并且只保留原来的功能以实现向后兼容性。

EmailMessage 负责创建电子邮件本身。这个 email backend 然后负责发送电子邮件。

为了方便, EmailMessage 提供了一个 send() 发送单个电子邮件的方法。如果您需要发送多封邮件,电子邮件后端API provides an alternative .

EmailMessage 对象

class EmailMessage[源代码]

这个 EmailMessage 类初始化时使用以下参数(如果使用位置参数,则按给定顺序)。所有参数都是可选的,可以在调用 send() 方法。

  • subject :电子邮件的主题行。

  • body :正文文本。这应该是一条纯文本消息。

  • from_email :发件人地址。两个 fred@example.com"Fred" <fred@example.com> 表格是合法的。如果省略, DEFAULT_FROM_EMAIL 使用设置。

  • to :收件人地址的列表或元组。

  • bcc :发送电子邮件时“bcc”头中使用的地址列表或元组。

  • connection :电子邮件后端实例。如果要对多条消息使用同一连接,请使用此参数。如果省略,则当 send() 被称为。

  • attachments :要放在邮件上的附件列表。这些可以是 MIMEBase 实例,或 (filename, content, mimetype) 三元组。

  • headers :要放在消息上的额外头的字典。键是标题名称,值是标题值。由调用者来确保邮件头名称和值的格式正确。相应的属性是 extra_headers .

  • cc :发送电子邮件时“cc”头中使用的收件人地址列表或元组。

  • reply_to :发送电子邮件时在“答复”标题中使用的收件人地址列表或元组。

例如::

from django.core.mail import EmailMessage

email = EmailMessage(
    "Hello",
    "Body goes here",
    "from@example.com",
    ["to1@example.com", "to2@example.com"],
    ["bcc@example.com"],
    reply_to=["another@example.com"],
    headers={"Message-ID": "foo"},
)

类具有以下方法:

  • send(fail_silently=False) 发送消息。如果在构建电子邮件时指定了连接,则将使用该连接。否则,将实例化并使用默认后端的一个实例。如果关键字参数 fail_silentlyTrue ,则发送消息时引发的异常将被撤销。空的收件人列表不会引发异常。它会回来的 1 如果消息已成功发送,则为 0

  • message() 构建一个 django.core.mail.SafeMIMEText 对象(python的子类 MIMEText 类) django.core.mail.SafeMIMEMultipart 保存要发送的消息的对象。如果你需要延长 EmailMessage 类,您可能希望重写此方法以将所需内容放入mime对象。

  • recipients() 返回邮件的所有收件人的列表,无论他们是否记录在 toccbcc 属性。这是子类化时可能需要重写的另一种方法,因为在发送邮件时,需要告知SMTP服务器完整的收件人列表。如果添加另一种方法来指定类中的收件人,则还需要从此方法返回这些收件人。

  • attach() 创建新的文件附件并将其添加到邮件中。调用有两种方式 attach()

    • 你可以给它传递一个单一的参数 MIMEBase 实例。这将直接插入到结果消息中。

    • 或者,你可以通过 attach() 三个论点: filenamecontentmimetype . filename 是将在电子邮件中显示的文件附件的名称, content 是将包含在附件中的数据,并且 mimetype 是附件的可选mime类型。如果省略 mimetype ,将根据附件的文件名猜测mime内容类型。

      例如::

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

      如果您指定一个 mimetypemessage/rfc822 ,它也会接受 django.core.mail.EmailMessageemail.message.Message

      对于一个 mimetype 从开始 text/ ,内容应为字符串。二进制数据将使用utf-8进行解码,如果失败,则mime类型将更改为 application/octet-stream 数据将保持不变。

      此外, message/rfc822 附件将不再是base64编码,违反 RFC 2046#section-5.2.1 ,这可能导致在中显示附件时出现问题 `Evolution`_`Thunderbird`_ _.

  • attach_file() 使用文件系统中的文件创建新附件。使用要附加的文件路径以及用于附件的MIME类型调用它。如果省略MIME类型,将从文件名中猜测。你可以这样使用它:

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

    对于以开头的mime类型 text/ ,二进制数据的处理方式与 attach() .

发送可选内容类型

在一封电子邮件中包含多个版本的内容可能很有用;经典的例子是同时发送文本和HTML版本的邮件。使用Django的电子邮件库,您可以使用 EmailMultiAlternatives 类。此子类 EmailMessage 有一个 attach_alternative() 在电子邮件中包含消息正文的额外版本的方法。所有其他方法(包括类初始化)都直接从 EmailMessage .

要发送文本和HTML组合,您可以编写:

from django.core.mail import EmailMultiAlternatives

subject, from_email, to = "hello", "from@example.com", "to@example.com"
text_content = "This is an important message."
html_content = "<p>This is an <strong>important</strong> message.</p>"
msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
msg.attach_alternative(html_content, "text/html")
msg.send()

默认情况下, body AN中的参数 EmailMessage"text/plain" . 最好不要这样做,因为这样可以保证任何收件人都能够阅读电子邮件,而不管他们的邮件客户是谁。但是,如果您确信收件人可以处理其他内容类型,则可以使用 content_subtype 属性 EmailMessage 类以更改主要内容类型。主要类型将始终是 "text" ,但您可以更改子类型。例如::

msg = EmailMessage(subject, html_content, from_email, [to])
msg.content_subtype = "html"  # Main content is now text/html
msg.send()

电子邮件后端

电子邮件的实际发送由电子邮件后端处理。

电子邮件后端类具有以下方法:

  • open() 实例化一个长期存在的电子邮件发送连接。

  • close() 关闭当前电子邮件发送连接。

  • send_messages(email_messages) 发送一个列表, EmailMessage 物体。如果连接未打开,则此调用将隐式打开连接,然后关闭连接。如果连接已打开,则在发送邮件后将保持打开状态。

它还可以用作上下文管理器,它将自动调用 open()close() 根据需要:

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()

获取电子邮件后端的实例

这个 get_connection() 中的函数 django.core.mail 返回可以使用的电子邮件后端实例。

get_connection(backend=None, fail_silently=False, *args, **kwargs)[源代码]

默认情况下,调用 get_connection() 将返回在中指定的电子邮件后端实例 EMAIL_BACKEND . 如果您指定 backend 参数,将实例化该后端的实例。

这个 fail_silently 参数控制后端应如何处理错误。如果 fail_silently 为真,电子邮件发送过程中的异常将被静默忽略。

所有其他参数都直接传递给电子邮件后端的构造函数。

Django提供了几个电子邮件发送后端。除了SMTP后端(默认情况下),这些后端只在测试和开发期间有用。如果您有特殊的电子邮件发送要求,您可以 write your own email backend .

SMTP后端

class backends.smtp.EmailBackend(host=None, port=None, username=None, password=None, use_tls=None, fail_silently=False, use_ssl=None, timeout=None, ssl_keyfile=None, ssl_certfile=None, **kwargs)

这是默认的后端。电子邮件将通过SMTP服务器发送。

如果参数为 None

SMTP后端是Django继承的默认配置。如果要显式指定,请将以下内容放入设置中:

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

如果未指定,则默认 timeout 将由提供 socket.getdefaulttimeout() ,默认为 None (没有超时时间)。

控制台后端

控制台后端不发送真实的电子邮件,只写将发送到标准输出的电子邮件。默认情况下,控制台后端写入 stdout . 通过提供 stream 构造连接时使用关键字参数。

要指定此后端,请在设置中放置以下内容:

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

这个后端并不打算用于生产——它是作为一种方便而提供的,可以在开发期间使用。

文件后端

文件后端将电子邮件写入文件。将为此后端上打开的每个新会话创建一个新文件。将文件写入的目录可以从 EMAIL_FILE_PATH 设置或来自 file_path 创建连接时使用关键字 get_connection() .

要指定此后端,请在设置中放置以下内容:

EMAIL_BACKEND = "django.core.mail.backends.filebased.EmailBackend"
EMAIL_FILE_PATH = "/tmp/app-messages"  # change this to a proper location

这个后端并不打算用于生产——它是作为一种方便而提供的,可以在开发期间使用。

内存后端

这个 'locmem' 后端将消息存储在 django.core.mail 模块。这个 outbox 属性在发送第一条消息时创建。它是一个带有 EmailMessage 将发送的每个消息的实例。

要指定此后端,请在设置中放置以下内容:

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

这个后端并不打算用于生产——它是在开发和测试期间提供的一种方便。

Django的测试运行程序 automatically uses this backend for testing .

虚拟后端

顾名思义,虚拟后端与您的消息没有任何关系。要指定此后端,请在设置中放置以下内容:

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

这个后端并不打算用于生产——它是作为一种方便而提供的,可以在开发期间使用。

定义自定义电子邮件后端

如果您需要更改电子邮件的发送方式,您可以编写自己的电子邮件后端。这个 EMAIL_BACKEND 设置文件中的设置是后端类的python导入路径。

自定义电子邮件后端应子类 BaseEmailBackend 位于 django.core.mail.backends.base 模块。自定义电子邮件后端必须实现 send_messages(email_messages) 方法。此方法接收 EmailMessage 实例并返回成功传递的消息数。如果后端有任何持久会话或连接的概念,那么还应该实现 open()close() 方法。参照 smtp.EmailBackend 用于引用实现。

发送多封电子邮件

建立和关闭一个SMTP连接(或任何其他网络连接,就这点而言)是一个昂贵的过程。如果你有很多邮件要发送,那么重新使用一个SMTP连接是有意义的,而不是每次你想发送邮件时都创建和破坏一个连接。

有两种方法可以告诉电子邮件后端重用连接。

首先,您可以使用 send_messages() 方法。 send_messages() 列出一个 EmailMessage 实例(或子类),并使用单个连接发送所有实例。

例如,如果有一个函数调用 get_notification_email() 返回一个列表 EmailMessage 对象表示您希望发送的某些定期电子邮件,您可以使用单个调用发送这些电子邮件以发送消息:

from django.core import mail

connection = mail.get_connection()  # Use default email connection
messages = get_notification_email()
connection.send_messages(messages)

在本例中,调用 send_messages() 在后端打开连接,发送消息列表,然后再次关闭连接。

第二种方法是使用 open()close() 方法在电子邮件后端手动控制连接。 send_messages() 如果连接已打开,则不会手动打开或关闭,因此如果手动打开连接,则可以控制连接关闭的时间。例如::

from django.core import mail

connection = mail.get_connection()

# Manually open the connection
connection.open()

# Construct an email message that uses the connection
email1 = mail.EmailMessage(
    "Hello",
    "Body goes here",
    "from@example.com",
    ["to1@example.com"],
    connection=connection,
)
email1.send()  # Send the email

# Construct two more messages
email2 = mail.EmailMessage(
    "Hello",
    "Body goes here",
    "from@example.com",
    ["to2@example.com"],
)
email3 = mail.EmailMessage(
    "Hello",
    "Body goes here",
    "from@example.com",
    ["to3@example.com"],
)

# Send the two emails in a single call -
connection.send_messages([email2, email3])
# The connection was already open so send_messages() doesn't close it.
# We need to manually close the connection.
connection.close()

为开发配置电子邮件

有时你根本不想让 Django 发送电子邮件。例如,在开发一个网站时,您可能不想发送数千封电子邮件,但您可能希望验证在正确的条件下将电子邮件发送给正确的人,并且这些电子邮件将包含正确的内容。

为本地开发配置电子邮件的最简单方法是使用 console 电子邮件后端。此后端会将所有电子邮件重定向到 stdout ,允许您检查邮件内容。

这个 file 电子邮件后端在开发过程中也很有用——这个后端将每个SMTP连接的内容转储到一个可以在空闲时检查的文件中。

另一种方法是使用“愚蠢的”SMTP服务器,它在本地接收电子邮件并将它们显示给终端,但实际上并不发送任何东西。这个 aiosmtpd Package提供了一种实现这一点的方法:

python -m pip install aiosmtpd

python -m aiosmtpd -n -l localhost:8025

此命令将启动侦听本地主机的端口8025的最小SMTP服务器。此服务器将所有电子邮件标题和电子邮件正文打印到标准输出。然后,您只需将 EMAIL_HOSTEMAIL_PORT 相应地。有关SMTP服务器选项的更详细讨论,请参阅 aiosmtpd 模块。

有关在应用程序中测试电子邮件发送的单元的信息,请参阅 电子邮件服务 测试文件的章节。