10

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.

5
  • 2
    @admix Slow down -- he doesn't have enough rep to downvote. Commented Dec 11, 2015 at 19:14
  • im pretty sure he is not the serial downvoter on this question ... Commented Dec 11, 2015 at 19:22
  • My bad @dpeach, didn't look at your rep score. Just don't like when people down-voting without any explanations.. Commented Dec 11, 2015 at 19:25
  • 1
    To whoever is downvoting Please by all means enlighten us with your knowledge. Commented Dec 11, 2015 at 19:25
  • No, I wasn't the serial downvoter. I was disappointed to see the downvoting on my very first question too. Commented Dec 11, 2015 at 19:50

3 Answers 3

14

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: [email protected]
    password: yourpassword

This way, you will never see the actual credentials in the script.

Sign up to request clarification or add additional context in comments.

5 Comments

This worked beautifully! It also gives me a great tutorial on how to do this for other types of information I want to insert into a script.
Glad to hear that @dpeach :)
This is one of the good solution. It hides the credential from the script which is how the question requested. It just doesn't protect the credential from plaintext. But this is another topic, which is big. I upvoted this answer. It doesn't deserve the downvote from ridiculous user.
Is there any difference in terms of security between this method and just use a credentials.py containing a dictionary with the credentials?
good answer, but I would use safe_load instead of load, since safe_load is safer after vulnerabilities issue of load: github.com/yaml/pyyaml/wiki/PyYAML-yaml.load(input)-Deprecation
13

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

12 Comments

This is the right answer. Store the email and password outside of the project and use the import os library to get it. You want to make sure that it never even gets a chance to be pushed into the public repository. DO NOT PUT IT IN settings.py. Oh god. Edit: if you're in Windows, you can still store it outside of the project and just import the file, followed by parsing it. The point is, keep it out of the project directory!
@PadraicCunningham I didn't make a recommendation in that regard. I was targeting the issue of mistakenly committing it to a public repo - which Microsoft did just this past week.
this is really the right answer if it is something the OP can do
Thanks @utkbansal. I will definitely take your advice and set the file permissions as 600. Since this is on an older Debian install for Raspberry Pi, and I am monitoring temperatures through the GPIO, I have to run the main script as root anyway. (The newest version of Raspbian (Debian for the Pi) allows GPIO control as a user.)
@Kris I think you're overdoing with the capitals and the "Oh god". For someone stating to be a basic programmer, using literal tutorial code to send e-mail and asking how to get the variables out of the script, putting it in a separate file is not wrong at all. Making it public or putting it a file with a .py extension are not the same thing. You're answering as if it was a question about best deployment practices.
|
5

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.