引用頭文件
創(chuàng)新互聯(lián)建站主要從事成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)市中,十多年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):18982081108
#!/usr/bin/env python
#-*-coding:utf-8-*-
import smtplib
import os
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
創(chuàng)建“連接郵件服務(wù)器”函數(shù)
def smtp_connect( smtp_server, account, password, target ):
global smtp
global e_smtpserver
global e_account
global e_password
global e_target
global msg
e_smtpserver = smtp_server
e_account = account
e_password = password
e_target = target
try:
smtp = smtplib.SMTP()
smtp.connect(e_smtpserver)
smtp.login(e_account, e_password)
except Exception, e:
print 'Mail connect failed: %s' % e
exit( -1 )
msg = MIMEMultipart('related')
創(chuàng)建“寫郵件內(nèi)容”函數(shù)
def smtp_set_content( subject, main_body ):
global msg
msg['Subject'] = subject
body = MIMEText( main_body, 'plain', 'utf-8' )
msg.attach( body )
創(chuàng)建“添加附件”函數(shù)
def smtp_set_attachment( file_path ):
global msg
part = MIMEBase( 'application', 'octet-stream' )
part.set_payload( open(file_path,'rb').read() )
encoders.encode_base64(part)
part.add_header( 'Content-Disposition', 'attachment; filename=%s' % file_path.split('/')[-1] )
msg.attach(part)
創(chuàng)建“發(fā)送郵件”函數(shù)
def smtp_send():
global smtp
global e_smtpserver
global e_account
global e_password
global e_target
global msg
try:
smtp.sendmail( e_account, e_target, msg.as_string() )
except Exception, e:
print 'Mail send Failed: %s' % e
exit( -1 )
使用示例
if __name__ == '__main__':
smtp_connect( 'smtp.xxxx.com.cn', 'xxxx@xxxx.com.cn', 'password',
'xxxx@xxxx.com.cn' )
smtp_set_content( 'Test subject', 'Test_content' )
smtp_set_attachment( os.getcwd() + '/mail.py' )
smtp_send()
'''''?
函數(shù)說明:Send_email_text()?函數(shù)實(shí)現(xiàn)發(fā)送帶有附件的郵件,可以群發(fā),附件格式包括:xlsx,pdf,txt,jpg,mp3等?
參數(shù)說明:?
1.?subject:郵件主題?
2.?content:郵件正文?
3.?filepath:附件的地址,?輸入格式為["","",...]?
4.?receive_email:收件人地址,?輸入格式為["","",...]?
'''??
def?Send_email_text(subject,content,filepath,receive_email):??
import?smtplib??
from?email.mime.multipart?import?MIMEMultipart???
from?email.mime.text?import?MIMEText???
from?email.mime.application?import?MIMEApplication??
sender?=?"發(fā)送方郵箱"??
passwd?=?"填入發(fā)送方密碼"??
receivers?=?receive_email???#收件人郵箱??
msgRoot?=?MIMEMultipart()???
msgRoot['Subject']?=?subject??
msgRoot['From']?=?sender??
if?len(receivers)1:??
msgRoot['To']?=?','.join(receivers)?#群發(fā)郵件??
else:??
msgRoot['To']?=?receivers[0]??
part?=?MIMEText(content)???
msgRoot.attach(part)??
##添加附件部分??
for?path?in?filepath:??
if?".jpg"?in?path:??
#jpg類型附件??
jpg_name?=?path.split("\\")[-1]??
part?=?MIMEApplication(open(path,'rb').read())???
part.add_header('Content-Disposition',?'attachment',?filename=jpg_name)??
msgRoot.attach(part)??
if?".pdf"?in?path:??
#pdf類型附件??
pdf_name?=?path.split("\\")[-1]??
part?=?MIMEApplication(open(path,'rb').read())???
part.add_header('Content-Disposition',?'attachment',?filename=pdf_name)???
msgRoot.attach(part)??
if?".xlsx"?in?path:??
#xlsx類型附件??
xlsx_name?=?path.split("\\")[-1]??
part?=?MIMEApplication(open(path,'rb').read())???
part.add_header('Content-Disposition',?'attachment',?filename=xlsx_name)??
msgRoot.attach(part)??
if?".txt"?in?path:??
#txt類型附件??
txt_name?=?path.split("\\")[-1]??
part?=?MIMEApplication(open(path,'rb').read())??
part.add_header('Content-Disposition',?'attachment',?filename=txt_name)??
msgRoot.attach(part)??
if?".mp3"?in?path:??
#mp3類型附件??
mp3_name?=?path.split("\\")[-1]??
part?=?MIMEApplication(open(path,'rb').read())???
part.add_header('Content-Disposition',?'attachment',?filename=mp3_name)???
msgRoot.attach(part)??
try:??
s?=?smtplib.SMTP()??
s.connect("smtp.mail.aliyun.com")?#這里我使用的是阿里云郵箱,也可以使用163郵箱:smtp.163.com??
s.login(sender,?passwd)??
s.sendmail(sender,?receivers,?msgRoot.as_string())??
print?("郵件發(fā)送成功")??
except?smtplib.SMTPException?as?e:??
print("Error,?發(fā)送失敗")??
finally:??
s.quit()
import xlrd
import os,time
#引入郵件相關(guān)庫
import smtplib
from email.mime.text import MIMEText
from email.header import Header
import base64
#處理從excel中讀取的float類型數(shù)據(jù)的類
#目前集成兩種處理:(1)float到int型的轉(zhuǎn)換(2)float到str型的轉(zhuǎn)換,后續(xù)有需要可以增加方法以集成其他類型的轉(zhuǎn)換
class judgeFloat:
def floatToInt(self,variable):
variable="%d"%variable
return variable
def floatToStr(self,variable):
variable=xlrd.xldate_as_tuple(variable,0)
variable=list(variable)
if variable[1]10:
variable[1]='0'+str(variable[1])
variable=str(variable[0])+str(variable[1])+str(variable[2])
return variable
#確定文檔是否修改的函數(shù):獲取文檔的修改時(shí)間與本地時(shí)間對比,不一致要求用戶確認(rèn)是否繼續(xù)執(zhí)行,一致則直接執(zhí)行
def openFile(filename,address):
filetime=time.strftime("%Y/%m/%d",time.localtime(os.stat(address+filename).st_mtime))
local=time.strftime("%Y/%m/%d",time.localtime())
if filetime!=local:
single=input("文檔今天還沒有修改過,請確認(rèn)是否繼續(xù)?確認(rèn)請輸入1后點(diǎn)擊回車,否則輸入2點(diǎn)擊回車。")
if single==1:
pass
elif single==2:
exit()
else:
print '您的輸入有誤!腳本即將結(jié)束。'
time.sleep(5)
exit()
else:
pass
#寫郵件的函數(shù)
def mailWrite(filename,address):
header='htmlheadmeta http-equiv="Content-Type" content="text/html; charset=utf-8" //head'
th='body text="#000000"committed缺陷詳情:table border="1" cellspacing="0" cellpadding="3" bordercolor="#000000" width="1800" align="left" tr bgcolor="#F79646" align="left" th標(biāo)識(shí)/thth摘要/thth狀態(tài)/thth優(yōu)先級/thth嚴(yán)重性/thth標(biāo)記/thth所有者/thth創(chuàng)建時(shí)間/thth修改時(shí)間/th/tr'
#打開文件
filepath=address+filename
book=xlrd.open_workbook(filepath)
sheet=book.sheet_by_index(0)
#獲取行列的數(shù)目,并以此為范圍遍歷獲取單元數(shù)據(jù)
nrows = sheet.nrows-1
ncols = sheet.ncols
body=''
cellData=1
for i in range(1,nrows+1):
td=''
for j in range(ncols):
#讀取單元格數(shù)據(jù),賦給cellData變量供寫入HTML表格中
cellData=sheet.cell_value(i,j)
#調(diào)用浮點(diǎn)型轉(zhuǎn)換方法解決讀取的日期內(nèi)容為浮點(diǎn)型數(shù)據(jù)的問題
if isinstance(cellData,float):
if j==0 and i0:
cellDataNew=judgeFloat()
cellData=cellDataNew.floatToInt(cellData)
else:
cellDataNew=judgeFloat()
cellData=cellDataNew.floatToStr(cellData)
else:
pass
tip='td'+cellData+'/td'
#并入tr標(biāo)簽
td=td+tip
tr='tr'+td+'/tr'
#為解決字符串拼接問題增設(shè)語句,tr從excel中讀取出來是unicode編碼,轉(zhuǎn)換成UTF-8編碼即可拼接
tr=tr.encode('utf-8')
#并入body標(biāo)簽
body=body+tr
tail='/table/body/html'
#將內(nèi)容拼接成完整的HTML文檔
mail=header+th+body+tail
return mail
#發(fā)送郵件
def mailSend(mail):
#設(shè)置發(fā)件人
sender = '***'
#設(shè)置接收人
receiver = '***@***.com'
#設(shè)置郵件主題
subject = '測試郵件,請忽略!'
#設(shè)置發(fā)件服務(wù)器,即smtp服務(wù)器
smtpserver = 'smtp.***.net'
#設(shè)置登陸名稱
username = '***@***.net'
#設(shè)置登陸密碼
password = '******'
#實(shí)例化寫郵件到正文區(qū),郵件正文區(qū)需要以HTML文檔形式寫入
msg = MIMEText(mail,'html','utf-8')
#輸入主題
msg['Subject'] = subject
#調(diào)用郵件發(fā)送方法,需配合導(dǎo)入郵件相關(guān)模塊
smtp = smtplib.SMTP()
#設(shè)置連接發(fā)件服務(wù)器
smtp.connect('smtp.***.net')
#輸入用戶名,密碼,登陸服務(wù)器
smtp.login(username, password)
#發(fā)送郵件
smtp.sendmail(sender, receiver, msg.as_string())
#退出登陸并關(guān)閉與發(fā)件服務(wù)器的連接
smtp.quit()
#入口函數(shù),配置文件地址和文件名
def main():
filename='Sheet1.xlsx'
address='d:/defectManage/'
openFile(filename,address)
mail=mailWrite(filename,address)
mailSend(mail)
#調(diào)用執(zhí)行main函數(shù)
if __name__=="__main__":
main()
眾所周知word/WPS中的郵件合并功能可以根據(jù)word模板從excel表格中讀取數(shù)據(jù),進(jìn)而生成不同的文件
但Excel卻沒有這個(gè)功能,如果需要根據(jù)excel表格模板生成不同文件的話,手動(dòng)填寫就顯得很麻煩
舉例:需對1、2圖片模板表格的2個(gè)sheet中所有'{姓名}'、'{案卷號}'修改為第3個(gè)圖片表格的數(shù)據(jù),按姓名保存為不同文件
使用程序讀取數(shù)據(jù)excel表格,對固定模板e(cuò)xcel表格指定內(nèi)容進(jìn)行替換,并生成文件,就是一個(gè)比較好的選擇
實(shí)際使用中,模板e(cuò)xcel表格中單個(gè)單元格內(nèi),可能有多個(gè)需要替換的內(nèi)容,為便于使用,單獨(dú)將字符串替換功能寫為函數(shù)
xlrd模塊,常用于讀取xls和xlsx格式excel表格
xlwt模塊,常用于寫入xls格式excel表格
xlutils模塊,可將xlrd.Book對象轉(zhuǎn)為xlwt.Workbook對象,從而實(shí)現(xiàn)對已有excel表格的寫入功能
方法1只能生成xls格式excel表格,如果需要生成xlsx格式,參考方式2
openpyxl模塊,常用于讀取、寫入xlsx格式excel表格
pywin32模塊可以直接調(diào)用Excel程序,試驗(yàn)使用該模塊實(shí)現(xiàn)以上功能
既然試驗(yàn)了pywin32調(diào)用Excel程序?qū)崿F(xiàn)郵件合并功能,為什么不直接在Excel中使用VBA呢?
由上篇文章我們已經(jīng)得知郵件從發(fā)送到接收的過程:
發(fā)件人-MUA-MTA-若干MTA-MDA-MUA-收件人
本節(jié)接收郵件主要就是編寫一個(gè) MUA 客戶端,從 MDA 將郵件取回本地。
收取郵件最常用的是 POP協(xié)議 ,目前版本是第三版,也稱 POP3 。python內(nèi)置了 poplib 模塊,支持POP3協(xié)議。
回想上一節(jié) SMTP ,我們對要發(fā)送的郵件內(nèi)容進(jìn)行了各種編碼,包括添加MIME header,編碼之后再進(jìn)行發(fā)送。
因此,我們通過POP3協(xié)議接收的也不是原內(nèi)容,而是經(jīng)過一系列編碼等處理的文本。
所以,要想把POP3收取的文本變?yōu)榭砷喿x的郵件對象,就需要利用 email 模塊對原始郵件進(jìn)行解析。
所以,郵件收取的流程就是:
由上一篇 文章 最后總結(jié)部分可知。郵件由字符到發(fā)送到網(wǎng)絡(luò)經(jīng)歷了如下的格式轉(zhuǎn)化:
純文本:
str-bytes-base64-str-bytes
二進(jìn)制文件:
binary code-base64-str-bytes
我們解析郵件也是按這個(gè)思路,逆序解析出內(nèi)容。
這里的 decode('utf-8') 先把字節(jié)流轉(zhuǎn)化為字符串,再將字符串轉(zhuǎn)化為 message 結(jié)構(gòu)的對象。這步與發(fā)送郵件的 as_string 函數(shù)相反。
先從上一節(jié)結(jié)構(gòu)化的 msg 中取出信件頭,打印出來。
如果是 multipart 結(jié)構(gòu), get_payload 函數(shù)會(huì)返回一個(gè)包含不同part的list,然后對每一part遞歸調(diào)用 print_info ,打印子信件頭和子信件內(nèi)容。
不是 multipart 時(shí),之后再依據(jù) Content-Type 作不同處理:
如果是 text :
利用 get_payload(decode = Ture) 取出子信件的內(nèi)容, decode 為True,則按照 Content-Transfer-Type 將 base64 或 QP 解碼為 bytes 。
再 guess_charset 猜出編碼方式,之后將其解碼為字符顯示。
如果不是 Text 對象,則為附件:
打印出附件的 Content-Type 。
函數(shù)如下:
使用正則表達(dá)式對輸入的字符串進(jìn)行驗(yàn)證
import?re
def?validateEmail(email):
if?len(email)??7:
if?re.match("^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$",?email)?!=?None:
return?1
return?0