Django筆記三十八之發(fā)送郵件

這一篇筆記介紹如何在 Django 中發(fā)送郵件。

在 Python 中,提供了 smtplib 的郵件模塊,而 Django 在這個基礎(chǔ)上對其進(jìn)行了封裝,我們可以通過 django.core.mail 來調(diào)用。

以下是本篇筆記的目錄:

  1. 郵件配置項
  2. send_mail
  3. EmailMessage
  4. 復(fù)用郵件發(fā)送連接
  5. 開發(fā)階段調(diào)試設(shè)置

1、郵件配置項

在正式發(fā)送郵件前,我們需要在 settings.py 里設(shè)置幾個參數(shù),如下:

# 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 日志記錄那一篇筆記中有過介紹,那是我們指定日志等級發(fā)送郵件的功能,這里再做一下簡單的介紹。

EMAIL_BACKEND 是我們指定的郵箱后端,在后面我們會介紹在開發(fā)調(diào)試階段的時候可以設(shè)置的其他值

EMAIL_HOST 發(fā)送郵箱的主機(jī)地址,這里我們使用的是 163 郵箱的地址

EMAIL_PORT EMAIL_HOST 使用的端口

EMAIL_HOST_USER 發(fā)件人郵箱地址

EMAIL_HOST_PASSWORD 163 郵箱開啟了 SMTP 服務(wù)提供的授權(quán)碼

EMAIL_USE_SSL 與 SMTP 服務(wù)器對話時是否使用隱式 TLS 連接,這種類型被稱為 SSL,通常在 465 端口使用,這個字段與 EMAIL_USE_TLS 是互相排斥的,只能設(shè)置一個為 True

EMAIL_USE_TLS 與 SMTP 服務(wù)器對話是否使用 TLS 連接,一般在 587 端口

以上就是在 Django 里使用 163 郵箱的一個配置項示例。

2、send_mail

配置好之后我們就可以嘗試發(fā)送一下郵件,最簡單的使用示例如下:

from django.core.mail import send_mail

send_mail(
    subject="subject 主題",
    message="郵件主體",
    from_email="hunterxx@163.com",
    recipient_list=["120460xxxx@qq.com"],
)

在上面的調(diào)用中,subject 是發(fā)送的郵件的標(biāo)題,

message 是郵件發(fā)送的正文內(nèi)容。

from_email 是發(fā)送郵件的郵箱

recipient_list 是接收收件人列表,可以接收多個郵箱地址

對于 message 參數(shù),接收的是純文本信息,會將參數(shù)內(nèi)容直接顯示在郵件正文,如果是想對文本進(jìn)行更多操作,比如加大字體,加粗,或者加上表格等操作,可以使用 html_message 參數(shù)來替代 message 參數(shù)。

比如:

send_mail(
    subject="subject 主題",
    from_email="hunterxx@163.com",
    recipient_list=["120460xxxx@qq.com"],
    html_message="<h1>html main body</h1>"
)

在這里,html_message 將參數(shù)內(nèi)容當(dāng)作一個 html 文本進(jìn)行解析,發(fā)送郵件后就可以在接收郵箱看到大號的文本字體了。

發(fā)送批量郵件

如果有批量發(fā)送郵件的需求,可以使用 send_mass_mail 方法。

from django.core.mail import send_mass_mail

message_1 = ("郵件標(biāo)題1", "郵件正文1", "hunterxxx@163.com", ["120460xxxx@qq.com"])
message_2 = ("郵件標(biāo)題2", "郵件正文2", "hunterxxx4@163.com", ["120460xxx6@qq.com"])
send_mass_mail(
    (message_1, message_2)

該方法接收列表參數(shù),其中列表的每一個元素的參數(shù)和參數(shù)順序都是固定的,分別是郵件標(biāo)題,正文,郵件發(fā)送人,和郵件接收人列表。

注意: 因為批量發(fā)送的參數(shù)是固定的,所以并不支持 send_mail 里的 html_message 參數(shù)。

3、EmailMessage

前面介紹的 send_mail() 方法簡單可用,但是并不支持郵件里的附件、抄送等功能,接下來我們使用 EmailMessage 這個類來實現(xiàn)這些額外的功能。

以下是使用 EmailMessage 實現(xiàn)發(fā)送郵件的簡單示例:

from django.core.mail import EmailMessage

email = EmailMessage(
    subject="郵件標(biāo)題",
    body="郵件主體",
    from_email="hunterxxx@163.com",
    to=["120460xxx@qq.com"],
)
email.send()

參數(shù)名稱與 send_mail() 略有不同,這里的郵件正文是 body,接收人列表為 to。

這里在實例化 EmailMessage 之后,調(diào)用 send() 方法即可發(fā)送郵件。

除了上面的這些參數(shù),還有 bcc,實現(xiàn)的是密送功能,也是郵件接收人列表,cc 是抄送人列表。

還有 attachments 參數(shù),實現(xiàn)的是附件功能,接下來介紹幾種發(fā)送附件的方式:

發(fā)送附件

1. attachments 參數(shù)

我們可以直接在 EmailMessage() 中添加附件參數(shù),attachments 參數(shù)接收一個列表,列表元素也是一個列表,內(nèi)層的這個列表接收三個元素,第一個元素為文件名,第二個元素為文件內(nèi)容,第三個元素為指定的附件的 MIME 類型,第三個參數(shù)省略的話就會參考附件的文件名自動選擇。

我們在系統(tǒng)根目錄下創(chuàng)建兩個文件 a.txt, b.txt,然后實現(xiàn)示例如下:

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="郵件標(biāo)題",
    body="郵件主體",
    from_email="hunterxxxx@163.com",
    to=["120460xxxx@qq.com"],
    attachments=attachments,
)
email.send()
2. attach() 方法

