本文首發於公眾號:Hunter後端 原文鏈接:Django筆記三十八之發送郵件 這一篇筆記介紹如何在 Django 中發送郵件。 在 Python 中,提供了 smtplib 的郵件模塊,而 Django 在這個基礎上對其進行了封裝,我們可以通過 django.core.mail 來調用。 以下是本 ...
本文首發於公眾號:Hunter後端
原文鏈接:Django筆記三十八之發送郵件
這一篇筆記介紹如何在 Django 中發送郵件。
在 Python 中,提供了 smtplib 的郵件模塊,而 Django 在這個基礎上對其進行了封裝,我們可以通過 django.core.mail
來調用。
以下是本篇筆記的目錄:
- 郵件配置項
- send_mail
- EmailMessage
- 復用郵件發送連接
- 開發階段調試設置
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 = '[email protected]'
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="[email protected]",
recipient_list=["[email protected]"],
)
在上面的調用中,subject 是發送的郵件的標題,
message 是郵件發送的正文內容。
from_email 是發送郵件的郵箱
recipient_list 是接收收件人列表,可以接收多個郵箱地址
對於 message 參數,接收的是純文本信息,會將參數內容直接顯示在郵件正文,如果是想對文本進行更多操作,比如加大字體,加粗,或者加上表格等操作,可以使用 html_message
參數來替代 message 參數。
比如:
send_mail(
subject="subject 主題",
from_email="[email protected]",
recipient_list=["[email protected]"],
html_message="<h1>html main body</h1>"
)
在這裡,html_message
將參數內容當作一個 html 文本進行解析,發送郵件後就可以在接收郵箱看到大號的文本字體了。
發送批量郵件
如果有批量發送郵件的需求,可以使用 send_mass_mail
方法。
from django.core.mail import send_mass_mail
message_1 = ("郵件標題1", "郵件正文1", "[email protected]", ["[email protected]"])
message_2 = ("郵件標題2", "郵件正文2", "[email protected]", ["[email protected]"])
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="[email protected]",
to=["[email protected]"],
)
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="[email protected]",
to=["[email protected]"],
attachments=attachments,
)
email.send()
2. attach() 方法
除了直接在 EmailMessage 實例中添加參數,我們還可以使用 attach() 方法。
示例如下:
email = EmailMessage(
subject="郵件標題",
body="郵件主體",
from_email="[email protected]",
to=["[email protected]"],
)
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="[email protected]",
to=["[email protected]"],
)
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="<h1>郵件主體</h1>",
from_email="[email protected]",
to=["[email protected]"],
)
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="[email protected]",
to=["[email protected]"],
)
email_2 = EmailMessage(
subject="郵件標題2",
body="郵件主體2",
from_email="[email protected]",
to=["[email protected]"],
)
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="[email protected]",
to=["[email protected]"],
connection=connection
)
email_1.send()
email_2 = mail.EmailMessage(
subject="郵件標題2",
body="郵件主體2",
from_email="[email protected]",
to=["[email protected]"],
)
email_3 = mail.EmailMessage(
subject="郵件標題3",
body="郵件主體3",
from_email="[email protected]",
to=["[email protected]"],
)
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: [email protected]
To: [email protected]
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
在調試階段,我們還可以指定將郵件的內容輸出到文件,同樣的修改郵件後端配置:
EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
EMAIL_FILE_PATH = './emails_file'
這裡設置了郵件後端為文件,EMAIL_FILE_PATH 則是指定了郵件內容放到系統根目錄下的 emails_file 文件中。
調用了發送郵件的函數後,在這個文件夾下就會多出一個文件,文件內容是我們前面在 console 控制台輸出的內容
如果想獲取更多後端相關文章,可掃碼關註閱讀: