How to use AWS Simple Email Service (SES) in Django? - python

I'm trying to use this library to integrate my Django project with AWS SES.
settings.py
EMAIL_BACKEND = 'django_ses.SESBackend'
AWS_ACCESS_KEY_ID = 'my_aws_access_key'
AWS_SECRET_ACCESS_KEY = 'my_aws_secret_access_key'
AWS_SES_REGION_NAME = 'us-west-2'
AWS_SES_REGION_ENDPOINT = 'email.us-west-2.amazonaws.com'
It throws the following error
SESAddressNotVerifiedError: 400 Email address is not verified.
<ErrorResponse xmlns="http://ses.amazonaws.com/doc/2010-12-01/">
<Error>
<Type>Sender</Type>
<Code>MessageRejected</Code>
<Message>Email address is not verified. The following identities failed the check in region US-WEST-2: jpark1320#gmail.com, webmaster#localhost</Message>
</Error>
<RequestId>0220c0a0-741b-11e8-a153-475b5dfc6545</RequestId>
</ErrorResponse>
I can't even guess why is wrong on my codes. But, one thing might be a problem is send_mail(). I'm using trying to send an email to a user for sign-up confirmation. I put the codes for sending email below.
SMTP settings
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'my_google_email#gmail.com'
EMAIL_HOST_PASSWORD = 'my_google_email_password'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
DEFAULT_FROM_EMAIL = 'My Team Name <noreply#gmail.com>'
Update
views.py
def signup(request):
if request.method == 'POST':
form = SignupForm(request.POST)
if form.is_valid():
# Create a user object to set email to be username before passing it to db
user = form.save(commit=False)
user.is_active = False
user.email = form.cleaned_data['username']
user.save()
current_site = get_current_site(request)
mail_subject = "[Modvisor] Please verify your email address."
message = render_to_string('accounts/account_active_email.html', {
'user': user,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': account_activation_token.make_token(user),
})
to_email = user.email
email = EmailMessage(
mail_subject, message, to=[to_email]
)
email.send()
return redirect('signup_confirm')
else:
form = SignupForm()
return render(request, 'accounts/register.html', {'form': form})

The relevant part of the error is "Email address is not verified". By default SES is in sandbox mode where it won't let you use From or To addresses that you have not previously verified. You need to verify the addresses in the SES console or open a support request to leave sandbox.
Verifying Email Addresses in Amazon SES
To verify an address go to the SES console. On the left side select Email Addresses and then click Verify New Email Address. You will need to have access to the email address so you can click the link that will be sent to it.
Moving Out of the Amazon SES Sandbox
To move out of the sandbox simply open a support request, describe your use case and wait a few days.

Related

SMTPServerDisconnected even though it was working properly a few days ago

I am using Django and I'm trying to send a verification email (with gmail) when the user registers, this was working fine some days ago, but then it suddenly stopped working. I have already created a new Google Application password and it is still not working. When the site tries to send the email it raises "SMTPServerDisconnected at /register/Connection unexpectedly closed".
This are my settings for email.
# EMAIL CONFIG
DEFAULT_FROM_EMAIL = 'mymail#gmail.com'
EMAIL_FROM_USER= 'mymail#gmail.com'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'mymail#gmail.com'
EMAIL_HOST_PASSWORD = 'password'
EMAIL_USE_TLS = True
EMAIL_PORT = 587
And this is my view:
def send_action_email(user,request):
current_site = get_current_site(request)
email_subject = 'Activa tu cuenta'
email_body = render_to_string('users/activate.html',{
'user':user,
'domain':current_site,
'uid':urlsafe_base64_encode(force_bytes(user.pk)),
'token': generate_token.make_token(user)
})
email = EmailMessage(subject=email_subject,body=email_body,
from_email=settings.EMAIL_FROM_USER,
to=[user.email]
)
email.send()
def activate_user(request,uidb64,token):
try:
uid=force_text(urlsafe_base64_decode(uidb64))
user= User.objects.get(pk=uid)
except Exception as e:
user=None
if user and generate_token.check_token(user,token):
user.email_is_verified=True
user.save()
messages.success(request, 'Se ha verificado tu email, ya puedes inciciar sesion!')
return redirect('login')
return render(request,'appName/activation_failed.html',{"user":user})
Might it be that google is not allowing me to login to the mail?

Email Not Sending in AWS SES

Settings.py
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_USE_TLS = True
EMAIL_HOST = 'email-smtp.us-west-2.amazonaws.com'
EMAIL_HOST_USER = config('SMTP_USER')
EMAIL_HOST_PASSWORD = config('SMTP_PW')
EMAIL_PORT = 587
VERIFIED_IDENTITY = config('VERIFIED_IDENTITY')
I have a verified email in my AWS SES and I am trying to send a message. I get a sent message everytime I use my contact form but no message actually gets sent.
if 'contactForm' in request.POST:
#print('Contact form')
contact_form = ContactForm(request.POST)
if contact_form.is_valid():
contact_form.save()
email_subject = f'New contact {contact_form.cleaned_data["email"]}: {contact_form.cleaned_data["subject"]}'
email_message = contact_form.cleaned_data['message']
print(email_subject,email_message)
try:
send_mail(email_subject, email_message,settings.VERIFIED_IDENTITY,[settings.VERIFIED_IDENTITY])
except BadHeaderError:
print('bad')
In my opinion the issue might be related to DNS SPF record. See below the link related.
"A sender policy framework (SPF) record is a type of DNS TXT record that lists all the servers authorized to send emails from a particular domain."
https://www.cloudflare.com/learning/dns/dns-records/dns-spf-record/#:~:text=A%20sender%20policy%20framework%20(SPF,Domain%20Name%20System%20(DNS).
https://docs.aws.amazon.com/ses/latest/dg/send-email-authentication-spf.html
To set up SPF, you publish a TXT record to the DNS configuration for your domain. This record contains a list of the servers that you authorize to send email from your domain. When an email provider receives a message from your domain, it checks the DNS records for your domain to make sure that the email was sent from an authorized server.
Regards,
Ed.

