Can't connect .env file of smtp details to django - django

settings.py
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = os.environ.get('EMAIL_HOST')
EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER')
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD')
.env
export EMAIL_HOST_PASSWORD=<>
export EMAIL_HOST_USER = <>
export EMAIL_HOST=<>
3.Termial
(Carealenv) E:\atom data\mywebsite>source .env
'source' is not recognized as an internal or external command,
operable program or batch file.
I am having error of SMTPserverdisconnected .. please run connect first
I want to connect my .env file to django so that SMTPServer get connected and i can send verfication email to users. It will be great help.. Thank you

Further to ruddra's answer, you can alternatively use python-dotenv.
pip install python-dotenv
then in your settings.py
# settings.py
from dotenv import load_dotenv
load_dotenv()
Then you can use the getenv or as you have in your example environ.get function from the built-in os module to grab env variables and provide defaults if they do not exist.
from os import getenv
EMAIL_HOST = getenv('EMAIL_HOST', 'localhost')
Where localhost is whatever you wish to set as default.

You can't use source in Windows machine as described in the Stackoverflow answer.
If you want to use .env file, consider using libraries like django-environ which will read the file directly, no need to load it from ENVIRONMENT Variables.
Sample usage in settings.py:
import environ
env = environ.Env(
# set casting, default value
DEBUG=(bool, False)
)
# reading .env file
environ.Env.read_env()
# False if not in os.environ
EMAIL_HOST = env('EMAIL_HOST')
Another alternative solution is to use Docker with docker-compose, where you can load the environment variables from file.

Related

Accessing environment variables in production in Django deployed to Heroku

I am developing a web-app in Django that needs to send automated emails. The username and password are saved locally in my Windows 10 environment variables. The app is able to send emails locally, but in proudction once deployed to Heroku, the following error is raised:
530, b'5.7.0 Authentication Required. Learn more at\n5.7.0 https://support.google.com/mail/?p=WantAuthError y7sm6660123qtn.11 - gsmtp', 'webmaster#localhost'
My guess is that the environment variables are not being accessed which is why this error is thrown.
Here is my code in settings.py
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST_USER = os.environ.get('NAHE-USER')
EMAIL_HOST_PASSWORD = os.environ.get('NAHE-PASS')
You can define the environment variables (NAHE-USER, NAHE-PASS) in Heroku using Config Vars.
There are injected at runtime and will be accessed by your code with os.environ.get('NAHE-USER')

How do I use .env in Django?

My goal is to email using Python Django without having my email password being shown in the actual code. After some research, I guess I can store my password in an .env file and then access the password from the .env file. So, I currently have an .env file in my Django project with this line of code:
export EMAIL_HOST = 'smtp.gmail.com'
And in my settings.py, I have these:
import environ
env = environ.Env()
environ.Env.read_env()
EMAIL_HOST = os.environ.get('EMAIL_HOST')
print(EMAIL_HOST)
But the printed result is None. print(os.environ) spits out something though. How can I get my .env file to work?
Not only in Django, in general use the library python-dotenv.
from dotenv import load_dotenv
import os
load_dotenv()
EMAIL_HOST = os.getenv("EMAIL_HOST")
https://gist.github.com/josuedjh3/38c521c9091b5c268f2a4d5f3166c497
created a file utils.py in your project.
1: Create an .env file to save your environment variables.
file env.
DJANGO_SECRET_KEY=%jjnu7=54g6s%qjfnhbpw0zeoei=$!her*y(p%!&84rs$4l85io
DJANGO_DATABASE_HOST=database
DJANGO_DATABASE_NAME=master
DJANGO_DATABASE_USER=postgres
2: For security purposes, use permissions 600 sudo chmod 600 .env
3: you can now use the varibles settigns.py
from .utils import load_env
get_env = os.environ.get
BASE_DIR = Path(__file__).parent.parent.parent
load_env(BASE_DIR / "../.env") #here you indicate where your .env file is
SECRET_KEY = get_env("DJANGO_SECRET_KEY", "secret")
This way it can handle multiple environments production or stagins
You can do it by importing os and creating a .env file where you will specify all the database details for connection.
settings.py file:
import os
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": os.environ.get('DB_NAME'),
"USER": os.environ.get('DB_USER'),
"PASSWORD": os.environ.get('DB_USER_PASSWORD'),
"HOST": os.environ.get('DB_HOST'),
"PORT": os.environ.get('DB_PORT'),
}
}
.env file:
export DB_NAME = dbname
export DB_USER = root
export DB_USER_PASSWORD = root
export DB_HOST = localhost
export DB_DB_PORT = 5432
This example is for PostgreSQL but other DB setup will be exact similar but engine name will need to be changed.

