• Django笔记三十八之发送邮件


    本文首发于公众号:Hunter后端

    原文链接:Django笔记三十八之发送邮件

    这一篇笔记介绍如何在 Django 中发送邮件。

    在 Python 中,提供了 smtplib 的邮件模块,而 Django 在这个基础上对其进行了封装,我们可以通过 django.core.mail 来调用。

    以下是本篇笔记的目录:

    1. 邮件配置项
    2. send_mail
    3. EmailMessage
    4. 复用邮件发送连接
    5. 开发阶段调试设置

    1、邮件配置项

    在正式发送邮件前,我们需要在 settings.py 里设置几个参数,如下:

    # hunter/settings.py
    
    EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
    EMAIL_HOST = 'smtp.163.com'     
    EMAIL_PORT = 465   
    EMAIL_HOST_USER = 'hunterxxxx04@163.com'  
    EMAIL_HOST_PASSWORD = 'JBDMVIXSHYxxxxx' 
    EMAIL_USE_SSL = True
    EMAIL_USE_TLS = False
    

    这些配置项在 log 日志记录那一篇笔记中有过介绍,那是我们指定日志等级发送邮件的功能,这里再做一下简单的介绍。

    EMAIL_BACKEND 是我们指定的邮箱后端,在后面我们会介绍在开发调试阶段的时候可以设置的其他值

    EMAIL_HOST 发送邮箱的主机地址,这里我们使用的是 163 邮箱的地址

    EMAIL_PORT EMAIL_HOST 使用的端口

    EMAIL_HOST_USER 发件人邮箱地址

    EMAIL_HOST_PASSWORD 163 邮箱开启了 SMTP 服务提供的授权码

    EMAIL_USE_SSL 与 SMTP 服务器对话时是否使用隐式 TLS 连接,这种类型被称为 SSL,通常在 465 端口使用,这个字段与 EMAIL_USE_TLS 是互相排斥的,只能设置一个为 True

    EMAIL_USE_TLS 与 SMTP 服务器对话是否使用 TLS 连接,一般在 587 端口

    以上就是在 Django 里使用 163 邮箱的一个配置项示例。

    2、send_mail

    配置好之后我们就可以尝试发送一下邮件,最简单的使用示例如下:

    from django.core.mail import send_mail
    
    send_mail(
        subject="subject 主题",
        message="邮件主体",
        from_email="hunterxx@163.com",
        recipient_list=["120460xxxx@qq.com"],
    )
    

    在上面的调用中,subject 是发送的邮件的标题,

    message 是邮件发送的正文内容。

    from_email 是发送邮件的邮箱

    recipient_list 是接收收件人列表,可以接收多个邮箱地址

    对于 message 参数,接收的是纯文本信息,会将参数内容直接显示在邮件正文,如果是想对文本进行更多操作,比如加大字体,加粗,或者加上表格等操作,可以使用 html_message 参数来替代 message 参数。

    比如:

    send_mail(
        subject="subject 主题",
        from_email="hunterxx@163.com",
        recipient_list=["120460xxxx@qq.com"],
        html_message="

    html main body

    "
    )

    在这里,html_message 将参数内容当作一个 html 文本进行解析,发送邮件后就可以在接收邮箱看到大号的文本字体了。

    发送批量邮件

    如果有批量发送邮件的需求,可以使用 send_mass_mail 方法。

    from django.core.mail import send_mass_mail
    
    message_1 = ("邮件标题1", "邮件正文1", "hunterxxx@163.com", ["120460xxxx@qq.com"])
    message_2 = ("邮件标题2", "邮件正文2", "hunterxxx4@163.com", ["120460xxx6@qq.com"])
    send_mass_mail(
        (message_1, message_2)
    

    该方法接收列表参数,其中列表的每一个元素的参数和参数顺序都是固定的,分别是邮件标题,正文,邮件发送人,和邮件接收人列表。

    注意: 因为批量发送的参数是固定的,所以并不支持 send_mail 里的 html_message 参数。

    3、EmailMessage

    前面介绍的 send_mail() 方法简单可用,但是并不支持邮件里的附件、抄送等功能,接下来我们使用 EmailMessage 这个类来实现这些额外的功能。

    以下是使用 EmailMessage 实现发送邮件的简单示例:

    from django.core.mail import EmailMessage
    
    email = EmailMessage(
        subject="邮件标题",
        body="邮件主体",
        from_email="hunterxxx@163.com",
        to=["120460xxx@qq.com"],
    )
    email.send()
    

    参数名称与 send_mail() 略有不同,这里的邮件正文是 body,接收人列表为 to。

    这里在实例化 EmailMessage 之后,调用 send() 方法即可发送邮件。

    除了上面的这些参数,还有 bcc,实现的是密送功能,也是邮件接收人列表,cc 是抄送人列表。

    还有 attachments 参数,实现的是附件功能,接下来介绍几种发送附件的方式:

    发送附件

    1. attachments 参数

    我们可以直接在 EmailMessage() 中添加附件参数,attachments 参数接收一个列表,列表元素也是一个列表,内层的这个列表接收三个元素,第一个元素为文件名,第二个元素为文件内容,第三个元素为指定的附件的 MIME 类型,第三个参数省略的话就会参考附件的文件名自动选择。

    我们在系统根目录下创建两个文件 a.txt, b.txt,然后实现示例如下:

    from django.core.mail import EmailMessage
    
    attachments = []
    for file_name in ["./a.txt", "./b.txt"]:
        with open(file_name, "r") as f:
            content = f.read()
            attachments.append((file_name, content))
    
    
    email = EmailMessage(
        subject="邮件标题",
        body="邮件主体",
        from_email="hunterxxxx@163.com",
        to=["120460xxxx@qq.com"],
        attachments=attachments,
    )
    email.send()
    
    2. attach() 方法

    除了直接在 EmailMessage 实例中添加参数,我们还可以使用 attach() 方法。

    示例如下:

    email = EmailMessage(
        subject="邮件标题",
        body="邮件主体",
        from_email="hunterxxxx@163.com",
        to=["120460xxxx@qq.com"],
    )
    
    
    file_name_1 = "./a.txt"
    f = open(file_name_1, "r")
    file_content_1 = f.read()
    f.close()
    
    
    email.attach(file_name_1, file_content_1)
    email.send()
    
    3. attach_file() 方法

    还有一个方式是使用 attach_file() 方法,参数内容是文件路径+文件名,系统会自动为我们解析该文件:

    email = EmailMessage(
        subject="邮件标题",
        body="邮件主体",
        from_email="hunterxxxx@163.com",
        to=["120460xxx@qq.com"],
    )
    
    email.attach_file("./b.txt")
    email.send()
    

    EmailMessage 发送 html 正文

    前面介绍了在 send_mail() 方法可以通过 html_message 的参数发送 html 页面的邮件,在 EmailMessage 也可以实现,但是需要修改 content_subtype 属性。

    默认情况下,EmailMessage.content_subtype 是 "plain",我们将其改为 "html" 即可发送 html 页面的邮件。

    email = EmailMessage(
        subject="邮件标题",
        body="

    邮件主体

    "
    , from_email="hunterxxxx@163.com", to=["120460xxx@qq.com"], ) email.content_subtype = "html" email.send()

    4、复用邮件发送连接

    因为发送邮件涉及到网络连接及可能存在的大量数据的传送,比如附件。

    所以,如果是在接口中有发送邮件的需求,我们可以通过 celery 的异步任务实现发送邮件的功能。

    而邮件的发送会涉及到 SMTP 连接的创建和关闭,所以复用连接也是一个好的方式。

    这里介绍两种方式:

    send_messages

    send_messages() 方法接收 EmailMessage 实例列表,然后实现批量发送的功能:

    from django.core import mail
    from django.core.mail import EmailMessage
    
    email_1 = EmailMessage(
        subject="邮件标题1",
        body="邮件主体1",
        from_email="hunterxxxx@163.com",
        to=["120460xxxx@qq.com"],
    )
    email_2 = EmailMessage(
        subject="邮件标题2",
        body="邮件主体2",
        from_email="hunterxxxx@163.com",
        to=["120460xxxx@qq.com"],
    )
    
    
    connection = mail.get_connection()
    messages = [email_1, email_2]
    connection.send_messages(messages)
    

    手动控制 connection

    我们可以手动控制 connection 的创建和关闭。

    from django.core import mail
    
    connection = mail.get_connection()
    
    email_1 = mail.EmailMessage(
        subject="邮件标题1",
        body="邮件主体1",
        from_email="hunterxxx@163.com",
        to=["120460xxx@qq.com"],
        connection=connection
    )
    email_1.send()
    
    
    email_2 = mail.EmailMessage(
        subject="邮件标题2",
        body="邮件主体2",
        from_email="hunterxxxx@163.com",
        to=["120460xxxx@qq.com"],
    )
    
    
    email_3 = mail.EmailMessage(
        subject="邮件标题3",
        body="邮件主体3",
        from_email="hunterxxxx@163.com",
        to=["120460xxxx@qq.com"],
    )
    messages = [email_2, email_3]
    connection.send_messages(messages)
    
    
    connection.close()
    

    在这里,email_1 的调用增加了 connection 参数,email_2 和 email_3 也是使用 connection 进行的批量发送

    这个过程中,connection 一直没有关闭,所以复用的是同一个连接,直到最后调用 close() 才算是手动关闭了这个 connection 连接。

    5、开发阶段调试设置

    在开发阶段,我们调试发送邮件功能的时候,有时候并不想每次都真的发送邮件给指定账户,尽管可能是测试账号,我们有时候只想看一下输出的内容,可以更改邮箱配置的后端

    console

    我们可以在 settings.py 里设置:

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

    这样,在调用我们前面的 send 方法后,系统就不会发送邮件给 to 的接收人列表了,而是会在控制台输出我们的邮件信息:
    类似如下:

    Content-Type: text/html; charset="utf-8"
    MIME-Version: 1.0
    Content-Transfer-Encoding: 8bit
    Subject: =?utf-8?b?6YKu5L2qCH6aKY?=
    From: hunterxiong04@163.com
    To: 120460xxxx@qq.com
    Date: Fri, 17 Feb 2023 18:01:21 -0000
    Message-ID: 
     <167665688132.1114.884170460108140763@1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa>
    
    
    

    邮件主体

    -------------------------------------------------------------------------------

    filebased

    在调试阶段,我们还可以指定将邮件的内容输出到文件,同样的修改邮件后端配置:

    EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
    EMAIL_FILE_PATH = './emails_file'
    

    这里设置了邮件后端为文件,EMAIL_FILE_PATH 则是指定了邮件内容放到系统根目录下的 emails_file 文件中。

    调用了发送邮件的函数后,在这个文件夹下就会多出一个文件,文件内容是我们前面在 console 控制台输出的内容

    如果想获取更多后端相关文章,可扫码关注阅读:
    image

  • 相关阅读:
    上传图片并显示#Vue3#后端接口数据
    Git——解决 TortoiseGit 提示 No supported authentication methods available 错误
    【跨境电商】全渠道客户服务终极指南(二):提供全渠道客户服务的 6 种方式
    第十五届蓝桥杯题解-好数
    ARM开发(5)ARM的接口技术(串行通信与并行通信,同步串行通信与异步串行通信,波特率,串行通信术语,uart,i2c,spi三种协议简单引入)
    北大肖臻老师《区块链技术与应用》系列课程学习笔记[9]比特币-匿名性
    SpringBoot+Vue项目智能选课系统
    KEPServerEX 6 之 高级标签插件 Advanced Tags 中文说明(完整版)
    win10 下 ipmitool 1.8.19编译
    点亮LED灯三盏
  • 原文地址:https://www.cnblogs.com/hunterxiong/p/17383195.html