Whenever I use send_mail in django it sends me emails from myself rather than the address I'm providing

So I've been working on this blog website and I wanted to add a form so that users can contact the blog admin. However when they fill out the form and send email.. The email I receive is from myself and not from the user. Someone Please help me to fix it.
The form is working correctly and message-email does return the email that they enter.
e.g. lets say in my form I add a user email as example1#example.com
but when I recieve an email it's not coming from example1#example.com but from my host email myemail#gmail.com.
views.py:
def contact(request):
if request.method == 'POST':
message_name = request.POST['message-name']
message_email = request.POST['message-email']
message = request.POST['message']
#send mail
send_mail(
'message from ' + message_name + ' their email ' + message_email ,
message,
message_email,
['myemail#gmail.com'],
)
return render(request, 'blog/contact.html', {'message_name':message_name})
settings.py:
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_POST = 587
EMAIL_HOST_USER = 'myemail#gmail.com'
EMAIL_HOST_PASSWORD = '******'
EMAIL_USE_TLS = True
This may have some useful information.
https://www.digitalocean.com/community/tutorials/how-to-use-google-s-smtp-server
Note: Google will automatically rewrite the From line of any email you
send via its SMTP server to the default email address associated with
the account if the one used is not on the Send mail as addresses list
in Gmail or G Suite settings. You can verify the list by going to the
Accounts and Import tab on the settings screen.
You need to be aware of this nuance because it affects the
presentation of your email, from the point of view of the recipient,
and it may also affect the Reply To setting of some programs.

Django 2.1: is it possible to include Ngrok's Domain in an email instead of localhost's?

i am using Ngrok to run my website with https://, and when i send an activation email to myself, instead of seeing 'https://something.ngrok.io/...' i get 'http://localhost:8000/...'.
This is the code responsible for sending the Activation Email which - to my opinion - it should send Ngrok's domain not the development domain ...
...
current_site = get_current_site(request)
mail_subject = 'Activate your customer account.'
message = render_to_string('user_register_email/account_activation_email.html', {
'user': user,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)).decode(),
'token': user_token.make_token(user),
})
receiver = form.cleaned_data['email']
email = EmailMessage(
mail_subject, message, to=[receiver]
)
email.send()
messages.info(
request, f'An activation link has been sent to %s' % (receiver))
return redirect('accounts:login')
is it possible ?
current_site.domain returns the value set on the site instance, you can either change it from the admin panel, or you can use request.get_host() instead

Forgot password emails not sending in Django

I am trying to implement password reset functionality.
My urls contains:
url(r'^password_reset/$','django.contrib.auth.views.password_reset', {'template_name': 'resetpassword.html', 'post_reset_redirect' : '/password_reset/mailed/'},
name="password_reset"),
url(r'^password_reset/mailed/$',
'django.contrib.auth.views.password_reset_done',{'template_name': 'resetpassword_mailed.html'}),
url(r'^password_reset/(?P<uidb36>[0-9A-Za-z]{1,13})-(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
'django.contrib.auth.views.password_reset_confirm',
{'post_reset_redirect' : '/password_reset/complete/'}),
url(r'^password_reset/complete/$',
'django.contrib.auth.views.password_reset_complete',{'template_name': 'resetpassword_complete.html'}),
and settings.py:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.mail.ru'
EMAIL_HOST_USER = 'noreply#mysite.com'
DEFAULT_FROM_EMAIL = 'noreply#mysite.com'
EMAIL_HOST_PASSWORD = 'password'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
URL routing works just fine, however email are not being sent.
If I try to use Django shell and test sending:
email = EmailMessage('Subject', 'Body', to=['test#email.com'])
email.send()
And it works just fine as well.
How could I fix this? I don't get any error messages and don't know how could I debug this.
UPD
I have found out that in django/contrib/auth/views.py: password_reset method I always go to
else:
post_reset_redirect = resolve_url(post_reset_redirect)
part and never to actually sending email. How's that?
if post_reset_redirect is None:
post_reset_redirect = reverse('password_reset_done')
else:
post_reset_redirect = resolve_url(post_reset_redirect)
if request.method == "POST":
form = password_reset_form(request.POST)
if form.is_valid():
print 'reset form valid'
opts = {
'use_https': request.is_secure(),
'token_generator': token_generator,
'from_email': from_email,
'email_template_name': email_template_name,
'subject_template_name': subject_template_name,
'request': request,
'html_email_template_name': html_email_template_name,
}
if is_admin_site:
opts = dict(opts, domain_override=request.get_host())
form.save(**opts)
return HttpResponseRedirect(post_reset_redirect)
If the user has no password (e.g. created with create_user()), the password reset won't send anything! Make sure you create a password as well via:
password = User.objects.make_random_password()
Then, you also need to set the password and save, for example
user.set_password(password)
user.save()
Could be a trivial question but the user you are using to test has a valid email set? If it's empty will not send the email neither raise an exception.
Check the send method source code.
Other way to see if the email is being generated is use the console backend:
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
and look at the console because the email should appears there.
Thanks

Categories

Resources