Distribute a script, but protect the password - python

I have a script which will log into a STMP server (GMail's) to send an email notification. How can I do this without distributing the password in plain text?

Have the script request the password when running.
Note, I wouldn't advise that it accept the password as a command line argument as this isn't very secure because it will be logged in the command history etc.

You can have the script look for an environmental variable for the password:
import os
password = os.environ['GMAIL_PASSWD']

check if your provider offers an smtp server that doesn't require authentication and use that instead.

Related

pass password to a Python script on prompt

How can I pass a password to my python script when it prompts for a password. I do not want the user to enter the password when it prompts. It should be passed directly from the script.
subprocess.run(['ansible-vault', 'decrypt', 'main.yml', 'linux.yml','--ask-vault-pass'])
While running the script it prompts for the password. I want the password to be passed from script only not by the user or passing a password file.
Is there a way to pass the password here? I have other ansible vault option like vault-password etc but that doesn't serve my purpose.
Instead of using the cmdline ansible-vault, you can use the Python package - ansible-vault which will allow you to hardcode the password inside the script itself:
from ansible_vault import Vault
vault = Vault('password')
main_data = vault.load(open('main.yml').read())
linux_data = vault.load(open('linux.yaml').read())
As you are hardcoding the password inside the code, ensure you don't commit this code anywhere or send it to anyone, it's a serious security risk.

Django email sending on Heroku

Here is my properties in settings.py file:
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'infobot9#gmail.com'
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD')
EMAIL_PORT = 587
and here is my send email method:
from django.core.mail import send_mail
def sendConfirmEmail(email, instance, code):
mail_subject = 'Confirmation code {}'.format(code)
message = render_to_string("msg.html", {
'user': instance,
'code': code
})
to_email = email
send_mail(mail_subject, message, 'infobot9#gmail.com', [to_email],
fail_silently=False)
My Django email sending methods work fine in my local host. After deploying it to Heroku I have allowed the login from unknown devices in my Gmail settings. Gmail does not allow the server login to my account and sends me a message:
spicious login attempt blocked
infobot9#gmail.com
Someone tried to log into your account using the password set for them. If it was not you, we recommend that you change your password as soon as possible.

Unknown Device

April 4, 11:39

Near this place: Dublin, Ireland
176.34.163.6 (IP address)
Should I set extra parameters in my settings.py file or I need change my Gmail account settings?
I urge you not to use Gmail for sending email in production. It's not designed for that, and as you've discovered there are measures in place to prevent it from being used as a spam relay. Even if you're sending legitimate email, Gmail is going to make things difficult for you.
Instead, use a service that's designed to send mail from hosted applications like SendGrid or Mailgun. These are both listed among Heroku's addons and both have free starter plans. Pick one and go through its getting sarted guide. Not only will this work better with small volumes of mail, it sets you up nicely for growth.
Allow less secure apps
Display Unlock Captcha
If you still want to use Gmail, #Pierre Monico's answer will work. I just wanted to make an edit. After allowing less secure apps to sign in to your account and Display Unlock Capatcha you should still keep two things in mind. First be sure to be logged into your browser through the account which you are using in your app to send email so that Capatch should be unlocked for that particular account and the second thing is that Google only allows Display Unlock Capatcha for Only 10 minutes . Thus if you want to use it again and again just keep Display Unlock Capatcha page open in your browser and keep it refreshing after sometime.
Also if you have 2 factor authentication enabled then these steps won't work. Those accounts have different procedure.
Above mentioned answers didn't work for me. So here's how I did it. Basically, you need to configure an app password.
Go to your Gmail account
Security > in 'Signing in to Google' section
Turn on 2-Step Verification
Set app password
and finally, need to configure settings.py or .env file(follow's the env),
EMAIL_HOST_USER=your_email#gmail.com
EMAIL_HOST_PASSWORD=generated_app_password
Tip
Using python-decouple makes it much easier to handle .env data

Using username and password safely in Python code

I'm using the Python requests library to make a call to an API that requires Windows Authentication. In C# I have always used the Directory Services, which has allowed me to avoid putting passwords in any of my code or configurations. From what I have found online, it seems that my only option in Python is to have a password somewhere. I have a service account that I will use, but I need to store the password securely. What is the best way to securely store and retrieve a service account password in Python without hard coding plain text?
The code that I am currently using is below. I have the username and password stored in plain text in my configuration:
auth = HttpNtlmAuth(
config.ServiceAccount["Username"],
config.ServiceAccount["Password"]
)
content = requests.post(call_string, json=parameters, auth=auth)
Edit: I should mention that this will not be a user-facing application. It will run as a batch job. So there will not be any way for a user to enter the username/password while running the application.
You could just not store the password at all and require the user to provide the password at runtime
import getpass
user = getpass.getuser()
password = getpass.getpass()
Otherwise, you could do something similar to git and just have the user store their password in plaintext in a config file in their home directory that you then read at runtime.
I know I asked this question a while ago, but I found a better solution to the NTLM/Windows authentication. I used the requests_negotiate_sspi library to avoid any passwords:
from requests_negotiate_sspi import HttpNegotiateAuth
auth = HttpNegotiateAuth()
content = requests.post(call_string, json=parameters, auth=auth)

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.

Login credentials not working with Gmail SMTP

I am attempting to send an email in Python, through Gmail. Here is my code:
import smtplib
fromaddr = '......................'
toaddrs = '......................'
msg = 'Spam email Test'
username = '.......'
password = '.......'
server = smtplib.SMTP('smtp.gmail.com', 587)
server.ehlo()
server.starttls()
server.login(username, password)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
I get the error:
Traceback (most recent call last):
File "email_send.py", line 18, in <module>
server.login(username, password)
File "C:\.....\Python\lib\smtplib.py", line 633
, in login
raise SMTPAuthenticationError(code, resp)
smtplib.SMTPAuthenticationError: (535, b'5.7.8 Username and Password not accepte
d. Learn more at\n5.7.8 http://support.google.com/mail/bin/answer.py?answer=1425
7\n5.7.8 {BADCREDENTIALS} s10sm9426107qam.7 - gsmtp')
This seems to be a problem with the login. I am certain that my login details are correct, except for one thing. Should username be "blah#gmail.com", or simply "blah"? I tried both, same error.
Any idea whats wrong?
NOTE: all the periods are instead of password/email/file paths/etc.
UPDATE:
This feature is no longer supported as of May 30th, 2022. See https://support.google.com/accounts/answer/6010255?hl=en&visit_id=637896899107643254-869975220&p=less-secure-apps&rd=1#zippy=%2Cuse-an-app-password
ORIGINAL ANSWER (No longer working):
I ran into a similar problem and stumbled on this question. I got an SMTP Authentication Error but my user name / pass was correct. Here is what fixed it. I read this:
https://support.google.com/accounts/answer/6010255
In a nutshell, google is not allowing you to log in via smtplib because it has flagged this sort of login as "less secure", so what you have to do is go to this link while you're logged in to your google account, and allow the access:
https://www.google.com/settings/security/lesssecureapps
Once that is set (see my screenshot below), it should work.
Login now works:
smtpserver = smtplib.SMTP("smtp.gmail.com", 587)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.ehlo()
smtpserver.login('me#gmail.com', 'me_pass')
Response after change:
(235, '2.7.0 Accepted')
Response prior:
smtplib.SMTPAuthenticationError: (535, '5.7.8 Username and Password not accepted. Learn more at\n5.7.8 http://support.google.com/mail/bin/answer.py?answer=14257 g66sm2224117qgf.37 - gsmtp')
Still not working? If you still get the SMTPAuthenticationError but now the code is 534, its because the location is unknown. Follow this link:
https://accounts.google.com/DisplayUnlockCaptcha
Click continue and this should give you 10 minutes for registering your new app. So proceed to doing another login attempt now and it should work.
This doesn't seem to work right away you may be stuck for a while getting this error in smptlib:
235 == 'Authentication successful'
503 == 'Error: already authenticated'
The message says to use the browser to sign in:
SMTPAuthenticationError: (534, '5.7.9 Please log in with your web browser and then try again. Learn more at\n5.7.9 https://support.google.com/mail/bin/answer.py?answer=78754 qo11sm4014232igb.17 - gsmtp')
After enabling 'lesssecureapps', go for a coffee, come back, and try the 'DisplayUnlockCaptcha' link again. From user experience, it may take up to an hour for the change to kick in. Then try the sign-in process again.
UPDATE:: See my answer here:
How to send an email with Gmail as provider using Python?
I had the same issue. The Authentication Error can be because of your security settings, the 2-step verification for instance. It wont allow third party apps to override the authentication.
Log in to your Google account, and use these links:
Step 1 [Link of Disabling 2-step verification]:
https://myaccount.google.com/security?utm_source=OGB&utm_medium=act#signin
Step 2: [Link for Allowing less secure apps]
https://myaccount.google.com/u/1/lesssecureapps?pli=1&pageId=none
It should be all good now.
I am also faced with the same error message when I try to use smtplib. The error message was like this;
error (535, b'5.7.8 username and password not accepted.
Google has changed access to less secure apps. Before that, there was a field to give access to. Now you can follow these steps;
Go to Google Account Page>Security>Signing in to Google section
turn on 2-Step Verification. You need this feature on.
When 2SV is on, go to App Password and generate new-app-password for mail access. It will generate it for you, then use this password in gmail_password function in Python.
gmail_password='google_generate_it_for_you'
If you're using smtp.gmail.com, then you have to do the following:
Turn on the less secure apps
You'll get the security mail in your gmail inbox, Click 'Yes,it's me' in that.
Now run your code again.
Denied
The solution of using "Access for the less secure app" in Gmail has been denied (find more here).
Update
By the way, you can get access to the gmail account by the solution proposed by Google, called "App password". The solution is simple:
1. Active two-step verification of the corresponding account.
2. Create an app password.
3. Exactly do the same implementation that you have for sending an email (explained in your question).
Except, replace the password with the generated app password (a sixteen digit password).
For more details you can also follow this post (it's working well for me).
I had same issue. And I fix it with creating an app-password for Email application on Mac.
You can find it at my account -> Security -> Signing in to Google -> App passwords.
below is the link for it.
https://myaccount.google.com/apppasswords?utm_source=google-account&utm_medium=web
If you turn-on 2-Step Verification, you need generate a special app password instead of using your common password.
https://myaccount.google.com/security#signin
if you are getting error this(535, b'5.7.8 Username and Password not accepted. Learn more at\n5.7.8 https://support.google.com/mail/?p=BadCredentials o60sm2132303pje.21 - gsmtp')
then simply go in you google accountsettings of security section and make a less secure account and turn on the less secure button
I had the same issue , i solved this by allowing "less secure app access" . This can be found in Security tab on Google Account:
Dec, 2022 Update:
You need to use an app password to allow your app to access your google account.
So, you need to:
generate an app password following my answer explaining how to generate an app password.
assign the generated app password to password in your code as shown below:
import smtplib
fromaddr = '......................'
toaddrs = '......................'
msg = 'Spam email Test'
username = '.......'
password = 'xylnudjdiwpojwzm' # Here
server = smtplib.SMTP('smtp.gmail.com', 587)
server.ehlo()
server.starttls()
server.login(username, password)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
Enable 2FA for your Google account
Then set an app password for your app
Use that new password
For email created by G-Suite or Google Workspace, you have to ask your admin to activate the Gmail app and assigned it to your email account. Without this step, trying either above methods still does not work.
Oct 3 2022
As per all the answers mentioned above.
Enabling 2Factor Authentication and creating an App Pasword does the trick with SMTP.
NOTE: Less secure apps toggle doesn't work anymore tbh?(Others confirm?)
Update after May 30th, 2022 :
To solve this problem it is necessary to activate two-step
verification on your Gmail account :
https://myaccount.google.com/u/1/security
Then you will have access to a new page to create an App Password :
https://myaccount.google.com/u/1/apppasswords
Finally, using this password on your django application should solve the problem.
Tutorial for more information: https://www.youtube.com/watch?v=sCsMfLf1MTg
less secure apps can now only be used in gmail if you turn on 2 factor auth and then generate an app password for a custom app
these steps worked for me :)
follow these steps https://myaccount.google.com/security
It is no longer possible as google has removed support for Less secure apps.
However you can still use App Passwords
Documentation from google -https://support.google.com/accounts/answer/185833?hl=en
Create & use App Passwords
If you use 2-Step-Verification and get a "password incorrect" error when you sign in, you can try to use an App Password.
Go to your Google Account.
Select Security.
Under "Signing in to Google," select App Passwords. You may need to sign in. If you don’t have this option, it might be because:
2-Step Verification is not set up for your account.
2-Step Verification is only set up for security keys.
Your account is through work, school, or other organization.
You turned on Advanced Protection.
At the bottom, choose Select app and choose the app you using and then Select device and choose the device you’re using and then Generate.
Follow the instructions to enter the App Password. The App Password is the 16-character code in the yellow bar on your device.
Tap Done.
Tip: Most of the time, you’ll only have to enter an App Password once per app or device, so don’t worry about memorizing it.
In my case, I allowed the access, but the problem was that I was using server.login('Name <email>', password). Please, make sure to use only your email here: server.login('youremail#gmail.com', password).
Response after change:
(235, '2.7.0 Accepted')
Response prior:
smtplib.SMTPAuthenticationError: (535, b'5.7.8 Username and Password not accepted. Learn more at\n5.7.8 https://support.google.com/mail/?p=BadCredentials 130sm13119106qkh.99 - gsmtp')
Try turning on less secure apps and make sure that you have smtp.gmail.com or for different search up

Categories