Django发送邮件

Django发送邮件流程分析

在这里插入图片描述

SMTP服务器介绍

SMTP服务器与IMAP或POP之间的区别
    发送(传递)邮件需要SMTP服务器,当用户使用电子邮件软件发送电子邮件时,通过电子邮件软件设置的SMTP服务器会将该电子邮件发送到目标服务器。更具体地说,邮件软件请求SMTP服务器传递邮件,请求邮件传递的SMTP服务器将传出邮件发送到管理目标邮件地址的SMTP服务器。
POP服务器的作用
    POP服务器是用于发送邮件所需的SMTP服务器,接收邮件需要POP服务器,SMTP服务器是将邮件发送给另一方,其中POP服务器对邮件服务器中的邮件进行储存。
IMAP服务器角色
    与POP服务器一样,IMAP服务器也是接收邮件所必需的服务器。对于将收到的邮件下载到收件人的个人计算机的POP服务器,通过使用IMAP服务器,对邮件进行读取。
SMTP服务器,POP服务器和IMAP服务器之间的差异
    发送邮件需要SMTP服务器,接收邮件需要POP服务器和IMAP服务器。
    用户在接收邮件时将使用POP服务器或IMAP服务器,两者之间的区别在于POP服务器将邮件从邮件服务器下载到收件人的计算机等,而IMAP服务器允许在保存邮件的同时读取邮件。IMAP服务器经常用于阅读

Django内置发送邮件的方法

send_email()方法介绍

  • 位置
    • django.core.mail模块提供了send_mail()来发送邮件。
  • 方法参数
    • send_mail(subject, message, from_email, recipient_list, html_message=None)
subject 邮件标题
message 普通邮件正文,普通字符串
from_email 发件人
recipient_list 收件人列表
html_message 多媒体邮件正文,可以是html字符串

准备发邮件服务器

1.点击进入《设置》界面, 再进入《客户端授权密码》界面
在这里插入图片描述
2. 开启《授权码》,并完成验证短信
在这里插入图片描述
3. 填写《授权码》
在这里插入图片描述
4. 完成《授权码》设置
在这里插入图片描述
5. 在django配置文件中配置邮件服务器

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' # 指定邮件后端
EMAIL_HOST = 'smtp.163.com' # 发邮件主机
EMAIL_PORT = 25 # 发邮件端口
EMAIL_HOST_USER = 'xxx' # 授权的邮箱
EMAIL_HOST_PASSWORD = 'xxx' # 邮箱授权时获得的密码,非注册登录密码
EMAIL_FROM = 'xxx' # 发件人抬头

发送邮件验证邮箱

发送邮箱验证邮件是耗时的操作,不能阻塞美多商城的响应,所以需要异步发送邮件。
我们继续使用Celery实现异步任务。

定义和调用发送邮件异步任务

@celery_app.task(bind=True, name='send_verify_email', retry_backoff=3)
def send_verify_email(self, to_email, verify_url):
    """
    发送验证邮箱邮件
    :param to_email: 收件人邮箱
    :param verify_url: 验证链接
    :return: None
    """
    subject = "邮箱验证"
    html_message = '<p>尊敬的用户您好!</p>' \
                   '<p>感谢您使用</p>' \
                   '<p>您的邮箱为:%s 。请点击此链接激活您的邮箱:</p>' \
                   '<p><a href="%s">%s<a></p>' % (to_email, verify_url, verify_url)
    try:
        send_mail(subject, "", settings.EMAIL_FROM, [to_email], html_message=html_message)
    except Exception as e:
        logger.error(e)
        # 有异常自动重试三次
        raise self.retry(exc=e, max_retries=3)

注册发邮件的任务:main.py

在发送邮件的异步任务中,我们用到了Django的配置文件。
所以我们需要修改celery的启动文件main.py。
在其中指明celery可以读取的Django配置文件。
最后记得注册新添加的email的任务

# celery启动文件
from celery import Celery

# 为celery使用django配置文件进行设置
import os
if not os.getenv('DJANGO_SETTINGS_MODULE'):
    os.environ['DJANGO_SETTINGS_MODULE'] = 'meiduo_mall.settings.dev'

# 创建celery实例
celery_app = Celery('meiduo')

# 加载celery配置
celery_app.config_from_object('celery_tasks.config')

# 自动注册celery任务
celery_app.autodiscover_tasks(['celery_tasks.sms', 'celery_tasks.email'])

调用发送邮件异步任务

send_verify_email.delay(email, verify_url)

启动Celery

celery -A celery_tasks.main worker -l info

生成邮箱验证链接

定义生成邮箱验证链接方法, 使用序列化器序列化发送的内容, 保证数据安全

def generate_verify_email_url(user):
    """
    生成邮箱验证链接
    :param user: 当前登录用户
    :return: verify_url
    """
    serializer = Serializer(settings.SECRET_KEY, expires_in=constants.VERIFY_EMAIL_TOKEN_EXPIRES)
    data = {'user_id': user.id, 'email': user.email}
    token = serializer.dumps(data).decode()
    verify_url = settings.EMAIL_VERIFY_URL + '?token=' + token
    return verify_url

配置相关参数

# 邮箱验证链接
EMAIL_VERIFY_URL = 'http://www.meiduo.site:8000/emails/verification/'

使用邮箱验证链接

verify_url = generate_verify_email_url(request.user)
send_verify_email.delay(email, verify_url)

验证邮箱后端逻辑

验证链接提取用户信息, 反序列化token, 提取里面的内容

def check_verify_email_token(token):
    """
    验证token并提取user
    :param token: 用户信息签名后的结果
    :return: user, None
    """
    serializer = Serializer(settings.SECRET_KEY, expires_in=constants.VERIFY_EMAIL_TOKEN_EXPIRES)
    try:
        data = serializer.loads(token)
    except BadData:
        return None
    else:
        user_id = data.get('user_id')
        email = data.get('email')
        try:
            user = User.objects.get(id=user_id, email=email)
        except User.DoesNotExist:
            return None
        else:
            return user

验证邮箱后端逻辑实现

验证邮箱的核心:就是将用户的email_active字段设置为True

class VerifyEmailView(View):
    """验证邮箱"""

    def get(self, request):
        """实现邮箱验证逻辑"""
        # 接收参数
        token = request.GET.get('token')

        # 校验参数:判断token是否为空和过期,提取user
        if not token:
            return http.HttpResponseBadRequest('缺少token')

        user = check_verify_email_token(token)
        if not user:
            return http.HttpResponseForbidden('无效的token')

        # 修改email_active的值为True
        try:
            user.email_active = True
            user.save()
        except Exception as e:
            logger.error(e)
            return http.HttpResponseServerError('激活邮件失败')

        # 返回邮箱验证结果
        return redirect(reverse('users:info'))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值