Django send_mail SMTPSenderRefused 530 with gmail - python

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')

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'

Flask application smptlib sender refused error after heroku deployment

message.send(connection)
2021-06-20T00:49:29.013482+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/flask_mail.py", line 427, in send
2021-06-20T00:49:29.013483+00:00 app[web.1]: connection.send(self)
File self.host.sendmail(sanitize_address(envelope_from or message.sender),
2021-06-20T00:49:29.013484+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/smtplib.py", line 882, in sendmail
2021-06-20T00:49:29.013484+00:00 app[web.1]: raise SMTPSenderRefused(code, resp, from_addr)
2021-06-20T00:49:29.013486+00:00 app[web.1]: smtplib.SMTPSenderRefused: (530, b'5.7.0 Authentication Required. Learn more at\n5.7.0 https://support.google.com/mail/?p=WantAuthError y24sm8273493qtn.57 - gsmtp', 'xxx#gmail.com')
I have deployed my flask app to heroku and I am facing this email authentication error. On my local machine the email part is working perfectly. Only after deploying to heroku it is giving this error. I have checked all the email and password variables and also allowed less secure apps access. Can some one pls advise. I am using flask-mail
My code is
__init__.py
app.config['MAIL_SERVER'] = 'smtp.gmail.com'
app.config['MAIL_PORT'] = 587
app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USERNAME'] = os.environ.get('EMAIL_USER')
app.config['MAIL_PASSWORD'] = os.environ.get('EMAIL_PASS')
In routes.py
def send_reset_email(user):
token=user.get_reset_token()
msg=Message("Password Reset Request",sender='xxx#gmail.com',recipients=[user.email])
msg.body=f'''To reset your password visit the following link:
{url_for('reset_password',token=token,_external=True)}
If you did not make this request please ignore this message.
'''
mail.send(msg)
#app.route("/reset_request",methods=["GET","POST"])
def reset_request():
form=ResetRequestForm()
if form.validate_on_submit():
user=User.query.filter_by(email=form.emailmain.data).first()
if user is None:
flash("No account exists with this email. Pls register first.",'danger')
else:
send_reset_email(user)
flash("An email has been sent with instructions to reset your password",'success')
time.sleep(2)
return redirect(url_for('login'))
In models.py
def get_reset_token(self, expires_sec=1800):
s = Serializer(app.config['SECRET_KEY'], expires_sec)
return s.dumps({'user_id': self.id}).decode('utf-8')
#staticmethod
def verify_reset_token(token):
s = Serializer(app.config['SECRET_KEY'])
try:
user_id = s.loads(token)['user_id']
except:
return None
Can someone pls tell me what I am missing
Google doesn't allow you to sign in like that from heroku. You can do the following.
Check your mails, there might be one telling about signin into your account.
Go to security and enable enable less secure app.
Note -After doing so my app to worked, but one day it again gave the same error. I got this DisplayUnlockCaptcha link from a SO question. But I need to fo it whenever I send email. So finally I got this.
Go to security enable 2 step verification and head to app passwords.
Choose your device (I chose windows computer ) and in app select mail. App password will be generated. Replace your password with this password in heroku env variables.

Couldn't able to import environment variable for django settings.py for sending email in linux ubuntu system

When I specify EMAIL_HOST_USER and EMAIL_HOST_PASSWORD directly email send properly but if try to get using os.environ it is throwing following error (530, b'5.7.0 Authentication Required. Learn more at\n5.7.0 https://support.google.com/mail/?p=WantAuthError l26sm20714449pgn.46 - gsmtp', 'webmaster#localhost'). I have tried to add variables in .bashrc and .bash_profile but it didn't worked. What I have tried shown below. can anyone help me this please.
settings.py
variables shown below.
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
# EMAIL_HOST_USER = 'name#gmail.com'
# EMAIL_HOST_PASSWORD = '123456789'
EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER')
print('variable :',os.environ.get('EMAIL_HOST_USER'))
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD')
.bashrc
This file is in the same directory where settings.py exist.
import os
export EMAIL_HOST_USER = 'name#gmail.com'
export EMAIL_HOST_PASSWORD = '9538913650'
main
below lines I have tried in terminal both in global and vertual envirnment.
EMAIL_HOST_USER=name#gmail.com
EMAIL_HOST_PASSWORD=123456789
using python comand
code shown below.
import os
os.environ.set('EMAIL_HOST_USER') = 'name#gmail.com'
os.environ.set('EMAIL_HOST_PASSWORD') = 12345678
Firstly, don't use os.environ.get('...') - it silently fails when the environment variable is missing. Use os.environ['...'] instead.
EMAIL_HOST_USER = os.environ['EMAIL_HOST_USER']
print('variable :',os.environ['EMAIL_HOST_USER'])
EMAIL_HOST_PASSWORD = os.environ['EMAIL_HOST_PASSWORD']
Next, the .bashrc or .bash_profile will only work if you are running Django from a shell that has sourced those files. Remove the import os, it is not Python.
Next, you still need the export in your shell if you set the variables before running Django.
export EMAIL_HOST_USER=name#gmail.com
export EMAIL_HOST_PASSWORD=123456789
If you want to set the environment variables in Python, then treat os.environ as a dict instead of trying to call .set(...).
import os
os.environ['EMAIL_HOST_USER'] = 'name#gmail.com'
os.environ['EMAIL_HOST_PASSWORD'] = 12345678
Finally, even if this works on your local box, it might stop working when you deploy on a server with a different IP address. Every week I see questions on Stack Overflow where users are struggling to send emails from Django using gmail. I usually suggest that they think about using a different email provider.
Have you tried the decouple library? Here is a good example: https://simpleisbetterthancomplex.com/2015/11/26/package-of-the-week-python-decouple.html
Usage:
# settings.py
from decouple import config
EMAIL_HOST_USER = config('EMAIL_HOST_USER')
Then create a .env file (and add it to .gitignore if needed):
# .env (save in the same folder as manage.py)
EMAIL_HOST_USER = 'my_email#some_url.some_extension'
Just wasted another 2 hours... you only need to restart your computer and it will work with your original code

Hide login credentials in Python script

I am using Python 2.7.3 and successfully passing my login credentials to an SMTP server to send me a text or email when an event trigger takes place. However, now I would like to store the SMTP server login and password in a separate file so that multiple scripts could use that information or so that I can share my script without having to remove my credentials each time.
I am using the great tutorial from Alex Le on sending an SMS via Python. But now I want to take the following segment and put it into another file that can be called by multiple scripts. This could be either just the username/password pair or the whole section.
server = smtplib.SMTP( "smtp.gmail.com", 587 )
server.starttls()
server.login( '<gmail_address>', '<gmail_password>' )
I would consider myself a pretty basic Python programmer. I don't mind doing some research, but I think I need help on what terms I should be looking for.
Get all the critical variables from .yml file:
import yaml
conf = yaml.load(open('conf/application.yml'))
email = conf['user']['email']
pwd = conf['user']['password']
server = smtplib.SMTP( "smtp.gmail.com", 587 ) # add these 2 to .yml as well
server.starttls()
server.login(email, pwd)
The application.yml will look similar to this:
user:
email: example#mail.com
password: yourpassword
This way, you will never see the actual credentials in the script.
In production environments what we usually do is make a seperate file and save it somewhere outside the project. Now do chmod 600, i.e. allow only root to access the file. Now in your code run read the file by running in the the superuser mode. Or you could also create a different user which can access the file and run the code using that user.
OR You could use environment variables in your system. You can set one by doing the following in bash shell
export KEY=some_value
And then in your Python code
os.environ.get('KEY')
Use a separate configuration file settings.py containing:
EMAIL = 'gmail address'
PASSWORD = 'gmail password'
As the configuration file is a Python file, you can import it from your actual code:
from . import settings
server = smtplib.SMTP( "smtp.gmail.com", 587 )
server.starttls()
server.login(settings.EMAIL, settings.PASSWORD)
This is similar to what projects such as Django use, which you can see here.
You would need to keep the settings.py file secret, so you would not add it to your revision control software and wouldn't make it publicly readable.

Django & Amazon SES SMTP. Cannot send email

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'

Categories