2023-05-27 TIL

0v0baek·2023년 5월 27일
0

TIL

목록 보기
62/92

[Django] 이메일 인증 구현하기

👉 참고한 블로그

[Django] 이메일 보내기
[Django] 이메일 인증하기 (+이메일 템플릿)
거의 이 블로그를 그대로 따라했다.
감사합니다... ㅎㅎ

1. 발송용 메일 세팅

Gmail을 이용했다. (새로 가입하기 편해서)

✅ IMAP 설정 허용

1) 빠른 설정 > 모든 설정 보기

2) 전달 및 POP/IMAP > IMAP 사용 > 변경사항 저장

✅ 앱 비밀번호 발급해주기

1) 구글 계정관리 들어가기

2) 보안 > 2단계 인증 설정

3) 설정 완료 후 다시 2단계 인증 클릭 > 앱 비밀번호

4) 메일 > 기타 > 이름 입력


이름 아무거나 입력해도 된다.
나는 django 프로젝트용 이라고 썼다.

2. django에서 이메일 보내보기

✅ 코드 세팅

🔎 settings.py

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = get_secret("EMAIL_HOST_USER")
EMAIL_HOST_PASSWORD = get_secret("EMAIL_HOST_PASSWORD")
EMAIL_USE_TLS = True
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER

지금 프로젝트는 secrets.json을 사용해서 그걸 응용해서 설정해줬다.

🔎 secrets.json

{
  "SECRET_KEY": "내 시크릿 키",
  "EMAIL_HOST_USER": "이메일 주소",
  "EMAIL_HOST_PASSWORD": "발급받은 앱 비밀번호"
}

secrets.json에 반드시 입력도 해주자.

✅ 이메일 전송

poetry run py manage.py shell

명령어 입력해주자.

from django.core.mail import EmailMessage
email = EmailMessage('제목', '내용', to=['받을 사람 이메일 주소'])
email.send()

차례대로 입력.

저렇게 email.send() 아래에 1이 뜨면 전송이 잘 된거다.

아주 잘 온다!
절반 성공.

3. 이메일 인증 구현하기

✅ 코드 세팅하기

이메일 인증을 위해서는 추가로 세팅해줘야 하는 부분이 있다.

🔎 users/tokens.py

from django.contrib.auth.tokens import PasswordResetTokenGenerator

class UserVerifyToken(PasswordResetTokenGenerator):
    def _make_hash_value(self, user, timestamp):
        return user.pk + timestamp + user.is_active

user_verify_token = UserVerifyToken()

생성할 토큰에 정보를 담아주기 위해 tokens.py 를 생성해주자.

PasswordResetTokenGenerator를 상속받아 UserVerifyToken을 만들었다.

그러고, user_verify_token 변수에 유저 pk값, 시간, active 여부를 담은 토큰을 생성하도록 _make_hash_value 메소드를 오버라이딩 해준다.

🔎 users/urls.py

urlpatterns = [
    ...
    path("verify/<str:uidb64>/<str:token>/", views.EmailVerifyView.as_view(), name="email_verify_view"),
    ]

이메일 인증 뷰 용 url을 추가해주자.

🔎 users/serializers.py

class UserSerializer(serializers.ModelSerializer):
	...

    def create(self, validated_data):
    	...

        uidb64 = urlsafe_base64_encode(force_bytes(user.id))
        token = user_verify_token.make_token(user)
        to_email = user.email
        email = EmailMessage(
            f"[IOTD] {user.nickname}님의 이메일 인증",
            f"http://127.0.0.1:8000/users/verify/{uidb64}/{token}",
            to=[to_email],
        )
        email.send()
        return user

유저 생성(회원가입) 시 사용하는 UserSerializer
email을 전송하는 메소드를 추가로 넣어줬다.

이때, url에 포함될 유저의 아이디가 에러나지 않게 인코딩 한 값을 넣어준다.

🔎 users/views.py

# 맨 윗줄
from django.utils.encoding import force_str
from django.utils.http import urlsafe_base64_decode
from rest_framework.generics import get_object_or_404
from .tokens import user_verify_token

...

class EmailVerifyView(APIView):
    def get(self, request, uidb64, token):
        try:
            uid = force_str(urlsafe_base64_decode(uidb64))
            user = User.objects.get(pk=uid)
            if user_verify_token.check_token(user, token):
                User.objects.filter(pk=uid).update(is_active=True)
                return Response({"message": "이메일 인증 완료"}, status=status.HTTP_200_OK)
            return Response({"error": "인증 실패"}, status=status.HTTP_400_BAD_REQUEST)
        except KeyError:
            return Response({"error": "KEY ERROR"}, status=status.HTTP_400_BAD_REQUEST)

먼저 url에서 받아온 id값을 디코딩 해준다.

그리고 PasswordResetTokenGenerator하위의 메소드인 check_token으로 토큰을 확인해준 뒤,
일치하는 유저의 is_activeTrue로 변경해준다.

그 과정에서 실패할 경우엔 인증 실패와 KeyError 두 부분으로 빠지도록 했다.

🔎 users/models.py

class User(AbstractBaseUser):
	...
    is_active = models.BooleanField(default=False)

이메일 인증 시에만 is_activeTrue로 바꾸도록
default값을 False로 설정,
migration 해주자!!

✅ 이메일 작동 확인

포스트맨에서 작동 테스트를 해봤다.


보낼 이메일과 비밀번호를 json 데이터 값으로 전송,
가입됐다는 메세지가 잘 전송됐다!

이메일도 무사히 전송됐다.
사용자 라는 닉네임이 default 값이니, 잘 온 것 같다!

링크를 눌러서 확인해보니, 인증도 잘 된다!!
db에서 is_active도 잘 활성화 되어있다.

profile
개발 공부 하는 비전공자 새내기. 꾸준히 합시다!

0개의 댓글