python的smtplib提供了一种很方便的途径发送电子邮件。它对smtp协议进行了简单的封装。
smtp协议的基本命令包括:
HELO 向服务器标识用户身份
MAIL 初始化邮件传输 mail from:
RCPT 标识单个的邮件接收人;常在MAIL命令后面,可有多个rcpt to:
DATA 在单个或多个RCPT命令后,表示所有的邮件接收人已标识,并初始化数据传输,以.结束
VRFY 用于验证指定的用户/邮箱是否存在;由于安全方面的原因,服务器常禁止此命令
EXPN 验证给定的邮箱列表是否存在,扩充邮箱列表,也常被禁用
HELP 查询服务器支持什么命令
NOOP 无操作,服务器应响应OK
QUIT 结束会话
RSET 重置会话,当前传输被取消
MAIL FROM 指定发送者地址
RCPT TO 指明的接收者地址
一般smtp会话有两种方式,一种是邮件直接投递,就是说,比如你要发邮件給zzz@163.com,那就直接连接163.com的邮件服务器,把信投給zzz@163.com; 另一种是验证过后的发信,它的过程是,比如你要发邮件給zzz@163.com,你不是直接投到163.com,而是通过自己在sina.com的另一个邮箱来发。这样就要先连接sina.com的smtp服务器,然后认证,之后在把要发到163.com的信件投到sina.com上,sina.com会帮你把信投递到163.com。
第一种方式的命令流程基本是这样:
1. helo
2. mail from
3. rcpt to
4. data
5. quit
但是第一种发送方式一般有限制的,就是rcpt to指定的这个邮件接收者必须在这个服务器上存在,否则是不会接收的。 先看看代码:
#-*- encoding: gb2312 -*- import os, sys, string import smtplib # 邮件服务器地址 mailserver = "smtp.163.com" # smtp会话过程中的mail from地址 from_addr = "asfgysg@zxsdf.com" # smtp会话过程中的rcpt to地址 to_addr = "zhaoweikid@163.com" # 信件内容 msg = "test mail" svr = smtplib.SMTP(mailserver) # 设置为调试模式,就是在会话过程中会有输出信息 svr.set_debuglevel(1) # helo命令,docmd方法包括了获取对方服务器返回信息 svr.docmd("HELO server") # mail from, 发送邮件发送者 svr.docmd("MAIL FROM: <%s>" % from_addr) # rcpt to, 邮件接收者 svr.docmd("RCPT TO: <%s>" % to_addr) # data命令,开始发送数据 svr.docmd("DATA") # 发送正文数据 svr.send(msg) # 比如以 . 作为正文发送结束的标记,用send发送的,所以要用getreply获取返回信息 svr.send(" . ") svr.getreply() # 发送结束,退出 svr.quit()
注意的是,163.com是有反垃圾邮件功能的,想上面的这种投递邮件的方法不一定能通过反垃圾邮件系统的检测的。所以一般不推荐个人这样发送。
第二种有点不一样:
1.ehlo
2.auth login
3.mail from
4.rcpt to
5.data
6.quit
相对于第一种来说,多了一个认证过程,就是auth login这个过程。
#-*- encoding: gb2312 -*- import os, sys, string import smtplib import base64 # 邮件服务器地址 mailserver = "smtp.163.com" # 邮件用户名 username = "xxxxxx@163.com" # 密码 password = "xxxxxxx" # smtp会话过程中的mail from地址 from_addr = "xxxxxx@163.com" # smtp会话过程中的rcpt to地址 to_addr = "yyyyyy@163.com" # 信件内容 msg = "my test mail" svr = smtplib.SMTP(mailserver) # 设置为调试模式,就是在会话过程中会有输出信息 svr.set_debuglevel(1) # ehlo命令,docmd方法包括了获取对方服务器返回信息 svr.docmd("EHLO server") # auth login 命令 svr.docmd("AUTH LOGIN") # 发送用户名,是base64编码过的,用send发送的,所以要用getreply获取返回信息 svr.send(base64.encodestring(username)) svr.getreply() # 发送密码 svr.send(base64.encodestring(password)) svr.getreply() # mail from, 发送邮件发送者 svr.docmd("MAIL FROM: <%s>" % from_addr) # rcpt to, 邮件接收者 svr.docmd("RCPT TO: <%s>" % to_addr) # data命令,开始发送数据 svr.docmd("DATA") # 发送正文数据 svr.send(msg) # 比如以 . 作为正文发送结束的标记 svr.send(" . ") svr.getreply() # 发送结束,退出 svr.quit()
上面说的是最普通的情况,但是不能忽略的是现在好多企业邮件是支持安全邮件的,就是通过SSL发送的邮件,这个怎么发呢?SMTP对SSL安全邮件的支持有两种方案,一种老的是专门开启一个465端口来接收ssl邮件,另一种更新的做法是在标准的25端口的smtp上增加一个starttls的命令来支持。
看看第一种怎么办:
#-*- encoding: gb2312 -*- import os, sys, string, socket import smtplib class SMTP_SSL (smtplib.SMTP): def __init__(self, host='', port=465, local_hostname=None, key=None, cert=None): self.cert = cert self.key = key smtplib.SMTP.__init__(self, host, port, local_hostname) def connect(self, host='localhost', port=465): if not port and (host.find(':') == host.rfind(':')): i = host.rfind(':') if i >= 0: host, port = host[:i], host[i+1:] try: port = int(port) except ValueError: raise socket.error, "nonnumeric port" if not port: port = 654 if self.debuglevel > 0: print>>stderr, 'connect:', (host, port) msg = "getaddrinfo returns an empty list" self.sock = None for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM): af, socktype, proto, canonname, sa = res try: self.sock = socket.socket(af, socktype, proto) if self.debuglevel > 0: print>>stderr, 'connect:', (host, port) self.sock.connect(sa) # 新增加的创建ssl连接 sslobj = socket.ssl(self.sock, self.key, self.cert) except socket.error, msg: if self.debuglevel > 0: print>>stderr, 'connect fail:', (host, port) if self.sock: self.sock.close() self.sock = None continue break if not self.sock: raise socket.error, msg # 设置ssl self.sock = smtplib.SSLFakeSocket(self.sock, sslobj) self.file = smtplib.SSLFakeFile(sslobj); (code, msg) = self.getreply() if self.debuglevel > 0: print>>stderr, "connect:", msg return (code, msg) if __name__ == '__main__': smtp = SMTP_SSL('192.168.2.10') smtp.set_debuglevel(1) smtp.sendmail("zzz@xxx.com", "zhaowei@zhaowei.com", "xxxxxxxxxxxxxxxxx") smtp.quit()
这里我是从原来的smtplib.SMTP派生出了新的SMTP_SSL类,它专门来处理ssl连接。我这里测试的192.168.2.10是我自己的测试服务器.
第二种是新增加了starttls的命令,这个很简单,smtplib里就有这个方法,叫smtplib.starttls()。当然,不是所有的邮件系统都支持安全邮件的,这个需要从ehlo的返回值里来确认,如果里面有starttls,才表示支持。相对于发送普通邮件的第二种方法来说,只需要新增加一行代码就可以了:
#-*- encoding: gb2312 -*- import os, sys, string import smtplib import base64 # 邮件服务器地址 mailserver = "smtp.163.com" # 邮件用户名 username = "xxxxxx@163.com" # 密码 password = "xxxxxxx" # smtp会话过程中的mail from地址 from_addr = "xxxxxx@163.com" # smtp会话过程中的rcpt to地址 to_addr = "yyyyyy@163.com" # 信件内容 msg = "my test mail" svr = smtplib.SMTP(mailserver) # 设置为调试模式,就是在会话过程中会有输出信息 svr.set_debuglevel(1) # ehlo命令,docmd方法包括了获取对方服务器返回信息,如果支持安全邮件,返回值里会有starttls提示 svr.docmd("EHLO server") svr.starttls() # <------ 这行就是新加的支持安全邮件的代码! # auth login 命令 svr.docmd("AUTH LOGIN") # 发送用户名,是base64编码过的,用send发送的,所以要用getreply获取返回信息 svr.send(base64.encodestring(username)) svr.getreply() # 发送密码 svr.send(base64.encodestring(password)) svr.getreply() # mail from, 发送邮件发送者 svr.docmd("MAIL FROM: <%s>" % from_addr) # rcpt to, 邮件接收者 svr.docmd("RCPT TO: <%s>" % to_addr) # data命令,开始发送数据 svr.docmd("DATA") # 发送正文数据 svr.send(msg) # 比如以 . 作为正文发送结束的标记 svr.send(" . ") svr.getreply() # 发送结束,退出 svr.quit()
注意:以上的代码为了方便我都没有判断返回值,严格说来,是应该判断一下返回的代码的,在smtp协议中,只有返回代码是2xx或者3xx才能继续下一步,返回4xx或5xx的,都是出错了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
本文向大家介绍python smtplib模块自动收发邮件功能(二),包括了python smtplib模块自动收发邮件功能(二)的使用技巧和注意事项,需要的朋友参考一下 接上篇python smtplib模块自动收发邮件功能(一) ,用python smtplib模块实现了发送邮件程序了,那么接下来我们需要现在要解决的问题如何在 test_report\目录下找到最新生成的报告,只有找到了才能把
本文向大家介绍python smtplib模块自动收发邮件功能(一),包括了python smtplib模块自动收发邮件功能(一)的使用技巧和注意事项,需要的朋友参考一下 自动化测试的脚本运行完成之后,可以生成test report,如果能将result自动的发到邮箱就不用每次打开阅读,而且随着脚本的不段运行,生成的报告会越来越多,找到最近的报告也是一个比较麻烦的事件;如果能自 动的将结果发到项目
本文向大家介绍python smtplib模块实现发送邮件带附件sendmail,包括了python smtplib模块实现发送邮件带附件sendmail的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了python smtplib实现发送邮件的具体代码,供大家参考,具体内容如下 从网上找了些资料,不会有个别错误,上面代码经调试测试通过。 以上就是本文的全部内容,希望对大家的学习有所帮
本文向大家介绍Python基于smtplib模块发送邮件代码实例,包括了Python基于smtplib模块发送邮件代码实例的使用技巧和注意事项,需要的朋友参考一下 smtplib模块负责发送邮件:是一个发送邮件的动作,连接邮箱服务器,登录邮箱,发送邮件(有发件人,收信人,邮件内容)。 email模块负责构造邮件:指的是邮箱页面显示的一些构造,如发件人,收件人,主题,正文,附件等。 email模块下
本文向大家介绍Python学习之os模块及用法,包括了Python学习之os模块及用法的使用技巧和注意事项,需要的朋友参考一下 os 模块代表了程序所在的操作系统,主要用于获取程序运行所在操作系统的相关信息。 在 Python 的交互式解释器中先导入 os 模块,然后输入 os.__all__ 命令(__all__ 变量代表了该模块开放的公开接口),即可看到该模块所包含的全部属性和函数。 此处仅介
本文向大家介绍跟老齐学Python之Import 模块,包括了跟老齐学Python之Import 模块的使用技巧和注意事项,需要的朋友参考一下 认识模块 对于模块,在前面的一些举例中,已经涉及到了,比如曾经有过:import random (获取随机数模块)。为了能够对模块有一个清晰的了解,首先要看看什么模块,这里选取官方文档中对它的定义: 都是洋码子,翻译一下不?不!还是只说要点: •模块就是