Security-concerns about Django email-host-data in settings.py

I've set up my e-mail settings for my Gmail-account like it's described in the django-documentation:
settings.py:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST_USER = 'me#gmail.com'
EMAIL_HOST_PASSWORD = 'password'
So, maybe I'm to concerned about this, but I have some doubts due security while writing this kind of sensitve data into my settings.py-file.
So, is there a more secure way to set that up?
The proper way of doing this is providing sensitive data like this via environment variables. You can manually set environment variables or via .env files. There are many python packages for setting environment variables (like this) from env files. Then get these variables using os.environ.
For example you set EMAIL_HOST_USER environment variable and you can define in settings like this.
EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER')

Send emails to the users without requiring EMAIL_HOST_PASSWORD in Django

I am trying to make a "noreply" email to send the users. But I dont want to put password in the EMAIL_HOST_PASSWORD field. Is it possible? I tried this exact thing with PHP and it was a success. How can I do this using Django?
Run in terminal:
pip3 install python-decouple
If you are using python3, but if you are using python2 type only pip instead of pip3
Create .env file in the root of your django project and write:
EMAIL_HOST_USER = 'blablabla#gmail.com' #my email
EMAIL_HOST_PASSWORD = 'fhiahsffd' #my password
Add the line .env in your .gitignore
...
#other lines
.env
...
In settings.py
import os
from decouple import config
...
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = config('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD')
EMAIL_USE_TLS = True
...
Doing this your email password is protected, that was the matter I imagine
No, you can't send emails in django without EMAIL_HOST_PASSWORD, because you need to authenticate to server(for example: smtp server) in order to successfully send emails.
You can use env file to store your those values and create environment variable in settings.py and these variable will get their value from env file.
This way you will be able to send emails in django without mentioning those values in settings.py and keep env secure and out of git(or any SCM/VCS sotfware you are using.)
If you are running internally, say from a company's server, you can use their SMTP server and send emails without a password. Just change the EMAIL_PORT to the needed email port, adjust the EMAIL_HOST to the company's SMTP server, and change the EMAIL_HOST_USER to the email being used.

Django send_mail() works from shell but not in nginx production

I would like to send email from a django view. I got it to work on my local machine with django development server with the following settings:
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'user#gmail.com'
EMAIL_HOST_PASSWORD = 'password'
EMAIL_PORT = 587
My view has
from django.core.mail import send_mail
def my_view(request):
send_mail('subject','body','user#gmail.com',['recipient#gmail.com'],fail_silently=False)
return render(request, 'index.html')
When I run send_mail() from manage.py shell on my production server, the email is successfully sent. However, when the view is invoked in production (nginx + uwsgi + django), no email is sent, even though the view runs without error and returns the expected response. I see no error in error.log.
Please help me set correct permissions and configurations for nginx so that this works.
NOTE: This question is similar to Send_mail in Django, works in shell, works locally, not in view, which was never resolved.
EDIT: When I do
sudo -u www-data python manage.py shell
to run as the nginx user, i can still successfully send mail, which confuses me even more.
If the email is printed in the console then you have probably set
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
which prints the email instead of sending it.
If this line is included in an alternative (to the default) settings file then it could somehow be used by your deployment setup, whereas the shell continues to use the default settings file where the backend is either set to:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
or not set at all, in which case the default value is smtp as well