Sendgrid working from terminal but not in pycharm - python

I am trying to connect a basic mail sender sendgrid function to my program's pipeline. Problem is when I do necessery commands from terminal it works fine like :
echo "export SENDGRID_API_KEY='YOUR_API_KEY'" > sendgrid.env
echo "sendgrid.env" >> .gitignore
source ./sendgrid.env
python3 sendgrid_mail.py
but when I try to run it from PyCharm it gives me HTTP Error 401: Unauthorized
error.
import os
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail
def mail_sender():
message = Mail(
from_email='from_mail',
to_emails='to_mail',
subject='hello pycharm',
html_content='<strong>and easy to do anywhere, even with Python</strong>')
try:
sg = SendGridAPIClient(os.environ.get('my_api_key'))
response = sg.send(message)
print(response.status_code)
print(response.body)
print(response.headers)
except Exception as e:
print(e)
mail_sender()

It's unclear how you're running in PyCharm. I'm guessing your environment variable is not actually set while you are in PyCharm. Try looking at the API key and see if it's what you're expecting (Either just print or use the debugger)
You can modify the environment variables in your run configuration
Run | Edit Configurations... | Select the run configuration you're using | Environment variables ....
You could also try setting the environment variable prior to starting PyCharm and it might pick it up, but that depends on a-lot of other things.

You're getting the environment variable my_api_key, but you're setting your environment variable as SENDGRID_API_KEY in the sendgrid.env. These two names need to match.
I'm assuming YOUR_API_KEY in your sendgrid.env file is the api key you've created. If not, that would need to be replaced with a real value.

Related

Sendgrid Introduction Throws Forbidden Error

I'm running through Sendgrid's intro material for Python but executing the example code throws a 403-Forbidden error.
Steps I took:
Create API Key & sendgrid.env file as instructed.
Create a conda environment with python 3.5: conda create -n sendgrid python=3.5
Install sendgrid: (sendgrid) pip install sendgrid
Run example: (sendgrid) python main.py
Where main.py contains the exact code copied from the example page linked above.
Issue: Running main.py throws the error HTTP Error 403: Forbidden.
Things I've tried:
I tried switching out the to and from emails in that example, but doesn't change the result.
I also tried the same flow but using NodeJS but same result.
Any ideas on what I'm doing wrong?
Give API Key its full access, follow steps:
Settings
API Keys
Edit API Key
Full Access
Update
Whitelist your domain, follow steps:
Settings
Sender Authentication
Domain Authentication
Select DNS Host
Enter your domain name
Copy all records and put them in your Advanced DNS management console
NOTE: When adding records, make sure not to have domain name in the host. Crop it out.
If you do not want to authenticate domain, you can try with Single Sender Verification as well.
Note: It might take some time for records to start functioning.
If you're using pylinter, e.message will say
Instance of 'Exception' has no 'message' member
This is because message attribute is generated dynamically by sendgrid which pylinter is unable to access as it doesn't exists before runtime.
So, to prevent that, at the top of your file or above print(e.message) line, you need to add either one of the below, they mean the same thing-
# pylint: disable=no-member
E1101 is code to no-member, fine more here
# pylint: disable=E1101
Now the code below should work for you. Just make sure you have SENDGRID_API_KEY set in environment. If not, you may also directly replace it with os.environ.get("SENDGRID_API_KEY") which is not a good practice though.
# pylint: disable=E1101
import os
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail
message = Mail(
from_email="from_email#your-whitelisted-domain.com",
to_emails=("recipient1#example.com", "recipient2#example.com"),
subject="Sending with Twilio SendGrid is Fun",
html_content="<strong>and easy to do anywhere, even with Python</strong>")
try:
sg = SendGridAPIClient(os.environ.get("SENDGRID_API_KEY"))
response = sg.send(message)
print(response.status_code)
print(response.body)
print(response.headers)
except Exception as e:
print(e.message)

Azure Python SDK - code only fails when debugging in VS Code

