C語言中文網 目錄

Python smtplib模塊詳解:發送郵件

< 上一頁UDP多點廣播 Python poplib下一頁 >

使用 Python 的 smtplib 模塊來發送郵件非常簡單,大部分底層的處理都由 smtplib 進行了封裝,開發者只需要按照如下 3 步來發送郵件即可:
  1. 連接 SMTP 服務器,并使用用戶名、密碼登錄服務器。
  2. 創建 EmailMessage 對象,該對象代表郵件本身。
  3. 調用代表與 SMTP 服務器連接的對象的 sendmail() 方法發送郵件。

下面程序按照上面步驟示范了如何發送郵件:
import smtplib
from email.message import EmailMessage

# 定義SMTP服務器地址:
smtp_server = 'smtp.qq.com'
# 定義發件人地址
from_addr = 'kongyeeku@qq.com'
# 定義登錄郵箱的密碼
password = '123456'
# 定義收件人地址:
to_addr = 'kongyeeku@163.com'

# 創建SMTP連接
#conn = smtplib.SMTP(smtp_server, 25)
conn = smtplib.SMTP_SSL(smtp_server,465)
conn.set_debuglevel(1)
conn.login(from_addr, password)            #①
# 創建郵件對象
msg = EmailMessage()
# 設置郵件內容
msg.set_content('您好,這是一封來自Python的郵件', 'plain', 'utf-8')
# 發送郵件
conn.sendmail(from_addr, [to_addr], msg.as_string())
# 退出連接
conn.quit()
上面程序中,第 15 行、19 行和 23 行代碼基本代表了使用 Python 的 smtp 模塊發送郵件的 3 大核心步驟,其中 ① 號代碼使用了發件人的地址和密碼來登錄郵箱。

關于該程序有以下幾點需要說明:
  • 程序中提供的郵箱密碼是錯誤的,不用嘗試。讀者必須改為使用自己的郵箱地址和密碼。
  • 早期SMTP 服務器都采用普通的網絡連接,因此默認端口是 25。但現在絕大部分 SMTP 都是基于 SSL(Secure Socket Layer)的,這樣保證網絡上傳輸的信息都是加密過的,從而使得信息更加安全。這種基于 SSL 的 SMTP 服務器的默認端口是 465。上面程序中連接的是 QQ 郵箱的基于 SSL 的 SMTP 服務器,QQ 郵箱服務器不支持普通的 SMTP。
  • 國內有些公司的免費郵箱(比如 QQ 郵箱)默認是關閉了 SMTP 的,因此需要讀者登錄郵箱進行設置。
  • 由于該程序發送的郵件太簡單,郵件沒有主題,而且程序在測試過程中可能會發送很多郵件,因此有些郵箱服務商會將該程序發送的郵件當成垃圾郵件。

早期 Python 2.x 提供了 email.mime、email.header、email.charset、email.encoders、email.iterators 等庫來處理郵件,這些庫設計得過于煩瑣,用起來極為不便,因此讀者應該盡快改為使用最新的 Python 庫。本教程不會介紹這些過時的庫。具體可參考 https://docs.python.org/3/library/email.html 頁面的說明。

由于程序打開了 smtplib 調試模式(將 debuglevel 設置為 1),因此在運行該程序時,可以看到 SMTP 發送郵件的詳細過程。當程序運行結束后,將可以在收件人郵箱中看到一封新郵件(可能在垃圾郵件內),如圖 1 所示。

在收件人郵箱內收到了 smtplib 模塊發送的郵件
圖 1 在收件人郵箱內收到了 smtplib 模塊發送的郵件

上面這封郵件是最簡單的,沒有為該郵件設置主題、發件人名字和收件人名字,郵件內容也只是簡單的文本。如果要為郵件設置主題、發件人名字和收件人名字,那么只需設置 EmailMessage 對象的相應屬性即可。如果程序要將郵件內容改為 HTML 內容,那么只需將調用 EmailMessage的set_content() 方法的第二個參數設置為 html 即可。

例如,如下程序只是對 EmailMessage 進行了修改:
import smtplib
from email.message import EmailMessage

# 定義SMTP服務器地址:
smtp_server = 'smtp.qq.com'
# 定義發件人地址
from_addr = 'kongyeeku@qq.com'
# 定義登錄郵箱的密碼
password = '123456'
# 定義收件人地址:
to_addr = 'kongyeeku@163.com'

# 創建SMTP連接
#conn = smtplib.SMTP(smtp_server, 25)
conn = smtplib.SMTP_SSL(smtp_server,465)
conn.set_debuglevel(1)
conn.login(from_addr, password)            #①
# 創建郵件對象
msg = EmailMessage()
# 設置郵件內容,指定郵件內容為HTML
msg.set_content('<h2>郵件內容</h2>' +
    '<p>您好,這是一封來自Python的郵件<p>' +
    '來自<a href="http://www.frifeb11.com">C語言中文網</a>', 'html', 'utf-8')
