0. 前言
發(fā)送電子郵件是個很常見的開發(fā)需求。比如你寫了個監(jiān)控天氣的腳本,發(fā)現(xiàn)第二天要下雨,或者網(wǎng)站上關注的某個商品降價了,就可以發(fā)個郵件到郵箱來提醒自己。
使用 Python 腳本發(fā)送郵件并不復雜。不過由于各家郵件的發(fā)送機制和安全策略不同,常常會因為一些配置問題造成發(fā)送失敗。今天我們來舉例講講如何使用 Python 發(fā)送郵件。
本文主要內容包括,了解發(fā)郵件的思路,發(fā)送郵件需要的一些設置,發(fā)送一封簡單的郵件,發(fā)送一封包含附件的郵件,在寫代碼過程中我們需要注意哪些問題等等。(完整參考代碼地址見文末)
1. 思路
使用腳本發(fā)送郵件的思路其實和客戶端發(fā)送郵件一樣,過程都是:
登錄 —> 寫郵件 —> 發(fā)送
只不過通過腳本發(fā)送時我們需要考慮到整個過程的方方面面。以下為思路導圖:
2. Python-email 模塊
與發(fā)送郵件相關的 Python 模塊:
smtplib
是關于 SMTP(簡單郵件傳輸協(xié)議)的操作模塊,在發(fā)送郵件的過程中起到服務器之間互相通信的作用。
簡單來說,即服務器之間通信的信息,包括信息頭、信息主體等等。
舉個簡單的例子,當你登錄郵箱,寫好郵件后點擊發(fā)送,這部分是由 SMTP 接管;而寫郵件、添加附件是由 email 模塊控制。
3. 開通電子郵箱的SMTP功能
在使用腳本發(fā)郵件之前,我們需要打開自己郵箱的 SMTP 功能,各家郵箱的設置方法就不一一講述了,具體使用時可以百度一下,下面以 163 郵箱設置為例做一個簡單的演示:
4. 簡單代碼
實踐出真知,我們結合一個簡單的代碼來理解這一過程:登錄 163 郵箱,向 qq 郵箱發(fā)送郵件。
腳本分為三個步驟:
- 設置好服務器端信息
- 郵件主體信息
- 登錄發(fā)送
另外在處理文本時,我們需要使用 MIMEText 類。
import smtplib
from email.mime.text import MIMEText
#設置服務器所需信息
#163郵箱服務器地址
mail_host = 'smtp.163.com'
#163用戶名
mail_user = '159*****02'
#密碼(部分郵箱為授權碼)
mail_pass = '7******x'
#郵件發(fā)送方郵箱地址
sender = '159*****02@163.com'
#郵件接受方郵箱地址,注意需要[]包裹,這意味著你可以寫多個郵件地址群發(fā)
receivers = ['59*****02@qq.com']
#設置email信息
#郵件內容設置
message = MIMEText('content','plain','utf-8')
#郵件主題
message['Subject'] = 'title'
#發(fā)送方信息
message['From'] = sender
#接受方信息
message['To'] = receivers[0]
#登錄并發(fā)送郵件
try:
smtpObj = smtplib.SMTP()
#連接到服務器
smtpObj.connect(mail_host,25)
#登錄到服務器
smtpObj.login(mail_user,mail_pass)
#發(fā)送
smtpObj.sendmail(
sender,receivers,message.as_string())
#退出
smtpObj.quit()
print('success')
except smtplib.SMTPException as e:
print('error',e) #打印錯誤
結果:
注意事項:
一些郵箱登錄比如 QQ 郵箱需要 SSL 認證,所以 SMTP 已經(jīng)不能滿足要求,而需要SMTP_SSL,解決辦法為:
#啟動
smtpObj = smtplib.SMTP()
#連接到服務器
smtpObj.connect(mail_host,25)
#######替換為########
smtpObj = smtplib.SMTP_SSL(mail_host)
5. 帶有附件的email
上面我們介紹了發(fā)送字符串的郵件,但這明顯不滿足現(xiàn)代郵件的需求,下面我們介紹如何發(fā)送內容以 HTML 格式,并且?guī)в袌D片和文本文件的郵件。
處理多種形態(tài)的郵件主體我們需要 MIMEMultipart 類,而處理圖片需要 MIMEImage 類。
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
#設置登錄及服務器信息
mail_host = 'smtp.163.com'
mail_user = '159*****02'
mail_pass = '7******x'
sender = '159*****02@163.com'
receivers = ['7******0@qq.com']
#設置eamil信息
#添加一個MIMEmultipart類,處理正文及附件
message = MIMEMultipart()
message['From'] = sender
message['To'] = receivers[0]
message['Subject'] = 'title'
#推薦使用html格式的正文內容,這樣比較靈活,可以附加圖片地址,調整格式等
with open('abc.html','r') as f:
content = f.read()
#設置html格式參數(shù)
part1 = MIMEText(content,'html','utf-8')
#添加一個txt文本附件
with open('abc.txt','r')as h:
content2 = h.read()
#設置txt參數(shù)
part2 = MIMEText(content2,'plain','utf-8')
#附件設置內容類型,方便起見,設置為二進制流
part2['Content-Type'] = 'application/octet-stream'
#設置附件頭,添加文件名
part2['Content-Disposition'] = 'attachment;filename="abc.txt"'
#添加照片附件
with open('1.png','rb')as fp:
picture = MIMEImage(fp.read())
#與txt文件設置相似
picture['Content-Type'] = 'application/octet-stream'
picture['Content-Disposition'] = 'attachment;filename="1.png"'
#將內容附加到郵件主體中
message.attach(part1)
message.attach(part2)
message.attach(picture)
#登錄并發(fā)送
try:
smtpObj = smtplib.SMTP()
smtpObj.connect(mail_host,25)
smtpObj.login(mail_user,mail_pass)
smtpObj.sendmail(
sender,receivers,message.as_string())
print('success')
smtpObj.quit()
except smtplib.SMTPException as e:
print('error',e)
6.小結
通過上面的代碼,想必大家已經(jīng)對發(fā)郵件有了基本的認識。
從整體上我們要把握整個過程的思路:
- 登錄
- 寫郵件
- 發(fā)送
微觀上我們需要了解:
- smtplib/email 模塊的代碼規(guī)則;
- 什么時候使用 SMTP,什么時候使用 SMTP_SSL?
- 針對不同的郵件內容需要使用到不同的類,MIMEmultipart、MIMEText、MIMEIamge 等等;
- 怎么去設置附件信息
當然,看再多教程,不如親自動手寫一段代碼。大家不妨都自己發(fā)一封郵件試一試。