我的网站搭建(第54天) Celery异步发送邮件

  • 发布时间:2017年5月16日 15:57
  • 作者:杨仕航
* 该文是基于Python2.7开发的,最新Python3.x和Django2.x视频教程可以前往 >> Django2.0视频教程

发送邮件是一个很耗时的操作。若不异步处理的话,会严重造成阻塞现象。

之前有关异步发送邮件先使用多线程异步处理,可参考我的网站搭建(第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:后面考虑加入站内信功能。即使收不到评论和回复这种类型的邮件,可以通过站内信发送通知。

上一篇:Python使用__new__方法实现单例模式

下一篇:Python正则使用函数替换

相关专题: Django+Celery+Redis   

评论列表

智慧如你,不想发表一下意见吗?

新的评论

清空