post params with groovy httpbuilder in mailgun

saurabh picture saurabh · Mar 28, 2015 · Viewed 9.3k times · Source

I am trying to invoke mailgun send message api. The following code works if I pass the params along with url -

String targetUrl = "https://api.mailgun.net/v2/my_domain_name/messages?from=fromAddress&to=toAddress&subject=sub&text=random+message" 

But when I try to add these params in the body then it does not work. I keep getting bad request from mailgun. -

String targetUrl = "https://api.mailgun.net/v2/my_domain_name/messages
body = [from:"fromAddress", to:"toAddress", subject:"sub", text:"random message"]

Here is the full code -

def sendEmail(String mailBody, String sub, String toIds) {
    String targetUrl = "https://api.mailgun.net/v2/my_domain_name/messages"
    def http = new HTTPBuilder(targetUrl)

    http.request( groovyx.net.http.Method.POST, groovyx.net.http.ContentType.JSON) {

        body = [from:"fromAddress", to:"toAddress", subject:"sub", text:"random message"]

        headers = ['Authorization':"Basic " + "api:my_api_key".bytes.encodeBase64().toString()]

        response.success = { resp, reader ->
            println "valid response: " + reader
        }
    }
}

Thanks!

Answer

jalopaba picture jalopaba · Mar 30, 2015

Your code is not working because you are telling HTTPBuilder that the request's parameters are encoded in JSON

http.request(Method.POST, ContentType.JSON)

so that you are encoding your parameters in request body in JSON, while mailgun API expects them with Content-Type: application/x-www-form-urlencoded.

curl -s --user 'api:YOUR_API_KEY' \
    https://api.mailgun.net/v2/YOUR_DOMAIN_NAME/messages \
    -F from='Excited User <mailgun@YOUR_DOMAIN_NAME>' \
    -F to=YOU@YOUR_DOMAIN_NAME \
    -F [email protected] \
    -F subject='Hello' \
    -F text='Testing some Mailgun awesomness!'

You can see it using as targetURL http://echo.httpkit.com, that returns the HTTP request in JSON format.

Doing that, it yields:

{
    "body": "\"from\":\"fromAddress\",\"to\":\"toAddress\",\"subject\":\"sub\",\"text\":\"random message\"}",
"docs": "http://httpkit.com/echo",
[...]

So you have to use ContentType.URLENC instead of ContentType.JSON (and optionally use Accept header for application/json type):

import groovy.json.*

import groovyx.net.*
import groovyx.net.http.*

import static groovy.json.JsonOutput.*

import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*

String targetUrl = 'http://echo.httpkit.com'
def http = new HTTPBuilder(targetUrl)

http.request(POST) {
    uri.path = '/'
    requestContentType = URLENC

    body = [from: 'fromAddress', to: 'toAddress', subject: 'sub', text: 'random message']

    headers.'Authorization' = "Basic " + "api:my_api_key".bytes.encodeBase64().toString()
    headers.'Accept' = 'application/json'

    response.success = { resp, json ->
        println prettyPrint(toJson(json))
    }
}

That yields this "echo" response (i.e., sent a POST request with urlencoded parameters):

{
    "body": "from=fromAddress&to=toAddress&subject=sub&text=random+message",
    "docs": "http://httpkit.com/echo",
    "headers": {
        "accept": "application/json",
        "authorization": "Basic YXBpOm15X2FwaV9rZXk=",
        "content-length": "61",
        "content-type": "application/x-www-form-urlencoded",
        "host": "echo.httpkit.com",
        "x-forwarded-for": "195.235.15.200"
    },
    "ip": "127.0.0.1",
    "method": "POST",
    "path": {
        "name": "/",
        "params": {

        },
        "query": ""
    },
    "powered-by": "http://httpkit.com",
    "uri": "/"
}