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)
Related
So I'm using the sample code provided by Twilio to send an SMS to my phone. When using the sample code I keep getting the same error and I'm not sure what the error is. I have already tried searching through this website to see if anyone has had any similar errors I also followed the Twilio step by step process for setting up and receiving the SMS. So I am very confused as to why this is happening. None of the resources I used gave me an answer as to why this is happening. My phone number is starred out for safety reasons.
# Download the helper library from https://www.twilio.com/docs/python/install
import os
from twilio.rest import Client
# Your Account Sid and Auth Token from twilio.com/console
# and set the environment variables. See http://twil.io/secure
account_sid = os.environ['ACa30b8fa59e7eba0e6dc5dbedaf5e8fcb']
auth_token = os.environ['REDACTED']
client = Client(account_sid, auth_token)
message = client.messages \
.create(
body="What is up Med",
from_='+***********',
to='+***********'
)
print(message.sid)
Error below:
Traceback (most recent call last):
File "/Users/administrator/Documents/Unit 5 Proj.py", line 8, in <module>
account_sid = os.environ['ACa30b8fa59e7eba0e6dc5dbedaf5e8fcb']
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/os.py", line 679, in __getitem__
raise KeyError(key) from None
KeyError: 'ACa30b8fa59e7eba0e6dc5dbedaf5e8fcb'
You are mixing up two concepts here:
Hard coding your Sid and Auth Token values in your code
Pulling your Sid and Auth Token vaules from the execution environment.
You only want to do one of these or the other, not both. The most straightforward approach would be to do just #1, which would look like this:
account_sid = 'ACa30b8fa59e7eba0e6dc5dbedaf5e8fcb'
auth_token = 'REDACTED'
If you want to do #2, then you need to define two exported variables in the environment in which you are running your program. It looks like you're on a Mac, so you could do something like this in, say, your ~/.bash_profile file:
export TWILIO_SID=ACa30b8fa59e7eba0e6dc5dbedaf5e8fcb
export TWILIO_AUTH_TOKEN=REDACTED
and then do this in your Python code:
account_sid = os.environ['TWILIO_SID']
auth_token = os.environ['TWILIO_AUTH_TOKEN']
UPDATE: I'll add that #2 is much preferred in production code because it avoids you having to check in sensitive account credentials to a shared source code repository that other people will see. That's the whole reason for the added complexity. If you're just fooling around or doing a personal project, then #1 might be fine. If you're doing work where your code will be seen by others, do #2 to keep your credentials to yourself.
Read your error!
Your call to os.eviron[your-key] is erroring with raise KeyError(key) from None KeyError. When googled, this error occurs when you are trying to access a missing key from the dictionary in os.eviron. Did you set your keys in env variables? If the key you are indexing in your code is your account_sid and auth_token, then you are doing it wrong for sure
I've create an API Key as required by the code and added it in the environments.
Below is the code I'm using and have followed the steps provided here.
# using SendGrid's Python Library
# https://github.com/sendgrid/sendgrid-python
import os
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail
message = Mail(
from_email='from_email#example.com',
to_emails='to#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)
It throws this error:
Traceback (most recent call last):
File "sendgrid_email.py", line 18, in <module>
print(e.message)
AttributeError: "ForbiddenError" object has no attribute "message"
And while printing exception it shows pylint warning-
Instance of "Exception" has no "message" member
Any ideas on what I'm doing wrong or what I'm missing?
Also, to_emails is having only one email address, how do we attach multiple recipients?
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)
to_emails can receive tuple for multiple recipients. e.g.
to_emails=("recipient1#example.com", "recipient2#example.com"),
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.
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.
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)