Sendgrid adding email to list, getting bad request in grails - grails

I am trying to use following code to send request to sendgrid for adding emails to list, but i always keep getting 404 : Bad request.
def chttps = new HTTPBuilder('https://api.sendgrid.com/api/newsletter/lists/email/add.json?&api_user=myUser&api_key=myKey')
chttps.request( Method.POST, ContentType.JSON ) { req ->
headers.'Content-Type' = 'application/json'
body = [
list : 'testlist',
data : [email : '123Ex#exm.pl', name : '123Ex' ]
]
response.success = { resp, json ->
// response handling here
}
// handler for any failure status code:
}
Following is the error i get:
Bad Request. Stacktrace follows:
groovyx.net.http.HttpResponseException: Bad Request
at groovyx.net.http.HTTPBuilder.defaultFailureHandler(HTTPBuilder.java:609)
at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:475)
at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:417)
at groovyx.net.http.HTTPBuilder.request(HTTPBuilder.java:366)
at com.farmfresh.brandywine.erp.SendGridService$$EOc3vKl8.addEmailsToRecipientList(SendGridService.groovy:16)
at com.farmfresh.brandywine.erp.CustomerController$_closure5$$EOc3pEvI.doCall(CustomerController.groovy:106)
at org.zkoss.zk.grails.web.ZKGrailsPageFilter.obtainContent(ZKGrailsPageFilter.java:238)
at org.zkoss.zk.grails.web.ZKGrailsPageFilter.doFilter(ZKGrailsPageFilter.java:189)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:662)
can't find what's wrong. Please help.
EDIT1:
So i tried using following code, and it works fine, but still cant specify list of emails in data section:
def chttps = new HTTPBuilder('https://api.sendgrid.com/api/newsletter/lists/email/add.json?&api_user=myUser&api_key=myKey')
def dataa = "list=testlist&data=%7B%22email%22%3A%22examuttample%40gmail.com%22%2C%22name%22%3A%22uttam%22%7D"
chttps.post( body: dataa
) { resp ->
println "${resp}"
resp.headers.each {
println "${it.name} : ${it.value}"
}
println "${resp.data}"
println "http POST Success: ${resp.statusLine}"
}
For adding multiple emails in single request i tried putting following format:
data=%5B%7B%22email%22%3A+%22example1112%40gmail.com%22%2C%22name%22%3A+%22112example%22%7D%2C%7B%22email%22%3A+%22example2222%40gmail.com%22%2C%22name%22%3A+%22222example%22%7D%5D
//encode for :: [{"email": "example1112#gmail.com","name": "112example"},{"email": "example2222#gmail.com","name": "222example"}]
but i keep getting following exception, is there a way around this to add multiple emails.
groovyx.net.http.HttpResponseException: Internal Server Error
at groovyx.net.http.HTTPBuilder.defaultFailureHandler(HTTPBuilder.java:642)
at groovyx.net.http.HTTPBuilder$1.handleResponse(HTTPBuilder.java:494)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:1070)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:1044)
at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:506)
at groovyx.net.http.HTTPBuilder.post(HTTPBuilder.java:343)
at com.farmfresh.brandywine.erp.SendGridService$$EOc9RNxT.addEmailsToRecipientList(SendGridService.groovy:40)
at com.farmfresh.brandywine.erp.CustomerController$_closure5$$EOc9QqKy.doCall(CustomerController.groovy:109)
at org.zkoss.zk.grails.web.ZKGrailsPageFilter.obtainContent(ZKGrailsPageFilter.java:238)
at org.zkoss.zk.grails.web.ZKGrailsPageFilter.doFilter(ZKGrailsPageFilter.java:189)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:662)

It looks like you are trying to post a JSON payload. The SendGrid API currently doesn't support JSON payloads, so you need to send your payload as POST data.