VS Code 1.14.0, Python 3.8.0 (in venv).
When I run the following code in VS Code, it works. When I run it in the debugger even with no breakpoints, it fails. This might be something to do with venvs, but I don't know. Ideas? BTW - I am referencing the other packages for what I will be building.
From the Bash shell, I have the following environment variables:
export AZURE_TENANT_ID = "tenant ID"
export AZURE_CLIENT_ID = "client ID"
export AZURE_CLIENT_SECRET = "client secret"
export AZURE_SUBSCRIPTION_ID = "subscription ID"
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
from azure.keyvault.keys import KeyClient
from azure.mgmt.keyvault import KeyVaultManagementClient
from azure.core.exceptions import HttpResponseError
import datetime
import os
credential = DefaultAzureCredential()
secret_client = SecretClient(vault_url="https://blahblahblah.vault.azure.net/", credential=credential)
print(os.environ["AZURE_TENANT_ID"])
print(os.environ["AZURE_CLIENT_ID"])
print(os.environ["AZURE_CLIENT_SECRET"])
print(os.environ["AZURE_SUBSCRIPTION_ID"])
try:
print("\n.. Get a Secret by name")
secret = secret_client.get_secret("mySecret")
print("Secret with name '{0}' was found with value '{1}'.".format(secret.name, secret.value))
except HttpResponseError as e:
print("\nThis sample has caught an error. {0}".format(e.message))
When I run this in DEBUG in VS Code, this is the error:
This sample has caught an error.
No credential in this chain provided a token.
Attempted credentials:
EnvironmentCredential: Incomplete environment configuration
ImdsCredential: IMDS endpoint unavailable
SharedTokenCacheCredential: The shared cache contains no signed-in accounts. To authenticate with SharedTokenCacheCredential, login
through developer tooling supporting Azure single sign on
What I have learned is the printed OS environ variables are accurate when I Run Python File in Terminal, but when I run the file in debug, it errors printing the first OS environ variable saying it doesn't exist.
This is my ignorance on setting debug correctly. Any pointers will help (and thank you for your responses)!**
To make the answer visible to others, I'm summarizing the answer shared in comment:
This issue occurred because of the missing of environment variables under debugger mode. Add the environment variables to the launch.json file solved this issue.
From my experience, BASH does not like spaces, when declaring variables;
export AZURE_TENANT_ID="tenant ID"
export AZURE_CLIENT_ID="client ID"
export AZURE_CLIENT_SECRET="client secret"
export AZURE_SUBSCRIPTION_ID="subscription ID"
Might do the trick.

How do I explicitly pass my authentication key into Google's text to speech engine?

I'm trying to use Google Cloud's text to speech engine for my robot, and I cannot understand the reference page for passing the key explicitly in Python as mentioned here.
I spent several hours yesterday exploring different options on how to set the environment variable GOOGLE_APPLICATION_CREDENTIALS needed for implicit authorization including an export command in the shell script I use to start the robot, using os.environ commands in Python, and using os.system to call an export command.
client = texttospeech.TextToSpeechClient()
voice = robot_config.get('google_cloud', 'voice')
keyFile = robot_config.get('google_cloud', 'key_file')
hwNum = robot_config.getint('tts', 'hw_num')
languageCode = robot_config.get('google_cloud', 'language_code')
voice = texttospeech.types.VoiceSelectionParams(
name=voice,
language_code=languageCode
)
audio_config = texttospeech.types.AudioConfig(
audio_config=texttospeech.enums.AudioEncoding.LINEAR16
)
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = keyFile
Logging in via SSH shows that I have successfully set the environment variable since it shows up in env; however a DefaultCredentialsError is thrown with the following message
Could not automatically determine credentials. Please set GOOGLE_APPLICATION_CREDENTIALS or explicitly create credentials and re-run the application. For more information, pease see https://cloud.google.com/docs/authentication/getting-started
Logging in and setting the environment variable manually will allow the script to run and work, but this is not a long term solution.
This works for me:
import os
from google.cloud import texttospeech
os.environ ["GOOGLE_APPLICATION_CREDENTIALS"]= "/home/pi/projectx-17f8348743.json"
client=texttospeech.TextToSpeechClient()
The correct answer lies in the google.oath2 library. The client object is not looking for a json key, and is instead looking for a service account object.
from google.oath2 import service_account
from google.cloud import texttospeech
client = texttospeech.TextToSpeechClient(
credentials=service_account.Credentials.from_service_account_file(keyFile)
)

Using Jupyter behind a proxy

