I have a python script that pulls customer transaction data from our DB and formats it to be used by SendGrid's Dynamic Templates, but I cannot figure out from the SendGrid docs or any other source how to insert each customer's unique data in their email. Here is the relevant code from the script (assume all variables are pre-filled by the script):
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail, To
message = Mail(
from_email=("no_reply#mywebsite.com", "My Website"),
to_emails=to_emails,
is_multiple=True)
message.template_id = "d-thetemplateidthatiamusing"
try:
sendgrid_client = SendGridAPIClient("SG.thesecretkeythatdoesnotbelongonstack")
sendgrid_client.send(message)
except Exception as e:
print(e)
When I run this, it sends to the correct customer emails, but without any custom data. I have the following object ready to send over for each customer, but have no idea how to attach it on an email by email basis:
{
"name": "Customer Name",
"games": [
{
"game_title": "Test Team vs. Demo Team",
"event_name": "Live Showcase I",
"date": "5/9/2021",
"score": "79-55",
"url": "app.website.com/"
},
{
"game_title": "Test Team vs. Demo Team",
"event_name": "Live Showcase I",
"date": "5/9/2021",
"score": "79-69",
"url": "app.website.com/"
}
]
}
When I throw this JSON in the SendGrid template test data area it works perfectly with my design. Any thoughts?
You are missing an attribute:
message.dynamic_template_data = {
"name": "Customer Name",
}
To pass information dynamically you need to pass an instance of the Customer to your email dispatcher:
def sendEmail(instance):
message = Mail(
from_email=("no_reply#mywebsite.com", "My Website"),
to_emails=to_emails,
is_multiple=True)
message.dynamic_template_data = {
"name":instance.name
}
message.template_id = "d-thetemplateidthatiamusing"
try:
sendgrid_client = SendGridAPIClient("SG.thesecretkeythatdoesnotbelongonstack")
sendgrid_client.send(message)
except Exception as e:
print(e)
You did not include your initialization code for to_emails,
here is a link to an example that shows how to set dynamic template data for each 'to' email address. Also, it wasn't clear to me, does each recipient have their own set of json data, or is name the only thing difference between them? In other words, would they all be receiving the same data for games?
And here is an excerpt (adjust the recipient and dynamic_template_data to fit your needs):
import os
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail, To
to_emails = [
To(email='test+to0#example.com',
name='Customer Name 0',
dynamic_template_data={
'name': 'Customer Name 0',
'games': games,
},
subject='Override Global Subject'),
To(email='test+to1#example.com',
name='Customer Name 1',
dynamic_template_data={
'name': 'Customer Name 1',
'games': games,
}),
]
message = Mail(
from_email=('test+from#example.com', 'Example From Name'),
to_emails=to_emails,
subject='Global subject',
is_multiple=True)
message.template_id = 'd-12345678901234567890123456789012'
try:
sendgrid_client = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY'))
response = sendgrid_client.send(message)
print(response.status_code)
print(response.body)
print(response.headers)
except Exception as e:
print(e.message)
just to add to what #jacko_iced_out answered, in SendGrid you should wrap the variable you want to set with {{}}
<div class="v-font-size" style="color: #444444; line-height: 170%; text-align: center; word-wrap: break-word;">
<p style="font-size: 14px; line-height: 170%;">
<span style="font-size: 20px; line-height: 34px;">
<strong>
<span style="line-height: 34px;">{{password}}</span>
</strong>
</span>
</p>
</div>
And here is an example of python code to send mail
from fastapi import HTTPException
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail
from config import settings
async def sendLoginMailClient(admin_mail, client_mail, password):
message = Mail(
subject='Invitation de création de maturité numirique profil',
from_email=("from_sendgridmail_mail"),
to_emails=client_mail
)
message.dynamic_template_data = {
"admin": admin_mail,
'client': client_mail,
"password": password
}
message.template_id = "d-c9f1894881ff426aa614e5c41e831f16"
try:
sg = SendGridAPIClient(settings.sendgrid_api_key)
response = sg.send(message)
code = response.status_code
return {
'success': True,
'data': code
}
except Exception as e:
raise HTTPException(
status_code=500,
detail=f'error:{e}'
)
For more detail check this link https://www.twilio.com/blog/send-dynamic-emails-python-twilio-sendgrid
Related
I am trying to use the POST method of Amadeus flight availabilities API on Python, but is is still giving me error 400. Any suggestions? Many thanks.
from amadeus import Client, ResponseError, Location
import requests
amadeus = Client(
client_id='My ID',
client_secret='My Secret')
try:
flights = amadeus.get('/v2/shopping/flight-offers',originLocationCode = "GIG",destinationLocationCode = "ATL",departureDate = "2023-01-31",nonStop = "true",travelClass = "BUSINESS",adults = 1)
body = flights.data[0]
print(body)
except ResponseError as error:
print(error)
try:
availability = amadeus.post('/v1/shopping/availability/flight-availabilities', body)
print(availability.result)
except ResponseError as error:
print('headers: ', error.response.request.headers)
print('body: ', error.response.request.params)
As per their API documentation, the body of the second API call needs to be in the following format:
{
"originDestinations": [
{
"id": "1",
"originLocationCode": "BOS",
"destinationLocationCode": "MAD",
"departureDateTime": {
"date": "2021-11-14",
"time": "21:15:00"
}
}
],
"travelers": [
{
"id": "1",
"travelerType": "ADULT"
}
],
"sources": [
"GDS"
]
}
Right now you are just feeding the second call the return from the first, which doesn't seem to be what they're looking for.
You might also need to feed the proper headers, something like:
headers = {"Content-Type": "application/json; charset=utf-8"}
then you would do
response = requests.post(url, headers=headers, json=body)
I ran the following script which works on my computer but doesnt work in AWS Lambda. All I did was added "def lambda_handler(event, context): return event" function as its required by the lambda. I ran the Lambda test a few times.
I am not getting the SES email and there's no errors when I execute it in Lambda. Any idea why?
import boto3
from botocore.exceptions import ClientError
SENDER = "Sender Name <testu#test.com>"
RECIPIENT = "test#test.com"
CONFIGURATION_SET = "ConfigSet"
AWS_REGION = "ap-southeast-2"
SUBJECT = "Amazon SES Test (SDK for Python)"
BODY_TEXT = ("Amazon SES Test (Python)\r\n"
"This email was sent with Amazon SES using the "
"AWS SDK for Python (Boto)."
)
BODY_HTML = """<html>
</html>
"""
def lambda_handler(event, context):
return event
# The character encoding for the email.
CHARSET = "UTF-8"
# Create a new SES resource and specify a region.
client = boto3.client('ses',region_name=AWS_REGION)
try:
response = client.send_email(
Destination={
'ToAddresses': [
RECIPIENT,
],
},
Message={
'Body': {
'Html': {
'Charset': CHARSET,
'Data': BODY_HTML,
},
'Text': {
'Charset': CHARSET,
'Data': BODY_TEXT,
},
},
'Subject': {
'Charset': CHARSET,
'Data': SUBJECT,
},
},
Source=SENDER,
ConfigurationSetName=CONFIGURATION_SET,
)
except ClientError as e:
print(e.response['Error']['Message'])
else:
print(response['MessageId'])
Just like what Anon Coward said, you have to perform the SES sending inside the handler function and put the return statement at the bottom of that function.
It should look something like this:
def lambda_handler(event, context):
response = client.send_email(PAYLOAD_HERE_)
return {
"statusCode": 200,
"headers": {
"Content-Type": "application/json"
},
"body": json.dumps({
"Region ": json_region
})
}
I have this code below with my credentials;
from facebook_business.api import FacebookAdsApi
from facebook_business.adobjects.adaccount import AdAccount
from facebook_business.adobjects.campaign import Campaign
my_app_id = ''
my_app_secret = ''
my_access_token = ''
FacebookAdsApi.init(my_app_id, my_app_secret, my_access_token)
my_account = AdAccount('')
my_campaign = Campaign('')
When I run the code below, I get an error.
Input:
my_account_insights = my_account.get_insights()
print(my_account_insights)
Output:
FacebookRequestError:
Message: Call was not successful
Method: GET
Path: https://graph.facebook.com/v12.0/act_2193000197632450/adsets
Params: {'summary': 'true'}
Status: 400
Response:
{
"error": {
"message": "(#100) Missing permissions",
"type": "OAuthException",
"code": 100,
"fbtrace_id": "AvMDtZu8KYqYG8qt3repNjL"
}
}
What am I missing? Could you please help me to figure it out?
Generate a new token https://developers.facebook.com/tools/explorer/ and set the permission accordingly
In the below lambda function, I want to pass "Message2" variable in the HTML "BODY_HTML". Is there a way to pass my event Message2 in the HTML.
import boto3
from botocore.exceptions import ClientError
def lambda_handler(event, context):
Message1 = event ["Message"]
print("Message_Received : ")
print(Message1)
Message2 = event ["Event"]
print("Event_Received : ")
print(Message2)
Message3 = event ["Sender"]
print("Sender : ")
print(Message3)
SENDER = "Redshift Pause Resuem Service <redshift#abc.com>"
RECIPIENT = Message3
#CONFIGURATION_SET = "ConfigSet"
AWS_REGION = "us-east-1"
SUBJECT = subject1
BODY_TEXT = ("Amazon SES Test (Python)\r\n"
"This email was sent with Amazon SES using the "
"AWS SDK for Python (Boto)."
)
BODY_HTML = **"""<html>
<head></head>
<body>
<p>I want to print here the variable "Message2"</p>
</body>
</html>
"""**
The character encoding for the email.
CHARSET = "UTF-8"
Create a new SES resource and specify a region.
client = boto3.client('ses',region_name=AWS_REGION)
Try to send the email.
try:
#Provide the contents of the email.
response = client.send_email(
Destination={
'ToAddresses': [
RECIPIENT,
],
},
Message={
'Body': {
'Html': {
'Charset': CHARSET,
'Data': BODY_HTML,
},
'Text': {
'Charset': CHARSET,
'Data': BODY_TEXT,
},
},
'Subject': {
'Charset': CHARSET,
'Data': SUBJECT,
},
},
Source=SENDER,
)
# Display an error if something goes wrong.
except ClientError as e:
print(e.response['Error']['Message'])
else:
print("Email sent! Message ID:"),
Try using string formatting:
BODY_HTML = f"""<html>
<head></head>
<body>
<p>{Message2}</p>
</body>
</html>
"""
Or string concatenation:
BODY_HTML = f"<html><head></head><body><p>" + Message2 + "</p></body></html>"
Hi I am using urrlib2 to send some data and custom headers to a link. Am getting 500 internal server error. I have contacted the service, and they are saying the data(json data) is correct but there is some error in my python code. What am I doing wrong ?
Following is the code.
import urllib2,urllib
import json
PREPAYMENT_URL = "https://services.gharpay.in/rest/GharpayService/"
PREPAYMENT_USERNAME = "somename"
PREPAYMENT_PASSWORD = "somepass"
data = {
"customerDetails":{
"address": "ads",
"contactNo": "9663924147",
"email": "a#c.com",
"firstName": "akash",
"lastName": "deshpande",
"prefix": "Mr."
},
"orderDetails" : {
"pincode": "411036",
"clientOrderID": "21234",
"deliveryDate": "13-10-2013",
"orderAmount": "123",
"clientComments": "please be carefull",
"paymentMode": "Cash",
"productDetails": {
"productID": "21334",
"productQuantity": "1",
"unitCost": "123",
"productDescription": "tshirt"
},
"templateID": ""
},
}
def create(request):
function = 'createOrder'
url = PREPAYMENT_URL
url = url+ function
headers= {'username':PREPAYMENT_USERNAME,'password':PREPAYMENT_PASSWORD,'Content-type':'application/json'}
data1 = urllib.urlencode(data)
req = urllib2.Request(url,data1,headers)
try:
contents = urllib2.urlopen(req).read()
except urllib2.HTTPError as e:
error_message = e.read()
print error_message # this error message is being printed. It is showing 500 error.
Your code is perfect except for one teensy-weensy detail:
The header should be Content-Type, not Content-type.
Maybe try changing this header and let me know if it works!