Solved it, turns out json arrays are not acceptable by server instead it accepts multiple "data[]" elements in query string, so all you need to do is call this:
sendgrid.com/api/newsletter/lists/email/add.json?list=testlist&data[]={"email"+%3A+"123Ex1%40exm.pl"%2C+"name"+%3A+"123Ex1"}&data[]={"email"+%3A+"123Ex2%40exm.pl"%2C+"name"+%3A+"123Ex2"}&api_user=myUser&api_key=myKey
Hope this helps someone else.

Related

A Python code used to get the parent message of a slack thread not working

I wanted to make an API call to get the parent message of a thread using the thread ID on zapier
This is the code I got by chatgpt to do that, I am getting a no output error and I am not sure why it happens
import requests
def main(input_data):
# Set the API endpoint, headers, and Slack API token for the request
api_endpoint = "https://slack.com/api/conversations.replies"
headers = {
"Authorization": "Bearer xoxb-3482548707638-4570295651095-8J4mDrROrcYV0U3L5FZhJtTf",
"Content-Type": "application/json; charset=utf-8"
}
slack_api_token = "xoxb-3482548707638-4570295651095-8J4mDrROrcYV0U3L5FZhJtTf"
# Set the request parameters
params = {
"channel": input_data["thread_id"],
"ts": input_data["thread_id"],
"inclusive": "true",
"limit": 1
}
# Make a GET request to the API endpoint
response = requests.get(api_endpoint, headers=headers, params=params)
# Get the first message in the result
message = response.json()["messages"][0]
# Print the message text to the console
print(message["text"])
This my first time working with API's or code, so I am pretty sure I mus have done something stupid. Could anyone point out what I did wrong
PS: After this, what should I learn to operate such codes, I find this interesting

http_request succeeds but Groovy code gets 401

I was using the HTTP Request Plugin to make an API call to my Bitbucket server.
The following call returns the desired result:
def my-url = "http://my-username:my-password#my-bitbucket-server.com:7990/rest/api/1.0/my-project/pull-request-10"
def response = http_request my-url
However, I had an issue with the HTTP Request Plugin, because it prints my password in plain text in the logs.
Therefore, I tried doing the same call from a groovy script:
def response = new URL(my-url).getText()
But for this I am getting a 401 server response.
Any idea why this time, the call fails?
You're trying to apply Basic auth using almost plain Java. You have to generate your auth key and attach it to the request headers. Try:
String addr = 'my-bitbucket-server.com:7990/rest/api/1.0/my-project/pull-request-10'
String authString = 'my-username:my-password'.getBytes().encodeBase64().toString()
def conn = addr.toURL().openConnection()
conn.setRequestProperty( "Authorization", "Basic ${authString}" )
def feed = new XmlSlurper().parseText( conn.content.text )
Hope this would help!

Post Method with NSDictionary Values using Swift