msg['subject'] = '一封HTML郵件'
msg['from'] = '李剛 <%s>' % from_addr
msg['to'] = '新用戶 <%s>' % to_addr
# 發送郵件
conn.sendmail(from_addr, [to_addr], msg.as_string())
# 退出連接
conn.quit()
該程序與上一個程序基本相似,只是在調用 set_content() 方法時將第二個參數改為了“html”。

此外,程序增加了上面 3 行代碼(第 24~26 行),分別用于設置郵件主題、發件人名字和收件人名字。運行上面程序,在目標郵箱內可以看到如圖 2 所示的郵件。

設置了郵件主題、發件人名字和收件人名字的 HTML 郵件
圖 2 設置了郵件主題、發件人名字和收件人名字的 HTML 郵件

打開該郵件,將可以看到如圖 3 所示的郵件內容。

HTML 郵件內容
圖 3 HTML 郵件內容

如果希望實現圖文并茂的郵件,也就是在郵件中插入圖片,則首先要給郵件添加附件(不要直接在郵件中嵌入外鏈的圖片,很多郵箱出于安全考慮,都會禁用郵件中外鏈的資源)。因此,如果直接在 HTML 右鍵中外鏈其他圖片,那么該圖片很有可能顯示不出來。

為了給郵件添加附件,只需調用 EmailMessage的add_attachment() 方法即可。該方法支持很多參數,最常見的參數如下:
  • maintype:指定附件的主類型。比如指定 image 代表附件是圖片。
  • subtype:指定附件的子類型。比如指定為 png,代表附件是 PNG 圖片。一般來說,子類型受主類型的限制。
  • filename:指定附件的文件名。
  • cid=img:指定附件的資源 ID,郵件正文可通過資源 ID 來引用該資源。

例如,如下程序為郵件添加了 3 個附件:
import smtplib, email.utils
from email.message import EmailMessage

# 定義SMTP服務器地址:
smtp_server = 'smtp.qq.com'
# 定義發件人地址
from_addr = 'kongyeeku@qq.com'
# 定義登錄郵箱的密碼
password = '123456'
# 定義收件人地址:
to_addr = 'kongyeeku@163.com'

# 創建SMTP連接
#conn = smtplib.SMTP(smtp_server, 25)
conn = smtplib.SMTP_SSL(smtp_server,465)
conn.set_debuglevel(1)
conn.login(from_addr, password)            #①
# 創建郵件對象
msg = EmailMessage()
# 隨機生成兩個圖片id
first_id, second_id = email.utils.make_msgid(), email.utils.make_msgid()
# 設置郵件內容,指定郵件內容為HTML
msg.set_content('<h2>郵件內容</h2>' +
    '<p>您好,這是一封來自Python的郵件' +
    '<img src="cid:' + second_id[1:-1] +'"><p>' +
    '來自<a href="http://www.frifeb11.com">C語言中文網</a>')
msg['subject'] = '一封HTML郵件'
msg['from'] = '李剛 <%s>' % from_addr
msg['to'] = '新用戶 <%s>' % to_addr
with open('E:/logo.jpg', 'rb') as f:
    # 添加第一個附件
    msg.add_attachment(f.read(), maintype='image',
        subtype='jpeg', filename='test.png', cid=first_id)
with open('E:/fklogo.gif', 'rb') as f:
    # 添加第二個附件
    msg.add_attachment(f.read(), maintype='image',
        subtype='gif', filename='test.gif', cid=second_id)
with open('E:/fkit.pdf', 'rb') as f:
    # 添加第三個附件,郵件正文不需引用該附件,因此不指定cid
    msg.add_attachment(f.read(), maintype='application',
        subtype='pdf', filename='test.pdf',)
# 發送郵件
conn.sendmail(from_addr, [to_addr], msg.as_string())
# 退出連接
conn.quit()
該程序與上一個程序的最大區別在于增加了一段代碼(31 行代碼起),它們為郵件添加了三個附件。

由于郵件正文不需要引用第三個附件,因此程序添加第三個附件時沒有指定 cid 屬性。

在添加附件時指定 cid 屬性之后,程序就可以在郵件正文中通過該 cid 來引用附件,如上面程序中郵件正文代碼所示。運行上面程序,可以在目標郵箱內看到一封新郵件。打開該郵件,可看到郵件內容。

通過上面三個示例,可以發現使用 smtplib 模塊發送郵件很簡單,基本只需要連接服務器、創建郵件和發送郵件三個步驟。如果要構建復雜的郵件內容,則主要通過 EmailMessage 對象來進行設置。EmailMessage 也是 Python 3.x 對郵件處理的巨大簡化,它把對郵件內容的各種處理都封裝在 EmailMessage 類中,因此使得編程變得輕松、簡單。
< 上一頁UDP多點廣播 Python poplib下一頁 >

精美而實用的網站,提供C語言、C++、STL、Linux、Shell、Java、Go語言等教程,以及socket、GCC、vi、Swing、設計模式、JSP等專題。

Copyright ?2011-2018 biancheng.net, 陜ICP備15000209號

底部Logo