Django & Amazon SES SMTP. Cannot send email - python

this is my settings.py :
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'email-smtp.us-east-1.amazonaws.com'
EMAIL_PORT = '465'
EMAIL_HOST_USER = config_data['EMAIL_HOST_USER']
EMAIL_HOST_PASSWORD = config_data['EMAIL_HOST_PASSWORD']
EMAIL_USE_SSL = True
I have verified the email addresses and have also generated SMTP credentials which I downloaded the credentials containing the IAM username, Smtp username, Smtp password. I used the smtp username for EMAIL_HOST_USER and smtp password for EMAIL_HOST_PASSWORD.
In django, I sent an email with this line (admin#admin.com is replaced with a gmail account that is in the verified email list) :
send_mail("Subject", "content", "admin#admin.com", [email], fail_silently=False)
That did not work. Sending a test email from the SES console (select one of the email in verified emails and click send a test email button) works though.
This document says that I can send email via command line with openssl command. So, i did ssh to the EC2 machine, and use :
openssl s_client -crlf -quiet -starttls smtp -connect email-smtp.us-east-1.amazonaws.com:25
Notice that i used 25 here, when i used port 465, it outputed :
didn't found starttls in server response, try anyway...
write:errno=32
So instead I tried port 25, It connected (250 OK) and then I typed :
AUTH LOGIN
334 VXNlcm5hbWU6
SMTP_USER
334 UGFzc3dvcmQ6
SMTP_PASSWORD
but it outputted : 535 Authentication Credentials Invalid. Could it be I used a wrong credentials? but I copy the username and password straight from the smtp user and password generation page.
I also tried to attach AmazonSESFullAccess policy to all of the IAM users but nothing happened.
I use the Django 1.8.2. Tried Django-ses but it did not work too (syntax error when running the tests, it does not support python 3?)
UPDATE
I changed the port to 587 and use USE_TLS True and now I can send_mail from django shell. I put the function in my app views.py :
def test_email(request):
send_mail("title", "content", "abc#gmail.com", ["def#gmail.com"], fail_silently=False)
return get_return_object(request, status_code=1)
and in urls.py I put this inside the urlpatterns :
url(r'^test_email/$', views.test_email, name="test_email"),
and when I visited the URL, nothing happens. I call the same function test_email from the shell and it works.
UPDATE
It turns out that I can also use port 465 and USE_SSL True and be able to send_mail from django shell. but still it does not work in views.py

2020 update
As the documentation says here: Django Email Documentation and Email_use_ssl
I am using Django 3.0 at this moment, and the documentation says that you can use
EMAIL_USE_SSL = True
... It is generally used on port 465
I make my think works and send emails using AWS SES and port 465 service using that line instead EMAIL_USE_TLS = True :)

If you use port 465:
Install django-smtp-ssl using pip
pip install django-smtp-ssl
then change EMAIL_BACKEND in settings.py as follows:
EMAIL_BACKEND = 'django_smtp_ssl.SSLEmailBackend'
If you use port 587:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'

Related

Sending email from DebuggingServer localhost:1025 not working

Im testing sending an email after filling out a form on a website and im using my local host. Upon submitting the form I'm using the django send_mail() method and Im sending the test email to a gmail account and I have the account as a list data type.
$ python -m smtpd -n -c DebuggingServer localhost:1025
And I'm getting this depreciated message after I turn on the server
and I also have yet to receive an email from my local host
C:\Users...\AppData\Local\Programs\Python\Python310\lib\smtpd.py:104: DeprecationWarning: The asyncore module is deprecated. The recommended replacement is asyncio
import asyncore
C:\Users...\AppData\Local\Programs\Python\Python310\lib\smtpd.py:105: DeprecationWarning: The asynchat module is deprecated. The recommended replacement is asyncio
import asynchat
Here's whats in my settings.py file:
EMAIL_HOST = 'localhost'
EMAIL_PORT = 1025
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
EMAIL_USE_TLS = False
Any ideas why its not sending?
First of all, you must configure your email to access your project. Use the following link to send a debt email:
https://dev.to/abderrahmanemustapha/how-to-send-email-with-django-and-gmail-in-production-the-right-way-24ab
#settings.py
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'yoorusername#gmail.com'
EMAIL_HOST_PASSWORD = 'key' #past the key or password app here
EMAIL_PORT = 587
EMAIL_USE_TLS = True
DEFAULT_FROM_EMAIL = 'default from email'
Sign in to gmail and then click Manage your google account then enter the security section from the page that opens, like this:
enter image description here
you have to type your password again
and
click on select app choose *** other (Custome Name) *** and give a name to you app
the last step click on generate and Gmail will generate a key or an app password make sure to copy this key or save it in a text file
and use for EMAIL_HOST_PASSWORD
I couldn't Completely get it but it seems like its asking for asynchronous task scheduler like celery with rabbitmq or radis.
more over this is the warning. I am not sure but you can pass this by changing your settings.py
DEBUG = True
to this
DEBUG = False
may this work.
more in your settings.py
EMAIL_HOST = 'localhost'
seems fishy,
you should use
EMAIL_HOST = 'smtp.gmail.com'

