python编写邮件_python编写客户端smtp,pop3收发邮件的综合应用

这个程序的构思大概有一个多星期。逐个解决功能应用问题,最简单是发送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.org-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 = re.compile(r']+>', re.S)

dd = dr.sub('', html)

dr = re.compile(r'<|&gt|\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.com'

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()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值