Django多线程异步发送邮件
在我们的系统很多地方会使用到发邮件的模块,以前我们使用同步发邮件,但是在很多时候,如果使用同步发邮件的话,在执行完发邮件的程序后,返回值在返回到前台,需要很长的时间等待,这样造成了非常不好体验,所以我们可以采用异步发邮件
这边我们来采用多线程的形式达到异步发邮件的效果
python中,要定制一个多线程类可以继承threading库中的Thread类,并实现run方法即可
在你的app里面新建一个sendemail.py的文件(跟你的views在同一层目录),代码如下:
#coding:utf-8
from django.template import loader
from django.conf import settings
from django.core.mail import EmailMessage
import threading
#继承Thread,需要实现run方法
class SendHtmlEmail(threading.Thread):
"""send html email"""
def __init__(self, subject, html_content, send_from, to_list, fail_silently = False):
self.subject = subject
self.html_content = html_content
self.send_from = send_from
self.to_list = to_list
self.fail_silently = fail_silently #默认fail_silently=True发送异常不报错
threading.Thread.__init__(self)
def run(self):
msg = EmailMessage(self.subject, self.html_content, self.send_from, self.to_list)
msg.content_subtype = "html" # Main content is now text/html
msg.send(self.fail_silently)
def send_email_by_template(subject, module, data, to_list):
"""
使用模版发送邮件,发件人默认使用配置的
subject: string, 主题
module: string, 模版名称
data: dict, 数据
to_list: list, 收件人
"""
html_content = loader.render_to_string(module, data)
send_from = settings.DEFAULT_FROM_EMAIL
send_email = SendHtmlEmail(subject, html_content, send_from, to_list)
send_email.start() #开启线程,自动运行线程里面的run方法
def send_html_email(subject, html_content, to_list):
"""发送html邮件"""
send_from = settings.DEFAULT_FROM_EMAIL
send_email = SendHtmlEmail(subject, html_content, send_from, to_list)
send_email.start()
其中,SendHtmlEmail类是继承了Thread类。
为了其他地方方便使用,再写了两个方法send_email_by_template和send_html_email进一步封装。这两个方法分别作用是用模版发送html邮件和直接发送html邮件。
发件人也是在settings.py中设置好。
在这两个方法中,可以看到用start方法执行线程,则运行线程类中的run方法。
另外,django发送邮件需要在settings.py设置一下相关的邮件配置。
– 在setting的最后加上如下代码:
#Email设置
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST= 'smtp.qq.com'#以QQ邮箱为例,SMTP服务器(邮箱需要开通SMTP服务)
EMAIL_PORT= 25 #QQ邮箱SMTP服务端口
EMAIL_HOST_USER = '**********@qq.com' #我的QQ邮箱帐号
EMAIL_HOST_PASSWORD = '**************' #SMTP服务授权码
EMAIL_SUBJECT_PREFIX = 'website' #为邮件标题的前缀,默认是'[django]'
EMAIL_USE_TLS = True #开启安全链接
DEFAULT_FROM_EMAIL = SERVER_EMAIL = EMAIL_HOST_USER #设置发件人
大家配置写好,前面的sendemail.py写好,就可以使用两个方法发邮件:
- 使用html模板来发邮件
在templates下面新建一个邮件模板,比如在这边我们新建一个directoremail.html的模板
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>邮件通知</title>
<style type="text/css">
.ListTable { border :1px solid #BDBCBC;border-collapse: collapse; width:100%;}
.ListTable td{ height:50px;font-size:12px;width:16.6%;border:1px #BDBCBC ; border-bottom-style:dashed; letter-spacing:1px; line-height:20px;}
.recordTable { border :1px solid #BDBCBC;border-collapse: collapse; width:100%; table-layout:fixed}
.recordTable td{ height:30px; font-size:12px;border:1px solid #BDBCBC ; letter-spacing:1px; text-align:center; }
.wordbreak{WORD-BREAK: break-all;word-wrap: break-word;}
</style>
</head>
<body>
<div>
<div style=" margin-top:20px;">
<table class="recordTable">
<tr>
<td style="width:80px;background:#EFEFEF;" align="center" valign="middle">申请人账号</td>
<td style="width:80px;background:#EFEFEF;" align="center" valign="middle">申请人</td>
<td style="width:80px;background:#EFEFEF;" align="center" valign="middle">申请类型</td>
<td style="width:100px;background:#EFEFEF;" align="center" valign="middle">申请内容</td>
<td style="width:150px;background:#EFEFEF;" align="center" valign="middle">申请时间</td>
</tr>
<div style=" margin-top:20px;font-size:12px;">
{% if emaillists != '' %}
{% for emaillist in emaillists %}
<tr>
<td> {{ emaillist.adaccount }} </td>
<td> {{ emaillist.displayname }} </td>
<td>{{ emaillist.applytype }}</td>
<td>{{ emaillist.applydetail }}</td>
<td>{{ emaillist.submittime|date:"Y-m-d H:i:s"}}</td>
</tr>
{% endfor %}
{% endif %}
</div>
</table>
</div>
<a href="http://127.0.0.1:8000">请登录</a>
</div>
</body>
</html>
然后在你需要发邮件的程序里面(比如我会在views里面),会调这个发模板的邮件程序,代码如下:
from sendmail import *
def test1(request):
#其他代码省略了
#需要查询的数据
emaillists=showemail(ids)
#邮件主题
subject = u'IT审批'
#模版需要的数据,到html模板里面使用Django的模板系统来显示数据
email_data={'emaillists':emaillists}
#模版文件的位置
template="directoremail.html"
#收件人列表
to_list = ['xxx@xx.com', ]
#根据模版发送邮件
send_email_by_template(subject,template,email_data,to_list)
这里面的email_data是一个字典类型,里面的数据可以直接在你html模板里面使用
就采用Django的模板来显示数据
- 直接发送html格式的邮件
例如也可以在你的views里面加如下代码:
def test2(request):
#其他代码省略了
#邮件主题
subject = u'IT审批'
#html内容
html_content = u'<p>hello,world!</a>'
#根据发送html邮件
send_html_email(subject, html_content, to_list)
这样就可以实现多线程异步发送邮箱。