关于本站
1、基于Django+Bootstrap开发
2、主要发表本人的技术原创博客
3、本站于 2015-12-01 开始建站
发送邮件是一个很耗时的操作。若不异步处理的话,会严重造成阻塞现象。
之前有关异步发送邮件先使用多线程异步处理,可参考我的网站搭建(第29天) 多线程异步发送邮件。
现在已经安装Redis和Celery,那么进一步完善修改异步发送邮件功能。
有关Redis和Celery的安装和使用可参考专题:Django+Celery+Redis。
为了讲解方便,先给出发送邮件的方法:
#coding:utf-8 from django.core.mail import EmailMessage def send_email_by_celery(subject, html_content, send_from, to_list, fail_silently=False): msg = EmailMessage(subject, html_content, send_from, to_list) msg.content_subtype = "html" msg.send(fail_silently)
Django发送邮件需要在Settings.py文件中配置。配置在上面多线程的链接有讲,这里不再赘述。
引入celery,修改代码如下:
#coding:utf-8 from __future__ import absolute_import from django.core.mail import EmailMessage from celery.decorators import task @task def send_email_by_celery(subject, html_content, send_from, to_list, fail_silently=False): msg = EmailMessage(subject, html_content, send_from, to_list) msg.content_subtype = "html" msg.send(fail_silently)
在需要发送邮件的地方使用delay方法,例如:
send_email_by_celery.delay(subject, html_content, send_from, to_list)
由于我前面开发过程中,无论是激活邮件还是评论邮件。最终都会调用一个send_html_email发送邮件的方法。在我的网站搭建(第29天) 多线程异步发送邮件中会使用多线程执行发送邮件代码。
将该部分代码修改为上面send_email_by_celery.delay即可。
这篇文章就结束了?当然没有!
之所以使用Celery来异步发送邮件还有个好处:可以在任务出错时,重新再执行一次。修改代码如下:
#coding:utf-8 from __future__ import absolute_import from django.core.mail import EmailMessage from celery.decorators import task @task(bind=True, max_retries=3, default_retry_delay=10) def send_email_by_celery(self, subject, html_content, send_from, to_list, fail_silently=False): try: msg = EmailMessage(subject, html_content, send_from, to_list) msg.content_subtype = "html" msg.send(fail_silently) except Exception as e: #出错尝试重新执行1次任务 raise self.retry(exc=e)
在task装饰器中加入3个参数,分别含义如下:
1)bind:是否绑定到Celery类中。绑定到类中,可以使用其他相关的方法
2)max_retries:最多尝试执行的次数
3)default_retry_delay:尝试执行的等待时间
这样,我们可以实现发送邮件出错了。再等10秒之后,重新发送一次。最多尝试执行3次。
还有要注意:send_email_by_celery加了self参数。
不过,绑定类的方法在执行过程中稍微会有点阻塞大概1~2秒。要求不是很严格的话,这点时间不算什么。
ps:之前有些网友反馈收不到用户激活邮件。我修改了用户中心,加入未验证邮箱的重新发送一次邮件的功能。该功能实现不难,判断是否绑定邮箱、是否激活,再发送一次邮件即可。同时可以写入缓存,限制发送邮件的频率。总不能一直让用户点发送,消耗服务器的资源。
再ps:后面考虑加入站内信功能。即使收不到评论和回复这种类型的邮件,可以通过站内信发送通知。
相关专题: Django+Celery+Redis