邮件"/>
python编写邮件
这个程序的构思大概有一个多星期。逐个解决功能应用问题,最简单是发送sendMail,MiMEtext信息以后就可以发送;其次比较复杂的是实现收取邮件信息后的读取和处理,有三个难题,一是正文部分往往会有多层嵌套,二是模块支持比较好IMAPLIB只支持2.7版本,三是文本的编码问题。目前这个版本用的是pop3协议以POPLIB模块收取后,以自带的EMAIL模块去解析。这段代码主要编辑了网上大咖的代码(增加了返回信息和部分编码处理),并非原创。第三个设想是应用,就是我儿子在做好英语练习系统以后,在shell中再增加一行代码,调用py文件,自动执行查询分数,并通过邮件发送分数结果的功能。
这个实际应用很有意思,另一方面也说明,邮件作为通知功能,可以应用的范围很广。总体架构上是三个类。一个类是邮件类,解决邮件收发问题;第二个类是数据库类,解决数据查询问题;第三个类是实际应用类,组合邮件和数据表类,解决何时及如何发送邮件问题。在这个例子中,邮件收发功能都被封装,需要发送只需要知道发送对象、主题和内容就可以。对于邮件密码等重要信息,也单独写了一个类,可以适用于不同的操作系统。数据库类作了适当的修订,兼顾以前的功能,增加了现有查询需求。
在网上收集邮件处理主要是解析邮件的时候,看到一点评论说,程序结构很重要。在写这个程序的时候,觉得这是一个很重要的思想。比如一个程序,里面有些功能需要模块化,以便有更清晰、更容易把握的结构,所以可以把这个功能在现有功能里面定义;如果这个功能会被多次复用,则另外单独在类之中或者另外以类封装。这样的架构是清楚的。比如Mail类中有InboxMailRead函数,print_info不能被其他函数所调用,所以是下面的次一级函数。要处理邮件的多层嵌套问题,print_info用递归处理信息,所以递归函数的参数,在使用时应该十分注意,初始值一般是空值;在递归环节,参数值应该准确反映前后递归值的关系。同样的,import应该在函数中而不是在函数之外。这不论是从效率上还是结构上都是有益的。
以下代码在python3.6 ,os环境下实测可以使用;emialPass类注意要将*****替换为自己实际的用户、密码;数据表处理没有放出,实际上与邮件收发关系不大,只是博主自己的应用。
class LeoEmail:
def __init__(self):
print("这是everyang-LEO邮件的封装")
print("***************************************")
print("1+收邮件,返回一个列表,每个元素包括发件人、收件人、主题的字典和一个内容文本")
print("2-发邮件,参数为收件人、主题、内容")
print("***************************************")
def sendMail(self,toWho, subject, content):
import smtplib
from email.mime.text import MIMEText
#import emailMesagePass # 这是博主自己写一个封装用户、密码的类
myMsg = emailMesagePass.emailPass()
mail_host, mail_user, mail_postfix, mail_pass, mail_simpleName = myMsg.outputSmtp()
emailAddr = mail_user + "@" + mail_postfix
me = mail_simpleName + ""
msg = MIMEText(content, _subtype='plain')
msg['Subject'] = subject
msg['From'] = me
msg['To'] = toWho
try:
smtpObj = smtplib.SMTP(mail_host)
smtpObj.ehlo()
smtpObj.starttls()
smtpObj.login(emailAddr,mail_pass)
smtpObj.sendmail(me,toWho,msg=msg.as_string())
smtpObj.quit()
except:
print('抱歉,邮件未能成功发送,请检查设置!')
return False
else:
print('Mail has been sent successfully!')
return True
def InboxEmailRead(self):
def print_info(msg, indent=0, blankStr='', VipMessage={}):
from email.header import decode_header
from email.utils import parseaddr
import pprint
def decode_str(s):
value, charset = decode_header(s)[0]
if charset:
value = value.decode(charset)
return value
def guess_charset(msg):
charset = msg.get_charset()
if charset is None:
content_type = msg.get('Content-Type', '').lower()
pos = content_type.find('charset=')
if pos >= 0:
charset = content_type[pos + 8:].strip()
return charset
def htmlElimating(html):
import re
dr = repile(r']+>', re.S)
dd = dr.sub('', html)
dr = repile(r'<|>|\r|\n| ', re.S)
dd = dr.sub('', dd)
return dd
if isinstance(msg, bytes):
msg = decode_str(msg)
if indent == 0:
for header in ['From', 'To', 'Subject']:
value = msg.get(header, '')
if value:
if header == 'Subject':
value = decode_str(value)
else:
hdr, addr = parseaddr(value)
name = decode_str(hdr)
value = u'%s ' % (name, addr)
print('%s%s: %s' % (' ' * indent, header, value))
VipMessage[header] = value
if (msg.is_multipart()):
parts = msg.get_payload()
for n, part in enumerate(parts):
blankStr, VipMessage = print_info(part, indent + 1, blankStr, VipMessage)
else:
content_type = msg.get_content_type()
if content_type == 'text/plain' or content_type == 'text/html':
content = msg.get_payload(decode=True)
charset = guess_charset(msg)
if charset:
content = content.decode(charset)
content = htmlElimating(content)
print("Text:")
pprint.pprint(content)
blankStr += content
else:
# 不是文本,作为附件处理:
print("附件出现!")
print('%sAttachment: %s' % (' ' * indent, content_type))
return blankStr, VipMessage
import poplib
from email.parser import Parser
import emailMesagePass
myMsg = emailMesagePass.emailPass()
host, user, postfix, password = myMsg.outputPop()
username = user + '@' + postfix
resultList = []
try:
pop_conn = poplib.POP3_SSL(host)
pop_conn.user(username)
pop_conn.pass_(password)
except:
print('无法通过pop3登陆邮箱')
exit(1)
else:
print(username + ',邮箱已经连接!')
resp, mails, octets = pop_conn.list()
for index in range(len(mails),0,-1):
print("*********************************")
print("*第%d封邮件:"%(index))
resp, lines, octets = pop_conn.retr(index)
linesStr = [bytes.decode(x) for x in lines]
msg_content = '\n'.join(linesStr)
msg = Parser().parsestr(msg_content)
thisMail = print_info(msg, indent=0, blankStr='', VipMessage={})
print('已读取邮件信息!\n')
resultList.append(thisMail)
pop_conn.close()
return resultList
class emailPass:
def __init__(self):
self.filePath = self.judgePath()
self.openShelveFile()
self.Email = self.openShelveFile()
def judgePath(self): # 在当前目录下
import os
filePath = os.path.abspath(os.curdir)
fileName = '*************'
return filePath + os.sep + fileName
def openShelveFile(self):
import shelve
try:
shelveFile = shelve.open(self.filePath)
except:
print('无法打开email数据表')
return None
else:
if 'Email' not in shelveFile.keys():
Email = {}
Email['smtpHost'] = '*************'
Email['pop3Host'] = '*************'
Email['user'] = '*************'
Email['pass'] = '*************'
Email['postfix'] = '*************'
Email['simpleName'] = '*************'
shelveFile['Email'] = Email
shelveFile.close()
else:
Email = shelveFile['Email']
return Email
def outputSmtp(self):
return self.Email['smtpHost'], self.Email['user'], self.Email['postfix'], self.Email['pass'], self.Email['simpleName']
def outputPop(self):
return self.Email['pop3Host'], self.Email['user'], self.Email['postfix'], self.Email['pass']
# 如果查询到今天到成绩则发一封邮件给dady
class noticeMark:
def __init__(self):
self.msgs = self.getMessage()
self.sendMailToDady()
def judgeToday(self,dateStr):
import time
nowDate = time.strftime("%Y-%m-%d", time.localtime())
return True if dateStr == nowDate else False
def getMessage(self):
import sqliteAbout
db = sqliteAbout.markViewClass()
data = db.queryTodayTest()
mark = db.tranDataToDraw(data)
msgs = {}
msgs['date'] = mark[0][0]
msgs['score'] = mark[1][0]
msgs['nums'] = mark[2][0]
print(msgs)
return msgs
def scoreValue(self,score):
if score > 100:
return '完美!'
elif score > 95:
return '优秀!'
elif score > 90:
return '良好!'
elif score >85:
return '不错!'
else:
return '不大理想!'
def sendMailToDady(self):
if self.judgeToday(self.msgs['date']):
import emailAbout_h, time
myMail = emailAbout_h.LeoEmail()
towho = 'm18655759211@163'
subject = '英语今天测试成绩' + str(self.msgs['score'])
content = '爸爸您好!\n我今天(' + self.msgs['date'] + ')的英语练习系统平均测试成绩是' + subject + '。\n一共做了' + str(self.msgs['nums']) + '个题目\n'
content += '今天的成绩自动评价是' + self.scoreValue(self.msgs['score'])
content += '\n这是来自您写的程序的自动报告' + '\n' + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
myMail.sendMail(towho, subject, content)
new = noticeMark()
更多推荐
python编写邮件
发布评论