package crmdna.mail2;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.microtripit.mandrillapp.lutung.MandrillApi;
import com.microtripit.mandrillapp.lutung.model.MandrillApiError;
import com.microtripit.mandrillapp.lutung.view.MandrillMessage;
import com.microtripit.mandrillapp.lutung.view.MandrillMessage.MergeVar;
import com.microtripit.mandrillapp.lutung.view.MandrillMessage.MergeVarBucket;
import com.microtripit.mandrillapp.lutung.view.MandrillMessage.Recipient;
import com.microtripit.mandrillapp.lutung.view.MandrillMessage.RecipientMetadata;
import com.microtripit.mandrillapp.lutung.view.MandrillMessageStatus;
import crmdna.common.Utils;
import crmdna.common.api.APIException;
import crmdna.common.api.APIResponse.Status;
import crmdna.mail2.Mail.MetaData;
import crmdna.mail2.MailMap.MergeVarID;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;
import java.util.logging.Logger;
import static crmdna.common.AssertUtils.*;
public class Mandrill {
static void send(String apiKey, MailMap mailMap,
String subject, String messageBody, String from, String fromName, String subaccount,
Map<String, String> globalMetaData, Set<String> tags) throws MandrillApiError, IOException {
ensureNotNull(messageBody, "messageBody is null");
ensureNotNull(from, "from is null");
ensureNotNull(mailMap, "mailMap is null");
ensureNotNull(subject, "subject is null");
ensureValidApiKey(apiKey);
mailMap.validateMergeVars();
Logger logger = Logger.getLogger(Mandrill.class.getName());
logger.info("mailMap.size() = " + mailMap.size());
if (mailMap.isEmpty())
return;
if (mailMap.size() > Mail.MAX_EMAILS_PER_SEND) {
throw new APIException().status(Status.ERROR_OVERFLOW).message(
"Attempt to send [" + mailMap.size() + "] emails in one shot. Maximum allowed is ["
+ Mail.MAX_EMAILS_PER_SEND + "]");
}
MandrillMessage message = new MandrillMessage();
message.setSubject(subject);
message.setHtml(messageBody);
message.setAutoText(true);
message.setTrackClicks(true);
message.setTrackOpens(true);
message.setFromEmail(from);
message.setFromName(fromName);
message.setInlineCss(true);
message.setPreserveRecipients(false);
message.setMergeLanguage("handlebars");
if ((tags != null) && !tags.isEmpty())
message.setTags(new ArrayList<>(tags));
List<MergeVarBucket> mergeVarBuckets = new ArrayList<>(mailMap.size());
List<MergeVar> globalMergeVars = new ArrayList<>();
List<RecipientMetadata> recipientMetadataList = new ArrayList<>(mailMap.size());
populateMergeVars(mailMap, globalMergeVars, mergeVarBuckets);
for (String email : mailMap.getEmails()) {
RecipientMetadata recipientMetadata = new RecipientMetadata();
recipientMetadata.setRcpt(email);
HashMap<String, String> map = new HashMap<>();
map.put(MetaData.MAIL_ID.toString(), mailMap.get(MergeVarID.MAIL_ID, email));
recipientMetadata.setValues(map);
recipientMetadataList.add(recipientMetadata);
}
message.setMergeVars(mergeVarBuckets);
message.setGlobalMergeVars(globalMergeVars);
message.setRecipientMetadata(recipientMetadataList);
message.setMetadata(globalMetaData);
MandrillApi mandrillApi = new MandrillApi(apiKey);
if ((subaccount != null) && !subaccount.isEmpty()) {
if (!isSubaccountValid(apiKey, subaccount)) {
createSubaccount(apiKey, subaccount);
}
ensureValidSubaccount(apiKey, subaccount); // just in case
message.setSubaccount(subaccount);
}
List<Recipient> recipients = new ArrayList<>();
Set<String> emails = mailMap.getEmails();
for (String email : emails) {
Recipient recipient = new Recipient();
recipient.setEmail(email);
recipients.add(recipient);
}
message.setTo(recipients);
if (emails.size() == 1) {
message.setBcc(from);
}
MandrillMessageStatus[] status = mandrillApi.messages().send(message, true);
ensureEqual(emails.size(), status.length,
"Num elements in MandrillMessageStatus does not match number of emails");
}
static List<MandrillEventProp> getMandrillEventProps(String postData)
throws UnsupportedEncodingException {
ensureNotNull(postData, "postData is null");
String json = URLDecoder.decode(postData, "UTF-8");
// json is of the format: mandrill_events=[{"event":....}]. remove mandrill_events=
ensure(json.contains("mandrill_events="),
"postData should start with 'mandrill_events=' (without quotes)");
json = json.substring(16);
Gson gson = new GsonBuilder().setPrettyPrinting().create();
MandrillEventProp[] mandrillEventProps = gson.fromJson(json, MandrillEventProp[].class);
return Arrays.asList(mandrillEventProps);
}
public static void populateMergeVars(MailMap mailMap, List<MergeVar> globalMergeVars,
List<MergeVarBucket> mergeVarBuckets) {
for (String email : mailMap.getEmails()) {
MergeVarBucket mergeVarBucket = new MergeVarBucket();
mergeVarBucket.setRcpt(email);
List<MergeVar> mergeVars = new ArrayList<>();
for (MergeVarID mergeVarID : MergeVarID.values()) {
String mergeVarValue = mailMap.get(mergeVarID, email);
if (mergeVarValue != null) {
mergeVars.add(new MergeVar(mergeVarID.toString(), mergeVarValue));
}
}
mergeVarBucket.setVars(mergeVars);
mergeVarBuckets.add(mergeVarBucket);
}
for (MergeVarID mergeVarID : MergeVarID.values()) {
String mergeVarValue = mailMap.get(mergeVarID);
if (mergeVarValue != null) {
globalMergeVars.add(new MergeVar(mergeVarID.toString(), mergeVarValue));
} else {
Object mergeVarObjectValue = mailMap.getObject(mergeVarID);
if (mergeVarObjectValue != null) {
globalMergeVars.add(new MergeVar(mergeVarID.toString(), mergeVarObjectValue));
}
}
}
}
public static String createSubaccount(String apiKey, String subaccount) throws IOException,
MandrillApiError {
ensureValidApiKey(apiKey);
ensureNotNull(subaccount, "subaccount is null");
// TODO: remove all non alpha numeric (here as well as in crmdna)
subaccount = Utils.removeSpaceUnderscoreBracketAndHyphen(subaccount).toLowerCase();
ensure(subaccount.length() > 0, "subaccount is empty string");
subaccount = Utils.removeSpaceUnderscoreBracketAndHyphen(subaccount).toLowerCase();
ensureValidApiKey(apiKey);
if (isSubaccountValid(apiKey, subaccount)) {
throw new APIException().status(Status.ERROR_RESOURCE_ALREADY_EXISTS).message(
"subaccount [" + subaccount + "] already exists");
}
MandrillApi mandrillApi = new MandrillApi(apiKey);
mandrillApi.subaccounts().add(subaccount, null, null, null);
return subaccount;
}
public static void ensureValidApiKey(String apiKey) {
ensureNotNull(apiKey, "apiKey is null");
MandrillApi mandrillApi = new MandrillApi(apiKey);
try {
mandrillApi.users().ping();
} catch (MandrillApiError | IOException e) {
throw new APIException().status(Status.ERROR_RESOURCE_NOT_FOUND).message(
"Mandrill Api Key [" + apiKey + "] is invalid");
}
}
private static void ensureValidSubaccount(String alreadyValidatedApiKey, String subaccount)
throws IOException {
ensureNotNull(alreadyValidatedApiKey, "alreadyValidatedApiKey is null");
ensureNotNull(subaccount, "subaccount is null");
if (!isSubaccountValid(alreadyValidatedApiKey, subaccount)) {
throw new APIException().status(Status.ERROR_RESOURCE_NOT_FOUND).message(
"Subaccount [" + subaccount + "] not found for api key [" + alreadyValidatedApiKey + "]");
}
}
private static boolean isSubaccountValid(String alreadyValidatedApiKey, String subaccount)
throws IOException {
ensureNotNull(alreadyValidatedApiKey, "alreadyValidatedApiKey is null");
ensureNotNull(subaccount, "subaccount is null");
MandrillApi mandrillApi = new MandrillApi(alreadyValidatedApiKey);
try {
mandrillApi.subaccounts().info(subaccount);
} catch (MandrillApiError e) {
return false;
}
return true;
}
}