本章目录

  • Python标准库smtplib

  • Python发送邮件并抄送

  • Python发送邮件带附件

  • Python发送HTML邮件

  • Python发送图片邮件

在写脚本时,放到后台运行,想知道执行情况,会通过邮件、SMS(短信)、飞信、微信等方式通知管理员,用的最多的是邮件。在linux下,Shell脚本发送邮件告警是件很简单的事,有现成的邮件服
在写脚本时,放到后台运行,想知道执行情况,会通过邮件、SMS(短信)、飞信、微信等方式通知管理员,用的最多的是邮件。在linux下,Shell脚本发送邮件告警是件很简单的事,有现成的邮件服务软件或者调用运营商邮箱服务器。
对于Python来说,需要编写脚本调用邮件服务器来发送邮件,使用的协议是SMTP。接收邮件,使用的协议是POP3和IMAP。我想有必要说明下 ,POP3和IMAP的区别:POP3在客户端邮箱中所做的操作不会反馈到邮箱服务器,比如删除一封邮件,邮箱服务器并不会删除。IMAP则会反馈到邮箱服务器,会做相应的操作。

1、Python标准库smtplib

Python分别提供了收发邮件的库:smtplib、poplib和imaplib。
其中smtplib库是用于发送邮件的,smtplib库主要用smtplib.SMTP()类,它用于连接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 ,xxx@163.com... Subject: test...... This is a test '''>>> s.sendmail("baojingtongzhi@163.com", tolist, msg){}

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

2、Python发送邮件并抄送

#!/usr/bin/python# -*- coding: utf-8 -*-import smtplibdef 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" %eif __name__ == "__main__":sendMail("This is a test!")

s.sendmail(from_mail,to_mail+cc_mail, msg) 在这里注意下,收件人和抄送人为什么放一起发送呢?其实无论是收件人还是抄送人,它们收到的邮件都是一样的,SMTP都是认为收件人这样一封一封的发出。所以实际上并没有抄送这个概念,只是在邮件头加了抄送人的信息罢了!另外,如果不需要抄送人,直接把上面cc的信息去掉即可。

3、Python发送邮件带附件

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

message = Message()message['Subject'] = '邮件主题'message['From'] = from_mailmessage['To'] = to_mailmessage['Cc'] = cc_mailmessage.set_payload('邮件内容')

基本的格式就是这样的!
继续回到主题,发送邮件带附件:

#!/usr/bin/python# -*- coding: utf-8 -*-import smtplibfrom email.mime.text import MIMETextfrom email.mime.multipart import MIMEMultipartfrom email.header import Headerfrom email import encodersfrom email.mime.base import MIMEBasefrom 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 = ['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'))    # 二进制方式模式文件    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" % eif __name__ == "__main__":    sendMail('附件是测试数据, 请查收!', 'test.txt')

4、Python发送HTML邮件

#!/usr/bin/python# -*- coding: utf-8 -*-import smtplibfrom email.mime.text import MIMETextfrom email.mime.multipart import MIMEMultipartfrom email.header import Headerfrom 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 = ['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" % eif __name__ == "__main__":    body = """    <h1>测试邮件</h1>    <h2 style="color:red">This is a test</h1>    """    sendMail(body)

5、Python发送图片邮件

#!/usr/bin/python# -*- coding: utf-8 -*-import smtplibfrom email.mime.text import MIMETextfrom email.mime.image import MIMEImagefrom email.mime.multipart import MIMEMultipartfrom email.header import Headerfrom 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 = ['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'))    # 二进制模式读取图片    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" % eif __name__ == "__main__":    body = """    <h1>测试图片</h1>    <img src="cid:image1"/>    # 引用图片    """    sendMail(body, 'test.png')

以上是Python常见的发送邮件方式,经常写脚本的朋友还是有必要熟悉下的!

©著作权归作者所有:来自51CTO博客作者mob604756e5abbc的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. Python 发送邮件各种姿势
  2. 【Nest教程】Nest项目配置邮件服务器,实现发送邮件
  3. 一沟绝望的死水:模拟邮件服务器,批量注册利器
  4. Exchange删除邮件
  5. Android通过Intent发送电子邮件含附件
  6. android email 邮件转发 附件不能转发问题的解决
  7. Android(安卓)平台未安装邮件客户端,点击邮件链接,程序崩溃问题
  8. Android实现电子邮箱客户端
  9. 【转】Android通过Intent发送电子邮件含附件

随机推荐

  1. Android(安卓)使用NDK编译sipdroid Libra
  2. 免费的阿里云盘邀请码,我刚试了一下,速度真
  3. 2021.1.14
  4. Android屏幕截图之View方法
  5. CSS Feature Query
  6. 定制替换Android桌面
  7. JDK10都发布了,nio你了解多少?
  8. 你不知道的,Java代码性能优化的 40+ 细节,
  9. [置顶] android利用zbar二维码扫描-(解决
  10. 还是初识