I'm completely new toSwift. I need to hit a Post Method webservice with NSDictionary parameters & get the JSON response. I tried usingAlamofire & also NSMutableUrlRequest. Nothing seems to workout for me. I either get 'JSON text did not start with array or object and option to allow fragments not set' error or 'Undefined Variable' response from the server. The same service works fine when I try using Objective-C. As I said earlier, I am completely new toSwift & need your assistance.
My base url: http://myofficeit.in/bizfeed/webservices/client.php
Parameter I wanna Pass:
Parameter =
{
UserName = xyz;
deviceModel = iPhone;
deviceToken = "949264bc cd9c6c851ee64cc74db9078770dd7d971618ec20ce91d2e6eb9f155e";
emailid = "xyz#gmail.com";
location = Asia;
userMobileNo = 1234567890;
};
functionName = register;
The code I used for hitting the service is: http://pastebin.com/aaT4uhS7
Thanks
you can use like
let param: [String:AnyObject] = [
"UserName": iPhone,
"deviceToken": "949264bc cd9c6c851ee64cc74db9078770dd7d971618ec20ce91d2e6eb9f155e",
"emailid": "xyz#gmail.com",
"location": Asia,
"userMobileNo": 1234567890
]
Alamofire.request(.POST, "http://myofficeit.in/bizfeed/webservices/client.php/register", parameters: param).responseJSON { (req, res, json, error) in
print(req)
print(res)
print(json)
print(error)
}
for sample request in Alamofire
As broad as your question is, the broad will be my answer:
The first thing to do, is to get a clear idea about the web service API, which also requires a basic knowledge of the HTTP protocol. So, what you need to understand is, what the server expects in HTTP terminology.
You eventually will find out, how the server will expect its "parameters". Note, that there is no term like "parameters" in the HTTP protocol. So, you need to map them into something the HTTP protocol provides.
Most likely, in a POST request, "parameters" are transferred as the body of the HTTP message, as a content-type which is application/x-www-form-urlencoded, multipart/form-data or application/json.
According to the needs of the server, and with your basic knowledge of HTTP and NSURLSession, NSURLComponents etc., you compose the URL and the body of the request, set Content-Type header and possibly other headers and you are ready to go.
How this eventually looks like is given in the answer of #AnbyKarthik, which used Alamofire, and a command that composes a POST request whose parameters are send in the body whose content-type is x-www-form-urlencoded.

Groovy HTTPBuilder POST: missing method(s)

