最近需要做集团的SRC系统。暂无安全研发,所以只能找我这个小菜兼职开发。系统使用Django框架,在整个过程中,有许多奇特的需求。在某项需求中,需要给厂商用户发送富文本邮件,漏洞详情,这个折腾了一下,感觉略有收获,所以记一篇随笔。
首先我在网上搜索了一些资料,发现都是python通过smtplib发送,使用MIME格式来生成富文本邮件:传送门
我想的是,使用Django框架,框架带了邮件模块,没必要引入smtplib吧。我就想,向上文传送门那样,生成一个MIME文件,然后通过
1
2
|
from django.core import mail
mail.send_mail
|
这种方式把MIMEMultipart对象使用as_string()方法生成的文件当做message发出去不就好了吗。呃,有兴趣的可以试一下。。我发出去了一堆字符串。。
好吧,失败了,难道真的要把smtplib引进来?
天无绝人之路,这个时候我看到了一句话:EmailMessage是Django封装好的smtp。哦?还有这回事?好吧,尝试一下看看源码?跳转至message.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class EmailMessage( object ):
"""
A container for email information.
"""
content_subtype = 'plain'
mixed_subtype = 'mixed'
encoding = None # None => use settings default
def __init__( self , subject = ' ', body=' ', from_email = None , to = None , bcc = None ,
connection = None , attachments = None , headers = None , cc = None ,
reply_to = None ):
"""
Initialize a single email message (which can be sent to multiple
recipients).
All strings used to create the message can be unicode strings
(or UTF-8 bytestrings). The SafeMIMEText class will handle any
necessary encoding conversions.
"""
|
恩!大体知道了用法。
1
|
msg = mail.EmailMessage( '富文本邮件测试' , html, from_mail, recipient_list)
|
就是这样了。而且看message.py文件
1
2
3
4
|
if to:
if isinstance (to, six.string_types):
raise TypeError( '"to" argument must be a list or tuple' )
self .to = list (to)
|
看到raise的信息,明白了,我们传给他的recipient_list应该是元组或者列表
1
|
self .from_email = from_email or settings.DEFAULT_FROM_EMAIL
|
我们传给他的就是Django settings.py文件里配置的邮箱,就是以下格式的:
1
2
3
4
5
6
7
8
|
# email config
# 这是我们工程目录下settings文件的配置
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST_PASSWORD = 'xxxxxxxx'
EMAIL_HOST_USER = 'xxxx@xxxx.xxxx'
EMAIL_HOST = 'smtp.xxxx.com'
EMAIL_PORT = port
|
好,到此为止,我们知道了这个类怎么用。我们看传送门里的代码,挑选比较重要的
1
2
3
4
5
6
7
8
9
10
|
msgRoot = MIMEMultipart( 'related' )
msgRoot[ 'Subject' ] = subject
msgRoot[ 'From' ] = strFrom
msgRoot[ 'To' ] = strTo
msgText = MIMEText(plainText, 'plain' , 'utf-8' )
msgAlternative.attach(msgText)
#设定HTML信息
msgText = MIMEText(htmlText, 'html' , 'utf-8' )
msgAlternative.attach(msgText)
|
然后我们对比一下message.py里面的代码:
1
2
3
4
5
6
7
|
def message( self ):
encoding = self .encoding or settings.DEFAULT_CHARSET
msg = SafeMIMEText( self .body, self .content_subtype, encoding)
msg = self ._create_message(msg)
msg[ 'Subject' ] = self .subject
msg[ 'From' ] = self .extra_headers.get( 'From' , self .from_email)
msg[ 'To' ] = self .extra_headers.get( 'To' , ', ' .join( map (force_text, self .to)))
|
篇幅所限不粘贴太多,有兴趣可以自己去研读。我们发现,他们是不是很像,其实读完整个message.py我们会发现一件事。原来EmailMessage这个类的对象,可以看做是MIMEMultipart对象加上了smtplib的发送功能。而且它也有attach方法,可以像MIMEMultipart对象那样拼接富文本邮件内容,好,这就有办法了!我们通过EmailMessage来发送富文本邮件!
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
48
49
50
51
52
53
|
# -*- coding: utf-8 -*-
# ===============================================================================
# @ Creator:首席小学生
# @ Date:2017-03-28
# 构造富文本邮件内容
# ===============================================================================
import os
from email.mime.image import MIMEImage
from django.conf import settings
from django.core import mail
def add_img(src, img_id):
"""
在富文本邮件模板里添加图片
:param src:
:param img_id:
:return:
"""
fp = open (src, 'rb' )
msg_image = MIMEImage(fp.read())
fp.close()
msg_image.add_header( 'Content-ID' , '<' + img_id + '>' )
return msg_image
def send_util():
path = os.getcwd()
path_use = path.replace( '\\', ' / ')
html = '''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
牛逼呀小伙子,你成功了
<img src="cid:test_cid"/>
</body>
</html>
'''
recipient_list = [ 'xxxx@xxxx.com' ]
from_mail = settings.EMAIL_HOST_USER
msg = mail.EmailMessage( '富文本邮件测试' , html, from_mail, recipient_list)
msg.content_subtype = 'html'
msg.encoding = 'utf-8'
image = add_img(path_use + '/mail_util/test.png' , 'test_cid' )
msg.attach(image)
if msg.send():
return True
else :
return False
|
我们在views中设置视图函数,调用上面这些测试方法尝试一下:
1
2
3
4
5
6
7
8
9
|
from django.shortcuts import render
from html_to_mail import send_util
def send_mail(request):
if send_util():
return render(request, 'ok.html' )
else :
return render(request, 'error.html' )
|
在urls里面随意配置一个映射指向这个视图函数,把Django工程run起来,直接在浏览器get这个映射。发现邮件发送成功!
工程目录如上图。我不想上传代码,我觉得直接下载源码用来用的话很难学会
就是这样,我完成了Django的富文本邮件发送。希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:http://www.cnblogs.com/hainan-zhang/p/6647980.html