1、配置邮件服务器
在学习怎么写代码来发送邮箱之前,我们先来认识下Django发送邮箱的过程是怎么样的。
如上图,我们的客户端是将邮件发送到一个叫做 SMTP 的服务器上面,SMTP转发邮件到 POP3 上,最后我们的用户从 POP3 去取邮件,这样的一个过程。
所以,我们在写具体的实现代码之前,需要配置好第三方的邮箱服务器。配置好了才可以借助第三方的服务器完成发送邮箱的功能。
配置完成后,我们只需要负责做好我们的客户端如何和SMTP之间通讯即可。我们Django的商城客户端通过send_mall()方法来发送邮箱到SMTP。如上图,我们需要传入这些参数即可。
接下来,我们来配置邮箱服务器。这里已QQ邮箱为例子。
I、点击进入"设置",进入"帐户",下拉找到"POP3"
点击"开启",开启POP3/SMTP服务,发送 短信验证
保存授权码,在你的项目中会用到
最后,在你项目的settings.py中添加以下代码
# EMAIL 发邮件服务器的配置
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' # 指定邮件后端
EMAIL_HOST = 'smtp.qq.com' # 发邮件主机
EMAIL_PORT = 25 # 发邮件端口
EMAIL_HOST_USER = '159****859@qq.com' # 授权的邮箱
EMAIL_HOST_PASSWORD = 'fsie****dwfgbj' # 邮箱授权时设置或者获取的授权码,非注册登录密码
EMAIL_FROM = '大象商城<159****859@qq.com>' # 发件人抬头
2、使用 django.core.mail.send_mail() 发送邮件
配置完成第三方的邮箱服务器之后,接下来,我们只需调用send_mail()方法,来给SMTP发送邮件就可以了。这里只需把send_mail需要的参数准备好传入就可以了。
定义一个签名工具类,加密userid
# sign.py
from django.conf import settings
from itsdangerous import TimedJSONWebSignatureSerializer, BadSignature
class Signer(object):
def __init__(self, expires_in):
self.serializer = TimedJSONWebSignatureSerializer(settings.SECRET_KEY, expires_in)
def sign(self, obj):
"""
对python字典先进行json序列化,再对序列化结果进行签名
:param obj:
:return: 签名后的字符串
"""
token = self.serializer.dumps(obj)
return token.decode()
def unsign(self, s):
"""
对传入的字符串验证签名, 验证成功返回字符串中的被签名的数据对应的python字典
:param s: 要验证的签名字符串
:return: python字典
"""
try:
obj = self.serializer.loads(s)
except BadSignature:
obj = None
return obj
具体的实现代码:
# views.py
userid = {"user_id": request.user.id}
token = Signer(constants.EMAIL_VERIFY_SIGN_EXPIRES).sign(userid)
verify_url = settings.EMAIL_VERIFY_URL + "?token=" + token
subject = "大象商城邮箱验证"
message = ""
from_email = settings.EMAIL_FROM
recipient_list = [email]
html_message = '<p>尊敬的用户您好!</p>' \
'<p>感谢您使用蜗牛商城。</p>' \
'<p>您的邮箱为:%s 。请点击此链接激活您的邮箱:</p>' \
'<p><a href="%s">%s<a></p>' % (email, verify_url, verify_url)
send_mail(subject, message, from_email, recipient_list, html_message=html_message)
这里我们实现的同步的发送邮箱验证的功能,但是发送邮件验证是耗时的操作,会阻塞我们的商城的响应,所以可以用异步发送邮件。使用celery实现异步任务。
3、邮件的验证功能实现
当点击邮件中的链接之后,就会触发验证的功能。
# urls.py
re_path(r"^emails/verification/$", views.EmailVerifyView.as_view(), name="emails_verify"),
# views.py
class EmailVerifyView(View):
def get(self, request):
"""
激活邮箱
:param request:
:return:
"""
# 1.服务器提取签名后的 userid
token = request.GET.get('token')
# 2.对userid进行签名验证, 验证失败,返回错误信息
if not token:
return HttpResponseForbidden("缺少必须参数")
user_id: dict = Signer(constants.EMAIL_VERIFY_SIGN_EXPIRES).unsign(token)
if not user_id or 'user_id' not in user_id.keys():
return HttpResponseForbidden("token 无效")
try:
# 3.1 查询userid是否存在, userid不存在,返回错误信息
user = User.objects.get(id=user_id.get("user_id"))
# 3.2 修改用户表中邮箱为激活状态
user.email_active = True
user.save()
except User.DoesNotExist:
return HttpResponseForbidden("激活邮箱失败")
# 4.重定向到用户中心页面
return redirect(reverse("users:info"))