除了直接在 EmailMessage 實例中添加參數(shù),我們還可以使用 attach() 方法。

示例如下:

email = EmailMessage(
    subject="郵件標(biāo)題",
    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() 方法,參數(shù)內(nèi)容是文件路徑+文件名,系統(tǒng)會自動為我們解析該文件:

email = EmailMessage(
    subject="郵件標(biāo)題",
    body="郵件主體",
    from_email="hunterxxxx@163.com",
    to=["120460xxx@qq.com"],
)

email.attach_file("./b.txt")
email.send()

EmailMessage 發(fā)送 html 正文

前面介紹了在 send_mail() 方法可以通過 html_message 的參數(shù)發(fā)送 html 頁面的郵件,在 EmailMessage 也可以實現(xiàn),但是需要修改 content_subtype 屬性。

默認(rèn)情況下,EmailMessage.content_subtype 是 "plain",我們將其改為 "html" 即可發(fā)送 html 頁面的郵件。

email = EmailMessage(
    subject="郵件標(biāo)題",
    body="<h1>郵件主體</h1>",
    from_email="hunterxxxx@163.com",
    to=["120460xxx@qq.com"],
)
email.content_subtype = "html"
email.send()

4、復(fù)用郵件發(fā)送連接

因為發(fā)送郵件涉及到網(wǎng)絡(luò)連接及可能存在的大量數(shù)據(jù)的傳送,比如附件。

所以,如果是在接口中有發(fā)送郵件的需求,我們可以通過 celery 的異步任務(wù)實現(xiàn)發(fā)送郵件的功能。

而郵件的發(fā)送會涉及到 SMTP 連接的創(chuàng)建和關(guān)閉,所以復(fù)用連接也是一個好的方式。

這里介紹兩種方式:

send_messages

send_messages() 方法接收 EmailMessage 實例列表,然后實現(xiàn)批量發(fā)送的功能:

from django.core import mail
from django.core.mail import EmailMessage

email_1 = EmailMessage(
    subject="郵件標(biāo)題1",
    body="郵件主體1",
    from_email="hunterxxxx@163.com",
    to=["120460xxxx@qq.com"],
)
email_2 = EmailMessage(
    subject="郵件標(biāo)題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 的創(chuàng)建和關(guān)閉。

from django.core import mail

connection = mail.get_connection()

email_1 = mail.EmailMessage(
    subject="郵件標(biāo)題1",
    body="郵件主體1",
    from_email="hunterxxx@163.com",
    to=["120460xxx@qq.com"],
    connection=connection
)
email_1.send()


email_2 = mail.EmailMessage(
    subject="郵件標(biāo)題2",
    body="郵件主體2",
    from_email="hunterxxxx@163.com",
    to=["120460xxxx@qq.com"],
)


email_3 = mail.EmailMessage(
    subject="郵件標(biāo)題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 的調(diào)用增加了 connection 參數(shù),email_2 和 email_3 也是使用 connection 進(jìn)行的批量發(fā)送

這個過程中,connection 一直沒有關(guān)閉,所以復(fù)用的是同一個連接,直到最后調(diào)用 close() 才算是手動關(guān)閉了這個 connection 連接。

5、開發(fā)階段調(diào)試設(shè)置

在開發(fā)階段,我們調(diào)試發(fā)送郵件功能的時候,有時候并不想每次都真的發(fā)送郵件給指定賬戶,盡管可能是測試賬號,我們有時候只想看一下輸出的內(nèi)容,可以更改郵箱配置的后端

console

我們可以在 settings.py 里設(shè)置:

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

這樣,在調(diào)用我們前面的 send 方法后,系統(tǒng)就不會發(fā)送郵件給 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>


<h1>郵件主體</h1>
-------------------------------------------------------------------------------

filebased

在調(diào)試階段,我們還可以指定將郵件的內(nèi)容輸出到文件,同樣的修改郵件后端配置:

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

這里設(shè)置了郵件后端為文件,EMAIL_FILE_PATH 則是指定了郵件內(nèi)容放到系統(tǒng)根目錄下的 emails_file 文件中。

調(diào)用了發(fā)送郵件的函數(shù)后,在這個文件夾下就會多出一個文件,文件內(nèi)容是我們前面在 console 控制臺輸出的內(nèi)容

原文鏈接:Django筆記三十八之發(fā)送郵件

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容