基于django和celery的邮件异步发送(记录)

本文总阅读量

前记

在验证用户邮箱时,需要发送一个链接给用户的邮箱,让用户点击以确保用户输入的邮箱是他本人所有。
但是email是由提供商进行发送的,我们需要先把请求发给提供商再由提供商发送,如果不使用异步发送,在用户点击按钮后,必须等到后台收到提供商的返回结果,我们才能把数据返回给用户。

1.Celery介绍

由于使用同步发送带来了许多麻烦,所以可以考虑用任务队列进行异步发送,在python中的Celery库发挥的就是这个作用,而且Celery接口简单,开发容易,5分钟就写出了一个异步发送邮件的服务。Celery本身不含消息服务,它使用第三方消息服务来传递任务,目前,Celery支持的消息服务有RabbitMQ、Redis甚至是数据库。
更多介绍以及入门

2.与django结合异步发送邮件的服务

假设之前已经完成了email发送逻辑(同步方式)

2.1setting.py设置

1
2
3
4
5
6
7
8
9
10
11
EMAIL_HOST = 'smtp.163.com'                # 服务提供商
EMAIL_PORT = 25 # 端口
EMAIL_HOST_USER = "***" # 用户名
EMAIL_HOST_PASSWORD = "***" # 密码
EMAIL_USE_TLS = False # False就好了
EMAIL_FROM = "***" # 来源名字


###配置Broker
BROKER_URL = 'redis://127.0.0.1:6379/0'
BROKER_TRANSPORT = 'redis'

2.2celery文件

在自己的project文件夹内(与setting.py同级)
创建celery.py文件,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import os
import django

from celery import Celery
from django.conf import settings

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_project.settings') # django_project 为自己的project名
django.setup()

app = Celery('django_project') # 定义自己的app名字后面调用需要用到

app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

2.3发送邮件的py

主要是从celery文件导入app并在自己发送的函数上面使用@app.task装饰器
其他的全是我自己的发送邮件规则

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
54
55
56
57
58
59
60
61
62
63
64
65
from random import Random


from django.core.mail import send_mail
from django_project.settings import EMAIL_FROM

from users.models import EmailVerifyRecord
from django_project.celery import app


@app.task
def send_register_email(email, send_type="register", num=16):
"""
发送注册邮件时的链接
:param email: email
:param send_type: 'register'or'forget'
:return:
"""
email_record = EmailVerifyRecord()
code_str = random_str(num)
email_record.code = code_str
email_record.email = email
email_record.send_type = send_type
email_record.save()

if send_type == 'register':
email_title = "注册激活链接"
email_body = "请点击下面的链接激活你的账号:http://127.0.0.1:8000/active/{0}".format(code_str)

send_mail(email_title, email_body, EMAIL_FROM, [email])

elif send_type == 'forget':
email_title = "重置密码链接"
email_body = "请点击下面的链接重置你的密码:http://127.0.0.1:8000/reset/{0}".format(code_str)

send_mail(email_title, email_body, EMAIL_FROM, [email])

elif send_type == 'update_email':
email_title = "邮箱修改验证码"
email_body = "验证码为:{0}".format(code_str)

send_mail(email_title, email_body, EMAIL_FROM, [email])

else:
pass


def random_str(random_length=8):
"""
随机字符串生成
:param random_length: 生成字符串长度(init)
:return: 返回字符串(str)
"""
code_str = ''
generate_random_str = [chr(i) for i in range(65, 91)] + \
[chr(i) for i in range(97, 123)] + \
[str(i) for i in range(10)]
chars = ''.join(generate_random_str)
length = len(chars) - 1
random = Random()
for i in range(random_length):
code_str += chars[random.randint(0, length)]
return code_str


2.4view

将原本发送邮件的函数

1
send_register_email(email, "update_email", num=4)

改为

1
send_register_email.delay(email, "update_email", num=4)

2.5运行celery服务

Broker设置为redis所以必须先启动

1
service redis start

检查是否启动并监听端口

1
ps aux|grep redis

在celery所在目录输入命令启动celery

1
celery -A (自己定义的名字) worker -l debug

2.6测试

发送时celery服务的提示,显示succeeded
image

查看评论