smtplib
--- SMTP 協(xié)議客戶端?
源代碼: Lib/smtplib.py
smtplib
模塊定義了一個 SMTP 客戶端會話對象,該對象可將郵件發(fā)送到互聯(lián)網(wǎng)上任何帶有 SMTP 或 ESMTP 監(jiān)聽程序的計算機。 關(guān)于 SMTP 和 ESMTP 操作的更多細(xì)節(jié)請參閱 RFC 821 (簡單郵件傳輸協(xié)議) 和 RFC 1869 (SMTP 服務(wù)擴展)。
- class smtplib.SMTP(host='', port=0, local_hostname=None, [timeout, ]source_address=None)?
SMTP
實例是對 SMTP 連接的封裝。 它提供了支持各種 SMTP 和 ESMTP 操作的方法。 如果給出了可選的 host 和 port 形參,則會在初始化期間調(diào)用 SMTPconnect()
方法并附帶這些形參。 如果指定了 local_hostname,它將在 HELO/EHLO 命令中被用作本地主機的 FQDN。 在其他情況下,會使用socket.getfqdn()
來找到本地主機名。 如果connect()
調(diào)用返回了表示成功的代碼以外的信息,則會引發(fā)SMTPConnectError
。 可選的 timeout 形參指定了阻塞操作如連接嘗試的超時秒數(shù)(如果未指定,則將使用全局默認(rèn)超時設(shè)置)。 如果達(dá)到超時限制,則會引發(fā)TimeoutError
。 可選的 source_address 形參允許在在有多張網(wǎng)卡的計算機中綁定到某些特定的源地址,和/或綁定到某些特定的源 TCP 端口。 它接受一個 2 元組 (host, port) 作為在連接之前所綁定作為其源地址的套接字。 如果省略(或者如果 host 或 port 為''
和/或分別為 0)則將使用 OS 的默認(rèn)行為。正常使用時,只需要初始化或 connect 方法,
sendmail()
方法,再加上SMTP.quit()
方法即可。下文包括了一個示例。SMTP
類支持with
語句。當(dāng)這樣使用時,with
語句一退出就會自動發(fā)出 SMTPQUIT
命令。例如:>>> from smtplib import SMTP >>> with SMTP("domain.org") as smtp: ... smtp.noop() ... (250, b'Ok') >>>
引發(fā)一個 審計事件
smtplib.send
,附帶參數(shù)self
,data
。在 3.3 版更改: 添加了對
with
語句的支持。在 3.3 版更改: 添加了 source_address 參數(shù)。
3.5 新版功能: 現(xiàn)在已支持 SMTPUTF8 擴展 (RFC 6531)。
在 3.9 版更改: 如果 timeout 形參被設(shè)為零,則它將引發(fā)
ValueError
來阻止創(chuàng)建非阻塞的套接字
- class smtplib.SMTP_SSL(host='', port=0, local_hostname=None, keyfile=None, certfile=None, [timeout, ]context=None, source_address=None)?
SMTP_SSL
實例與SMTP
實例的行為完全相同。在開始連接就需要 SSL,且starttls()
不適合的情況下,應(yīng)該使用SMTP_SSL
。如果未指定 host,則使用 localhost。如果 port 為 0,則使用標(biāo)準(zhǔn) SMTP-over-SSL 端口(465)。可選參數(shù) local_hostname、timeout 和 source_address 的含義與SMTP
類中的相同??蛇x參數(shù) context 是一個SSLContext
對象,可以從多個方面配置安全連接。請閱讀 安全考量 以獲取最佳實踐。keyfile 和 certfile 是 context 的傳統(tǒng)替代物,它們可以指向 PEM 格式的私鑰和證書鏈文件用于 SSL 連接。
在 3.3 版更改: 增加了 context。
在 3.3 版更改: 添加了 source_address 參數(shù)。
在 3.4 版更改: 本類現(xiàn)在支持使用
ssl.SSLContext.check_hostname
和 服務(wù)器名稱指示 (參閱ssl.HAS_SNI
)進(jìn)行主機名檢查。3.6 版后已移除: keyfile 和 certfile 已棄用并轉(zhuǎn)而推薦 context。 請改用
ssl.SSLContext.load_cert_chain()
或讓ssl.create_default_context()
為你選擇系統(tǒng)所信任的 CA 證書。在 3.9 版更改: 如果 timeout 形參被設(shè)為零,則它將引發(fā)
ValueError
來阻止創(chuàng)建非阻塞的套接字
- class smtplib.LMTP(host='', port=LMTP_PORT, local_hostname=None, source_address=None[, timeout])?
LMTP 協(xié)議與 ESMTP 非常相似,它很大程度上基于標(biāo)準(zhǔn)的 SMTP 客戶端。將 Unix 套接字用于 LMTP 是很常見的,因此
connect()
方法支持 Unix 套接字,也支持常規(guī)的 host:port 服務(wù)器??蛇x參數(shù) local_hostname 和 source_address 的含義與SMTP
類中的相同。要指定 Unix 套接字,host 必須使用絕對路徑,以 '/' 開頭。支持使用常規(guī)的 SMTP 機制來進(jìn)行認(rèn)證。 當(dāng)使用 Unix 套接字時,LMTP 通常不支持或要求任何認(rèn)證,但你的情況可能會有所不同。
在 3.9 版更改: 添加了可選的 timeout 形參。
同樣地定義了一組精心選擇的異常:
- exception smtplib.SMTPException?
OSError
的子類,它是本模塊提供的所有其他異常的基類。在 3.4 版更改: SMTPException 已成為
OSError
的子類
- exception smtplib.SMTPServerDisconnected?
當(dāng)服務(wù)器意外斷開連接,或在
SMTP
實例連接到服務(wù)器之前嘗試使用它時將引發(fā)此異常。
- exception smtplib.SMTPResponseException?
包括 SMTP 錯誤代碼的所有異常的基類。 這些異常會在 SMTP 服務(wù)器返回錯誤代碼時在實例中生成。 錯誤代碼存放在錯誤的
smtp_code
屬性中,并且smtp_error
屬性會被設(shè)為錯誤消息。
- exception smtplib.SMTPSenderRefused?
發(fā)送方地址被拒絕。 除了在所有
SMTPResponseException
異常上設(shè)置的屬性,還會將 'sender' 設(shè)為代表拒絕方 SMTP 服務(wù)器的字符串。
- exception smtplib.SMTPRecipientsRefused?
所有接收方地址被拒絕。 每個接收方的錯誤可通過屬性
recipients
來訪問,該屬性是一個字典,其元素順序與SMTP.sendmail()
所返回的一致。
- exception smtplib.SMTPDataError?
SMTP 服務(wù)器拒絕接收消息數(shù)據(jù)。
- exception smtplib.SMTPConnectError?
在建立與服務(wù)器的連接期間發(fā)生了錯誤。
- exception smtplib.SMTPHeloError?
服務(wù)器拒絕了我們的
HELO
消息。
- exception smtplib.SMTPNotSupportedError?
嘗試的命令或選項不被服務(wù)器所支持。
3.5 新版功能.
- exception smtplib.SMTPAuthenticationError?
SMTP 認(rèn)證出現(xiàn)問題。 最大的可能是服務(wù)器不接受所提供的用戶名/密碼組合。
參見
SMTP 對象?
一個 SMTP
實例擁有以下方法:
- SMTP.set_debuglevel(level)?
設(shè)置調(diào)試輸出級別。 如果 level 的值為 1 或
True
,就會產(chǎn)生連接的調(diào)試信息,以及所有發(fā)送和接收服務(wù)器的信息。 如果 level 的值為 2 ,則這些信息會被加上時間戳。在 3.5 版更改: 添調(diào)試級別 2 。
- SMTP.docmd(cmd, args='')?
向服務(wù)器發(fā)送一條命令 cmd 。 可選的參數(shù) args 被簡單地串聯(lián)到命令中,用一個空格隔開。
這將返回一個由數(shù)字響應(yīng)代碼和實際響應(yīng)行組成的2元組(多行響應(yīng)被連接成一個長行)。
在正常操作中,應(yīng)該沒有必要明確地調(diào)用這個方法。它被用來實現(xiàn)其他方法,對于測試私有擴展可能很有用。
如果在等待回復(fù)的過程中,與服務(wù)器的連接丟失,
SMTPServerDisconnected
將被觸發(fā)。
- SMTP.connect(host='localhost', port=0)?
連接到某個主機的某個端口。默認(rèn)是連接到 localhost 的標(biāo)準(zhǔn) SMTP 端口(25)上。如果主機名以冒號 (
':'
) 結(jié)尾,后跟數(shù)字,則該后綴將被刪除,且數(shù)字將視作要使用的端口號。如果在實例化時指定了 host,則構(gòu)造函數(shù)會自動調(diào)用本方法。返回包含響應(yīng)碼和響應(yīng)消息的 2 元組,它們由服務(wù)器在其連接響應(yīng)中發(fā)送。觸發(fā)一個 auditing event
smtplib.connect
,其參數(shù)為self
,host
,port
。
- SMTP.helo(name='')?
使用
HELO
向 SMTP 服務(wù)器表明自己的身份。 hostname 參數(shù)默認(rèn)為本地主機的完全合格域名。服務(wù)器返回的消息被存儲為對象的helo_resp
屬性。在正常操作中,應(yīng)該沒有必要明確調(diào)用這個方法。它將在必要時被
sendmail()
隱式調(diào)用。
- SMTP.ehlo(name='')?
使用
EHLO
向 ESMTP 服務(wù)器表明自己的身份。 hostname 參數(shù)默認(rèn)為本地主機的完全合格域名。 檢查 ESMTP 選項的響應(yīng),并存儲它們供has_extn()
使用。同時設(shè)置幾個信息屬性:服務(wù)器返回的消息被存儲為ehlo_resp
屬性,does_esmtp
根據(jù)服務(wù)器是否支持 ESMTP 被設(shè)置為True
或False
,而esmtp_features
將是一個字典,包含這個服務(wù)器支持的 SMTP 服務(wù)擴展的名稱,以及它們的參數(shù)(如果有)。除非你想在發(fā)送郵件前使用
has_extn()
,否則應(yīng)該沒有必要明確調(diào)用這個方法。 它將在必要時被sendmail()
隱式調(diào)用。
- SMTP.ehlo_or_helo_if_needed()?
如果這個會話中沒有先前的
EHLO
或HELO
命令,該方法會調(diào)用ehlo()
和/或helo()
。它首先嘗試 ESMTPEHLO
。SMTPHeloError
服務(wù)器沒有正確回復(fù)
HELO
問候。
- SMTP.verify(address)?
使用 SMTP
VRFY
檢查此服務(wù)器上的某個地址是否有效。 如果用戶地址有效則返回一個由代碼 250 和完整 RFC 822 地址(包括人名)組成的元組。 否則返回 400 或更大的 SMTP 錯誤代碼以及一個錯誤字符串。備注
許多網(wǎng)站都禁用 SMTP
VRFY
以阻止垃圾郵件。
- SMTP.login(user, password, *, initial_response_ok=True)?
登錄到一個需要認(rèn)證的 SMTP 服務(wù)器。 參數(shù)是用于認(rèn)證的用戶名和密碼。 如果會話在之前沒有執(zhí)行過
EHLO
或HELO
命令,此方法會先嘗試 ESMTPEHLO
。 如果認(rèn)證成功則此方法將正常返回,否則可能引發(fā)以下異常:SMTPHeloError
服務(wù)器沒有正確回復(fù)
HELO
問候。SMTPAuthenticationError
服務(wù)器不接受所提供的用戶名/密碼組合。
SMTPNotSupportedError
服務(wù)器不支持
AUTH
命令。SMTPException
未找到適當(dāng)?shù)恼J(rèn)證方法。
smtplib
所支持的每種認(rèn)證方法只要被服務(wù)器聲明支持就會被依次嘗試。 請參閱auth()
獲取受支持的認(rèn)證方法列表。 initial_response_ok 會被傳遞給auth()
。可選的關(guān)鍵字參數(shù) initial_response_ok 對于支持它的認(rèn)證方法,是否可以與
AUTH
命令一起發(fā)送 RFC 4954 中所規(guī)定的“初始響應(yīng)”,而不是要求回復(fù)/響應(yīng)。在 3.5 版更改: 可能會引發(fā)
SMTPNotSupportedError
,并添加 initial_response_ok 形參。
- SMTP.auth(mechanism, authobject, *, initial_response_ok=True)?
為指定的認(rèn)證機制 mechanism 發(fā)送
SMTP
AUTH
命令,并通過 authobject 處理回復(fù)響應(yīng)。mechanism 指定要使用何種認(rèn)證機制作為
AUTH
命令的參數(shù);可用的值是在esmtp_features
的auth
元素中列出的內(nèi)容。authobject 必須是接受一個可選的單獨參數(shù)的可調(diào)用對象:
data = authobject(challenge=None)
如果可選的關(guān)鍵字參數(shù) initial_response_ok 為真值,則將先不帶參數(shù)地調(diào)用
authobject()
。 它可以返回 RFC 4954 "初始響應(yīng)" ASCIIstr
,其內(nèi)容將被編碼并使用下述的AUTH
命令來發(fā)送。 如果authobject()
不支持初始響應(yīng)(例如由于要求一個回復(fù)),它應(yīng)當(dāng)將None
作為附帶challenge=None
調(diào)用的返回值。 如果 initial_response_ok 為假值,則authobject()
將不會附帶None
被首先調(diào)用。如果初始響應(yīng)檢測返回了
None
,或者如果 initial_response_ok 為假值,則將調(diào)用authobject()
來處理服務(wù)器的回復(fù)響應(yīng);它所傳遞的 challenge 參數(shù)將為一個bytes
。 它應(yīng)當(dāng)返回用 base64 進(jìn)行編碼的 ASCIIstr
data 并發(fā)送給服務(wù)器。SMTP
類提供的authobjects
針對CRAM-MD5
,PLAIN
和LOGIN
等機制;它們的名稱分別是SMTP.auth_cram_md5
,SMTP.auth_plain
和SMTP.auth_login
。 它們都要求將user
和password
這兩個SMTP
實例屬性設(shè)為適當(dāng)?shù)闹怠?/p>用戶代碼通常不需要直接調(diào)用
auth
,而是調(diào)用login()
方法,它將按上述順序依次嘗試上述每一種機制。auth
被公開以便輔助實現(xiàn)smtplib
沒有(或尚未)直接支持的認(rèn)證方法。3.5 新版功能.
- SMTP.starttls(keyfile=None, certfile=None, context=None)?
將 SMTP 連接設(shè)為 TLS (傳輸層安全) 模式。 后續(xù)的所有 SMTP 命令都將被加密。 你應(yīng)當(dāng)隨即再次調(diào)用
ehlo()
。如果提供了 keyfile 和 certfile,它們會被用來創(chuàng)建
ssl.SSLContext
。可選的 context 形參是一個
ssl.SSLContext
對象;它是使用密鑰文件和證書的替代方式,如果指定了該形參則 keyfile 和 certfile 都應(yīng)為None
。如果這個會話中沒有先前的
EHLO
orHELO
命令,該方法會首先嘗試 ESMTPEHLO
。3.6 版后已移除: keyfile 和 certfile 已棄用并轉(zhuǎn)而推薦 context。 請改用
ssl.SSLContext.load_cert_chain()
或讓ssl.create_default_context()
為你選擇系統(tǒng)所信任的 CA 證書。SMTPHeloError
服務(wù)器沒有正確回復(fù)
HELO
問候。SMTPNotSupportedError
服務(wù)器不支持 STARTTLS 擴展。
RuntimeError
SSL/TLS 支持在你的 Python 解釋器上不可用。
在 3.3 版更改: 增加了 context。
在 3.4 版更改: 此方法現(xiàn)在支持使用
SSLContext.check_hostname
和 服務(wù)器名稱指示符 (參見HAS_SNI
) 進(jìn)行主機名檢查。在 3.5 版更改: 因缺少 STARTTLS 支持而引發(fā)的錯誤現(xiàn)在是
SMTPNotSupportedError
子類而不是SMTPException
基類。
- SMTP.sendmail(from_addr, to_addrs, msg, mail_options=(), rcpt_options=())?
發(fā)送郵件。必要參數(shù)是一個 RFC 822 發(fā)件地址字符串,一個 RFC 822 收件地址字符串列表(裸字符串將被視為含有 1 個地址的列表),以及一個消息字符串。調(diào)用者可以將 ESMTP 選項列表(如
8bitmime
)作為 mail_options 傳入,用于MAIL FROM
命令。需要與所有RCPT
命令一起使用的 ESMTP 選項(如DSN
命令)可以作為 rcpt_options 傳入。(如果需要對不同的收件人使用不同的 ESMTP 選項,則必須使用底層的方法來發(fā)送消息,如mail()
,rcpt()
和data()
。)備注
from_addr 和 to_addrs 形參被用來構(gòu)造傳輸代理所使用的消息封包。
sendmail
不會以任何方式修改消息標(biāo)頭。msg 可以是一個包含 ASCII 范圍內(nèi)字符的字符串,或是一個字節(jié)串。 字符串會使用 ascii 編解碼器編碼為字節(jié)串,并且單獨的
\r
和\n
字符會被轉(zhuǎn)換為\r\n
字符序列。 字節(jié)串則不會被修改。如果在此之前本會話沒有執(zhí)行過
EHLO
或HELO
命令,此方法會先嘗試 ESMTPEHLO
。 如果服務(wù)器執(zhí)行了 ESMTP,消息大小和每個指定的選項將被傳遞給它(如果指定的選項屬于服務(wù)器聲明的特性集)。 如果EHLO
失敗,則將嘗試HELO
并屏蔽 ESMTP 選項。如果郵件被至少一個接收方接受則此方法將正常返回。 在其他情況下它將引發(fā)異常。 也就是說,如果此方法沒有引發(fā)異常,則應(yīng)當(dāng)會有人收到你的郵件。 如果此方法沒有引發(fā)異常,它將返回一個字典,其中的條目對應(yīng)每個拒絕的接收方。 每個條目均包含由服務(wù)器發(fā)送的 SMTP 錯誤代碼和相應(yīng)錯誤消息所組成的元組。
如果
SMTPUTF8
包括在 mail_options 中,并且被服務(wù)器所支持,則 from_addr 和 to_addrs 可能包含非 ASCII 字符。此方法可能引發(fā)以下異常:
SMTPRecipientsRefused
所有收件人都被拒絕。 無人收到郵件。 該異常的
recipients
屬性是一個字典,其中有被拒絕收件人的信息(類似于至少有一個收件人接受郵件時所返回的信息)。SMTPHeloError
服務(wù)器沒有正確回復(fù)
HELO
問候。SMTPSenderRefused
服務(wù)器不接受 from_addr。
SMTPDataError
服務(wù)器回復(fù)了一個意外的錯誤代碼(而不是拒絕收件人)。
SMTPNotSupportedError
在 mail_options 中給出了
SMTPUTF8
但是不被服務(wù)器所支持。
除非另有說明,即使在引發(fā)異常之后連接仍將被打開。
在 3.2 版更改: msg 可以為字節(jié)串。
在 3.5 版更改: 增加了
SMTPUTF8
支持,并且如果指定了SMTPUTF8
但是不被服務(wù)器所支持則可能會引發(fā)SMTPNotSupportedError
。
- SMTP.send_message(msg, from_addr=None, to_addrs=None, mail_options=(), rcpt_options=())?
本方法是一種快捷方法,用于帶著消息調(diào)用
sendmail()
,消息由email.message.Message
對象表示。參數(shù)的含義與sendmail()
中的相同,除了 msg,它是一個Message
對象。如果 from_addr 為
None
或 to_addrs 為None
,那么``send_message``將根據(jù) RFC 5322,從 msg 頭部提取地址填充下列參數(shù):如果頭部存在 Sender 字段,則用它填充 from_addr,不存在則用 From 字段填充 from_addr。to_addrs 組合了 msg 中的 To, Cc 和 Bcc 字段的值(字段存在的情況下)。如果一組 Resent-* 頭部恰好出現(xiàn)在 message 中,那么就忽略常規(guī)的頭部,改用 Resent-* 頭部。如果 message 包含多組 Resent-* 頭部,則引發(fā)ValueError
,因為無法明確檢測出哪一組 Resent- 頭部是最新的。send_message
使用BytesGenerator
來序列化 msg,且將\r\n
作為 linesep,并調(diào)用sendmail()
來傳輸序列化后的結(jié)果。無論 from_addr 和 to_addrs 的值為何,send_message
都不會傳輸 msg 中可能出現(xiàn)的 Bcc 或 Resent-Bcc 頭部。如果 from_addr 和 to_addrs 中的某個地址包含非 ASCII 字符,且服務(wù)器沒有聲明支持SMTPUTF8
,則引發(fā)SMTPNotSupported
錯誤。如果服務(wù)器支持,則Message
將按新克隆的policy
進(jìn)行序列化,其中的utf8
屬性被設(shè)置為True
,且SMTPUTF8
和BODY=8BITMIME
被添加到 mail_options 中。3.2 新版功能.
3.5 新版功能: 支持國際化地址 (
SMTPUTF8
)。
- SMTP.quit()?
終結(jié) SMTP 會話并關(guān)閉連接。 返回 SMTP
QUIT
命令的結(jié)果。
與標(biāo)準(zhǔn) SMTP/ESMTP 命令 HELP
, RSET
, NOOP
, MAIL
, RCPT
和 DATA
對應(yīng)的低層級方法也是受支持的。 通常不需要直接調(diào)用這些方法,因此它們沒有被寫入本文檔。 相關(guān)細(xì)節(jié)請參看模塊代碼。
SMTP 示例?
這個例子提示用戶輸入消息封包所需的地址 ('To' 和 'From' 地址),以及所要封包的消息。 請注意包括在消息中的標(biāo)頭必須包括在輸入的消息中;這個例子不對 RFC 822 標(biāo)頭進(jìn)行任何處理。 特別地,'To' 和 'From' 地址必須顯式地包括在消息標(biāo)頭中。
import smtplib
def prompt(prompt):
return input(prompt).strip()
fromaddr = prompt("From: ")
toaddrs = prompt("To: ").split()
print("Enter message, end with ^D (Unix) or ^Z (Windows):")
# Add the From: and To: headers at the start!
msg = ("From: %s\r\nTo: %s\r\n\r\n"
% (fromaddr, ", ".join(toaddrs)))
while True:
try:
line = input()
except EOFError:
break
if not line:
break
msg = msg + line
print("Message length is", len(msg))
server = smtplib.SMTP('localhost')
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
備注
通常,你將需要使用 email
包的特性來構(gòu)造電子郵件消息,然后你可以通過 send_message()
來發(fā)送它,參見 email: 示例。