Reputation: 175
So I have been scouring the internet trying to get my code to work and i feel like I've read every post about this issue and still haven't figured out why I can't get my form to send me an email. I created a class based view which inherits FormView and have written a method that should send an email to me anytime there is a post-request. For the life of me, I can't get it to work.
For those who are in the same boat, this is one post that seemed promising so hopefully this will help you even if it doesn't help me:
My views.py: (both email addresses are the same. It should simulate me sending an email to myself.)
class CandRegisterView(FormView):
template_name = 'website/candidate_register.html'
form_class = UploadResumeForm
def send_email(self, request):
if request.method == 'POST':
send_mail('Test', 'This is a test', '[email protected]', ['[email protected]'], fail_silently=False)
my forms.py:
from django import forms
class UploadResumeForm(forms.Form):
first_name = forms.CharField(
widget=forms.TextInput(
attrs={
'type':'text',
'class': 'form-control',
'placeholder': 'First Name',
}),
required=True)
my settings.py (the variables are stored in a .env file and I use python decouple to add them without exposing the information on github. But these are their associated values)
EMAIL_USE_TLS=True
EMAIL_USE_SSL=False
EMAIL_HOST=smtp.gmail.com
[email protected]
EMAIL_HOST_PASSWORD=***************
EMAIL_PORT=587
EMAIL_BACKEND='django.core.mail.backends.smtp.EmailBackend'
DEFAULT_FROM_EMAIL='[email protected]'
SERVER_EMAIL='[email protected]
urls.py:
from django.urls import path, re_path
from .views import CandRegisterView
re_path(r'^candidate-register/$', CandRegisterView.as_view(success_url="/candidate-register/"), name='cand_register'),
candidate_register.html:
<form method= "post" action="" accept-charset="UTF-8" role="form">
{% csrf_token %}
<fieldset>
<div class="form-group">
<div class="input-group input-group-lg">
<span class="input-group-addon"><i class="fa fa-fw fa-user"></i></span>
{{form.first_name}}
<!-- <input type="text" class="form-control" placeholder="First Name" name={{form.first_name}}> -->
</div>
</div>
<input class="btn btn-lg btn-primary btn-block" type="submit" value="Send Email">
</fieldset>
</form>
Here is what i get from the console after clicking the 'submit' button.:
[10/Jul/2019 13:19:21] "POST /candidate-register/ HTTP/1.1" 302 0
[10/Jul/2019 13:19:22] "GET /candidate-register/ HTTP/1.1" 200 16782
[10/Jul/2019 13:19:22] "GET /candidate-register/ HTTP/1.1" 200 16782
All i want it to be able to do is send me the first name of the person for right now. later on i want them to be able to send me a file with their resume but i figured that I'd start off simple and make it more complex as include other fields but I can't even get this to work. Any help or tips would be greatly appreciated. It seems like the Post Request is happening but the email isn't being sent. I also tried using the send_mail function in the python manage.py shell and it showed a response that looked promising (the log showed what the email would have looked like.) but it didn't send an email to my account.
Upvotes: 0
Views: 435
Reputation: 31
In your form class, you will want to define a send_mail function that can be called after form_valid. So for example:
from django.core.mail import EmailMessage as email_msg
class UploadResume(forms.Form):
first_name = forms.CharField()
last_name = forms.CharField()
email = forms.EmailField()
resume_file = forms.FileField()
class Meta:
title = 'Resume Upload'
def send_message(self, email, first_name, last_name, file):
'''
This function will be used to create an email object that will then be \
transmitted via a connection call. This function takes in arguments that will \
be provided by the corresponding CBV's form_valid function.
'''
email_obj = email_msg(
subject=f'Resumed Uploaded by {first_name} {last_name}!',
body = 'You received a resume upload from {first_name} {last_name} \
at {email}. Please follow-up. \nThank you,\nYour Platform'
from_email=email,
to=['[email protected]'],
reply_to= ['[email protected]']
)
# after creating the email object with the cleaned data generated from
# the form fields, we will attach the resume contents to the object,
# then submit it via SMTP settings from the settings.py file.
attach_name = file.name
try:
attach_content = file.open().read()
except Exception:
attach_content = file.getvalue()
attach_mimetype = mimetypes.guess_type(attach_name)[0]
email_obj.attach(attach_name, attach_content, attach_mimetype)
try:
email_obj.send()
except Exception as e:
print(type(e), e.args, e)
From here, you can overwrite the form_valid function in your CBV, pull the relevant arguments by using the form.cleaned_data.get(insert_arg_here)
function.
An example of how to do this could be in the following way:
class CandRegisterView(FormView):
template_name = 'website/candidate_register.html'
form_class = UploadResumeForm
def form_valid(self, form):
if form.is_valid:
email_addr = form.cleaned_data.get('email')
first_name = form.cleaned_data.get('first_name')
last_name = form.cleaned_data.get('last_name')
file = form.cleaned_data.get('resume_file')
form.send_message(email_addr, first_name, last_name, file)
else:
return form.errors
Just noticed this: when you're crafting your form tag in your HTML, ensure that enctype="multipart/form-data"
is present in the tag.
Upvotes: 1