Python发送邮件(常见四种邮件内容)
Python发送邮件(常见四种邮件内容)
转自:http://lizhenliang.blog.51cto.com/7876557/1875330
在写脚本时,放到后台运行,想知道执行情况,会通过邮件、SMS(短信)、飞信、微信等方式通知管理员,用的最多的是邮件。在linux下,Shell脚本发送邮件告警是件很简单的事,有现成的邮件服务软件或者调用运营商邮箱服务器。
对于Python来说,需要编写脚本调用邮件服务器来发送邮件,使用的协议是SMTP。接收邮件,使用的协议是POP3和IMAP。我想有必要说明下 ,POP3和IMAP的区别:POP3在客户端邮箱中所做的操作不会反馈到邮箱服务器,比如删除一封邮件,邮箱服务器并不会删除。IMAP则会反馈到邮箱服务器,会做相应的操作。
Python分别提供了收发邮件的库,smtplib、poplib和imaplib。
本章主要讲解如果使用smtplib库实现发送各种形式的邮件内容。在smtplib库中,主要主要用smtplib.SMTP()类,用于连接SMTP服务器,发送邮件。
这个类有几个常用的方法:
方法 |
描述 |
SMTP.set_debuglevel(level) | 设置输出debug调试信息,默认不输出 |
SMTP.docmd(cmd[, argstring]) | 发送一个命令到SMTP服务器 |
SMTP.connect([host[, port]]) | 连接到指定的SMTP服务器 |
SMTP.helo([hostname]) | 使用helo指令向SMTP服务器确认你的身份 |
SMTP.ehlo(hostname) | 使用ehlo指令像ESMTP(SMTP扩展)确认你的身份 |
SMTP.ehlo_or_helo_if_needed() | 如果在以前的会话连接中没有提供ehlo或者helo指令,这个方法会调用ehlo()或helo() |
SMTP.has_extn(name) | 判断指定名称是否在SMTP服务器上 |
SMTP.verify(address) | 判断邮件地址是否在SMTP服务器上 |
SMTP.starttls([keyfile[, certfile]]) | 使SMTP连接运行在TLS模式,所有的SMTP指令都会被加密 |
SMTP.login(user, password) | 登录SMTP服务器 |
SMTP.sendmail(from_addr, to_addrs, msg, mail_options=[], rcpt_options=[]) |
发送邮件 from_addr:邮件发件人 to_addrs:邮件收件人 msg:发送消息 |
SMTP.quit() | 关闭SMTP会话 |
SMTP.close() | 关闭SMTP服务器连接 |
看下官方给的示例:
- >>> import smtplib
- >>> s=smtplib.SMTP("localhost")
- >>> tolist=["one@one.org","two@two.org","three@three.org","four@four.org"]
- >>> msg = '''''\
- ... From: Me@my.org
- ... Subject: testin'...
- ...
- ... This is a test '''
- >>> s.sendmail("me@my.org",tolist,msg)
- { "three@three.org" : ( 550 ,"User unknown" ) }
- >>> s.quit()
我们根据示例给自己发一个邮件测试下:
我这里测试使用本地的SMTP服务器,也就是要装一个支持SMTP协议的服务,比如sendmail、postfix等。
CentOS安装sendmail:yum install sendmail
- >>> import smtplib
- >>> s = smtplib.SMTP("localhost")
- >>> tolist = ["xxx@qq.com", "xxx@163.com"]
- >>> msg = '''''\
- ... From: Me@my.org
- ... Subject: test
- ... This is a test '''
- >>> s.sendmail("me@my.org", tolist, msg)
- {}
进入腾讯和网易收件人邮箱,就能看到刚发的测试邮件,一般都被邮箱服务器过滤成垃圾邮件,所以收件箱没有,你要去垃圾箱看看。
可以看到,多个收件人可以放到一个列表中进行群发。msg对象里From表示发件人,Subject是邮件标题,换行后输入的是邮件内容。
上面是使用本地SMTP服务器发送的邮件,测试下用163服务器发送邮件看看效果:
- >>> import smtplib
- >>> s = smtplib.SMTP("smtp.163.com")
- >>> s.login("baojingtongzhi@163.com", "xxx")
- (235, 'Authentication successful')
- >>> tolist = ["xxx@qq.com", "xxx@163.com"]
- >>> msg = '''''\
- ... From: baojingtongzhi@163.com
- ... Subject: test
- ... This is a test '''
- >>> s.sendmail("baojingtongzhi@163.com", tolist, msg)
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- File "/usr/lib64/python2.6/smtplib.py", line 725, in sendmail
- raise SMTPDataError(code, resp)
- smtplib.SMTPDataError: (554, 'DT:SPM 163 smtp10,DsCowAAXIdDIJAtYkZiTAA--.65425S2 1477125592,please see http://mail.163.com/help/help_spam_16.htm?ip=119.57.73.67&hostid=smtp10&time=1477125592')
访问给出的163网址,SMTP554错误是: "554 DT:SUM 信封发件人和信头发件人不匹配;"
大概已经明白啥意思,看上面再使用本地SMTP服务器时候,收件人位置是“undisclosed-recipients”,看这样163的SMTP服务器不给我们服务的原因就是这里收件人没指定。
重新修改下msg对象,添加上收件人:
- >>> msg = '''''\
- ... From: baojingtongzhi@163.com
- ... To: 962510244@qq.com ,zhenliang369@163.com
- ... Subject: test
- ...
- ... This is a test '''
- >>> s.sendmail("baojingtongzhi@163.com", tolist, msg)
- {}
好了,可以正常发送邮件了。msg这个格式是SMTP规定的,一定要遵守。
1、Python发送邮件并抄送
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- import smtplib
- def sendMail(body):
- smtp_server = 'smtp.163.com'
- from_mail = 'baojingtongzhi@163.com'
- mail_pass = 'xxx'
- to_mail = ['962510244@qq.com', 'zhenliang369@163.com']
- cc_mail = ['lizhenliang@xxx.com']
- from_name = 'monitor'
- subject = u'监控'.encode('gbk') # 以gbk编码发送,一般邮件客户端都能识别
- # msg = '''\
- # From: %s <%s>
- # To: %s
- # Subject: %s
- # %s''' %(from_name, from_mail, to_mail_str, subject, body) # 这种方式必须将邮件头信息靠左,也就是每行开头不能用空格,否则报SMTP 554
- mail = [
- "From: %s <%s>" % (from_name, from_mail),
- "To: %s" % ','.join(to_mail), # 转成字符串,以逗号分隔元素
- "Subject: %s" % subject,
- "Cc: %s" % ','.join(cc_mail),
- "",
- body
- ]
- msg = '\n'.join(mail) # 这种方式先将头信息放到列表中,然后用join拼接,并以换行符分隔元素,结果就是和上面注释一样了
- try:
- s = smtplib.SMTP()
- s.connect(smtp_server, '25')
- s.login(from_mail, mail_pass)
- s.sendmail(from_mail, to_mail+cc_mail, msg)
- s.quit()
- except smtplib.SMTPException as e:
- print "Error: %s" %e
- if __name__ == "__main__":
- sendMail("This is a test!")
s.sendmail(from_mail,
to_mail+cc_mail, msg)
在这里注意下,收件人和抄送人为什么放一起发送呢?其实无论是收件人还是抄送人,它们收到的邮件都是一样的,SMTP都是认为收件人这样一封一封的发出。所以实际上并没有抄送这个概念,只是在邮件头加了抄送人的信息罢了!另外,如果不需要抄送人,直接把上面cc的信息去掉即可。
2 Python发送邮件带附件
由于SMTP.sendmail()方法不支持添加附件,所以可以使用email模块来满足需求。email模块是一个构造邮件和解析邮件的模块。
先看下如何用email库构造一个简单的邮件:
- message = Message()
- message['Subject'] = '邮件主题'
- message['From'] = from_mail
- message['To'] = to_mail
- message['Cc'] = cc_mail
- message.set_payload('邮件内容')
基本的格式就是这样的!
继续回到主题,发送邮件带附件:
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- import smtplib
- from email.mime.text import MIMEText
- from email.mime.multipart import MIMEMultipart
- from email.header import Header
- from email import encoders
- from email.mime.base import MIMEBase
- from email.utils import parseaddr, formataddr
- # 格式化邮件地址
- def formatAddr(s):
- name, addr = parseaddr(s)
- return formataddr((Header(name, 'utf-8').encode(), addr))
- def sendMail(body, attachment):
- smtp_server = 'smtp.163.com'
- from_mail = 'baojingtongzhi@163.com'
- mail_pass = 'xxx'
- to_mail = ['962510244@qq.com', 'zhenliang369@163.com']
- # 构造一个MIMEMultipart对象代表邮件本身
- msg = MIMEMultipart()
- # Header对中文进行转码
- msg['From'] = formatAddr('管理员 <%s>' % from_mail).encode()
- msg['To'] = ','.join(to_mail)
- msg['Subject'] = Header('监控', 'utf-8').encode()
- # plain代表纯文本
- msg.attach(MIMEText(body, 'plain', 'utf-8'))
- # 二进制方式模式文件
- with open(attachment, 'rb') as f:
- # MIMEBase表示附件的对象
- mime = MIMEBase('text', 'txt', filename=attachment)
- # filename是显示附件名字
- mime.add_header('Content-Disposition', 'attachment', filename=attachment)
- # 获取附件内容
- mime.set_payload(f.read())
- encoders.encode_base64(mime)
- # 作为附件添加到邮件
- msg.attach(mime)
- try:
- s = smtplib.SMTP()
- s.connect(smtp_server, "25")
- s.login(from_mail, mail_pass)
- s.sendmail(from_mail, to_mail, msg.as_string()) # as_string()把MIMEText对象变成str
- s.quit()
- except smtplib.SMTPException as e:
- print "Error: %s" % e
- if __name__ == "__main__":
- sendMail('附件是测试数据, 请查收!', 'test.txt')
3 Python发送HTML邮件
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- import smtplib
- from email.mime.text import MIMEText
- from email.mime.multipart import MIMEMultipart
- from email.header import Header
- from email.utils import parseaddr, formataddr
- # 格式化邮件地址
- def formatAddr(s):
- name, addr = parseaddr(s)
- return formataddr((Header(name, 'utf-8').encode(), addr))
- def sendMail(body):
- smtp_server = 'smtp.163.com'
- from_mail = 'baojingtongzhi@163.com'
- mail_pass = 'xxx'
- to_mail = ['962510244@qq.com', 'zhenliang369@163.com']
- # 构造一个MIMEMultipart对象代表邮件本身
- msg = MIMEMultipart()
- # Header对中文进行转码
- msg['From'] = formatAddr('管理员 <%s>' % from_mail).encode()
- msg['To'] = ','.join(to_mail)
- msg['Subject'] = Header('监控', 'utf-8').encode()
- msg.attach(MIMEText(body, 'html', 'utf-8'))
- try:
- s = smtplib.SMTP()
- s.connect(smtp_server, "25")
- s.login(from_mail, mail_pass)
- s.sendmail(from_mail, to_mail, msg.as_string()) # as_string()把MIMEText对象变成str
- s.quit()
- except smtplib.SMTPException as e:
- print "Error: %s" % e
- if __name__ == "__main__":
- body = """
- <h1>测试邮件</h1>
- <h2 style="color:red">This is a test</h1>
- """
- sendMail(body)
4 Python发送图片邮件
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- import smtplib
- from email.mime.text import MIMEText
- from email.mime.image import MIMEImage
- from email.mime.multipart import MIMEMultipart
- from email.header import Header
- from email.utils import parseaddr, formataddr
- # 格式化邮件地址
- def formatAddr(s):
- name, addr = parseaddr(s)
- return formataddr((Header(name, 'utf-8').encode(), addr))
- def sendMail(body, image):
- smtp_server = 'smtp.163.com'
- from_mail = 'baojingtongzhi@163.com'
- mail_pass = 'xxx'
- to_mail = ['962510244@qq.com', 'zhenliang369@163.com']
- # 构造一个MIMEMultipart对象代表邮件本身
- msg = MIMEMultipart()
- # Header对中文进行转码
- msg['From'] = formatAddr('管理员 <%s>' % from_mail).encode()
- msg['To'] = ','.join(to_mail)
- msg['Subject'] = Header('监控', 'utf-8').encode()
- msg.attach(MIMEText(body, 'html', 'utf-8'))
- # 二进制模式读取图片
- with open(image, 'rb') as f:
- msgImage = MIMEImage(f.read())
- # 定义图片ID
- msgImage.add_header('Content-ID', '<image1>')
- msg.attach(msgImage)
- try:
- s = smtplib.SMTP()
- s.connect(smtp_server, "25")
- s.login(from_mail, mail_pass)
- s.sendmail(from_mail, to_mail, msg.as_string()) # as_string()把MIMEText对象变成str
- s.quit()
- except smtplib.SMTPException as e:
- print "Error: %s" % e
- if __name__ == "__main__":
- body = """
- <h1>测试图片</h1>
- <img src="cid:image1"/> # 引用图片
- """
- sendMail(body, 'test.png')
上面发邮件的几种常见的发邮件方法基本满足日常需求了。
Python发送邮件(常见四种邮件内容)的更多相关文章
- 【转】【Python】Python发送邮件(常见四种邮件内容)
在写脚本时,放到后台运行,想知道执行情况,会通过邮件.SMS(短信).飞信.微信等方式通知管理员,用的最多的是邮件.在linux下,Shell脚本发送邮件告警是件很简单的事,有现成的邮件服务软件或者调 ...
- python接口自动化(三十二)--Python发送邮件(常见四种邮件内容)番外篇——上(详解)
简介 本篇文章与前边没有多大关联,就是对前边有关发邮件的总结和梳理.在写脚本时,放到后台运行,想知道执行情况,会通过邮件.SMS(短信).飞信.微信等方式通知管理员,用的最多的是邮件.在linux下, ...
- 最全总结!聊聊 Python 发送邮件的几种方式
1. 前言 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人,却不知道如何去学习更加高深的知识.那么针对这三类人,我给大 ...
- Python自动化测试发送邮件太麻烦?!一起聊一聊 Python 发送邮件的3种方式
1. 前言 发送邮件,我们在平时工作中经用到,做为测试人员,在自动化测试中用的也比较多,需要发送邮件给某领导 SMTP是Python默认的邮件模块,可以发送纯文本.富文本.HTML 等格式的邮件 今天 ...
- Python实现接口测试中的常见四种Post请求数据
前情: 在日常的接口测试工作中,模拟接口请求通常有两种方法, 利用工具来模拟,比如fiddler,postman,poster,soapUI等 利用代码来模拟,使用到一些网络模块,比如HttpClie ...
- Python请求外部POST请求,常见四种请求体
原文http://blog.csdn.net/silencemylove/article/details/50462206 HTTP 协议规定 POST 提交的数据必须放在消息主体(entity-bo ...
- Mysql常见四种索引的使用
提到MySQL优化,索引优化是必不可少的.其中一种优化方式 --索引优化,添加合适的索引能够让项目的并发能力和抗压能力得到明显的提升. 我们知道项目性能的瓶颈主要是在"查(select)&q ...
- python函数的四种参数传递方式
python中函数传递参数有四种形式 fun1(a,b,c) fun2(a=1,b=2,c=3) fun3(*args) fun4(**kargs) 四种中最常见是前两种,基本上一般点的教程都会涉及, ...
- Python单例模式的四种方法
在这之前,先了解super()和__new__()方法 super()方法: 返回一个父类或兄弟类类型的代理对象,让你能够调用一些从继承过来的方法. 它有两个典型作用: a. 在单继承的类层次结构中, ...
随机推荐
- 2、Java调用C语言(JNative法)
这个方法也是挺麻烦的…… 一.下载JNative.jar,把它放在你jdk下的\jre\lib\ext目录下 二.在 F:\MinGW\JNative 新建 Test.java: public cla ...
- 配置ssh免密码登录设置后还是提示需要输入密码
工作之余搭建了一个集群测试,配置了ssh免密码登录以后 ,所有的ssh-copy-id 密钥也都分发了 ,各项配置也没有问题,但是使用ssh进行免密登录时,没有报错,但是要输入被ssh主机的登录密码 ...
- Composer学习
Composer简介 Composer是PHP的一个依赖管理工具,不是包管理器:在项目中声明所依赖的外部工具库(libraries),Composer会自动安装止血工具库及依赖的库文件. 安装方式 C ...
- vscode 热部署 spring-mvc
1.添加maven插件 <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId> ...
- pycharm链接数据库以及连接时候出现错误的集合
1.pycharm如何直接连接数据库? 作用:这是一种管理数据库的方式而已,因为在开发过程中结合使用还是不错的!当然,还有有很多管理数据库的工具和方法. 比如:navicat工具 1.1 如何找到管 ...
- egret 发布ios记录
根据官方文档http://developer.egret.com/cn/github/egret-docs/Native/native/hybrid/hybrid/index.html 将现有的项目发 ...
- Redis5新特性
Redis5.0的12个新特性 1.数据类型Stream 本质上是一个消费者等待生产者发送新的数据 使用情景 其他五种数据结构无法实现的需求,可以通过stream来实现 直接贴近业务需求,提升开发效率 ...
- Matlab 2019a 下载和安装步骤
目录 1. 安装包下载 + 多套数学建模视频教程 2. 安装步骤 1. 安装包下载 + 多套数学建模视频教程 参考:https://blog.csdn.net/COCO56/article/detai ...
- 《Java核心技术卷I》——第5章 继承
在C++中,没有提供用于表示抽象类的特殊关键字.只要有一个纯虚函数,这个类就是抽象类. hashCode()方法是定义在Object类中,因此每个对象都有一个默认的散列码,其值为对象的存储地址. 绝大 ...
- centos 安装代理服务 proxy server squild
以下内容复制自https://blog.csdn.net/qingfengxulai/article/details/80853870 放置此处便于检索 1 安装 sudo yum install s ...