最近设计了一个小的应用程序,主要是根据文件中邮件地址发送一份excel中内容,并且在接受方收到邮件都是以网页的格式呈现的。
下面主要是对python发送邮件涉及到的部分知识点做个总结
一、先介绍一下Smtp协议和POP3协议
SMTP (Simple Mail Transfer Protocol)
http://www.rfc-editor.org/info/rfc821 RFC821文档详细描述了这个协议信息;
邮件传送代理 (Mail Transfer Agent,MTA) 程序使用SMTP协议来发送电邮到接收者的邮件服务器。SMTP协议只能用来发送邮件,不能用来接收邮件。大多数的邮件发送服务器 (Outgoing Mail Server) 都是使用SMTP协议。SMTP协议的默认TCP端口号是25。
SMTP协议的一个重要特点是它能够接力传送邮件。它工作在两种情况下:一是电子邮件从客户机传输到服务器;二是从某一个服务器传输到另一个服务器。
POP3 (Post Office Protocol) & IMAP (Internet Message Access Protocol)
POP协议和IMAP协议是用于邮件接收的最常见的两种协议。几乎所有的邮件客户端和服务器都支持这两种协议。
POP3协议为用户提供了一种简单、标准的方式来访问邮箱和获取电邮。使用POP3协议的电邮客户端通常的工作过程是:连接服务器、获取所有信息并保存在用户主机、从服务器删除这些消息然后断开连接。POP3协议的默认TCP端口号是110。
IMAP协议也提供了方便的邮件下载服务,让用户能进行离线阅读。使用IMAP协议的电邮客户端通常把信息保留在服务器上直到用户显式删除。这种特性使得多个客户端可以同时管理一个邮箱。IMAP协议提供了摘要浏览功能,可以让用户在阅读完所有的邮件到达时间、主题、发件人、大小等信息后再决定是否下载。IMAP协议的默认TCP端口号是143。
二、模块介绍
在python发送邮件主要涉及到两个模块:smtplib和email模块
1、smtplib模块
这个模块提供的功能主要是:
链接smtp服务器
登入smtp服务器
发送邮件
http://www.cnpaf.net/Class/SMTP/200408/106.html
smtplib.SMTP([host[, port[, local_hostname[, timeout]]]])
SMTP类构造函数,表示与SMTP服务器之间的连接,通过这个连接我们可以向smtp服务器发送指令,执行相关操作(如:登陆、发送邮件)。 该类提供了许多方法,将在下面介绍。它的所有参数都是可选的,其中host参数表示smtp服务器主机名,上面例子中的smtp主机 为"smtp.yeah.net";port表示smtp服务的端口,默认是25;如果在创建SMTP对象的时候提供了这两个参数,在初始化的时候会自动 调用connect方法去连接服务器。
smtplib模块还提供了SMTP_SSL类和LMTP类,对它们的操作与SMTP基本一致。
smtplib.SMTP提供的方法:
SMTP.set_debuglevel(level)
设置是否为调试模式。默认为False,即非调试模式,表示不输出任何调试信息。
SMTP.connect([host[, port]])
连接到指定的smtp服务器。参数分别表示smpt主机和端口。注意: 也可以在host参数中指定端口号(如:smpt.yeah.net:25),这样就没必要给出port参数。
SMTP.docmd(cmd[, argstring])
向smtp服务器发送指令。可选参数argstring表示指令的参数。
2、email模块
这个模块设计邮件格式的
以及如何设置发送各种复杂的邮件(附件,图片,音频等等网页格式等等)
3、代码实现
# encoding: utf-8import sysimport osimport timeimport xlrdimport smtplibfrom email.mime.text import MIMETextfrom email.utils import COMMASPACE,formatdatefrom email import encodersreload(sys)sys.setdefaultencoding('utf8')def readFileFormal(fileName): data= xlrd.open_workbook(fileName)# 读excel文件 table = data.sheet_by_name(u'Sheet1')# 获取一个工作表 有多种方法 rownum = table.nrows colnum = table.ncols flag = False #获取表格的标题 title = table.cell(0,0).value if colnum != 16: flag = True return flag #将execl中数据形成html格式def produceHtml(baseinfo,deductinfo,rowdata): content = '''<table border="0" cellpadding="0" cellspacing="0" width="1267" style="border-collapse:collapse;width:950pt"> <colgroup><col width="72" style="width:54pt"/> <col width="79" span="2" style="mso-width-source:userset;mso-width-alt:2528;width:59pt"/> <col width="72" span="2" style="width:54pt"/> <col width="72" span="10" style="width:54pt"/> <col width="173" style="mso-width-source:userset;mso-width-alt:5536;width:130pt"/> </colgroup><tbody><tr height="19" style="mso-height-source:userset;height:14.25pt"> <td rowspan="2" height="38" class="xl76" width="72" style="height: 28.5pt; width: 54pt; padding-top: 1px; padding-right: 1px; padding-left: 1px; color: windowtext; font-size: 10pt; font-family: 宋体; vertical-align: middle; border: 0.75pt solid windowtext; white-space: nowrap; text-align: center;">姓名</td> <td rowspan="2" class="xl71" width="79" style="width: 59pt; padding-top: 1px; padding-right: 1px; padding-left: 1px; font-size: 10pt; font-family: 宋体; vertical-align: middle; border: 0.75pt solid windowtext; text-align: center;">学号</td> <td rowspan="2" class="xl71" width="79" style="width: 59pt; padding-top: 1px; padding-right: 1px; padding-left: 1px; font-size: 10pt; font-family: 宋体; vertical-align: middle; border: 0.75pt solid windowtext; text-align: center;">成绩</td><td> </tbody></table>''' return content #发送邮件def send_mail(mail_host,mail_user,mail_password,receiveAdd,subject,content):#receiveAdd:收件人;subject:主题;content:邮件内容 flag = False info = '' sender=mail_user+"<"+mail_user+">" #这里的hello可以任意设置,收到信后,将按照设置显示 msg = MIMEText(content,_subtype='html',_charset='utf-8') #创建一个实例,这里设置为html格式邮件 msg['Subject'] = subject #设置主题 msg['From'] = sender msg['To'] = receiveAdd try: s = smtplib.SMTP() s.connect(mail_host)#连接smtp服务器 s.login(mail_user,mail_password)#登陆服务器 s.sendmail(sender, receiveAdd, msg.as_string())#发送邮件 s.close() flag = True except Exception, e: #print str(e) info = str(e) flag = False return flag,infodef start(mailhost,mailuser,mailpassword,filename): baseinfo,deductinfo,alldata,title= readFile(filename) stateinfo=[] for i in range(len(alldata)): rowdata = alldata[i] content = produceHtml(baseinfo,deductinfo,rowdata) #这里的baseinfo 与 defuctinfo可以直接定死吗? receiveadd = rowdata[len(rowdata)-1] #print receiveadd if receiveadd != '': flag,info = send_mail(mailhost,mailuser,mailpassword,receiveadd,title,content) if flag: #printreceiveadd+" "+"发送成功"+" "+ time.ctime(time.time()) sendinfo = receiveadd+" "+"发送成功"+" "+ time.ctime(time.time()) else: #print "发送失败" sendinfo = '发送失败' else: #print ('此联系人地址不存在!!') sendinfo = '此联系人地址不存在!!' stateinfo.append(sendinfo) producetxt(stateinfo)#生成日志文件 主要是记录发送邮件的时间和信息def producetxt(info): timeinfo =time.strftime('%Y-%m-%d(%X)',time.localtime(time.time())) filename = os.getcwd() filename =filename +'/'+timeinfo+ '.txt' filename = 'logfile'+'.txt' f = open(filename,'a') for i in range(len(info)): f.write(info[i]+'/n') f.close()def issendmail(mail_host,mail_user,mail_password):#receiveAdd:收件人;subject:主题;content:邮件内容 flag = False info = '' try: s = smtplib.SMTP() s.connect(mail_host)#连接smtp服务器 s.login(mail_user,mail_password)#登陆服务器 s.close() flag = True except Exception, e: #print str(e) info = str(e) flag = False return flag,info#检验发件者的邮件是否可以登入到服务器,判断验证是否成功
def isExisting(user,password): flag = False # ostrich="smtp.163.com"#设置服务器 # user="iphonexb@163.com" #用户名 # password="iphonexiaoxiao55" #口令 host = user.strip('') hostlist = host.split('@') host = hostlist[1] host = 'smtp.'+host #print host flag ,info= issendmail(host,user,password) #print flag,info return flag#def initValue(user,password,filenameStr): host = user.strip('') hostlist = host.split('@') host = hostlist[1] host = 'smtp.'+host mailhost = host #设置服务器 mailuser = user #用户名 mailpassword=password #口令 filename = filenameStr start(mailhost,mailuser,mailpassword,filename)'''if __name__ == "__main__": print #isExisting() mail_host="smtp.163.com"#设置服务器 mail_user="xxx@163.com" #用户名 mail_password="xxxxx" #口令 mail_postfix="163.com"#发件箱的后缀 filename = '成绩.xls' start(mail_host,mail_user,mail_password,filename)'''
界面如图一二
验证错误
三、在程序实现过程中会出现各样的错误:
http://blog.csdn.net/mindmb/article/details/7898528
解决UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xe5 in position 108: ordinal not in range(128
http://www.oschina.net/code/snippet_111708_15987
如果是认证失败,登入服务器时密码账号有问题
(535, 'authentication failed 95187d9c-ee91-45a9-b7d5-c495c23abbd7’)
4 Authentication failed, please open smtp flag first!
http://blog.csdn.net/bruce128/article/details/8761949
(535, 'Error: authentication failed')
http://bbs.chinaunix.net/thread-717982-1-1.html
(454, 'Error: authentication failed, system busy')
一般情况,为了保障用户邮箱的安全,QQ邮箱设置了POP3/SMTP的开关。系统缺省设置是“关闭”,在用户需要POP3/SMTP功能时请“开启”。关闭POP3/SMTP后,您将只能接受邮件,不能发送邮件。
如果不是因为设置问题,试试QQ重新更改下登录密码。这时邮箱密码需要重新设置。
如果重设后没有用,可以考虑过几天试试,有可能QQ的邮件服务器认为你发的邮件为垃圾邮件。网上搜索的答案中,目前没有个定论,但是在QQ邮箱中,这种情况也是多见的。
还有呢,可以试试换个别的邮件客户端KOOMAIL。
用163.com的smtp服务器比较稳定,qq的出现不知道的问题
http://www.altn.cn/qa/ec/qa_ec_mta.htm 邮件服务器常见错误代码解释
以上错误发送都是有关smtp服务器认证出现。
相关链接:
https://docs.python.org/2/library/email-examples.html 官方例子
http://www.jb51.net/article/49216.htm
http://my.oschina.net/dillan/blog/133344 smtplib和 email模块的介绍
http://blog.csdn.net/goof/article/details/7921851
http://www.cnblogs.com/lonelycatcher/archive/2012/02/09/2343480.html
http://www.cnblogs.com/xiaowuyi/archive/2012/03/17/2404015.html
http://bbs.chinaunix.net/thread-836514-1-1.html login错误
//原文:
http://blog.csdn.net/liuxb1223/article/details/39588129