
org.rajivprab.sava.email.Mandrill Maven / Gradle / Ivy
package org.rajivprab.sava.email;
import javax.ws.rs.core.MediaType;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONObject;
import org.rajivprab.cava.Validatec;
import org.rajivprab.cava.exception.IOExceptionc;
import java.io.IOException;
/**
* Client for sending emails and common Mandrill APIs
*
* Created by rprabhakar on 8/28/15.
*/
public class Mandrill {
private static final Logger log = LogManager.getLogger(Mandrill.class);
private final String apiKey;
// ---------------------------
public static Mandrill client(String apiKey) {
return new Mandrill(apiKey);
}
private Mandrill(String apiKey) {
this.apiKey = apiKey;
log.info("Mandrill email client instantiated");
}
// ----------------------------
public void unsubscribe(String email, String subaccount) {
JSONObject params = getBaseRequestParams(email, subaccount).put("comment", "Email.blacklist()");
JSONObject responseBody = sendMandrillRequest(params, "/rejects/add.json");
Validatec.equals(responseBody.getString("email"), email, responseBody.toString());
Validate.isTrue(responseBody.getBoolean("added"), responseBody.toString());
log.info("Blacklisted: " + Pair.of(email, subaccount));
}
public void resubscribe(String email, String subaccount) {
JSONObject params = getBaseRequestParams(email, subaccount);
JSONObject responseBody = sendMandrillRequest(params, "/rejects/delete.json");
Validatec.equals(responseBody.getString("email"), email, responseBody.toString());
Validatec.equals(responseBody.getString("subaccount"), subaccount, responseBody.toString());
Validate.isTrue(responseBody.getBoolean("deleted"), responseBody.toString());
}
public boolean sendEmail(EmailInfo info) {
JSONObject params = constructEmailRequest(info);
JSONObject responseBody = sendMandrillRequest(params, "/messages/send.json");
return parseEmailResponse(responseBody);
}
// -----------------------------
private JSONObject getBaseRequestParams(String email, String subaccount) {
return new JSONObject().put("key", apiKey)
.put("email", email)
.put("subaccount", subaccount);
}
private JSONObject constructEmailRequest(EmailInfo info) {
if (info.getSuppressionGroup() > Integer.MIN_VALUE) {
throw new UnsupportedOperationException("Functionality not implemented yet");
}
JSONObject toObject = new JSONObject().put("email", info.getToEmail()).put("name", info.getToName());
JSONArray toField = new JSONArray().put(toObject);
JSONObject messageJson = new JSONObject()
.put("html", info.getBody())
.put("subject", info.getTitle())
.put("from_email", info.getFromEmail())
.put("from_name", info.getFromName())
.put("subaccount", "TODO")
.put("to", toField)
.put("track_opens", true)
.put("track_clicks", true)
.put("auto_text", true)
.put("auto_html", true)
.put("preserve_recipients", true)
.put("view_content_link", true);
if (info.getBccEmail().isPresent()) {
messageJson.put("bcc_address", info.getBccEmail().get());
}
return new JSONObject().put("key", apiKey).put("message", messageJson);
}
private static JSONObject sendMandrillRequest(JSONObject params, String restSuffix) {
try {
StringEntity entity = new StringEntity(params.toString());
entity.setContentType(MediaType.APPLICATION_JSON);
HttpPost post = new HttpPost("https://mandrillapp.com/api/1.0" + restSuffix);
post.setEntity(entity);
// Reusing a single HttpClient results in errors/timeouts when sending many requests
HttpResponse response = HttpClients.createDefault().execute(post);
String responseString = EntityUtils.toString(response.getEntity());
if (responseString.startsWith("{")) {
return new JSONObject(responseString);
} else {
JSONArray responses = new JSONArray(responseString);
Validate.isTrue(responses.length() == 1, responseString);
return responses.getJSONObject(0);
}
} catch (IOException e) {
throw new IOExceptionc(e);
}
}
private static boolean parseEmailResponse(JSONObject responseBody) {
switch (responseBody.getString("status")) {
case "queued":
case "sent":
return true;
case "rejected":
processEmailRejection(responseBody);
return false;
case "scheduled":
case "invalid":
default:
throw new IllegalStateException(responseBody.toString());
}
}
private static void processEmailRejection(JSONObject responseBody) {
switch (responseBody.getString("reject_reason")) {
case "hard-bounce":
log.warn(responseBody);
break;
case "spam":
case "unsub":
log.error(responseBody);
break;
case "soft-bounce":
case "custom":
log.info(responseBody);
break;
case "rule":
case "invalid-sender":
case "invalid":
case "test-mode-limit":
default:
throw new IllegalStateException("Email rejected by Mandrill: " + responseBody.toString());
}
}
}