smtplib
— SMTP 協議客戶端¶
原始碼: Lib/smtplib.py
smtplib
模組定義了一個 SMTP 客戶端會話物件,該物件可用於向任何具有 SMTP 或 ESMTP 監聽守護程式的 Internet 計算機發送郵件。 有關 SMTP 和 ESMTP 操作的詳細資訊,請參考 RFC 821 (簡單郵件傳輸協議) 和 RFC 1869 (SMTP 服務擴充套件)。
可用性: 不支援 WASI。
此模組在 WebAssembly 上不起作用或不可用。 有關更多資訊,請參閱 WebAssembly 平臺。
- class smtplib.SMTP(host='', port=0, local_hostname=None, [timeout, ]source_address=None)¶
SMTP
例項封裝了一個 SMTP 連線。它具有支援完整 SMTP 和 ESMTP 操作的方法。如果給出了可選的 host 和 port 引數,則在初始化期間使用這些引數呼叫 SMTPconnect()
方法。 如果指定了 local_hostname,則在 HELO/EHLO 命令中用作本地主機的 FQDN。 否則,使用socket.getfqdn()
查詢本地主機名。 如果connect()
呼叫返回除成功程式碼之外的任何內容,則會引發SMTPConnectError
。 可選的 timeout 引數指定阻塞操作(如連線嘗試)的超時時間(以秒為單位)(如果未指定,則將使用全域性預設超時設定)。如果超時到期,則會引發TimeoutError
。 可選的 source_address 引數允許在具有多個網路介面的計算機中繫結到某個特定的源地址,和/或繫結到某個特定的源 TCP 埠。它採用 2 元組(host, port)
,以便套接字在連線之前繫結到其作為源地址。 如果省略(或者如果 host 或 port 分別是''
和/或0
),將使用作業系統預設行為。在正常使用中,您應該只需要初始化/連線、
sendmail()
和SMTP.quit()
方法。 下面包含一個示例。SMTP
類支援with
語句。 像這樣使用時,當with
語句退出時,會自動發出 SMTPQUIT
命令。 例如:>>> from smtplib import SMTP >>> with SMTP("domain.org") as smtp: ... smtp.noop() ... (250, b'Ok') >>>
所有命令都會引發 審計事件
smtplib.SMTP.send
,其引數為self
和data
,其中data
是即將傳送到遠端主機的位元組。在 3.3 版本中更改: 添加了對
with
語句的支援。在 3.3 版本中更改: 添加了 source_address 引數。
3.5 版本新增: 現在支援 SMTPUTF8 擴充套件 (RFC 6531)。
在 3.9 版本中更改: 如果 timeout 引數設定為零,則會引發
ValueError
,以防止建立非阻塞套接字。
- class smtplib.SMTP_SSL(host='', port=0, local_hostname=None, *, [timeout, ]context=None, source_address=None)¶
SMTP_SSL
例項的行為與SMTP
例項完全相同。SMTP_SSL
應該用於從連線開始就需要 SSL 並且不適合使用starttls()
的情況。 如果未指定 host,則使用本地主機。 如果 port 為零,則使用標準的 SMTP over SSL 埠 (465)。可選引數 local_hostname、timeout 和 source_address 與在SMTP
類中的含義相同。 context 也是可選的,可以包含一個SSLContext
,並允許配置安全連線的各個方面。 請閱讀 安全注意事項 以瞭解最佳實踐。在 3.3 版本中更改: 添加了 context。
在 3.3 版本中更改: 添加了 source_address 引數。
在 3.4 版本中更改: 該類現在支援使用
ssl.SSLContext.check_hostname
和伺服器名稱指示的主機名檢查(請參閱ssl.HAS_SNI
)。在 3.9 版本中更改: 如果 timeout 引數設定為零,則會引發
ValueError
,以防止建立非阻塞套接字。在 3.12 版本中更改: 已刪除已棄用的 keyfile 和 certfile 引數。
- class smtplib.LMTP(host='', port=LMTP_PORT, local_hostname=None, source_address=None[, timeout])¶
LMTP 協議與 ESMTP 非常相似,它很大程度上基於標準的 SMTP 客戶端。LMTP 通常使用 Unix 套接字,因此我們的
connect()
方法必須同時支援 Unix 套接字和常規的 host:port 伺服器。可選引數 local_hostname 和 source_address 與SMTP
類中的含義相同。要指定 Unix 套接字,您必須使用 host 的絕對路徑,以 '/' 開頭。支援使用常規 SMTP 機制進行身份驗證。當使用 Unix 套接字時,LMTP 通常不支援或不需要任何身份驗證,但具體情況可能會有所不同。
在 3.9 版本中更改: 添加了可選的 timeout 引數。
還定義了一系列很好的異常。
- exception smtplib.SMTPException¶
OSError
的子類,是此模組提供的所有其他異常的基類。在 3.4 版本中更改: SMTPException 成為
OSError
的子類
- exception smtplib.SMTPResponseException¶
所有包含 SMTP 錯誤程式碼的異常的基類。當 SMTP 伺服器返回錯誤程式碼時,會在某些情況下生成這些異常。錯誤程式碼儲存在錯誤的
smtp_code
屬性中,並且smtp_error
屬性設定為錯誤訊息。
- exception smtplib.SMTPSenderRefused¶
發件人地址被拒絕。除了在所有
SMTPResponseException
異常上設定的屬性之外,此異常還將 'sender' 設定為 SMTP 伺服器拒絕的字串。
- exception smtplib.SMTPRecipientsRefused¶
所有收件人地址都被拒絕。每個收件人的錯誤都可以透過屬性
recipients
訪問,它是一個與SMTP.sendmail()
返回的完全相同的字典。
- exception smtplib.SMTPDataError¶
SMTP 伺服器拒絕接受訊息資料。
- exception smtplib.SMTPConnectError¶
在與伺服器建立連線期間發生錯誤。
- exception smtplib.SMTPHeloError¶
伺服器拒絕了我們的
HELO
訊息。
- exception smtplib.SMTPNotSupportedError¶
伺服器不支援嘗試的命令或選項。
在 3.5 版本中新增。
- exception smtplib.SMTPAuthenticationError¶
SMTP 身份驗證出錯。很可能是伺服器不接受提供的使用者名稱/密碼組合。
另請參閱
SMTP 物件¶
一個 SMTP
例項具有以下方法
- SMTP.set_debuglevel(level)¶
設定除錯輸出級別。level 的值為 1 或
True
會導致為連線以及傳送到伺服器和從伺服器接收的所有訊息輸出除錯訊息。level 的值為 2 會導致這些訊息帶有時間戳。在 3.5 版本中更改: 添加了除錯級別 2。
- SMTP.docmd(cmd, args='')¶
向伺服器傳送命令 cmd。可選引數 args 只是簡單地與命令連線,用空格分隔。
這將返回一個由數字響應程式碼和實際響應行組成的 2 元組(多行響應連線成一行。)
在正常操作中,不需要顯式呼叫此方法。它用於實現其他方法,並且可能對測試私有擴充套件有用。
如果在等待回覆時與伺服器的連線丟失,將引發
SMTPServerDisconnected
。
- SMTP.connect(host='localhost', port=0)¶
連線到給定埠上的主機。預設值是連線到標準 SMTP 埠 (25) 上的本地主機。如果主機名以冒號 (
':'
) 後跟一個數字結尾,則該字尾將被剝離,並且該數字將被解釋為要使用的埠號。如果在例項化期間指定了主機,則此方法會自動由建構函式呼叫。返回伺服器在其連線響應中傳送的響應程式碼和訊息的 2 元組。引發一個 審計事件
smtplib.connect
,其中包含引數self
、host
、port
。
- SMTP.helo(name='')¶
使用
HELO
向 SMTP 伺服器標識自己。主機名引數預設為本地主機的完全限定域名。伺服器返回的訊息儲存為物件的helo_resp
屬性。在正常操作中,不需要顯式呼叫此方法。必要時,
sendmail()
會隱式呼叫它。
- SMTP.ehlo(name='')¶
使用
EHLO
向 ESMTP 伺服器標識自己。主機名引數預設為本地主機的完全限定域名。檢查響應中的 ESMTP 選項,並將其儲存以供has_extn()
使用。還設定幾個資訊性屬性:伺服器返回的訊息儲存為ehlo_resp
屬性,does_esmtp
根據伺服器是否支援 ESMTP 設定為True
或False
,並且esmtp_features
將是一個字典,其中包含此伺服器支援的 SMTP 服務擴充套件的名稱及其引數(如果有)。除非你希望在傳送郵件前使用
has_extn()
,否則通常不需要顯式呼叫此方法。 當必要時,sendmail()
會隱式呼叫它。
- SMTP.ehlo_or_helo_if_needed()¶
如果當前會話之前沒有傳送過
EHLO
或HELO
命令,此方法將呼叫ehlo()
和/或helo()
。 它會首先嚐試 ESMTPEHLO
。SMTPHeloError
伺服器沒有正確響應
HELO
問候語。
- SMTP.verify(address)¶
使用 SMTP
VRFY
檢查此伺服器上地址的有效性。 如果使用者地址有效,則返回包含程式碼 250 和完整的 RFC 822 地址(包括人名)的元組。 否則,返回 400 或更大的 SMTP 錯誤程式碼和一個錯誤字串。注意
許多站點為了阻止垃圾郵件傳送者而停用 SMTP
VRFY
。
- SMTP.login(user, password, *, initial_response_ok=True)¶
在需要身份驗證的 SMTP 伺服器上登入。 引數是用於身份驗證的使用者名稱和密碼。 如果當前會話之前沒有傳送過
EHLO
或HELO
命令,此方法將首先嚐試 ESMTPEHLO
。 如果身份驗證成功,此方法將正常返回,否則可能會引發以下異常SMTPHeloError
伺服器沒有正確響應
HELO
問候語。SMTPAuthenticationError
伺服器不接受使用者名稱/密碼組合。
SMTPNotSupportedError
伺服器不支援
AUTH
命令。SMTPException
未找到合適的身份驗證方法。
如果伺服器宣告支援
smtplib
支援的每種身份驗證方法,則會依次嘗試這些方法。 有關支援的身份驗證方法的列表,請參見auth()
。 initial_response_ok 將傳遞給auth()
。可選關鍵字引數 initial_response_ok 指定對於支援它的身份驗證方法,是否可以按照 RFC 4954 中的規定,將“初始響應”與
AUTH
命令一起傳送,而不是需要質詢/響應。在 3.5 版本中更改: 可能會引發
SMTPNotSupportedError
異常,並添加了 initial_response_ok 引數。
- SMTP.auth(mechanism, authobject, *, initial_response_ok=True)¶
為指定的身份驗證 mechanism 發出
SMTP
AUTH
命令,並透過 authobject 處理質詢響應。mechanism 指定要用作
AUTH
命令引數的身份驗證機制;有效值是esmtp_features
的auth
元素中列出的值。authobject 必須是可呼叫的物件,它接受一個可選的單個引數。
data = authobject(challenge=None)
如果可選關鍵字引數 initial_response_ok 為 true,則將首先呼叫不帶引數的
authobject()
。 它可以返回 RFC 4954 中的“初始響應” ASCIIstr
,該字串將被編碼並與AUTH
命令一起傳送,如下所示。 如果authobject()
不支援初始響應(例如,因為它需要質詢),則當使用challenge=None
呼叫時,它應返回None
。 如果 initial_response_ok 為 false,則不會首先使用None
呼叫authobject()
。如果初始響應檢查返回
None
,或者如果 initial_response_ok 為 false,則將呼叫authobject()
來處理伺服器的質詢響應;傳遞給它的 challenge 引數將是一個bytes
。 它應該返回 ASCIIstr
data,該 data 將進行 base64 編碼併發送到伺服器。SMTP
類為CRAM-MD5
、PLAIN
和LOGIN
機制提供了authobjects
;它們分別命名為SMTP.auth_cram_md5
、SMTP.auth_plain
和SMTP.auth_login
。 它們都要求將SMTP
例項的user
和password
屬性設定為適當的值。使用者程式碼通常不需要直接呼叫
auth
,而是可以呼叫login()
方法,該方法將依次嘗試上述每種機制,按列出的順序排列。auth
的公開是為了方便實現smtplib
未直接(或尚未)支援的身份驗證方法。在 3.5 版本中新增。
- SMTP.starttls(*, context=None)¶
將 SMTP 連線置於 TLS(傳輸層安全性)模式。 之後的所有 SMTP 命令都將被加密。 然後,您應再次呼叫
ehlo()
。如果提供了 keyfile 和 certfile,則它們用於建立
ssl.SSLContext
。可選的 context 引數是一個
ssl.SSLContext
物件; 這是使用金鑰檔案和證書檔案的替代方法,如果指定了該物件,則 keyfile 和 certfile 都應為None
。如果當前會話之前沒有傳送過
EHLO
或HELO
命令,此方法將首先嚐試 ESMTPEHLO
。在 3.12 版本中更改: 已刪除已棄用的 keyfile 和 certfile 引數。
SMTPHeloError
伺服器沒有正確響應
HELO
問候語。SMTPNotSupportedError
伺服器不支援 STARTTLS 擴充套件。
RuntimeError
您的 Python 直譯器無法使用 SSL/TLS 支援。
在 3.3 版本中更改: 添加了 context。
3.4 版本更改: 該方法現在支援使用
SSLContext.check_hostname
進行主機名檢查和伺服器名稱指示(請參閱HAS_SNI
)。3.5 版本更改: 現在,對於缺少 STARTTLS 支援而引發的錯誤,將使用
SMTPNotSupportedError
子類,而不是基類SMTPException
。
- SMTP.sendmail(from_addr, to_addrs, msg, mail_options=(), rcpt_options=())¶
傳送郵件。必需的引數是 RFC 822 發件人地址字串,一個 RFC 822 收件人地址字串列表(一個單獨的字串將被視為包含 1 個地址的列表)和一個訊息字串。呼叫者可以傳遞一個 ESMTP 選項列表(例如
8bitmime
),以便在MAIL FROM
命令中作為 mail_options 使用。應該與所有RCPT
命令一起使用的 ESMTP 選項(例如DSN
命令)可以作為 rcpt_options 傳遞。(如果您需要對不同的收件人使用不同的 ESMTP 選項,則必須使用低階方法(例如mail()
、rcpt()
和data()
)來發送訊息。)注意
from_addr 和 to_addrs 引數用於構造傳輸代理使用的訊息信封。
sendmail
不會以任何方式修改訊息頭。msg 可以是包含 ASCII 範圍字元的字串或位元組字串。字串使用 ascii 編解碼器編碼為位元組,並且單獨的
\r
和\n
字元會轉換為\r\n
字元。位元組字串不會被修改。如果此會話中之前沒有
EHLO
或HELO
命令,則此方法會首先嚐試 ESMTPEHLO
。如果伺服器執行 ESMTP,則訊息大小和每個指定的選項都將傳遞給它(如果該選項在伺服器通告的功能集中)。如果EHLO
失敗,則將嘗試HELO
並取消 ESMTP 選項。如果郵件至少被一個收件人接受,此方法將正常返回。否則,它會引發異常。也就是說,如果此方法沒有引發異常,則應該有人收到您的郵件。如果此方法沒有引發異常,則它會返回一個字典,其中包含每個被拒絕的收件人的一個條目。每個條目包含一個由 SMTP 錯誤程式碼和伺服器傳送的隨附錯誤訊息組成的元組。
如果 mail_options 中包含
SMTPUTF8
,並且伺服器支援它,則 from_addr 和 to_addrs 可以包含非 ASCII 字元。此方法可能會引發以下異常
SMTPRecipientsRefused
所有收件人都被拒絕。沒有人收到郵件。異常物件的
recipients
屬性是一個字典,其中包含有關被拒絕的收件人的資訊(類似於至少一個收件人被接受時返回的資訊)。SMTPHeloError
伺服器沒有正確響應
HELO
問候語。SMTPSenderRefused
伺服器不接受 from_addr。
SMTPDataError
伺服器回覆了一個意外的錯誤程式碼(而不是拒絕收件人)。
SMTPNotSupportedError
mail_options 中給出了
SMTPUTF8
,但伺服器不支援。
除非另有說明,否則即使在引發異常後,連線也會保持開啟狀態。
3.2 版本更改: msg 可以是位元組字串。
3.5 版本更改: 添加了
SMTPUTF8
支援,如果指定了SMTPUTF8
但伺服器不支援,則可能會引發SMTPNotSupportedError
。
- SMTP.send_message(msg, from_addr=None, to_addrs=None, mail_options=(), rcpt_options=())¶
這是一種方便的方法,用於呼叫
sendmail()
,其中訊息由email.message.Message
物件表示。引數的含義與sendmail()
相同,只是 msg 是一個Message
物件。如果 from_addr 為
None
或 to_addrs 為None
,則send_message
會使用從 msg 的頭中提取的地址來填充這些引數,如 RFC 5322 中所指定的:如果存在 Sender 欄位,則 from_addr 設定為該欄位,否則設定為 From 欄位。to_addrs 組合了 msg 中 To、Cc 和 Bcc 欄位的值(如果有)。如果訊息中恰好出現一組 Resent-* 標頭,則會忽略常規標頭,並改用 Resent-* 標頭。如果訊息包含多組 Resent-* 標頭,則會引發ValueError
,因為無法明確檢測到最新的一組 Resent- 標頭。send_message
使用BytesGenerator
將 msg 序列化,並將\r\n
作為 linesep,並呼叫sendmail()
來傳輸生成的訊息。無論 from_addr 和 to_addrs 的值如何,send_message
都不會傳輸可能出現在 msg 中的任何 Bcc 或 Resent-Bcc 標頭。如果 from_addr 和 to_addrs 中的任何地址包含非 ASCII 字元,並且伺服器不通告SMTPUTF8
支援,則會引發SMTPNotSupported
錯誤。否則,將使用其policy
的克隆(其中utf8
屬性設定為True
)來序列化Message
,並將SMTPUTF8
和BODY=8BITMIME
新增到 mail_options。3.2 版本中新增。
3.5 版本新增: 對國際化地址的支援 (
SMTPUTF8
)。
- SMTP.quit()¶
終止 SMTP 會話並關閉連線。返回 SMTP
QUIT
命令的結果。
還支援與標準 SMTP/ESMTP 命令 HELP
、RSET
、NOOP
、MAIL
、RCPT
和 DATA
相對應的低階方法。通常不需要直接呼叫這些方法,因此此處不作介紹。有關詳細資訊,請查閱模組程式碼。
SMTP 示例¶
此示例提示使用者輸入訊息信封中需要的地址(“To”和“From”地址)以及要傳遞的訊息。請注意,要包含在訊息中的標頭必須包含在輸入的訊息中;此示例不對 RFC 822 標頭進行任何處理。特別是,“To”和“From”地址必須明確包含在訊息頭中
import smtplib
def prompt(title):
return input(title).strip()
from_addr = prompt("From: ")
to_addrs = prompt("To: ").split()
print("Enter message, end with ^D (Unix) or ^Z (Windows):")
# Add the From: and To: headers at the start!
lines = [f"From: {from_addr}", f"To: {', '.join(to_addrs)}", ""]
while True:
try:
line = input()
except EOFError:
break
else:
lines.append(line)
msg = "\r\n".join(lines)
print("Message length is", len(msg))
server = smtplib.SMTP("localhost")
server.set_debuglevel(1)
server.sendmail(from_addr, to_addrs, msg)
server.quit()
注意
通常,您需要使用 email
包的功能來構造電子郵件訊息,然後可以透過 send_message()
傳送該訊息;請參閱 email: 示例。