I'm laying the groundwork for a very basic Grails app that integrates with Last.fm. I'm stuck on the user authentication where I get a session key. From the documentation, it sounds like a very simple HTTP POST in the format I have below in code. I've tried every variation of the HTTPBuilder's post and request(POST) I've found but all error out with something like this:
| Server running. Browse to http://localhost:8080/GroovyLastFM
| Error 2013-05-14 19:57:10,042 [http-bio-8080-exec-3] ERROR errors.GrailsExceptionResolver - MissingPropertyException occurred when processing request: [GET] /GroovyLastFM/RecentSongs/tokenChecker - parameters:
token: 452b5619f98e3b66cec11b61940af500
No such property: Method for class: GroovyLastFM.User. Stacktrace follows:
Message: No such property: Method for class: GroovyLastFM.User
Line | Method
->> 28 | getSession in GroovyLastFM.User
I don't know what else I could need to import, but obviously something is missing. Is this where the grails plugins come in? If so, what do I need to include at the app level to make HTTPBuilder work? I'm very new to grails and am not sure what merits an addition to the dependencies, or how to do it. Also, I'm on Grails 2.1.1 and am not using an IDE. Thanks!
package GroovyLastFM
#Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.5.0-RC2' )
import java.security.MessageDigest
import groovyx.net.http.HTTPBuilder
import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*
class User {
String token
String api_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
String secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
User (String token) {
this.token = token
getSession()
}
def getSession() {
String signature = md5("api_key" + api_key + "methodauth.getSessiontoken" + token + secret)
def postbody = [token:token, api_key:api_key, method:'auth.getSession', api_sig:signature]
def http = new HTTPBuilder("http://wx.audioscrobbler.com/2.0/")
http.request(Method.POST) {req->
headers.accept = "application/xml"
requestContentType = ContentType.URLENC
body = postbody
response.success { resp,xml->
// read xml response
}
}
}
I did also try a basic curl post to make sure my parameters are correct, and it did return the session key as I expected:
curl -X POST -d "token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&api_key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&method=auth.getSession&api_sig=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" http://ws.audioscrobbler.com/2.0/
Links:
Last.fm API: www.last.fm/api/webauth
Previous post I was building on: HTTPBuilder HTTP Post url encoded parameters and accept xml response?
HTTPBuilder Post Doc: http://groovy.codehaus.org/modules/http-builder/doc/post.html
You are importing groovyx.net.http.Method.* and using Method.POST, that's why you are getting No such property: Method.
Replace it with:
http.request(POST) { req -> ... }
... that should do.
Alternatively, you could also change the import to:
import static groovyx.net.http.Method
and continue using Method.POST.

Microsoft Translator API answers 500 internal server error

I'm trying to use Microsoft's Translator API in my Rails app. Unfortunately and mostly unexpected, the server answers always with an internal server error. I also tried it manually with Poster[1] and I get the same results.
In more detail, what am I doing? I'm creating an XML string which goes into the body of the request. I used the C# Example of the API documentation. Well, and then I'm just invoking the RESTservice.
My code looks like this:
xmlns1 = "http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2"
xmlns2 = "http://schemas.microsoft.com/2003/10/Serialization/Arrays"
xml_builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
xml.TranslateArrayRequest("xmlns:ms" => xmlns1, "xmlns:arr" => xmlns2) {
xml.AppId token #using temporary token instead of appId
xml.From source
xml.To target
xml.Options {
xml["ms"].ContentType {
xml.text "text/html"
}
}
xml.Texts {
translate.each do |key,val|
xml["arr"].string {
xml.text CGI::unescape(val)
}
end
}
}
end
headers = {
'Content-Type' => 'text/xml'
}
uri = URI.parse(##msTranslatorBase + "/TranslateArray" + "?appId=" + token)
req = Net::HTTP::Post.new(uri.path, headers)
req.body = xml_builder.to_xml
response = Net::HTTP.start(uri.host, uri.port) { |http| http.request(req) }
# [...]
The xml_builder produces something like the following XML. Differently to the example from the API page, I'm defining two namespaces instead of referencing them on the certain tags (mainly because I wanted to reduces the overhead) -- but this doesn't seem to be a problem, when I do it like the docu-example I also get an internal server error.
<?xml version="1.0" encoding="UTF-8"?>
<TranslateArrayRequest xmlns:ms="http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2" xmlns:arr="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<AppId>TX83NVx0MmIxxCzHjPwo2_HgYN7lmWIBqyjruYm7YzCpwnkZL5wtS5oucxqlEFKw9</AppId>
<From>de</From>
<To>en</To>
<Options>
<ms:ContentType>text/html</ms:ContentType>
</Options>
<Texts>
<arr:string>Bitte übersetze diesen Text.</arr:string>
<arr:string>Das hier muss auch noch übersetzt werden.</arr:string>
</Texts>
</TranslateArrayRequest>
Every time I request the service it answers with
#<Net::HTTPInternalServerError 500 The server encountered an error processing the request. Please see the server logs for more details.>
... except I do some unspecified things, like using GET instead of POST, then it answers with something like "method not allowed".
I thought it might be something wrong with the XML stuff, because I can request an AppIdToken and invoke the Translate method without problems. But to me, the XML looks just fine. The documentation states that there is a schema for the expected XML:
The request body is a xml string generated according to the schema specified at http:// api.microsofttranslator.com/v2/Http.svc/help
Unfortunately, I cannot find anything on that.
So now my question(s): Am I doing something wrong? Maybe someone experienced similar situations and can report on solutions or work-arounds?
[1] Poster FF plugin > addons.mozilla.org/en-US/firefox/addon/poster/
Well, after lot's of trial-and-error I think I made it. So in case someone has similar problems, here is how I fixed this:
Apparently, the API is kind of fussy with the incoming XML. But since there is no schema (or at least I couldn't find the one specified in the documentation) it's kind of hard to do it the right way: the ordering of the tags is crucial!
<TranslateArrayRequest>
<AppId/>
<From/>
<Options />
<Texts/>
<To/>
</TranslateArrayRequest>
When the XML has this ordering it works. Otherwise you'll only see the useless internal server error response. Furthermore, I read a couple of times that the API also breaks if the XML contains improper UTF-8. One can force untrusted UTF-8 (e.g. coming from a user form) this way:
ic = Iconv.new('UTF-8//IGNORE', 'UTF-8')
valid_string = ic.iconv(untrusted_string + ' ')[0..-2]

Resources