参考简书,廖雪峰python
import smtplib
import os
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import traceback
import time
def send(self,content=None):
'''''
发送邮件
'''
server = None
index = 1 #邮件重试
while index < 3:
index += 1
try:
server = smtplib.SMTP_SSL("smtp.exmail.qq.com",port=465)
server.login(self.user,self.passwd)
server.sendmail("<%s>" % self.user, self.to_list + self.cc_list, self.get_attach(content=content))
server.close()
print("send email successful")
break
except Exception as e:
traceback.print_exc()
time.sleep(5)
print("send email failed")
finally:
try:
if server is not None:
server.close()
except Exception as e:
traceback.print_exc()
def get_attach(self,content=None,subtype='html'):
'''''
构造邮件内容
'''
attach = MIMEMultipart()
#添加邮件内容
txt = MIMEText(content, _subtype=subtype, _charset='utf-8')
attach.attach(txt)
if self.subject is not None:
#主题,最上面的一行
attach["Subject"] = self.subject
if self.user is not None:
#显示在发件人
attach["From"] = "Data Team<%s>" % self.user
if self.to_list:
attach["To"] = ";".join(self.to_list)#收件人列表
if self.cc_list:
attach["Cc"] = ";".join(self.cc_list)#抄送列表
if self.doc:
#估计任何文件都可以用base64,比如rar等
#文件名汉字用gbk编码代替
name = os.path.basename(self.doc).encode("gbk")
f = open(self.doc,"rb")
doc = MIMEText(f.read(), "base64", "gb2312")
doc["Content-Type"] = 'application/octet-stream'
doc["Content-Disposition"] = 'attachment; filename="' + name +'"'
attach.attach(doc)
f.close()
return attach.as_string()
def get_jobs_descript(self):
"""
获取任务的执行str
:return:
"""
html ='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
html += '<html xmlns="http://www.w3.org/1999/xhtml">'
html += '<head>'
html += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />'
html += '<title>调度报告</title>'
html += '<meta name="viewport" content="width=device-width, initial-scale=1.0"/>'
html +='</head>'
html +='<body>'
till = str(datetime.datetime.now() - self.start_time)
till = till[0:till.index(".")] #精确到秒级小数点,然后要自己弄好,
html +='<p>启动时间:[' + self.start_time.strftime("%Y-%m-%d %H:%M:%S") +'] 结束时间:[' + self.get_end_time_str() +'] 持续时间:'+till+'</p>'
ss = 0
er = 0
skip = 0
run_c = 0
pl = ''
for job_name in self.job_run_:
node = self.dag_job.get_node(job_name=job_name)
if node.status == 1:
if node.is_active == False:
skip += 1
else:
ss += 1
elif node.status == -1:
er += 1
elif node.status == 0:
run_c += 1
pl += node.get_job_mail_str()
html +="<h2>统计 [成功:" + str(ss) +' 错误:' + str(er)+' 跳过:'+str(skip)+' 未执行:' + str(self.job_size - ss - er - skip)+'] 总任务数: ' + str(self.job_size)+'<h2>'
html +='<h1>邮件发送时间:' + str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M')) +'</h1>'
html += '<h1>调度报告</h1>'
html +='<table border="1" cellpadding="0" cellspacing="0">'
html +='<thead bgcolor="#A9A9A9" style="color:#000000; text-align:left; font-size:14px; font-weight:bold; margin-left:220px;text-align:center">'
html +='<tr>'
html +='<th>状态</th>'
html +='<th>任务名</th>'
html +='<th>创建时间</th>'
html +='<th>结束时间</th>'
html +='<th>持续时间</th>'
html +='<th>重试次数</th>'
html +='<th>重试上限</th>'
html +='<th>是否跳过</th>'
html +='<th>一定正确</th>'
html +='<th>优先级</th>'
html +='</tr>'
html +='</thead>'
html +='<tbody>'
html += pl
html +='</tbody></table></body></html>'
return html
def get_job_mail_str(self):
"""
获取发送邮件的行数
:return:
"""
sz = "<tr>"
if self.start_time is None:
sz += "<td>SKIP</td><td>" + self.name +'</td><td></td><td></td><td></td></tr>'
else:
if self.status == 1:
sz += "<td><font color="blue">SUCCEED</font></td><td>" + self.name+'</td>'
elif self.status ==-1:
sz += "<td><font color="red">ERROR</font></td><td>" + self.name+'</td>'
elif self.status ==0:
sz += "<td><font color="green">RUNNING</font></td><td>" + self.name+'</td>'
elif self.status is None:
sz += "<td><font color="black">NOT_RUN</font></td><td>" + self.name+'</td>'
if self.start_time is not None:
sz +='<td>' + self.start_time.strftime('%Y-%m-%d %H:%M:%S')+'</td>'
else:
sz +='<td></td>'
if self.end_time is not None:
sz +='<td>'+self.end_time.strftime('%Y-%m-%d %H:%M:%S') +'</td>'
else:
sz +='<td></td>'
if self.start_time is None or self.end_time is None:
sz +='<td></td>'
else:
plz = str(self.end_time - self.start_time)
if plz.index(':') == 1:
sz += '<td>0' + str(self.end_time - self.start_time)[0:7] +'</td>'
else:
sz += '<td>' + str(self.end_time - self.start_time)[0:8] +'</td>'
sz += '<td>' + str(self.retry_time) + '</td>'
sz += '<td>' + str(self.retry_limit) + '</td>'
if self.is_active:
sz +='<td></td>'
else:
sz += '<td><font color="red">' + str(self.is_active == False) +'</font></td>'
if self.forver_right:
sz += '<td><font color="red">' + str(self.forver_right == True) +'</font></td>'
else:
sz += '<td></td>'
sz += '<td>' + str(self.priority) +'</td>'
sz += '</tr>'
return sz