Creating AWS SES SMTP credentials using IAM Role

I am trying to use an IAM Role that I have attached to an EC2 instance to generate a set of AWS SES SMTP credentials. However, after using the script given by Amazon to generate the SMTP Password from the Secret_Key of the IAM Role, and using the Access_Key_ID of the IAM Role, when trying to send an email via django.core.mail, I get error (535, b'Authentication Credentials Invalid').
This is how I am sending the email:
#django.core.mail
EMAIL_USE_TLS = True
EMAIL_HOST = 'email-smtp.us-east-1.amazonaws.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = credentials.access_key
EMAIL_HOST_PASSWORD = SMTP_PASSWORD
send_mail(
'Subject here',
'Here is the message.',
'from#example.com',
['to#example.com'],
fail_silently=False,
)
And how am I generating the password:
session = boto3.session.Session()
credentials = session.get_credentials().get_frozen_credentials()
region = requests.get('http://169.254.169.254/latest/dynamic/instance-identity/document').json()['region']
SMTP_PASSWORD = smtp_credentials_generate.calculate_key(secret_access_key=credentials.secret_key, region=region)
The SMTP Password generate script is here: https://docs.aws.amazon.com/ses/latest/DeveloperGuide/smtp-credentials.html.
Through some research, I found these links that say you cannot use an IAM Role to use generate SMTP credentials:
https://serverfault.com/questions/584789/is-it-possible-to-send-email-via-the-amazon-ses-smtp-service-with-a-iam-role-acc
https://hector.dev/2015/01/17/sending-e-mail-via-amazon-ses-over-smtp-with-iam-roles.html
However, Amazons official QA says that it is possible:
https://aws.amazon.com/premiumsupport/knowledge-center/ses-create-smtp-credentials/
Important: The IAM user or role that you use to create the SMTP credentials...
So is it possible or not? What am I doing wrong?
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/smtp-credentials.html
Don't use temporary AWS credentials to derive SMTP credentials. The Amazon SES SMTP interface doesn't support SMTP credentials that have been generated from temporary security credentials.
Regarding the Amazon official QA that you referenced, it's saying that you can use the role to create SMTP credentials in the web console.

