[Django] 이메일 보내기
[Django] 이메일 인증하기 (+이메일 템플릿)
거의 이 블로그를 그대로 따라했다.
감사합니다... ㅎㅎ
Gmail
을 이용했다. (새로 가입하기 편해서)
이름 아무거나 입력해도 된다.
나는 django
프로젝트용 이라고 썼다.
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
을 사용해서 그걸 응용해서 설정해줬다.
{
"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
이 뜨면 전송이 잘 된거다.
아주 잘 온다!
절반 성공.
이메일 인증을 위해서는 추가로 세팅해줘야 하는 부분이 있다.
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
메소드를 오버라이딩 해준다.
urlpatterns = [
...
path("verify/<str:uidb64>/<str:token>/", views.EmailVerifyView.as_view(), name="email_verify_view"),
]
이메일 인증 뷰 용 url
을 추가해주자.
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에 포함될 유저의 아이디가 에러나지 않게 인코딩 한 값을 넣어준다.
# 맨 윗줄
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_active
를 True
로 변경해준다.
그 과정에서 실패할 경우엔 인증 실패와 KeyError
두 부분으로 빠지도록 했다.
class User(AbstractBaseUser):
...
is_active = models.BooleanField(default=False)
이메일 인증 시에만 is_active
를 True
로 바꾸도록
default
값을 False
로 설정,
꼭 migration
해주자!!
포스트맨에서 작동 테스트를 해봤다.
보낼 이메일과 비밀번호를 json
데이터 값으로 전송,
가입됐다는 메세지가 잘 전송됐다!
이메일도 무사히 전송됐다.
사용자 라는 닉네임이 default 값이니, 잘 온 것 같다!
링크를 눌러서 확인해보니, 인증도 잘 된다!!
db에서 is_active
도 잘 활성화 되어있다.