Is there a similar config to that of .condarc (anaconda 4.0.0) that allows Jupyter to be configured to work behind a corporate proxy on a local machine?
Error received:
HTTPError: HTTP Error 407: Proxy Authentication Required
Way easier: Just add the following to your notebook:
In [1]: import os
os.environ['http_proxy'] = "http://user:passwd#host:port"
os.environ['https_proxy'] = "https://user:passwd#host:port"
after that, requests will work OK=200, e.g.
In [2]: import requests
requests.get("https://google.com")
Out[2]: <Response [200]>
Based on this link.
You have to modify the Jupyter notebook server env. Create a file named 00-something.py under your Jupyter notebook server profile and add the following:
For example:
vi /.jupyter/profile_myserver/startup/00-startup.py
(or on Windows open up "C:/Users/your username/.jupyter/profile_myserver/startup/00-startup.py" in your editor of choice)
and add
import sys,os,os.path
os.environ['HTTP_PROXY']="http://proxy.example.com:80"
os.environ['HTTPS_PROXY']="https://proxy.example.com:443"
you can confirm the env variables by running
%env
in a cell and the output
{'CLICOLOR': '1',
'GIT_PAGER': 'cat',
'HOME': '/home/jay',
'HTTP_PROXY': 'http://proxy.example.com:80',
..
Next try
import requests
requests.get("http://google.com")
If you get a response [200] then you are all set.
Use the lowercase variable instead, it works for me:
import sys,os,os.path
os.environ['http_proxy']="http://user:passwd#host:port"
os.environ['https_proxy']="http://user:passwd#host:port"
Then check your env variable using this:
%env
The output will be like this:
{'CLICOLOR': '1',
'...'
'...'
'http_proxy': 'http://gunawan.marbun:xxxxxxxx#cache.itb.ac.id:8080'
'https_proxy': 'https://gunawan.marbun:xxxxxxxx#cache.itb.ac.id:8080'
'no_proxy': 'localhost,127.0.0.0/8,::1'}
Notes: Since I can't comment due to my reputation (req 50 and I'm newbie), I present new answer instead.
An easier solution for me was to add an exception to my proxy configuration. I just put the address http://localhost:8888 to my exception list and it worked.
Based on these Jupyter customization instructions:
Create the directory .jupyter_config in your home directory
Add the line JUPYTER_CONFIG_DIR=~/.jupyter_config to your bash/shell profile (eg. .bash_profile).
Add a script titled startup.py to ~/.jupyter_config with the following code, customized with your specific proxy information:
import os
os.environ['http_proxy']= "http://user:passwd#host:port"
os.environ['https_proxy']= "https://user:passwd#host:port"
os.environ['HTTP_PROXY']= os.environ['http_proxy']
os.environ['HTTPS_PROXY']= os.environ['https_proxy']
1. Ensure you are connected to VPN to office network
2. You can set up proxy before starting notebook or in every notebook
A. before starting
from jupyer notebok, start terminal (From option New on right top)
set HTTP_PROXY=http://fakeserver:fakeport
set HTTPS_PROXY=http://fakeserver:fakeport
jupyter notebook
(This will start notebook in new terminal, with proxy set that can be checked with %env)
B. in every notebook
import sys,os,os.path
os.environ['HTTP_PROXY']="http://fakeserver:fakeport"
os.environ['HTTPS_PROXY']="http://fakeserver:fakeport"
3. in windows, set the environmental variables
This PC (Rt Click) >> propertis>> Advanced System Setting >> Advanced >> Envioronmental variables>> click NEW to add 2 variables pointing HTTP_PROXY and HTTPS_PROXY to "http://fakeserver:fakeport"
Mostly the problem comes due to adding HTTPS in the proxy server URL. For both HTTP and HTTPS, the proxy server URL should be "http://" only
import os
os.environ['http_proxy'] = "http://username:complexpassword!#34#serverIP:port"
os.environ['https_proxy'] = "http://username:complexpassword!#34#serverIP:port"
import requests
requests.get("https://google.com")
Response should be 200 OK
If you are in a Windows domain and use domain\username for authentication, just use username instead of domain\username in python setting above
For those of you who may need a socks5 proxy, the following did the trick for me:
os.environ['http_proxy'] = "socks5h://host:port"
os.environ['https_proxy'] = "socks5h://host:port"
The only difference with the http proxy was the socks5h part in the url. In my case the proxy didn't have username and password but I suppose these too may be added to the url like socks5h://user:passwd#host:port.

How do I connect to a kerberos authenticated REST service in Python on Windows

I am trying to create a very simple Python script to download the contents of an internal service at my company that sits within our firewall and authenticates using kerberos.
When I installed the requests_kerberos module I first edited the import kerberos in it to use import kerberos_sspi as kerberos instead after having installed the kerberos_sspi module.
Thus I have the following Python script
import requests
from requests_kerberos import HTTPKerberosAuth
response = requests.get('http://service.internaldomain',auth=HTTPKerberosAuth())
print response
While trying to process the 401 it crashes out with the error.
error: (-2146893053, 'InitializeSecurityContext', 'The specified target is unknown or unreachable')
While looking into seeing if I could do this with curl instead I ran kinit and noticed that it asked me for the password to authorisation with the following prompt:
Password for username#additionalInternalDomain.internaldomain
Thus I wondered if this might be what is causing the issue.
I have tried multiple libraries on python and failed when trying to authenticate from a windows machine.There is no easy way. The Kerberos libraries mainly work on Linux. The workarounds for Windows do not work. So what can be the solution to this.
Well... be a Roman while in Rome. Try the windows native libraries from Python.
import sys
import clr
from System.Net.Http import *
myClienthandler = HttpClientHandler()
myClienthandler.UseDefaultCredentials = True
myClient = HttpClient(myClienthandler)
x = myClient.GetStringAsync("putyourURLwithinthequoteshere")
myresult = x.Result
print(myresult)
Note that the this python script will have to run by the user who has access to the URL you are trying to access. By setting UseDefaultCredentials property as True, you are passing the Kerberos tickets for the logged in user.
The server is giving you a 401 challenge - and the client (usually a browser or even curl) provides the credentials in a subsequent call. If you are already logged in at your domain - try forcing a pre-emptive hop, i.e. you’d carry your Kerberos ticket with your call and the server will not give you a 401 challenge:
kerberos_auth = HTTPKerberosAuth(force_preemptive=True)
r = requests.get("http://myhost/DXAPIGraphQL/api/graphql", auth=kerberos_auth)
If the above doesn't help look into the:
principal and hostname_override arguments of the HTTPKerberosAuth class.
I had to connecto to a REST API who's in a keberized environment just now.
After some reading, i came to this (and it worked):
tk = 'long_kerberos_token'
headers = {'Authorization': 'Negotiate' + tk}
r = requests.get(url=PING_URL, headers=headers)

Categories

Resources