smtplib.SMTPSenderRefused: (530, b'5.7.0 Authentication Required.) in flask

I see many solutions but still, I have a problem for send mail and I also set email and password to
~/.bash_profile so please help me.
Here my connfig.py file code
import os
class Config:
SECRET_KEY=os.environ.get('SECRET_KEY')
SQLALCHEMY_DATABASE_URI=os.environ.get('SQLALCHEMY_DATABASE_URI')
MAIL_SERVER = 'smtp.googlemail.com'
MAIL_PORT = 465
MAIL_USE_SSL= True
MAIL_USERNAME=os.environ.get('EMAIL_USER')
MAIL_PASSWORD=os.environ.get('EMAIL_PASS')
I also try the google two-step verification and app password still I have a problem. What can I do now?
I had the same problem when I debugged my code I found that my os.environ.get('EMAIL_USER') was empty. Make sure it has your exact credentials.
What I did was hardcoding my username and password (it is not recommended to do it for security purposes) :
class Config:
SECRET_KEY=os.environ.get('SECRET_KEY')
SQLALCHEMY_DATABASE_URI=os.environ.get('SQLALCHEMY_DATABASE_URI')
MAIL_SERVER = 'smtp.googlemail.com'
MAIL_PORT = 465
MAIL_USE_SSL= True
MAIL_USERNAME='youremailhere'
MAIL_PASSWORD='yourpasswordemailhere'
... and then make sure you have the Less Secure App Access turned on in your google account, you'll find it here -> https://myaccount.google.com/lesssecureapps

Django send_mail SMTPSenderRefused 530 with gmail

I've been trying for some time to be able to receive emails with Django from a website I'm developing. Now, I haven't deployed it yet, and I am using the Django Development Server, and I don't know if this affects it.
Here is my settings.py configuration:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'my_email#gmail.com'
EMAIL_HOST_PASSWROD = 'my_password'
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
DEFAULT_TO_EMAIL = EMAIL_HOST_USER
Then, through the root folder of the project I run python manage.py shell, and type the following:
>>> import django
>>> from django.conf import settings
>>> from django.core.mail import send_mail
>>> send_mail('test', 'test', settings.EMAIL_HOST_USER, [settings.EMAIL_HOST_USER], fail_silently=False)
And what I receive back is the following error:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/paulo/anaconda3/envs/MyDjangoEnv/lib/python3.6/site-packages/django/core/mail/__init__.py", line 62, in send_mail
return mail.send()
File "/home/paulo/anaconda3/envs/MyDjangoEnv/lib/python3.6/site-packages/django/core/mail/message.py", line 348, in send
return self.get_connection(fail_silently).send_messages([self])
File "/home/paulo/anaconda3/envs/MyDjangoEnv/lib/python3.6/site-packages/django/core/mail/backends/smtp.py", line 111, in send_messages
sent = self._send(message)
File "/home/paulo/anaconda3/envs/MyDjangoEnv/lib/python3.6/site-packages/django/core/mail/backends/smtp.py", line 127, in _send
self.connection.sendmail(from_email, recipients, message.as_bytes(linesep='\r\n'))
File "/home/paulo/anaconda3/envs/MyDjangoEnv/lib/python3.6/smtplib.py", line 866, in sendmail
raise SMTPSenderRefused(code, resp, from_addr)
smtplib.SMTPSenderRefused: (530, b'5.5.1 Authentication Required. Learn more at\n5.5.1 https://support.google.com/mail/?p=WantAuthErrorv11sm8729581qkl.88 - gsmtp', 'my_email#gmail.com')
I have enabled the option to allow less secure applications.
I tried, when using 2-step verification, to input, instead of EMAIL_HOST_PASSWORD = "my_password", to input EMAIL_HOST_PASSWORD = 'myapplicationpassword' provided by google. It didn't work.
Then I have disabled the 2-step verification and changed from the application password back to my actual password, and the error remains.
Am I doing something wrong? Has Google somehow blocked these types of application? Would I do better if I ran my own mail server?
Make sure that you do the following two things:
Go to App passwords for 2-factor authentication, or look into "Less secure app access" if you're not using MFA. The password google provides when setting up as is a 16 digit code that includes spaces, they count.
Make sure the settings imported or password set and/or retrieved is in the same terminal shell:
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_PASSWORD')
export EMAIL_PASSWORD="xxxx xxxx xxxx xxxx"
If you are using Google SMTP, Google has introducted a new security feature which blocks use of SMTP directly. In order to use Google SMTP, you need to sign into your Google account and enable access to less secure app. This option os present under Security Checkup under My Account. See the screenshot below.
I tried to edit bash_profile, bashrc, zshrc, profile etc. and nothing worked. If the variables are returning "None" try this :
As mentioned in this link python-dotenv create an .env file (preferably in the root directory of your project) and put your credentials into it. Then in settings.py (if you are using django), use the following code:
from pathlib import Path
from dotenv import load_dotenv
env_path = Path('Path to the .env file')
load_dotenv(dotenv_path=env_path)
Then access the variable using the following code and you should be fine:
os.environ.get('var_name')

Django detect errors while sending mail

def send_one_mail(request):
send_mail('The subject', 'The body to testing', 'userone#example.com',['usertwo#gmail.com'], fail_silently=False)
return HttpResponse("This mail has sent successfull")
And my settings.py is
EMAIL_USE_TLS = True
EMAIL_HOST = 'mail.example.com'
EMAIL_HOST_USER = 'userone#example.com'
EMAIL_HOST_PASSWORD = 'password'
EMAIL_PORT = 587
DEFAULT_FROM_EMAIL = 'userone#example.com'
SERVER_EMAIL = 'userone#example.com'
I have a view (which works) as shown above, here userone#example.com is sender and usertwo#gmail.com
is the receiver.
How can i check and act according to errors in sending mail?
(I want to show "Some error occured" in such errors)
How can i determine if the usertwo#gmail.com(reciver) exists or not?
(if email can't be reached, i want to show the user that the email doesn't exist)
I am using postfix,dovecot etc. in server.
You can pick up some errors when you use fail_silently = False. Just wrap send_mail in try/except.
When i wanted more control over e-mail sending, then i stopped using django mailing completely and installed lamson instead (lamsonproject.org). You can basically create your own mail server with it, attach your django orm to it and provide detailed feedback about what has happened to your e-mails. If you insert some kind of downloadable content into those e-mails (like images), then you can even give hashes to images and verify this way if e-mail has been opened too. You could do that with django based email sending too. Lamson just gives bit more control over the what and how that goes on after you hit send button.
django-mail-queue
Anyway, i finally ended-up with using the below package.
pip install django-mail-queue
And here is the docs
https://django-mail-queue.readthedocs.org/en/latest/

Categories