※ 프로젝트를 진행하며 dj_rest_auth
의 이메일 인증 방식을 사용해보았으며, 해당 작업을 하면서 이해가 잘 안되서 글로 정리하면서 한번더 복습을 해보려 합니다.
※ dj_rest_auth.registration
의 기본 설정이 다 되었다는 가정하에 진행하였습니다.
(views, urls, settings 등...)
# settings.py
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = env('EMAIL_HOST_USER') # 가입 인증 메일을 보낼 이메일
EMAIL_HOST_PASSWORD = env('EMAIL_HOST_PASSWORD') # 비밀번호(구글에서 앱 비밀번호 발급 필요)
EMAIL_USE_TLS = True
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
ACCOUNT_CONFIRM_EMAIL_ON_GET = True
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL = '/'
ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 1
ACCOUNT_EMAIL_SUBJECT_PREFIX = '인증 메일 제목앞에 붙일 접두사'
EMAIL_BACKEND
django.core.mail.backends.smtp.EmailBackend
을 지정하여 설정EMAIL_HOST
, EMAIL_PORT
, EMAIL_HOST_USER
, EMAIL_HOST_PASSWORD
, DEFAULT_FROM_EMAIL
ACCOUNT_CONFIRM_EMAIL_ON_GET
True
이면, 사용자가 회원가입 폼을 제출할 때 이메일 확인 링크를 받을 수 있습니다.ACCOUNT_EMAIL_REQUIRED
True
로 설정하면, 사용자는 반드시 이메일 주소를 입력해야 합니다.ACCOUNT_EMAIL_VERIFICATION
EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL
ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS
# accounts앱/urls.py
from .views import ConfirmEmailView
from dj_rest_auth.registration.views import VerifyEmailView
urlpatterns = [
...기타 url...
re_path(r'^account-confirm-email/$', VerifyEmailView.as_view(), name='account_email_verification_sent'),
re_path(r'^account-confirm-email/(?P<key>[-:\w]+)/$', ConfirmEmailView.as_view(), name='account_confirm_email'),
]
account-confirm-email/
로 접속하여 이메일 확인 메시지를 전송account-confirm-email/<key>/
)를 클릭하여 이메일 주소를 확인from allauth.account.models import EmailConfirmation, EmailConfirmationHMAC
from django.http import HttpResponseRedirect
from rest_framework.views import APIView
from rest_framework.permissions import AllowAny
class ConfirmEmailView(APIView):
permission_classes = [AllowAny]
def get(self, *args, **kwargs):
self.object = confirmation = self.get_object()
confirmation.confirm(self.request)
return HttpResponseRedirect('/login/success/') # 인증성공
def get_object(self, queryset=None):
key = self.kwargs['key']
email_confirmation = EmailConfirmationHMAC.from_key(key)
if not email_confirmation:
if queryset is None:
queryset = self.get_queryset()
try:
email_confirmation = queryset.get(key=key.lower())
except EmailConfirmation.DoesNotExist:
return HttpResponseRedirect('/login/failure') # 인증실패
return email_confirmation
def get_queryset(self):
qs = EmailConfirmation.objects.all_valid()
qs = qs.select_related("email_address__user")
return qs
def get()
- HTTP GET 요청을 처리
• get_object
메소드를 통해 확인 객체를 얻습니다.
• 확인 객체의 confirm 메소드를 호출하여 이메일 주소를 확인합니다.
• 이메일 주소가 성공적으로 확인되면 /login/success/로 리다이렉트합니다.
• 확인이 실패하면 /login/failure로 리다이렉트합니다
def get_object()
• URL에서 전달된 키(key)를 사용하여 이메일 확인 객체(EmailConfirmationHMAC
)를 가져오는 역할을 합니다.
• 만약 해당 키로 EmailConfirmationHMAC 객체를 가져오지 못하면, 기본적인 EmailConfirmation
모델을 사용하여 키와 일치하는 객체를 조회합니다.
• 만약 이메일 확인 객체가 존재하지 않으면 /login/failure
로 리다이렉트합니다.
def get_queryset()
• EmailConfirmation
모델에서 모든 유효한 객체를 가져오는데, 이때 all_valid 메소드를 사용합니다.
• select_related
를 사용하여 관련된 이메일 주소의 사용자 정보를 함께 조회하도록 설정합니다.
템플릿 위치 설정
# settings.py
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [BASE_DIR, 'templates'],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
manage.py와 같은 디렉토리에 templates/account/email 폴더 생성
email_confirmation_signup_message.html
작성 - 이메일의 메인 컨텐츠가 되겠습니다.
<!-- email_confirmation_signup_message.html -->
{% load account %}
{% load i18n %}
{% block content %}
{% autoescape off %}
{% user_display user as user_display %}
{% blocktrans with site_name=current_site.name site_domain=current_site.domain %}
<!DOCTYPE html>
<html lang="ko-KR">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title></title>
</head>
<body>
<div>
<div>
<h1>안녕하세요, ~~~입니다</h1>
<p>아래 버튼을 눌러 계정을 인증하고, 로그인해주세요!</p>
<p>귀하의 아이디는 <span style="font-weight: bold;">{{ user_display }}</span>입니다.</p>
<div>
<a href="{{ activate_url }}">계정 인증하기</a>
</div>
<p>만약 동작하지 않는다면 다음 링크를 복사해 브라우저에 붙여넣기해주세요</p>
<p>{{ activate_url }}</p>
<p>문의사항이 있다면 이메일 주소로 보내주세요</p>
</div>
</div>
</body>
</html>
{% endblocktrans %}
{% endautoescape %}
{% endblock %}
email_confirmation_subject.txt
작성 - 이메일의 제목이 되겠습니다.
<!--email_confirmation_subject.txt-->
{프로젝트명}에 오신 것을 환영합니다!
회원가입 시 사용하는 템플릿 명
account/email/email_confirmation_signup_message.html
인증 시 사용하는 템플릿 명
account/email/email_confirmation_message.html