Full disclosure: I am very new to coding and I really don't know what I'm doing. Currently trying to send multiple transactional emails using SendinBlue SMTP API based on the one I pick. I have already made the templates on SendinBlue, but how do I call a specific template?
My code
from __future__ import print_function
import sib_api_v3_sdk
import smtplib
from sib_api_v3_sdk.rest import ApiException
from pprint import pprint
from email.mime.text import MIMEText
from flask import request, render_template
from sql_helper import *
# Configuration of API key authorization:
api_config = sib_api_v3_sdk.Configuration()
api_config.api_key['api-key'] = 'api_key'
#If Partnership Account:
#api_config = sib_api_v3_sdk.Configuration()
#api_config.api_key['partner-key'] = 'API_Key'
api_instance = sib_api_v3_sdk.TransactionalEmailsApi(sib_api_v3_sdk.ApiClient(api_config))
subject = "My Subject"
html_content = "<html><body><h1>This is my first transactional email </h1></body></html>"
sender = {"name":"company name","email":"admin#company.com"}
to = [{"email":"example#example.com","name":"Jane Doe"}]
# cc = [{"email":"example2#example2.com","name":"Janice Doe"}]
# bcc = [{"name":"John Doe","email":"example#example.com"}]
reply_to = {"email":"admin#company.com","name":"John Doe"}
headers = {"Some-Custom-Name":"unique-id-1234"}
params = {"parameter":"My param value","subject":"New Subject"}
send_smtp_email = sib_api_v3_sdk.SendSmtpEmail(to=to, reply_to=reply_to, headers=headers, html_content=html_content, sender=sender, subject=subject)
def send_email(template, recipient, custom_message = None):
if template == "approve":
template_id = 1
elif template == "deny":
template_id = 2
elif template == "skip":
template_id = 3
try:
#send transactional email
api_response = api_instance.send_transac_email(send_smtp_email)
pprint(api_response)
except ApiException as e:
print("Exception when calling SMTPApi -> send_transac_email: %s\n" % e)
Any help would be appreciated.
I really am not quite sure what I'm doing, so anything would help. I'm sorry if the code is bad, I'm just starting out.
Related
I'm trying to send a bulk email using Sendgrid Dynamic Templates in Django and getting this error: The personalizations field is required and must have at least one personalization.
Using sendgrid 6.9.7
Does anyone see where I might be going wrong:
from django.conf import settings
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail, To
def send_mass_email():
to_emails = [
To(email='email1#gmail.com',
dynamic_template_data={
"thing_i_want_personalized": 'hello email 1',
}),
To(email='email2#gmail.com',
dynamic_template_data={
"thing_i_want_personalized": 'hello email 2',
}),
]
msg = Mail(
from_email='notifications#mysite.com>',
)
msg.to_emails = to_emails
msg.is_multiple = True
msg.template_id = "d-template_id"
try:
sendgrid_client = SendGridAPIClient(settings.SENDGRID_API_KEY)
response = sendgrid_client.send(msg)
print(response.status_code)
print(response.body)
print(response.headers)
except Exception as e:
print(e)
print(e.body)
return
The output is
HTTP Error 400: Bad Request
b'{"errors":[{"message":"The personalizations field is required and must have at least one personalization.","field":"personalizations","help":"http://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/errors.html#-Personalizations-Errors"}]}'
The Mail class does some stuff during initialization with the initial values (it sets private internal values based on to_emails), so you need to pass to_emails and is_multiple in the initializer and not later:
from django.conf import settings
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail, To
def send_mass_email():
to_emails = [
To(email='email1#gmail.com',
dynamic_template_data={
"thing_i_want_personalized": 'hello email 1',
}),
To(email='email2#gmail.com',
dynamic_template_data={
"thing_i_want_personalized": 'hello email 2',
}),
]
msg = Mail(
from_email='notifications#mysite.com>',
to_emails = to_emails,
is_multiple = True
)
msg.template_id = "d-template_id"
try:
sendgrid_client = SendGridAPIClient(settings.SENDGRID_API_KEY)
response = sendgrid_client.send(msg)
print(response.status_code)
print(response.body)
print(response.headers)
except Exception as e:
print(e)
print(e.body)
return
I have created a Cloud Compute Engine instance on Debian, and have successfully created a PUSH subscription to a topic with
from google.cloud import pubsub_v1
project_id = "censored"
topic_name = "censored"
subscription_name = "censored"
endpoint = "https://censored.appspot.com/pubsub/push?token=censored"
def create_push_subscription(project_id,
topic_name,
subscription_name,
endpoint):
"""Create a new push subscription on the given topic."""
# [START pubsub_create_push_subscription]
subscriber = pubsub_v1.SubscriberClient()
topic_path = subscriber.topic_path(project_id, topic_name)
subscription_path = subscriber.subscription_path(
project_id, subscription_name)
push_config = pubsub_v1.types.PushConfig(
push_endpoint=endpoint)
subscription = subscriber.create_subscription(
subscription_path, topic_path, push_config)
print('Push subscription created: {}'.format(subscription))
print('Endpoint for subscription is: {}'.format(endpoint))
# [END pubsub_create_push_subscription]
create_push_subscription(project_id, topic_name, subscription_name, endpoint)
but I'm not sure how exactly incoming messages arrive. I have found this sample code to parse messages, but I'm not sure how to get it to monitor in the background and 'activate' whenever incoming messages arrive.
import argparse
import base64
import json
import sys
import time
from google.cloud import pubsub_v1
def summarize(message):
# [START parse_message]
data = message.data.decode('utf-8')
attributes = message.attributes
name = attributes['name']
time_created = attributes['timeCreated']
bucket_id = attributes['bucketId']
object_id = attributes['objectId']
generation = attributes['objectGeneration']
description = (
'\tName: {name}\n'
'\tTime Created: {time_created}\n'
'\tBucket ID: {bucket_id}\n'
'\tObject ID: {object_id}\n'
'\tGeneration: {generation}\n'
).format(
name=name,
time_created=time_created,
bucket_id=bucket_id,
object_id=object_id,
generation=generation
)
if 'overwroteGeneration' in attributes:
description += '\tOverwrote generation: %s\n' % (
attributes['overwroteGeneration'])
if 'overwrittenByGeneration' in attributes:
description += '\tOverwritten by generation: %s\n' % (
attributes['overwrittenByGeneration'])
payload_format = attributes['payloadFormat']
if payload_format == 'JSON_API_V1':
object_metadata = json.loads(data)
name = object_metadata['name']
time_created = object_metadata['timeCreated']
size = object_metadata['size']
content_type = object_metadata['contentType']
metageneration = object_metadata['metageneration']
description += (
'\tName: {name}\n'
'\tTime Created: {time_created}\n'
'\tContent type: {content_type}\n'
'\tSize: {object_size}\n'
'\tMetageneration: {metageneration}\n'
).format(
name=name,
time_created=time_created,
content_type=content_type,
object_size=size,
metageneration=metageneration
)
return description
print('Note for developer: If BucketId and ObjectId listed, utf encoding.')
print('If not, JSON_V1 encoding. Adjust accordingly.')
# [END parse_message]
while(True):
print("signpost 1")
summarize(message)
print("signpost 2")
time.sleep(10)
print("signpost 3")
For example, this code will return
NameError: name 'message' is not defined
which is expected...
Could someone please help me set it up properly?
I know it's different in PULL because then the message will be defined during the pull, but I'd like to keep it as PUSH, if possible.
You need to create a long-running process which is either able to continuously poll for new messages (pull subscription) or have a reachable endpoint to receive new messages (push subscription).
See the example here: https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/pubsub/cloud-client/subscriber.py, as well as the differences between push and pull here: https://cloud.google.com/pubsub/docs/subscriber
I am using SendGrid for Python. I want to CC some people in an email. It seems like they may no longer support CC'ing on emails, though I'm not positive if that's true? But surely there is a work around to it somehow, but I am surprised I can't find much support on this.
Here is my basic code:
sg = sendgrid.SendGridAPIClient(apikey='*****')
from_email = Email(sender_address, sender_name)
to_email = Email(email_address)
subject = subject
content = Content("text/plain", email_message)
mail = Mail(from_email, subject, to_email, content)
response = sg.client.mail.send.post(request_body=mail.get())
How can I modify this so it will CC someone on an email?
Using the SendGrid's Personalization() or Email() class did not work for me. This is how I got it to work:
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail, Cc
# using a list of tuples for emails
# e.g. [('email1#example.com', 'email1#example.com'),('email2#example.com', 'email2#example.com')]
to_emails = []
for r in recipients:
to_emails.append((r, r))
# note the Cc class
cc_emails = []
for c in cc:
cc_emails.append(Cc(c, c))
message = Mail(
from_email=from_email,
to_emails=to_emails,
subject='My Subject',
html_content=f'<div>My HTML Email...</div>'
)
if cc_emails:
message.add_cc(cc_emails)
try:
sg = SendGridAPIClient(os.getenv('SENDGRID_API_KEY'))
sg.send(message)
except Exception as e:
print(f'{e}')
Hopefully this helps someone.
I resolved it. Santiago's answer got me mostly there, but here is what I needed to do:
sg = sendgrid.SendGridAPIClient(apikey='****')
from_email = Email(sender_address, sender_name)
to_email = Email(to_email)
cc_email = Email(cc_email)
p = Personalization()
p.add_to(to_email)
p.add_cc(cc_email)
subject = subject
content = Content("text/plain", email_message)
mail = Mail(from_email, subject, to_email, content)
mail.add_personalization(p)
response = sg.client.mail.send.post(request_body=mail.get())
If you don't include the p.add_to(to_email) it rejects it because there is no "to email" in the personalization object. Also, if you don't include the "to_email" inside the mail object it rejects it because it is looking for that argument, so you have to be a bit redundant and define it twice.
I've been looking at the code: https://github.com/sendgrid/sendgrid-python/blob/master/examples/mail/mail.py
And it looks like you can do that by adding a personalization to the mail, for example:
cc_email = Email(cc_address)
p = Personalization()
p.add_cc(cc_email)
mail.add_personalization(p)
Based on the answers here you can CC to email if you add another email to 'to_email'.
If you want to cc multiple user then in djanogo using sendgrid you need to import the below line
the function that will be used to send the mail
and finally how you ned to send the data paramters to the above function so that it can CC the person
email = send_sandgridmail(sender=sender,receiver=receivers,subject=subject,content=message,reply_to=sender,cc=[admin_mail_account_mail,"rawatanup918#gmail.com"],attachment=None)
i hope this'll help.simplified from #anurag image script
import os
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import To,Mail,ReplyTo,Email,Cc
def send_sandgridmail (sender, receiver, subject, content, reply_to=None, cc=[], attachment=None) :
# content = convert_safe_text(content)
# to email = To(receiver)
message = Mail(
from_email=str(sender),
to_emails=receiver,
subject= str(subject),
html_content = content)
if reply_to:
message.reply_to= ReplyTo(reply_to)
if attachment:
message.add_attachment (attachment)
if len(cc):
cc_mail = []
for cc_person in cc:
cc_mail.append(Cc(cc_person, cc_person))
message.add_cc (cc_mail)
try:
SENDGRID_API_KEY = 'your sendgrid api key'
sg= SendGridAPIClient (SENDGRID_API_KEY)
response= sg.send(message)
print (response.status_code)
# print (response.body)
# print (response.headers)
except Exception as e:
print(e)
return response
I am trying to send a request to an api using suds client.
The request is formed like this:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v20="https://API">
<soapenv:Header>
<v20:apiHeader>
<v20:username>username</v20:username>
<v20:password>password</v20:password>
<!--Optional:-->
<v20:name>?</v20:name>
</v20:apiHeader>
</soapenv:Header>
<soapenv:Body>
<v20:getLoginDetails/>
</soapenv:Body>
</soapenv:Envelope>
I am sending the request for this like:
client = Client('https://wsdl', faults=False)
client.set_options(headers={'username': username 'authToken': auth_token, 'name': ''})
client.service.getLoginDetails()
the error I am receiving is:
(<HTTPStatus.INTERNAL_SERVER_ERROR: 500>, (Fault){
faultcode = "soap:Server"
faultstring = "apiHeader should not be null"
detail = ""
})
Is this how I should be sending the request? It is definitely something to do with the apiHeader I think; not sure what though, I get the same error using this:
username = Element('username').setText(name)
password= Element('password').setText(pass)
header_list = [username, pass]
self.client.set_options(soapheaders=header_list)
return self.client.service.getLoginDetails()
#Code for your server:
from spyne import Application, rpc, ServiceBase, Unicode
from spyne.model.complex import ComplexModel
from spyne.protocol.soap import Soap11
from spyne.server.wsgi import WsgiApplication
import json
class RequestHeader(ComplexModel):
user_name = Unicode
user_pass = Unicode
class ServiceTest(ServiceBase):
__in_header__ = RequestHeader
#rpc(Unicode, _returns=Unicode)
def getLoginDetails(ctx, request):
values = json.loads(request)
values['user_name'] = ctx.in_header.user_name
values['user_pass'] = ctx.in_header.user_pass
return json.dumps(values)
application = WsgiApplication(Application([ServiceTest],
tns='yourcompany.request',
in_protocol=Soap11(validator='lxml'),
out_protocol=Soap11()
))
if __name__ == '__main__':
from wsgiref.simple_server import make_server
server = make_server('0.0.0.0', 8000, application)
server.serve_forever()
#Code for your client:
import json
from suds.client import Client
#Prepare the request in a JSON format
request = json.dumps({})
#Create a client for the API and make the request
api_client = Client('http://localhost:8000/?wsdl')
header = api_client.factory.create("RequestHeader")
header.user_name = 'my_user_name'
header.user_pass = 'my_user_pass'
api_client.set_options(soapheaders=header)
response = api_client.service.getLoginDetails(request)
print(response)
#it would print:
#{"user_name": "my_user_name", "user_pass": "my_user_pass"}
I've made this work by using something similar to this:
from suds.sax.element import Element
from suds.sax.attribute import Attribute
code = Element('serviceCode').setText('PABB4BEIJING')
pwd = Element('servicePwd').setText('QWERTPABB')
reqsoapheader = Element('ReqSOAPHeader').insert(code)
reqsoap_attribute = Attribute('xmlns', "http://schemas.acme.eu/")
reqsoapheader.append(reqsoap_attribute)
client.set_options(soapheaders=reqsoapheader)
If you wish to add several elements to the SOAP header:
userName = Element('UserName').setText(config['fco.user'])
password = Element('Password').setText(config['fco.pwd'])
fdxns = Attribute('xmlns', "http://fdx.co.il/Authentication")
for field in userName, password:
field.append(fdxns)
soapheaders = [userName, password]
client.set_options(soapheaders=tuple(soapheaders))
This is working for me with Python 2.7, suds 0.4.
Is there a way to modify user details (email in particular) using jenkins api?
Posting a modified json file to {root}/user/{username}/api/json does not seem to modify the underlying data:
import urllib2
import json
root = 'your_url'
username = 'your_username'
user_url = root +'/user/{username}/api/json'.format(username=username)
orig_d = json.loads((urllib2.urlopen(user_url).read()))
d = dict(orig_d)
d['fullName'] = 'XXXXX'
json_data = json.dumps(d)
request = urllib2.Request(user_url)
request.add_header('Content-type', 'application/json')
new_d = json.loads(urllib2.urlopen(request, json_data).read())
print new_d, '\n', orig_d
assert orig_d!=new_d, 'They are equal!'
After looking at jenkins source code model/User.java it looks like the only "POST" configuration that is supported on User model is done through doConfigSubmit() member function. So I eneded up faking web POST form at jenkins_url/user/{username}/configSubmit. The following snippet worked for me:
import urllib2, urllib
import json
root = jenkins_url
username = username
user_url = root +'/user/{username}/api/json'.format(username=username)
config_url = root + '/user/{username}/configSubmit'.format(username=username)
d = json.loads((urllib2.urlopen(user_url).read()))
fullname = d['fullName']
description = d['description']
new_email = 'new_user_email'
post_d = {"userProperty1": {"address": new_email}}
request = urllib2.Request(config_url)
values = {'json': json.dumps(post_d),
'fullName': fullname,
'email.address': new_email,
'description': description}
data = urllib.urlencode(values)
response = urllib2.urlopen(request, data).read()