diff --git a/account/tasks.py b/account/tasks.py new file mode 100644 index 00000000..6470b704 --- /dev/null +++ b/account/tasks.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from celery import shared_task +from utils.mail import send_email + + +@shared_task +def _send_email(from_name, to_email, to_name, subject, content): + send_email(from_name, to_email, to_name, subject, content) diff --git a/account/templates/reset_password_email.html b/account/templates/reset_password_email.html new file mode 100644 index 00000000..5a0b5915 --- /dev/null +++ b/account/templates/reset_password_email.html @@ -0,0 +1,78 @@ + + + + + + +
+ + + + + + +
+ {{ website_name }} 登录信息找回 +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Hello, {{ username }}: +
+ 您刚刚在 {{ website_name }} 申请了找回登录信息服务。 +
+ 请在30分钟内点击下面链接设置您的新密码: +
+ 重置密码 +
+ 如果上面的链接点击无效,请复制以下链接至浏览器的地址栏直接打开。 +
+ + {{ link }} + +
+ 如果您没有提出过该申请,请忽略此邮件。有可能是其他用户误填了您的邮件地址,我们不会对你的帐户进行任何修改。 + 请不要向他人透露本邮件的内容,否则可能会导致您的账号被盗。 +
+
\ No newline at end of file diff --git a/account/views/oj.py b/account/views/oj.py index 1d63f0b4..86f82d6b 100644 --- a/account/views/oj.py +++ b/account/views/oj.py @@ -1,14 +1,18 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +import os + from datetime import timedelta from django.contrib import auth +from django.conf import settings from django.core.exceptions import MultipleObjectsReturned from django.utils.translation import ugettext as _ from django.utils.timezone import now from otpauth import OtpAuth +from conf.models import WebsiteConfig from utils.api import APIView, validate_serializer from utils.captcha import Captcha from utils.shortcuts import rand_str @@ -18,6 +22,7 @@ from ..models import User, UserProfile from ..serializers import (UserChangePasswordSerializer, UserLoginSerializer, UserRegisterSerializer, ApplyResetPasswordSerializer) +from ..tasks import _send_email class UserLoginAPI(APIView): @@ -114,14 +119,24 @@ class ApplyResetPasswordAPI(APIView): except User.DoesNotExist: return self.error(_("User does not exist")) if user.reset_password_token_expire_time and 0 < ( - user.reset_password_token_expire_time - now()).total_seconds() < 20 * 60: + user.reset_password_token_expire_time - now()).total_seconds() < 20 * 60: return self.error(_("You can only reset password once per 20 minutes")) user.reset_password_token = rand_str() user.reset_password_token_expire_time = now() + timedelta(minutes=20) user.save() - # TODO:email template - # TODO:send email + email_template = open("reset_password_email.html", "w", + encoding="utf-8").read() + email_template = email_template.replace("{{ username }}", user.username). \ + replace("{{ website_name }}", settings.WEBSITE_INFO["website_name"]). \ + replace("{{ link }}", settings.WEBSITE_INFO["url"] + "/reset_password/t/" + + user.reset_password_token) + config = WebsiteConfig.objects.first() + _send_email.delay(config.name, + user.email, + user.username, + config.name + " 登录信息找回邮件", + email_template) return self.success(_("Succeeded")) diff --git a/requirements.txt b/requirements.txt index c8376311..f17f7a4c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,6 @@ djangorestframework==3.4.0 dateutil otpauth pillow -python-dateutil \ No newline at end of file +python-dateutil +celery +Envelopes \ No newline at end of file diff --git a/reset_password_email.html b/reset_password_email.html new file mode 100644 index 00000000..e69de29b diff --git a/utils/mail.py b/utils/mail.py new file mode 100644 index 00000000..6ff7e7d4 --- /dev/null +++ b/utils/mail.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from envelopes import Envelope + +from conf.models import SMTPConfig + + +def send_email(from_name, to_email, to_name, subject, content): + smtp = SMTPConfig.objects.first() + if not smtp: + return + envlope = Envelope(from_addr=(smtp.email, from_name), + to_addr=(to_email, to_name), + subject=subject, + html_body=content) + envlope.send(smtp.server, + login=smtp.email, + password=smtp.password, + port=smtp.port, + tls=smtp.tls)