在写脚本时,放到后台运行,想知道执行情况,会通过邮件、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服务器连接

看下官方给的示例:1

2

3

4

5

6

7

8

9

10

11>>>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 sendmail1

2

3

4

5

6

7

8

9>>>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服务器发送邮件看看效果:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15>>>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 "", line1,in

File "/usr/lib64/python2.6/smtplib.py", line725,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对象,添加上收件人:1

2

3

4

5

6

7

8>>> msg= '''\

... From: baojingtongzhi@163.com

... To: 962510244@qq.com ,xxx@163.com

... Subject: test

...

... This is a test '''

>>> s.sendmail("baojingtongzhi@163.com", tolist, msg)

{}

好了,可以正常发送邮件了。msg这个格式是SMTP规定的,一定要遵守。

14.1 Python发送邮件并抄送1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35#!/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= ['xxx@qq.com','xxx@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的信息去掉即可。

14.2 Python发送邮件带附件

由于SMTP.sendmail()方法不支持添加附件,所以可以使用email模块来满足需求。email模块是一个构造邮件和解析邮件的模块。

先看下如何用email库构造一个简单的邮件:1

2

3

4

5

6message= Message()

message['Subject']= '邮件主题'

message['From']= from_mail

message['To']= to_mail

message['Cc']= cc_mail

message.set_payload('邮件内容')

基本的格式就是这样的!

继续回到主题,发送邮件带附件:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47#!/usr/bin/python

# -*- coding: utf-8 -*-

import smtplib

from email.mime.textimport MIMEText

from email.mime.multipartimport MIMEMultipart

from email.headerimport Header

from emailimport encoders

from email.mime.baseimport MIMEBase

from email.utilsimport 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= ['xxx@qq.com','xxx@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'))

# 二进制方式模式文件

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

博客地址:http://lizhenliang.blog.51cto.com

QQ群:323779636(Shell/Python运维开发群)

14.3 Python发送HTML邮件1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37#!/usr/bin/python

# -*- coding: utf-8 -*-

import smtplib

from email.mime.textimport MIMEText

from email.mime.multipartimport MIMEMultipart

from email.headerimport Header

from email.utilsimport 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= ['xxx@qq.com','xxx@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= """

测试邮件

This is a test

"""

sendMail(body)

14.4 Python发送图片邮件1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44#!/usr/bin/python

# -*- coding: utf-8 -*-

import smtplib

from email.mime.textimport MIMEText

from email.mime.imageimport MIMEImage

from email.mime.multipartimport MIMEMultipart

from email.headerimport Header

from email.utilsimport 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= ['xxx@qq.com','xxx@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'))

# 二进制模式读取图片

withopen(image,'rb') as f:

msgImage= MIMEImage(f.read())

# 定义图片ID

msgImage.add_header('Content-ID','')

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= """

测试图片

# 引用图片

"""

sendMail(body,'test.png')

python 邮件_Python发送邮件(常见四种邮件内容)相关推荐

  1. python接口自动化(三十二)--Python发送邮件(常见四种邮件内容)番外篇——上(详解)...

    简介 本篇文章与前边没有多大关联,就是对前边有关发邮件的总结和梳理.在写脚本时,放到后台运行,想知道执行情况,会通过邮件.SMS(短信).飞信.微信等方式通知管理员,用的最多的是邮件.在linux下, ...

  2. python接口自动化(三十二)--Python发送邮件(常见四种邮件内容)番外篇——上

    简介 本篇文章与前边没有多大关联,就是对前边有关发邮件的总结和梳理.在写脚本时,放到后台运行,想知道执行情况,会通过邮件.SMS(短信).飞信.微信等方式通知管理员,用的最多的是邮件.在linux下, ...

  3. python 实现SMTP发送邮件(四)-添加附件

    Python实现SMTP发送邮件(四)-添加附件 [Python]  纯文本查看  复制代码 ? 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 ...

  4. python写错了怎么更改-Python中修改字符串的四种方法

    在Python中,字符串是不可变类型,即无法直接修改字符串的某一位字符. 因此改变一个字符串的元素需要新建一个新的字符串. 常见的修改方法有以下4种. 方法1:将字符串转换成列表后修改值,然后用joi ...

  5. 如何打开python的交互窗口-Python多版本情况下四种快速进入交互式命令行的操作技巧...

    原标题:Python多版本情况下四种快速进入交互式命令行的操作技巧 因为工作需求或者学习需要等原因,部分小伙伴的电脑中同时安装了Python2和Python3,相信在Python多版本的切换中常常会遇 ...

  6. Perl,Python,Ruby,Javascript 四种脚本语言比较

    Perl 为了选择一个合适的脚本语言学习,今天查了不少有关Perl,Python,Ruby,Javascript的东西,可是发现各大阵营的人都在吹捧自己喜欢的语言,不过最没有争议的应该是Javascr ...

  7. python单向认证_使用Python进行单向方差分析的四种方法

    python单向认证 The current post will focus on how to carry out between-subjects ANOVA using Python. As m ...

  8. anydesk远程计算机,AnyDesk远程软件连接失败的常见四种状况?

    AnyDesk远程软件是我们日常生活工作中常用的一款远程软件.体积小,灵活又便捷,帮助我们随时随地移动办公.但我们使用AnyDesk远程软件时,也会出现一些连接失败的情况.接下来,下文将详细叙述一下A ...

  9. 大金空调自动关机常见四种原因

    大金空调属于空调界的NO.1有着完美的技术,但是缺点就是价格有点高,所以维修起来难度也大,在此株洲大金空调维修售后提供大金空调自动关机常见四种问题和原因,望对各位技师或用户有一定的帮助 1.遥控器设置 ...

最新文章

  1. pgpool-II的性能缺陷(二)
  2. python操作mysql操作步骤
  3. iphone自定义铃声
  4. 贝叶斯分类器_python机器学习API介绍10:多项式贝叶斯分类器
  5. list python 转tensor_Tensorflow模型量化4 --pb转tflite(uint8量化)小结
  6. SpringBoot2.x整合Swagger2 实现API文档实时生成
  7. 隔一段时间查找一次 golang_剑指 offer-04 二维数组中的查找
  8. python获取文件路径下指定的类型的文件_python学习1-列出指定目录下的指定类型文件...
  9. python随机分组的思路_python – 对对象进行分组以实现所有组的类似平均属性
  10. 【Spring Boot】Spring Boot之整合RabbitMQ并实现消息的发送和接收
  11. 任意阶幻方解法及c++实现
  12. php修改学生信息代码_PHP连接MySQL数据库添加图书功能
  13. Glide 4.x之生命周期与Activity的绑定原理详解
  14. base64格式的pdf预览
  15. 毕设教程系列 - FCM模糊聚类算法
  16. 开启和关闭Windows远程管理(WinRM)
  17. Python学习之波形图
  18. python 输出数据到excel设置超链接及格式设置
  19. 写空到linux文件系统,谢烟客---------Linux之文件系统及其命令
  20. 国子监祭酒是个什么官

热门文章

  1. 《程序员的修炼之道——从小工到专家》读书笔记
  2. Altium Designer 2020 如何修改现有原理图图纸尺寸
  3. 《超算竞赛导引》笔记
  4. 【周志华机器学习】三、线性模型
  5. 显卡发展史浅谈 显卡历史大全
  6. 分支定界算法理解(摘抄)
  7. 【C++从0到1】7.C++中标识符的命名
  8. 音频怎么在线转换成文字?试试这几个音频转文字的方法
  9. 内存和FLASH的区别
  10. 10分钟解读《财富自由之路》