Henu
개발냥발
Henu
전체 방문자
오늘
어제
  • 분류 전체보기 (411)
    • DevOps (52)
      • Kubernetes (19)
      • Docker (14)
      • AWS (3)
      • Nginx (4)
      • Linux (4)
      • ArgoCD (1)
      • CN (2)
      • NATS (0)
      • Git (5)
    • Back-End (30)
      • Django (18)
      • Spring (5)
      • JPA (1)
      • MSA (5)
    • CS (87)
      • SystemSoftware (20)
      • OS (25)
      • Computer Architecture (16)
      • Network (23)
      • Database (2)
    • Lang (21)
      • Java (9)
      • Python (4)
      • C# (8)
    • Life (12)
    • 블록체인 (2)
    • Algorithm (204)
      • BOJ (160)
      • 프로그래머스 (19)
      • LeetCode (4)
      • SWEA (1)
      • 알고리즘 문제 해결 전략 (8)
      • DS, algorithms (7)
      • Checkio (5)
    • IT (2)

블로그 메뉴

  • GitHub
  • 글쓰기
  • 관리자

공지사항

  • Free!

인기 글

태그

  • Kubernetes
  • docker
  • DFS
  • 백트래킹
  • boj
  • BFS
  • 프로그래머스
  • django
  • 다이나믹 프로그래밍
  • Network

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Henu

개발냥발

Back-End/Django

[Djnago] Django 이메일 인증하기(Thread)

2021. 10. 27. 21:53

비밀번호를 찾기 위해서 가입 했던 이메일로 인증번호을 보내는 기능에 대한 설명

## 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
    'Back-End/Django' 카테고리의 다른 글
    • [Django] django-debug-toolbar 안보임 오류 해결
    • [Django] DataFrame to CSV (download)
    • [Django] Django Api 인증, 권한 설정
    • [Django] PROJECT 홈페이지 (유저 모델, 쿼리 최적화)

    티스토리툴바