python之使用smtp发邮件

最近在做zabbix的一个报表系统,用到了发邮件这部分的功能,所以就研究了下如何使用python的smtp模块进行发送附近、url、邮件内嵌图片等。

为什么使用倒腾这个?

  • 最近的报表系统需要用这块的功能
  • 和同事一起做告警平台的时候,更希望能有一个公共的、完善的接口去共有出来使用
  • 网上太多的误导,算是一个分享吧

实现的功能

  • 发送消息

    • 发送纯文本消息
    • 发送小心url
    • 发送消息内嵌图片(外链形式)
    • 发送消息内嵌图片(本地文件)
  • 发送附件

实现方法

发送消息的实现原理

这个其很简单,都是上网的例子,说穿了就是把需要发送的消息放到html里面去,然后发送邮件的时候直接发送整个html。

而html的格式中对于url、内嵌图片等对应的写入了href 、img 标签,所以传入相应的参数就可以了。但对与图片,必须是外链的,就是说必须在网络上可以访问的,否则无法正常显示的(例如本地图片插入就会异 常)。

这个确实是没有办法的事情,因为html的img本身也就是一个引用服务器上的文件或者链接。对于邮件发送出去了,再引用本地路径的文件,客户端本地没有,那肯定是没办法的事情了,所以这部分的内嵌图片只是 外链才ok,当然了,你也可以把本地的图片全部扔到apache等的一个目录下,这样也算是变形的解决了。至于如何才能使用本地文件的方式,下面会说道。

发送附件的实现原理

发送附件主要是将附件文件以二进制的方式读进来,然后放到mimetext中去,最后attach到整个msg中。

其实前面说的发送消息内嵌图片(本地文件)的实现,就是利用发送附件的方法做的,同样是以二进制方式读入进来,然后放到mimeimage中去,再设置对应的header,最后打到html格式的消息体中去,通过cid的引用>,告诉html引用的图片在附件中,好吧,大致是这么会事。

代码

忽悠了大半天,其实最有价值的代码还没给出来,看下代码吧,一切都在代码里:

# -*- coding: utf-8 -*-
#!/usr/bin/env python
#导入smtplib and MIMEText
import smtplib
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.MIMEMultipart import MIMEMultipart
#####################
mailto_list=["huangsicong@letv.com"]
#####################
#mail server config
mail_host="mail.letv.com"
mail_user="user"
mail_pass="passwd"
mail_postfix="letv.com"


#####################

def HtmlContent(info,url='',url_msg='',url_img=''):

    content='''
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf8" />
<title>Demo: CSS3 Buttons</title>
<style type="text/css">

.download {
    display: inline-block;
    margin-top: 20px;
    padding: 15px;
    font-size: 26px;
    font-weight: bold;
    color: #fff;
    text-shadow: none;
    border-radius: 4px;
    -webkit-animation-name: fadeIn;
    -moz-animation-name: fadeIn;
    -ms-animation-name: fadeIn;
    -o-animation-name: fadeIn;
    animation-name: fadeIn;
    -webkit-animation-delay: .9s;
    -webkit-animation-fill-mode: both;
    -webkit-animation-duration: 1.2s;
    -webkit-animation-iteration-count: 1;
    -webkit-animation-timing-function: ease;
    -webkit-transition: all 0.3s ease;
    -moz-transition: all 0.3s ease;
    -o-transition: all 0.3s ease;
    transition: all 0.3s ease;
}

.download:hover {
    -webkit-transform: scale(1.1);
    -moz-transform: scale(1.1);
    -o-transform: scale(1.1);
    transform: scale(1.1);
}

a {
text-decoration: none;
}


div.twitter {
    font-size: 20px;
    padding: 5px;
    color: #fff;
    background: #2da1ec;
    border-radius: 3px;
}

div.twitter:hover {
    color: #fff;
    background: #2eacff;
}

div.twitter:active {
    top: 1px;
}

  padding: 0px 20.48px;
}



</style>    <body>

<div>
</div>
<!--     <div class="twitter" data-tip="twitter"> -->
 <table width="750" border="1" cellpadding="0" cellspacing="0" style="border:0px solid #ff0000">
            %s
        </table>
<!--     </div> -->

<br>
<br>
<a href="%s">%s</a>
<br>
<br>
<br>
<img src="%s" />
<br>
</body>
</html>

'''%(info,url,url_msg,url_img)
    return content

def send_mail(to_list,sub,content,att_file = '',img = ''):

    '''
    to_list:
    sub:
    content:
    att_file:
    send_mail("rfyiamcool@163.com","sub","content","/var/www/html/report/KVM.xls")
    '''
    me=mail_user+"<"+mail_user+"@"+mail_postfix+">"
    msg = MIMEMultipart()
    msg['Subject'] = sub

    if(att_file != ''):
            att = MIMEText(open(att_file,'rb').read(),'base64','gb2312')
            att["Content-Type"] = 'application/octet-stream'
            att_file = ''.join(att_file.split('/')[-1:])
            att["Content-Disposition"] = "attachment;filename=%s" %att_file
            msg.attach(att)
    if(img != ''):
            msg_image = MIMEImage(open(img,'rb').read())
            msg_image.add_header('Content-ID',"<%s>" %img);
            msg.attach(msg_image)
            content += "<td><img src='cid:%s'></td>" %img

    body = MIMEText(content,_subtype='html',_charset='utf8')
    msg.attach(body)

    msg['From'] = "oss-autoreport@letv.com"
    msg['To'] = to_list
    try:
        s = smtplib.SMTP()
        s.connect(mail_host)
#       s.login(mail_user,mail_pass)
        s.sendmail(me, to_list, msg.as_string())
        s.close()
        return True
    except Exception, e:
        print str(e)
        return False


if __name__ == '__main__':

    #content = HtmlContent('阿萨阿斯');
    content = HtmlContent('测试','furion.info');
    if send_mail(mailto_list[0],'测试',content,'','eg_tulip.jpg'):
        print "success"
    else:
        print "fail"

使用方法

* 配置下自己的邮件服务器信息、用户名、密码等
* 调用htmlcontent传入需要包含的纯文本、url、图片等,除了第一个参时,其他的都可选的。
* 调用send_mail发邮件,最后的附件、图片参数可选

使用效果

效果

使用效果

总结

虽然发邮件这个事很简单,但如果没有一个公共的接口去做,那基本是每个部分都会自己去写这种脚本, 虽然没啥太难的,但总归是人力的重复浪费不是。如果能有一个接口去提供服务,那其他部门的同时需要 做的可能就是简单的传入json就ok了。

Leave a Reply

Your email address will not be published. Required fields are marked *


To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax