簡(jiǎn)介
本篇文章與前邊沒有多大關(guān)聯(lián),就是對(duì)前邊有關(guān)發(fā)郵件的總結(jié)和梳理。在寫腳本時(shí)戳葵,放到后臺(tái)運(yùn)行,想知道執(zhí)行情況坝茎,會(huì)通過郵件、SMS(短信)暇番、飛信嗤放、微信等方式通知管理員,用的最多的是郵件壁酬。在linux下斤吐,Shell腳本發(fā)送郵件告警是件很簡(jiǎn)單的事,有現(xiàn)成的郵
件服務(wù)軟件或者調(diào)用運(yùn)營(yíng)商郵箱服務(wù)器厨喂。
對(duì)于Python來說,需要編寫腳本調(diào)用郵件服務(wù)器來發(fā)送郵件庄呈,使用的協(xié)議是SMTP蜕煌。接收郵件,使用的協(xié)議是POP3和IMAP诬留。我想有必要說明下?斜纪,POP3和IMAP的區(qū)別:POP3在客戶端郵箱中所做的操作不會(huì)反饋到郵箱服務(wù)器贫母,比如刪除一封郵件,郵箱服務(wù)器并不
會(huì)刪除盒刚。IMAP則會(huì)反饋到郵箱服務(wù)器腺劣,會(huì)做相應(yīng)的操作。
Python分別提供了收發(fā)郵件的庫因块,smtplib橘原、poplib和imaplib。
本章主要講解如果使用smtplib庫實(shí)現(xiàn)發(fā)送各種形式的郵件內(nèi)容涡上。在smtplib庫中趾断,主要主要用smtplib.SMTP()類,用于連接SMTP服務(wù)器吩愧,發(fā)送郵件芋酌。
這個(gè)類有幾個(gè)常用的方法:
方法描述
SMTP.set_debuglevel(level)設(shè)置輸出debug調(diào)試信息,默認(rèn)不輸出
SMTP.docmd(cmd[, argstring])發(fā)送一個(gè)命令到SMTP服務(wù)器
SMTP.connect([host[, port]])連接到指定的SMTP服務(wù)器
SMTP.helo([hostname])使用helo指令向SMTP服務(wù)器確認(rèn)你的身份
SMTP.ehlo(hostname)使用ehlo指令像ESMTP(SMTP擴(kuò)展)確認(rèn)你的身份
SMTP.ehlo_or_helo_if_needed()如果在以前的會(huì)話連接中沒有提供ehlo或者h(yuǎn)elo指令雁佳,這個(gè)方法會(huì)調(diào)用ehlo()或helo()
SMTP.has_extn(name)判斷指定名稱是否在SMTP服務(wù)器上
SMTP.verify(address)判斷郵件地址是否在SMTP服務(wù)器上
SMTP.starttls([keyfile[, certfile]])使SMTP連接運(yùn)行在TLS模式脐帝,所有的SMTP指令都會(huì)被加密
SMTP.login(user, password)登錄SMTP服務(wù)器
SMTP.sendmail(from_addr, to_addrs, msg, mail_options=[], rcpt_options=[])發(fā)送郵件
from_addr:郵件發(fā)件人
to_addrs:郵件收件人
msg:發(fā)送消息
SMTP.quit()關(guān)閉SMTP會(huì)話
SMTP.close()關(guān)閉SMTP服務(wù)器連接
看下官方給的示例:
我們根據(jù)示例給自己發(fā)一個(gè)郵件測(cè)試下:
我這里測(cè)試使用本地的SMTP服務(wù)器,也就是要裝一個(gè)支持SMTP協(xié)議的服務(wù)糖权,比如sendmail堵腹、postfix等。
CentOS安裝sendmail:yum install sendmail
1>>> import smtplib2>>> s = smtplib.SMTP("localhost")3>>> tolist = ["xxx@qq.com","xxx@163.com"]4>>> msg ='''\5... From: Me@my.org6... Subject: test7... Thisisa test'''8>>> s.sendmail("me@my.org", tolist, msg)9{}
進(jìn)入騰訊和網(wǎng)易收件人郵箱温兼,就能看到剛發(fā)的測(cè)試郵件秸滴,一般都被郵箱服務(wù)器過濾成垃圾郵件,所以收件箱沒有募判,你要去垃圾箱看看荡含。
可以看到,多個(gè)收件人可以放到一個(gè)列表中進(jìn)行群發(fā)届垫。msg對(duì)象里From表示發(fā)件人释液,Subject是郵件標(biāo)題,換行后輸入的是郵件內(nèi)容装处。
1.1 Python發(fā)送郵件并抄送
1#!/usr/bin/python 2# -*- coding: utf-8-*- 3import smtplib 4def sendMail(body): 5smtp_server ='smtp.163.com' 6from_mail ='hongge@163.com' 7mail_pass ='xxx' 8to_mail = ['xxx@qq.com','xxx@163.com'] 9cc_mail = ['hongge@xxx.com']10from_name ='monitor'11subject = u'監(jiān)控'.encode('gbk')? # 以gbk編碼發(fā)送误债,一般郵件客戶端都能識(shí)別12#? ? msg ='''\13# From: %s <%s>14# To: %s15# Subject: %s16# %s''' %(from_name, from_mail, to_mail_str, subject, body)? # 這種方式必須將郵件頭信息靠左,也就是每行開頭不能用空格妄迁,否則報(bào)SMTP 55417mail = [18"From: %s <%s>"% (from_name, from_mail),19"To: %s"%','.join(to_mail),? # 轉(zhuǎn)成字符串寝蹈,以逗號(hào)分隔元素20"Subject: %s"% subject,21"Cc: %s"%','.join(cc_mail),22"",23? ? ? ? body24? ? ? ? ]25msg ='\n'.join(mail)? # 這種方式先將頭信息放到列表中,然后用join拼接登淘,并以換行符分隔元素箫老,結(jié)果就是和上面注釋一樣了26try:27s = smtplib.SMTP()28s.connect(smtp_server,'25')29? ? ? ? s.login(from_mail, mail_pass)30s.sendmail(from_mail, to_mail+cc_mail, msg)? 31? ? ? ? s.quit()32except smtplib.SMTPExceptionas e:33print"Error: %s"%e34if__name__ =="__main__":35sendMail("This is a test!")
s.sendmail(from_mail, to_mail+cc_mail, msg) 在這里注意下,收件人和抄送人為什么放一起發(fā)送呢黔州?其實(shí)無論是收件人還是抄送人耍鬓,它們收到的郵件都是一樣的阔籽,SMTP都是認(rèn)為收件人這樣一封一封的發(fā)出。所以實(shí)際上并沒有抄送這個(gè)概念牲蜀,只是在郵件頭加了抄送人的信息罷了笆制!另外,如果不需要抄送人涣达,直接把上面cc的信息去掉即可在辆。
另外以上代碼發(fā)送的郵件會(huì)出現(xiàn)主題中文亂碼:
解決方案:三行代碼即可,修改成紅色框代碼即可
1.2 Python發(fā)送郵件帶附件
由于SMTP.sendmail()方法不支持添加附件峭判,所以可以使用email模塊來滿足需求开缎。email模塊是一個(gè)構(gòu)造郵件和解析郵件的模塊。
先看下如何用email庫構(gòu)造一個(gè)簡(jiǎn)單的郵件:
message = Message()
message['Subject'] = '郵件主題'
message['From'] = from_mail
message['To'] = to_mail
message['Cc'] = cc_mail
message.set_payload('郵件內(nèi)容')
基本的格式就是這樣的林螃!
繼續(xù)回到主題奕删,發(fā)送郵件帶附件:
1# coding=utf-8 2#1.先設(shè)置編碼,utf-8可支持中英文疗认,如上完残,一般放在第一行 3 4#2.注釋:包括記錄創(chuàng)建時(shí)間,創(chuàng)建人横漏,項(xiàng)目名稱谨设。 5''' 6Created on2019-5-9 7@author: 北京-宏哥 8Project:學(xué)習(xí)和使用郵箱發(fā)帶有附件郵件 9'''10#3.導(dǎo)入模塊11import smtplib12from email.mime.text import MIMEText13from email.mime.multipart import MIMEMultipart14from email.header import Header15from email import encoders16fromemail.mime.base import MIMEBase1718def send_mail(file_new):19#-----------1.跟發(fā)件相關(guān)的參數(shù)------20smtpserver ='smtp.mxhichina.com'? ? ? ? ? ? ? ? #發(fā)件服務(wù)器21port =0? ? ? ? ? ? ? ? ? ? ? #端口22username ='noreply@cxx.cn'? #發(fā)件箱用戶名23password ='xx@@123'? ? ? ? #發(fā)件箱密碼24sender ='noreply@cxx.cn'? ? #發(fā)件人郵箱25receiver = ['hongge@cedex.cn','1918991791@qq.com'] #收件人郵箱26# ----------2.編輯郵件的內(nèi)容------27? ? #讀文件內(nèi)容28f = open(file_new,'rb')29mail_body = f.read()30? ? f.close()31? ? # 郵件正文是MIMEText32body = MIMEText(mail_body,'html','utf-8')33? ? # 郵件對(duì)象34msg = MIMEMultipart()35msg['Subject'] = Header("自動(dòng)化測(cè)試報(bào)告",'utf-8').encode()#主題36msg['From'] = Header(u'測(cè)試機(jī) <%s>'%sender)? ? ? ? ? ? ? ? #發(fā)件人37msg['To'] = Header(u'測(cè)試負(fù)責(zé)人 <%s>'%receiver)? ? ? ? ? ? #收件人38msg['To'] =';'.join(receiver)39? ? msg.attach(body)40? ? # # MIMEBase表示附件的對(duì)象41att = MIMEText(mail_body,"base64","utf-8")42att["Content-Type"] ="application/octet-stream"43? ? # filename是顯示附件名字44att["Content-Disposition"] ='attachment; filename="test_report.html"'45? ? msg.attach(att)46# ----------3.發(fā)送郵件------47try:48smtp = smtplib.SMTP()49? ? ? ? smtp.connect(smtpserver)? # 連服務(wù)器50? ? ? ? smtp.login(sender, password)51? ? except:52smtp = smtplib.SMTP_SSL(smtpserver, port)53? ? ? ? smtp.login(sender, password)? # 登錄54? ? smtp.sendmail(sender, receiver, msg.as_string())? # 發(fā)送55? ? smtp.quit()5657if__name__ =="__main__":58? ? #本地文件的路徑59att_path= r'E:\pythontest\text.txt'60send_mail(att_path)
1.3 Python發(fā)送HTML郵件
1# coding=utf-8 2#1.先設(shè)置編碼,utf-8可支持中英文缎浇,如上扎拣,一般放在第一行 3 4#2.注釋:包括記錄創(chuàng)建時(shí)間,創(chuàng)建人素跺,項(xiàng)目名稱二蓝。 5''' 6Created on2019-5-9 7@author: 北京-宏哥 8Project:學(xué)習(xí)和使用郵箱發(fā)HTML郵件 9'''10#3.導(dǎo)入模塊11#"-*- coding: utf-8 -*-"12import smtplib13from email.mime.text import MIMEText1415mail_user="XXX@163.com"16mail_password="******q1125"17mailto_list=["1918991791<1918991791@qq.com>","2014816656@qq.com"]18mail_host="smtp.163.com"19mail_postfix="163.com"2021def sendmail(to_list,sub,content):22me="北京-宏哥"+"<"+mail_user+"@"+mail_postfix+">"23msg=MIMEText("<a ><font color='red'>北京-宏哥</font></a>","html","utf-8")24msg['Subject']=sub25msg['From']=me26msg['To']=",".join(to_list)27try:28server=smtplib.SMTP()29? ? ? ? server.connect(mail_host)30? ? ? ? server.login(mail_user,mail_password)31? ? ? ? server.sendmail(me,to_list,msg.as_string())32? ? ? ? server.close()33return True34except Exceptionas e:35? ? ? ? print (str(e))36return False37ifsendmail(mailto_list,"標(biāo)題:發(fā)送的是html格式","<a ):38print ("done!")39else:40print ("falsed!")
1.4 Python發(fā)送圖片郵件
# coding=utf-8#1.先設(shè)置編碼,utf-8可支持中英文指厌,如上刊愚,一般放在第一行
#2.注釋:包括記錄創(chuàng)建時(shí)間,創(chuàng)建人踩验,項(xiàng)目名稱鸥诽。'''Created on2019-5-9@author: 北京-宏哥
Project:學(xué)習(xí)和使用1郵箱發(fā)HTML郵件'''#3.導(dǎo)入模塊
#"-*- coding: utf-8 -*-"import smtplibfrom email.mime.text import MIMEText
mail_user="@@@@@163.com"mail_password="@@@@"mailto_list=["1918991791<1918991791@qq.com>","2014816656@qq.com"]
mail_host="smtp.163.com"mail_postfix="163.com"def sendmail(to_list,sub,content):
? ? me="北京-宏哥"+"<"+mail_user+"@"+mail_postfix+">"? ? msg=MIMEText('<html><body><img hidefocus="true" class="index-logo-src" src="http://www.baidu.com/img/bd_logo1.png" width="270" height="129" usemap="#mp"></body></html>','html','utf-8')
? ? msg['Subject']=sub
? ? msg['From']=me
? ? msg['To']=",".join(to_list)
? ? try:
? ? ? ? server=smtplib.SMTP()
? ? ? ? server.connect(mail_host)
? ? ? ? server.login(mail_user,mail_password)
? ? ? ? server.sendmail(me,to_list,msg.as_string())
? ? ? ? server.close()
? ? ? ? return True
? ? except Exception as e:
? ? ? ? print (str(e))
? ? ? ? return Falseifsendmail(mailto_list,"標(biāo)題:發(fā)送的是HTML格式","<a ):
? ? print ("done!")else:
? ? print ("falsed!")
上面發(fā)郵件的幾種常見的發(fā)郵件方法基本滿足日常需求了。
小結(jié)
1箕憾、linux環(huán)境下提示AttributeError: module 'smtplib' has no attribute 'SMTP'牡借,Windows環(huán)境運(yùn)行代碼也報(bào)如下錯(cuò)誤:
2、原因當(dāng)然不是模塊的問題袭异,檢查了一下拼寫也沒有出問題钠龙,最后在這個(gè)帖子(鏈接)的啟發(fā)下發(fā)現(xiàn),發(fā)現(xiàn)自己的文件命名為email.py,和模塊中的函數(shù)有沖突俊鱼,改名之后Linux環(huán)境郵件正常發(fā)送。