I'm trying to add a feature on my Django App to send users who forgot their passwords a link to reset them via email. I'm not sure if I have set up my password reset email feature correctly, or if my AWS SES isn't configured to it.
I have successfully sent email with a verified email in django shell with the method:
send_mail('title','message','[email protected]',['[email protected]])
Which means that I have configured my environment variables correctly, but incase you need to see it: Here's my Django Settings.py:
AWS_ACCESS_KEY_ID = env('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = env('AWS_SECRET_ACCESS_KEY')
EMAIL_BACKEND = 'django_ses.SESBackend'
AWS_SES_REGION_NAME = 'us-east-2'
AWS_SES_REGION_ENDPOINT = 'email.us-east-2.amazonaws.com'
Here are my files
views.py:
from re import search
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .forms import SignUpForm, AddRecordForm, RecordFilterForm, CustomUserChangeForm, CustomPasswordChangeForm
from .models import Record
from django.db.models import Q
from django.views.decorators.http import require_http_methods
from django.http import JsonResponse
from django.contrib.auth.forms import UserChangeForm
from django.core.exceptions import ValidationError
from django.contrib.auth import update_session_auth_hash
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
#here is the homepage containing all the search filters
def home(request):
records = Record.objects.all().order_by('created_at')
search_form = RecordFilterForm(request.GET)
if search_form.is_valid():
search_query = search_form.cleaned_data.get('search')
university_filter = search_form.cleaned_data.get('university_filter')
course_name_filter = search_form.cleaned_data.get('course_name_filter')
is_paid_filter = search_form.cleaned_data.get('is_paid')
courses_filter = search_form.cleaned_data.get('course_category')
duration_filter = search_form.cleaned_data.get('duration')
gpa_filter = search_form.cleaned_data.get('gpa')
if search_query:
records = records.filter(
Q(student_name__icontains=search_query) |
Q(university__icontains=search_query) |
Q(course_name__icontains=search_query) |
Q(professor_name__icontains=search_query) |
Q(description__icontains=search_query)
)
if university_filter:
records = records.filter(university__icontains=university_filter)
if course_name_filter:
records = records.filter(course_name__icontains=course_name_filter)
if is_paid_filter:
records = records.filter(is_paid=is_paid_filter)
if courses_filter:
records = records.filter(course_category__iexact=courses_filter)
if duration_filter:
records = records.filter(duration=duration_filter)
gpa_filter = search_form.cleaned_data.get('gpa')
if gpa_filter:
records = records.filter(result__startswith=gpa_filter)
# Pagination
page = request.GET.get('page', 1)
paginator = Paginator(records, 15)
try:
records = paginator.page(page)
except PageNotAnInteger:
records = paginator.page(1)
except EmptyPage:
records = paginator.page(paginator.num_pages)
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
messages.success(request, "You Have Been Logged In!")
return redirect('home')
else:
messages.success(request, "There Was An Error Logging In, Please Try Again...")
return redirect('login')
else:
return render(request, 'home.html', {'records': records, 'search_form': search_form})
def login_user(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
messages.success(request, "You have been logged in successfully!")
return redirect('home')
else:
messages.error(request, "Invalid login credentials. Please try again.")
return render(request, 'login.html')
def profile(request):
if request.user.is_authenticated:
user_records = Record.objects.filter(created_by=request.user)
bookmarked_records = Record.objects.filter(bookmarked_by=request.user)
return render(request, 'profile.html', {
'records': user_records,
'bookmarked_records': bookmarked_records,
})
else:
messages.success(request, "You must be logged in to view that page...")
return redirect('home')
def logout_user(request):
logout(request)
messages.success(request, "You Have Been Logged Out...")
return redirect('home')
def register_user(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
form.save()
# Authenticate and login
username = form.cleaned_data['username']
password = form.cleaned_data['password1']
user = authenticate(username=username, password=password)
login(request, user)
messages.success(request, "You Have Successfully Registered! Welcome!")
return redirect('home')
else:
form = SignUpForm()
return render(request, 'register.html', {'form':form})
return render(request, 'register.html', {'form':form})
def update_profile(request):
if request.method == 'POST':
profile_form = CustomUserChangeForm(request.POST, instance=request.user)
password_form = CustomPasswordChangeForm(request.user, request.POST)
if profile_form.is_valid() and password_form.is_valid():
profile_form.save()
password_form.save()
update_session_auth_hash(request, request.user) # to avoid logging out after a password change
messages.success(request, "Profile updated successfully!")
return redirect('profile')
else:
profile_form = CustomUserChangeForm(instance=request.user)
password_form = CustomPasswordChangeForm(request.user)
return render(request, 'update_profile.html', {'profile_form': profile_form, 'password_form': password_form})
def delete_user(request):
try:
if request.user.is_authenticated:
# Check if the user making the request is the account owner
if request.user == request.user:
user = request.user
user.delete()
messages.success(request, "Bye Bye!")
return redirect('home')
else:
return JsonResponse({'error': 'You are not authorized to delete this account'}, status=403)
else:
return JsonResponse({'error': 'User not authenticated'}, status=401)
except Exception as e:
return redirect('home')
def customer_record(request, pk):
try:
customer_record = Record.objects.get(id=pk)
# Check if the user has bookmarked the record
is_bookmarked = False
if request.user.is_authenticated:
is_bookmarked = customer_record.bookmarked_by.filter(id=request.user.id).exists()
if request.method == 'POST':
if not request.user.is_authenticated:
messages.success(request, "You must be logged in to perform this action.")
return redirect('login')
action = request.POST.get('action')
if action == 'bookmark':
customer_record.bookmarked_by.add(request.user)
elif action == 'unbookmark':
customer_record.bookmarked_by.remove(request.user)
return redirect('record', pk=pk)
return render(request, 'record.html', {'customer_record': customer_record, 'is_bookmarked': is_bookmarked})
except Record.DoesNotExist:
messages.error(request, "The record does not exist.")
return redirect('home')
def add_record(request):
if request.user.is_authenticated:
if request.method == "POST":
form = AddRecordForm(request.POST)
if form.is_valid():
try:
record = form.save(commit=False)
record.created_by = request.user
record.save()
messages.success(request, "Record Added...")
return redirect('home')
except ValidationError as e:
messages.error(request, str(e))
else:
form = AddRecordForm()
return render(request, 'add_record.html', {'form': form})
else:
messages.success(request, "You Must Be Logged In...")
return redirect('home')
def delete_record(request, pk):
if request.user.is_authenticated:
delete_it = Record.objects.get(id=pk)
delete_it.delete()
messages.success(request, "Record Deleted Successfully...")
return redirect('home')
else:
messages.success(request, "You Must Be Logged In To Do That...")
return redirect('home')
def update_record(request, pk):
if request.user.is_authenticated:
current_record = Record.objects.get(id=pk)
form = AddRecordForm(request.POST or None, instance=current_record)
if form.is_valid():
form.save()
messages.success(request, "Record Has Been Updated!")
return redirect('profile')
return render(request, 'update_record.html', {'form':form})
else:
messages.success(request, "You Must Be Logged In...")
return redirect('home')
# custom 404 view
def custom_404(request, exception=None):
return render(request, '404.html', status=404)
def notion_templates(request):
return render(request, 'notion_templates.html')
def about(request):
return render(request, 'about.html')
def faq(request):
return render(request, 'faq.html')
Urls.py
#password section
path('password_reset/', auth_views.PasswordResetView.as_view(template_name='password_reset_form.html'), name='password_reset'),
path('password_reset_done/', auth_views.PasswordResetDoneView.as_view(template_name='password_reset_done.html'), name='password_reset_done'),
path('password_reset_confirm/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(template_name='password_reset_confirm.html'), name='password_reset_confirm'),
path('password_reset_complete/', auth_views.PasswordResetCompleteView.as_view(template_name='password_reset_complete.html'), name='password_reset_complete'),
password_reset_form.html:
{% extends 'base.html' %}
{% block content %}
<h1> Forgot Password</h1>
<form method = "POST">
{% csrf_token %}
{{ form.as_p}}
<button type="submit">Submit</button>
</form>
{% endblock %}
password_reset_done.html:
{% extends 'base.html' %}
{% block content %}
<p>
We've emailed you instructions for setting your password. If an email exists in our records, you should be receiving it shortly.
</p>
<p>
If you have not recieved an email in our inbox, then check your spam folder, any spelling mistakes, or the correct email associated with us.
</p>
{% endblock %}
password_reset_confirm.html:
{% extends 'base.html' %}
{% block content %}
{% if validlink %}
<h3>Change Password</h3>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Change password</button>
</form>
{% else %}
<p>
This password link has already been used. Please request a new password link.
</p>
{% endif %}
{% endblock %}
password_reset_complete.html:
{% extends 'base.html' %}
{% block content %}
<p>
Your password has been set. Click here to return to the Login Screen: <a href="{% url 'home' %}"></a>
</p>
{% endblock %}
When I navigate to the password_reset_form.html and enter in verified email it will return the password_reset_confirm.html page. When I navigate to the email, nothing shows. It will return an error if the email isn't verified through aws. (I'm still in sandbox mode I just sent a request to change it to production today.)
If it's these files what am I doing incorrectly?