Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mailgun Java API send HTML emails

I am trying to get "html": "... entire contents of HTML page goes here ..." in Java using Unirest HTTP communication with MailGun API.

So far I have verified my domain, successfully sent an email via the API, and successfully sent an HTML (basic) email via the API in Java. I am having trouble sending emails (via the API, in Java), whenever I am trying to use any email templates. I was trying to use the suggested email templates present here: https://github.com/mailgun/transactional-email-templates/tree/master/templates .

My code for sending the email is in line with the documentation

public static JsonNode sendSimpleMessage() throws UnirestException {
        HttpResponse<com.mashape.unirest.http.JsonNode> request = Unirest.post("https://api.mailgun.net/v3/sub.domain.com" + "/messages")
                .basicAuth("api",  API_KEY)
                .queryString("from", "name <[email protected]>")
                .queryString("to", "[email protected]")
                .queryString("subject", "Great")
                .queryString("html", returnEmail())
                .asJson();

        return request.getBody();
    }

public static String returnEmail() {
        try {
            return StreamUtils.copyToString(new ClassPathResource("email.html").getInputStream(), Charset.defaultCharset());
        } catch (IOException e) {
            e.printStackTrace();
        }

        return "<html><strong>not today</strong></html>";
    }

And email.html contains an example from the emails mentioned above (https://github.com/mailgun/transactional-email-templates/tree/master/templates) or any HTML emails, as none work.

The error that I am get is:

com.mashape.unirest.http.exceptions.UnirestException: java.lang.RuntimeException: java.lang.RuntimeException: org.json.JSONException: A JSONArray text must start with '[' at 1 [character 2 line 1].

Stacktrace:

com.mashape.unirest.http.exceptions.UnirestException: java.lang.RuntimeException: java.lang.RuntimeException: org.json.JSONException: A JSONArray text must start with '[' at 1 [character 2 line 1]
at com.mashape.unirest.http.HttpClientHelper.request(HttpClientHelper.java:143)
at com.mashape.unirest.request.BaseRequest.asJson(BaseRequest.java:68)
at com..application.ApplicationController.sendSimpleMessage(ApplicationController.java:78)
at com.application.ApplicationController.create(ApplicationController.java:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.RuntimeException: java.lang.RuntimeException: org.json.JSONException: A JSONArray text must start with '[' at 1 [character 2 line 1]
    at com.mashape.unirest.http.HttpResponse.<init>(HttpResponse.java:106)
    at com.mashape.unirest.http.HttpClientHelper.request(HttpClientHelper.java:139)
    ... 57 more
Caused by: java.lang.RuntimeException: org.json.JSONException: A JSONArray text must start with '[' at 1 [character 2 line 1]
    at com.mashape.unirest.http.JsonNode.<init>(JsonNode.java:51)
    at com.mashape.unirest.http.HttpResponse.<init>(HttpResponse.java:95)
    ... 58 more
Caused by: org.json.JSONException: A JSONArray text must start with '[' at 1 [character 2 line 1]
    at org.json.JSONTokener.syntaxError(JSONTokener.java:433)
    at org.json.JSONArray.<init>(JSONArray.java:105)
    at org.json.JSONArray.<init>(JSONArray.java:144)
    at com.mashape.unirest.http.JsonNode.<init>(JsonNode.java:48)
    ... 59 more

I also get the same error if I simply paste all the HTML as a string instead of returnEmail(). I also get the same error message if I escape the special characters and/or minify the HTML before sending.

Now I assume that as Unirest is an http library it builds a JSON from the queryString keys and values. While it appears to work with simpel html like "HTML version whatever , it certainly does not like any lengthy/'normal' html, such as an email template.

Can you please suggest any working examples for html emails using the Java API or any hint on how to send the html and have a valid json?

Thanks a ton

like image 316
flashjpr Avatar asked Jan 03 '23 05:01

flashjpr


2 Answers

From the error message reported:

org.json.JSONException: A JSONArray text must start with '[' at 1 [character 2 line 1].

I'm not sure what Unirest is trying to do but it seems to be trying to encode something to JSON. But the Mailgun API doesn't require JSON encoding, you are fine using good old application/x-www-form-urlencoded encoding. Check with Unirest documentation to see if you can force other encoding types.

Alternatively you can use this other library (disclaimer: I am the developer) as noted in the comments of the question. The OP complains that doesn't work with complex html as mentioned here. What I meant there is the content helper mechanism where you build the HTML content using chained method calls (DSL style). If you already have the HTML you just need to pass it to the html() method call as noted also on the comments.

Your code would look a bit like this:

// somewhere else
Configuration configuration = new Configuration()
    .domain("sub.domain.com")
    .apiKey(API_KEY)
    .from("name", "[email protected]");

public static void sendSimpleMessage() {
    Mail.using(configuration)
        .to("[email protected]")
        .subject("Great")
        .html(returnEmail())
        .build()
        .send();
}
like image 171
sargue Avatar answered Jan 04 '23 19:01

sargue


I was getting the same error trying to post a large HTML document via Unirest.post(...).queryString("html", massiveStringHere)..asJson();

and found that "com.mashape.unirest.http.exceptions.UnirestException: java.lang.RuntimeException: java.lang.RuntimeException: org.json.JSONException: A JSONArray text must start with '[' at 1 [character 2 line 1]"

Actually results from trying to parse the response into JSON. Change the asJson() to asString() and you'll see the actual error Mailgun is giving you:

<html>
<head><title>414 Request-URI Too Large</title></head>
<body bgcolor="white">
<center><h1>414 Request-URI Too Large</h1></center>
<hr><center>nginx</center>
</body>
</html>

This is because Unirest has you adding the html body as a queryString, which exceeds the allowable query string length configured in Nginx. I tried changing the Content to form url-encoded and using .field("html", massiveStringHere), but this didn't work as I had expected. Why all fields of a POST must be specified in the URL is a design flaw IMO. I've not found a workaround yet, but will try the suggestions given here.. hoping not to resort to going the MIME route :-/

UPDATE: Confirmed https://github.com/sargue/mailgun is the way to go for Mailgun integration and does not suffer from HTML size limitations that apparently plague Unirest. Easily integrated in a few mins.

like image 22
user10161825 Avatar answered Jan 04 '23 19:01

user10161825