비밀번호를 찾기 위해서 가입 했던 이메일로 인증번호을 보내는 기능에 대한 설명
## users/apis.py
class SendPasswordEmailApi(PublicApiMixin, APIView):
def post(self, request, *args, **kwargs):
"""
비밀번호 변경 인증 코드 발송
"""
target_username = request.data.get('username', '')
target_email = request.data.get('email', '')
target_user = User.objects.filter(
username=target_username,
email=target_email
)
if target_user.exists():
auth_string = email_auth_string()
target_user.first().profile.auth = auth_string
target_user.first().profile.save()
try:
send_mail(
'PROJECT 비밀번호 찾기 인증 메일입니다.',
recipient_list=[target_email],
html=render_to_string('recovery_email.html', {
'auth_string': auth_string,
})
)
except:
return Response({
"message": "email error",
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
return Response({
"message": "Verification code sent"
}, status=status.HTTP_200_OK)
else:
return Response({
"message": "User does not exist"
}, status=status.HTTP_404_NOT_FOUND)
class ConfirmPasswordEmailApi(PublicApiMixin, APIView):
def post(self, request, *args, **kwagrs):
"""
1. 인증 코드 확인
2. 해당 username으로 로그인
"""
target_username = request.data.get('username', '')
target_code = request.data.get('code', '')
user = User.objects.get(username=target_username)
profile = user.profile
if profile.auth == target_code:
profile.auth = get_random_secret_key()
profile.save()
response = Response({
"message": "Verification success",
"user": target_username,
}, status=status.HTTP_202_ACCEPTED)
response = jwt_login(response=response, user=user)
return response
else:
return Response({
"message": "Verification Failed"
}, status=status.HTTP_401_UNAUTHORIZED)
SendPasswordEmailApi
코드의 중간을 보면
try:
send_mail(
'PROJECT 비밀번호 찾기 인증 메일입니다.',
recipient_list=[target_email],
html=render_to_string('recovery_email.html', {
'auth_string': auth_string,
})
)
send_mail 이라는 함수를 발견할 수 있다.
이 함수가 user의 이메일로 인증 코드를 발송해주는 역할을 수행한다.
## users/services.py
import string
import random
import threading
from django.conf import settings
from django.core.mail import EmailMultiAlternatives
class EmailThread(threading.Thread):
def __init__(self, subject, message, from_email, recipient_list,
fail_silently, html):
self.subject = subject
self.message = message
self.from_email = from_email
self.recipient_list = recipient_list
self.fail_silently = fail_silently
self.html = html
threading.Thread.__init__(self)
def run(self):
msg = EmailMultiAlternatives(
self.subject, self.message, self.from_email, to=self.recipient_list)
if self.html:
msg.attach_alternative(self.html, "text/html")
msg.send(self.fail_silently)
def send_mail(subject, recipient_list, message='',
from_email=settings.EMAIL_HOST_USER,
fail_silently=False, html=None, *args, **kwargs):
EmailThread(
subject, message, from_email, recipient_list, fail_silently, html
).start()
def email_auth_string():
LENGTH = 12
string_pool = string.ascii_letters + string.digits
auth_string = ""
for i in range(LENGTH):
auth_string += random.choice(string_pool)
return auth_string
send_mail
Django 에는 기본적으로 send_mail 함수가 내장되어있다. 하지만 내장된 send_mail 함수는 '동기식 방법'으로, 메일의 전송이 완료되어 결과를 받아야지만 함수가 return을 수행하기 때문에 여러명이 사용하는 홈페이지에서는 딜레이 때문에 사용이 불가능하다고 판단했다.
제목, 수취인 리스트, 메시지, 이메일 송신자, fail_silently(false인 경우 메일 발송에 실패 했을 때 알림), html
위 정보를 받아서 EmailThread 객체를 만들고, 바로 start메서드를 실행시켜 Thread의 run을 통해 이메일을 전송한다.
email_auth_string
인증 번호를 랜덤으로 생성해주는 함수이다.
ascii_letters는 영문 대소문자이고 digits는 숫자이다. 이들을 조합해 12자리의 랜덤 인증번호를 생성한 후 이를 반환한다.
'Back-End > Django' 카테고리의 다른 글
[Django] django-debug-toolbar 안보임 오류 해결 (0) | 2021.12.17 |
---|---|
[Django] DataFrame to CSV (download) (0) | 2021.12.01 |
[Django] Django Api 인증, 권한 설정 (0) | 2021.10.27 |
[Django] PROJECT 홈페이지 (유저 모델, 쿼리 최적화) (2) | 2021.10.24 |
[Django] ORM 쿼리 최적화 (select_related, annotate, aggregates) (0) | 2021.10.11 |