smtplib模塊實現郵件的發送功能,模擬一個stmp客戶端,經過與smtp服務器交互來實現郵件發送的功能,能夠理解成Foxmail的發郵件功能,在使用以前咱們須要準備smtp服務器主機地址、郵箱帳號以及密碼信息。php
在python2.3之後python自帶smtplib模塊,無需額外安裝。html
class smtplib.SMTP(host="",port=0,local_hostname=None,[timeout,]source_address=None):python
SMTP類定義做爲SMTP的構造函數,定義了一個SMTP客戶端會話對象,功能是與smtp服務器創建連接,在連接成功後,就能夠向服務器發送相關請求,好比登錄、校驗、發送、退出等。chrome
SMTP類方法:瀏覽器
SMTP.connect(host='localhost',port=0) :連接到遠程SMTP主機的方法,host爲遠程主機地址,port爲遠程主機smtp端口,默認爲25,也能夠直接使用host:port形式來表示:如:SMTP.connect('smtp.163.com','25')安全
SMTP.login(user,password):登錄須要認證的SMTP服務器,參數爲用戶名與密碼,如SMTP.login('python@163.com','123')服務器
SMTP.sendmail(from_addr,to_addrs,msg,mail_options=[],rcpt_options=[]):實現郵件的發送功能,參數from_addr爲發件人,to_addrs爲收件人,msg爲郵件內容,如:SMTP.sendmail('python@163.com','demo@qq.com',body)。網絡
SMTP.starttls(keyfile=None,certfile=None):啓用TLS安全傳輸模式,全部SMTP指令都將加密傳輸,如使用gmail的smtp服務時需喲啊啓動此項才能正常發送郵件。app
SMTP.quit():斷開smtp服務器連接iphone
SMTP.set_debuglevel(level):設置調試輸出級別,值爲1,2或True,發送調試消息到服務器
SMTP.send_message(msg,from_addr=None,to_addrs=None,mail_options=[],rcpt_options=[]):這是使用有email.message.Message對象表示的消息進行調用的便捷方法使用sendmail(),參數的含義與sendmail()相同,只有msg是一個Message對象;若是from_addr是None或者to_addrs是None,則send_message用從msg頭部提取的地址填充那些參數,from設置爲發件人自動,TO設置爲to_addrs。
實例1實現簡單郵件發送:
import smtplib from smtplib import SMTP HOST="smtp.163.com" #定義smtp主機 SUBJECT="test email form python" #定義郵件主題 TO = "11111@163.com" #定義郵件收件人 FROM="22222@163.com" #定義郵件發件人 text="python is test smtp" #郵件內容,編碼爲ASCII範圍內的字符或字節字符串,因此不能寫中文 BODY = '\r\n'.join(( #組合sendmail方法的郵件主體內容,各段以"\r\n"進行分離 "From: %s" %"admin", "TO: %s" %TO, "subject: %s" %SUBJECT, "", text )) server = SMTP() #建立一個smtp對象 server.connect(HOST,'25') #連接smtp主機 server.login(FROM,"123") #郵箱帳號登錄 server.sendmail(FROM,TO,BODY) #發送郵件 server.quit() #端口smtp連接
實例2:讀取文件內容發送郵件主體
import smtplib from email.utils import formataddr from email.mime.text import MIMEText with open('textfile','rb') as fp: #讀取文件內容 msg=MIMEText(fp.read(),'plain','utf-8') #建立消息對象 msg['Subject'] = "emailMessage" msg['From'] = formataddr(["張三","920664709@163.com"]) msg['To'] = formataddr(["李四","920664709@163.com"]) try: server = smtplib.SMTP() # 建立一個 SMTP() 對象 server.connect("smtp.163.com","25") # 經過 connect 方法鏈接 smtp 主機 #server.starttls() # 啓動安全傳輸模式 server.login("920664709@163.com","xxxxxx") # 郵箱帳號登陸校驗 server.sendmail("92066@163.com","92066@163.com", msg.as_string()) # 郵件發送 server.quit() # 斷開 smtp 鏈接 print("郵件發送成功!") except Exception as e: print('失敗:'+str(e))
經過郵件傳輸簡單的文本已經沒法知足咱們的需求,好比咱們時常會定製業務質量報表,在郵件主體中會包含 HTML、圖像、聲音以及附件格式等,MIME(Multipurpose Internet Mail Extensions,多用途互聯網郵件擴展)做爲一種新的擴展郵件格式很好地補充了這一點,更多MIME 知識見 https://docs.python.org/3/library/email.html。下面介紹幾個 Python 中經常使用的 MIME 實現類:
email.mime.base.
MIMEBase
(_maintype,_subtype,*,policy = compat32,** _ params ):
這是全部MIME特定類的基類,_maintpe是Content-Type主要類型(text or image),_subtype是Content-Type次要類型(plain or gif),_params是一個鍵值字典參數直接傳遞給Message.add_header
filename1 = '圖片.pdf' attachfile_base = MIMEBase('application', 'octet-stream') #建立基礎對象指定類型 attachfile_base.set_payload(open(filename,'rb').read()) #設置我有效負載 attachfile_base.add_header('Content-Disposition', 'attachment', filename=('utf-8', '', filename1) ) encoders.encode_base64(attachfile_base) msg.attach(attachfile_base)
email.mime.multipart.MIMEMultipart(_subtype='mixed',boundary= None,_subparts = None,*,policy = compat32,** _ params ):
做用是生成包含多個部分的郵件體的 MIME 對象,參數 _subtype 指定要添加到"Content-type:multipart/subtype" 報頭的可選的三種子類型,分別爲 mixed、related、alternative,默認值爲 mixed。定義 mixed實現構建一個帶附件的郵件體;定義related 實現構建內嵌資源的郵件體;定義alternative 則實現構建純文本與超文本共存的郵件體;_subparts是有效負載的一系類初始部分,可使用attach()方法將子部件附加到消息中。
from email.mime.multipart import MIMEMultipart msg1 = MIMEMultipart('mixed') #建立帶附件的實例 msg2 = MIMEMultipart('related') #建立內嵌資源的實例 msg3 = MIMEMultipart('alternative') #建立純文本與超文本實例
email.mime.application.
MIMEApplication
(_data, _subtype='octet-stream', _encoder=email.encoders.encode_base64, *, policy=compat32, **_params):
被用來表示主要類型的MIME消息對象應用,_data是一個包含原始字節數據的字符串,_subtype指定MIME子類型默認爲八位字節流,_encoder是一個可調用函數,它執行傳輸數據的實際編碼,使用set_payload()將有效載荷改成編碼形式,默認編碼位base64,可以使用email.encoders模塊查看內置編碼表。
filename = '簡歷.pdf' with open(filename,'rb') as f: attachfile = MIMEApplication(f.read()) attachfile.add_header('Content-Disposition', 'attachment', filename=filename) msg.attach(attachfile)
email.mime.audio.MIMEAudio (_audiodata[, _subtype[, _encoder]]):
建立包含音頻數據的郵件體,_audiodata 包含原始二進制音頻數據的字節字符串;_subtype音頻類型,_encoder編碼。
from email.mime.audio import MIMEAudio msgaudio = MIMEAudio(open('yishengsuoai.mp3','rb').read(),'plain') #文本音頻對象 msgaudio.add_header('Content-Disposition','attachment',filename='text.mp3') #擴展標題類型,文件名 msg.attach(msgaudio) #附加對象加入到msg
email.mime.image.MIMEImage(_imagedata[, _subtype[, _encoder[, **_params]]]):
MIMENonMultipart中的一個子類,建立包含圖片數據的郵件體,_imagedata 是包含原始圖片數據的字節字符串;_sutype指定圖像子類型;_encoder指定一個函數內部編碼默認爲:email.encoders.encode_base64默認爲base64編碼
from email.mime.image import MIMEImage #導入MIMEImage類 with open('test.png','rb') as fp: msgImage = MIMEImage(fp.read()) #讀取圖片賦值一個圖片對象 msgImage.add_header('Content-ID','imgid') #爲圖片對象拓展標題字段和值 msg.attach(msgImage) #將圖像負載添加到msg負載
email.mime.text.MIMEText (_text[, _subtype[, _charset]]):
MIMENonMultipart中的一個子類,建立包含文本數據的郵件體,_text 是包含消息負載的字符串,_subtype 指定文本類型,支持 plain(默認值)或 html類型的字符串。_charset設置字符集,參數接受一個charset實例。
from email.mime.text import MIMEText #建立文本內容的郵件體 msg = MIMEText("python test email",'plain','utf-8') #建立HTML格式的郵件體 msg = MIMEText("<p>python test email</p><p><a href="http://www.demo.com">連接</a></p>",'html','utf-8')
MIME實例對象的方法:
msg.add_header('Content-ID','imgid') #設置圖片ID msg.add_header('Content-Disposition','attachment',filename='test.xlsx') #爲附件添加一個標題 msg.add_header('Content-Disposition','attachment',filename=('utf-8','','中文標題')) #添加非ASCII字符時需指定編碼
email.header.Header(s=None,charset=None):建立一個能夠包含不一樣字符集中的字符串,並符合MIME的標頭。
可選參數:s是初始標題值默認爲None,可使用append()方法追加到標題,charset指定字符集
from email.header import Header msg['From'] = Header("測試郵件來自",'utf-8')
附加工具:email.utils
email.utils.localtime(dt=None) :返回當前時間,dt參數爲datetime實例
email.utils.formataddr(pair,charset='utf-8') :pair是一個元祖或列表返回分割的標題和地址如郵箱收件人暱稱和郵箱帳號
from email.utils import formataddr msg['From'] = formataddr(['Meslef','92066@163.com']) msg['To'] = formataddr(['Anybody','92066@163.com'])
前面介紹了 Python 的 smtplib 及 email模塊的經常使用方法,那麼二者在郵件定製到發送過程當中是如何分工的?咱們能夠將 email.mime 理解成 smtplib 模塊郵件內容主體的擴展,從原先默認只支持純文本格式擴展到HTML,同時支持附件、音頻、圖像等格式,smtplib 只負責郵件的投遞便可。下面介紹在平常運營工做中郵件應用的幾個示例
經過引入email.mime的MIMEText類來實現支持HTML格式的郵件,支持全部HTML元素,包括表格、圖片、動畫、CSS樣式、表單等。
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/6/1 11:58 # @Author : Py.qi # @File : fangwenliang.py # @Software: PyCharm import smtplib from email.mime.text import MIMEText # 導入 MIMEText 類 HOST = "smtp.qq.com" # 定義 smtp 主機 SUBJECT = u" 官網流量數據報表 " # 定義郵件主題 TO = "92066@163.com" # 定義郵件收件人 FROM = "92066@qq.com" # 定義郵件發件人 test = """ <body> <table width="800" border="1" cellspacing="0" cellpadding="4"> <tr> <td bgcolor="#CECFAD" height="20" style="font-size:14px">* 官網數據 <a href="http://www.baidu.com"> 更多 >></a></td> </tr> <tr> <td bgcolor="#EFEBDE" height="100" style="font-size:13px"> 一、 日訪問量 :<font color=red>152433</font> 訪問次數 :23651 頁面瀏覽量 :45123 點擊數 :545122 數據流量 :504Mb<br> 二、狀態碼信息 <br> 500:105 404:3264 503:214<br> 三、訪客瀏覽器信息 <br> IE:50% firefox:10% chrome:30% other:10%<br> 四、頁面信息 <br> /index.php 42153<br> /view.php 21451<br> /login.php 5112<br> </td> </tr> </table> """ msg = MIMEText(test,"html","utf-8") #定義主體內容 msg['Subject'] = SUBJECT # 郵件主題 msg['From']=FROM # 郵件發件人 , 郵件頭部可見 msg['To']=TO # 郵件收件人 , 郵件頭部可見 try: server = smtplib.SMTP() # 建立一個 SMTP() 對象 server.connect(HOST,"25") # 經過 connect 方法鏈接 smtp 主機 server.starttls() # 啓動安全傳輸模式 server.login("92066@qq.com","iqcuwzhgmj") # 郵箱帳號登陸校驗 server.sendmail(FROM, TO, msg.as_string()) # 郵件發送 server.quit() # 斷開 smtp 鏈接 print("郵件發送成功!") except Exception as e: print('失敗:'+str(e))
發送帶圖片的郵件時,須要引入MIMEImage類和MIMEText類組合實現圖文格式的數據發送;經過MIMEMultipart類來進行組裝
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/6/1 11:58 # @Author : Py.qi # @File : fangwenliang.py # @Software: PyCharm import smtplib from email.mime.text import MIMEText # 導入 MIMEText 類 from email.mime.multipart import MIMEMultipart #導入MIMEMultipart類 from email.mime.image import MIMEImage #導入MIMEImage類 HOST = "smtp.qq.com" # 定義 smtp 主機 SUBJECT = u"系統性能報表" # 定義郵件主題 TO = "92066@163.com" # 定義郵件收件人 FROM = "92066@qq.com" # 定義郵件發件人 def addimg(src,imgid): #定義圖片讀取函數,參數1爲圖片路徑,2爲圖片ID機標識符 with open(src,'rb') as f: msgimage = MIMEImage(f.read()) #讀取圖片內容 msgimage.add_header('Content-ID',imgid) #指定文件的Content-ID,<img>,在HTML中圖片src將用到 return msgimage msg = MIMEMultipart('related') #建立MIMEMultipart對象,採用related定義內嵌資源郵件體 test = """ <table width="600" border="0" cellspacing="0" cellpadding="4"> <tr bgcolor="#CECFAD" height="20" style="font-size:14px"> <td colspan=2>*系統性能數據 <a href="10.0.0.10"> 更多 >></a></td> </tr> <tr bgcolor="#EFEBDE" height="100" style="font-size:13px"> <td> <img src="cid:io"> #圖片地址由MIMEMultipart經過ID傳遞 </td> <td> <img src="cid:key_hit"> </td> </tr> <tr bgcolor="#EFEBDE" height="100" style="font-size:13px"> <td> <img src="cid:men"> </td> <td> <img src="cid:swap"> </td> </tr> </table> """ msgtext = MIMEText(test,"html","utf-8") #建立Text對象內容,包括圖片<img> msg.attach(msgtext) #MIMEMultipart對象附加MIMEText的內容 msg.attach(addimg("1.png",'io')) #附加圖片內容,io指向HTML文本內的參數 msg.attach(addimg("2.png",'key_hit')) msg.attach(addimg("3.png",'men')) msg.attach(addimg("4.png",'swap')) msg['Subject'] = SUBJECT # 郵件主題 msg['From']=FROM # 郵件發件人 , 郵件頭部可見 msg['To']=TO # 郵件收件人 , 郵件頭部可見 try: server = smtplib.SMTP() # 建立一個 SMTP() 對象 server.connect(HOST,"25") # 經過 connect 方法鏈接 smtp 主機 server.starttls() # 啓動安全傳輸模式 server.login("92066@qq.com","iqcuwzhgmj") # 郵箱帳號登陸校驗 server.sendmail(FROM, TO, msg.as_string()) # 郵件發送 server.quit() # 斷開 smtp 鏈接 print("郵件發送成功!") except Exception as e: print('失敗:'+str(e))
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/6/1 14:55 # @Author : Py.qi # @File : attach_smtp.py # @Software: PyCharm import smtplib from email.mime.text import MIMEText # 導入 MIMEText 類 from email.mime.multipart import MIMEMultipart #導入MIMEMultipart類 from email.mime.image import MIMEImage #導入MIMEImage類 from email.mime.base import MIMEBase #MIME子類的基類 from email import encoders #導入編碼器 HOST = "smtp.qq.com" # 定義 smtp 主機 SUBJECT = u"系統性能報表" # 定義郵件主題 TO = "92066@163.com" # 定義郵件收件人 FROM = "92066@qq.com" # 定義郵件發件人 def addimg(src,imgid): #定義圖片讀取函數,參數1爲圖片路徑,2爲圖片ID機標識符 with open(src,'rb') as f: msgimage = MIMEImage(f.read()) #讀取圖片內容 msgimage.add_header('Content-ID',imgid) #指定文件的Content-ID,<img>,在HTML中圖片src將用到 return msgimage msg = MIMEMultipart('related') #建立MIMEMultipart對象,採用related定義內嵌資源郵件體 #建立一個MIMEText對象,HTML元素包括文字與圖片 msgtext = MIMEText("<font color=red> 官網業務周平均延時圖表 :<br><img src=\"cid:weekly\"border=\"1\"><br> 詳細內容見附件。</font>","html","utf-8") msg.attach(msgtext) #將msgtext內容附加到MIMEMultipart對象中 msg.attach(addimg("1.png",'weekly')) #使用MIMEMultipart對象附加MIMEImage的內容 #附件文件定義 #建立一個MIMEText對象,附加表格文件(week.xlsx) filename = 'week.xlsx' attachfile = MIMEBase('applocation','octet-stream') #建立對象指定主要類型和次要類型 attachfile.set_payload(open(filename,'rb').read()) #將消息內容設置爲有效載荷 attachfile.add_header('Content-Disposition','attachment',filename=('utf-8','',filename)) #擴展標題設置 encoders.encode_base64(attachfile) msg.attach(attachfile) #附加對象加入到msg msg['Subject'] = SUBJECT # 郵件主題 msg['From']=FROM # 郵件發件人 , 郵件頭部可見 msg['To']=TO # 郵件收件人 , 郵件頭部可見 try: server = smtplib.SMTP() # 建立一個 SMTP() 對象 server.connect(HOST,"25") # 經過 connect 方法鏈接 smtp 主機 server.starttls() # 啓動安全傳輸模式 server.login("92066@qq.com","iqcuwzhgmj") # 郵箱帳號登陸校驗 server.sendmail(FROM, TO, msg.as_string()) # 郵件發送 server.quit() # 斷開 smtp 鏈接 print("郵件發送成功!") except Exception as e: print('失敗:'+str(e))
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/6/2 12:06 # @Author : Py.qi # @File : coent_smtp.py # @Software: PyCharm import smtplib from email.utils import make_msgid,formatdate from email.mime.text import MIMEText #html格式和文本格式郵件 from email.mime.multipart import MIMEMultipart #帶多個部分的郵件 from email.mime.image import MIMEImage #帶圖片格式郵件 from email.mime.audio import MIMEAudio #音頻文件對象 from email.utils import formataddr #分隔標題與地址 from email.header import Header #設置標題字符集 from email import encoders #編碼器 from email.mime.application import MIMEApplication #主要類型的MIME消息對象應用 from email.mime.base import MIMEBase # 發件人地址,經過控制檯建立的發件人地址 username = 'service@gemail.com' # 發件人密碼,經過控制檯建立的發件人密碼 password = '*****' # 自定義的回覆地址 replyto = '92066@qq.com' # 收件人地址或是地址列表,支持多個收件人,最多30個 rcptto = ['***', '***'] #構建信件標頭結構 msg = MIMEMultipart('alternative') #建立一個多部分的郵件對象 msg['Subject'] = Header('自定義信件主題', 'utf-8') msg['From'] = formataddr([Header('自定義發信暱稱','utf-8'),username]) msg['To'] = formataddr([Header('自定義收信暱稱','utf-8'),rcptto]) msg['Reply-to'] = replyto msg['Message-id'] = make_msgid() #Message-ID標頭 msg['Date'] = formatdate() #日期 #構建文本郵件內容 msg_text = MIMEText('自定義TEXT純文本部分','plain','utf-8') msg.attach(msg_text) #讀取文件建立郵件內容 with open('textfile','rb') as fp: #讀取文件內容 msg_text=MIMEText(fp.read(),'plain','utf-8') #構建HTML格式的郵件內容 msg_html = MIMEText("<h1>HTML格式郵件</h1>","html","utf-8") msg.attach(msg_html) #構建HTML格式郵件帶圖片內容 html1 = "<div><img src='cid:imgid'></div>" msg_html_img = MIMEText(html1,'html','utf-8') msg.attach(msg_html_img) with open("imgfile","rb") as f: msg_img = MIMEImage(f.read()) msg_img.add_header('Content-ID','imgid') #擴展圖片標題 msg.attach(msg_img) #帶附件的郵件MIMEApplication filename = '簡歷.pdf' with open(filename,'rb') as f: attachfile = MIMEApplication(f.read()) attachfile.add_header('Content-Disposition', 'attachment', filename=filename) msg.attach(attachfile) #帶多個附件的郵件MIMEApplication filenames = ['簡歷.pdf','副本.pdf'] for tmp in filename: with open(tmp,'rb') as f: attachfiles = MIMEApplication(f.read()) attachfiles.add_header('Content-Disposition', 'attachment', filename=tmp) msg.attach(attachfiles) #帶附件的郵件MIMEBase filename1 = '圖片.pdf' attachfile_base = MIMEBase('application', 'octet-stream') #建立基礎對象指定類型 attachfile_base.set_payload(open(filename,'rb').read()) #設置我有效負載 attachfile_base.add_header('Content-Disposition', 'attachment', filename=('utf-8', '', filename1) ) encoders.encode_base64(attachfile_base) msg.attach(attachfile_base) #建立音頻文件 AUDIO_HTML = ''' <p>this's audio file</p> <audio controls> <source src="cid:audioid" type="audio/mpeg"> </audio> ''' msg_test1 = MIMEText(AUDIO_HTML,'html','utf-8') msg_audio = MIMEAudio(open('iphone.mp3','rb').read(),'plain') msg_audio.add_header('Content-ID','audioid') msg.attach(msg_test1) msg.attach(msg_audio) #收到郵件不能播放,有待解決! # 發送郵件 try: client = smtplib.SMTP() #須要使用SSL,能夠這樣建立client #client = smtplib.SMTP_SSL() client.connect('smtp.163.com', 25) #開啓DEBUG模式 client.set_debuglevel(1) client.login(username, password) client.sendmail(username, rcptto, msg.as_string()) client.quit() print('email send success!') except smtplib.SMTPConnectError as e: print('郵件發送失敗,鏈接失敗:', e.smtp_code, e.smtp_error) except smtplib.SMTPAuthenticationError as e: print('郵件發送失敗,認證錯誤:', e.smtp_code, e.smtp_error) except smtplib.SMTPSenderRefused as e: print('郵件發送失敗,發件人被拒絕:', e.smtp_code, e.smtp_error) except smtplib.SMTPRecipientsRefused as e: print('郵件發送失敗,收件人被拒絕:', e.smtp_code, e.smtp_error) except smtplib.SMTPDataError as e: print('郵件發送失敗,數據接收拒絕:', e.smtp_code, e.smtp_error) except smtplib.SMTPException as e: print('郵件發送失敗, ', e.message) except Exception as e: print('郵件發送異常, ', str(e))
(5)別人的類寫法借鑑
import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase from email import encoders class mailsender(object): _from = None _attachments = [] def __init__(self,host,port): self.smtp = smtplib.SMTP() self.smtp_ssl = smtplib.SMTP_SSL() self.smtp.connect(host,port) def login(self, user, pwd): self._from = user print("login ...") self.smtp.login(user, pwd) def add_attachment(self, filename): #添加附加 att = MIMEBase('application', 'octet-stream') att.set_payload(open(filename,'rb').read()) att.add_header('Content-Disposition', 'attachment', filename = ('utf-8','',filename)) encoders.encode_base64(att) self._attachments.append(att) def send(self, subject, content, to_addr): msg = MIMEMultipart('alternative') contents = MIMEText(content, 'plain', _charset ='utf-8') msg['subject'] = subject msg['from'] = self._from msg['to'] = to_addr for att in self._attachments: msg.attach(att) msg.attach(contents) try: self.smtp.sendmail(self._from, to_addr, msg.as_string()) self.smtp.quit() print('郵件發送成功!') except Exception as e: print(str(e)) if __name__ == '__main__': emailtext,to_email = input('郵件消息:').split() email = mailsender('smtp.163.com','25') email.login('92066@163.com','xxxxx') email.add_attachment('2.png') email.send('hello test',emailtext,to_email)
更多內容參考官方文檔: 電子郵件和MIME處理軟件包
#################################後期待更新Django實例郵件!