/* * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.entando.entando.plugins.jpmailgun.aps.system.services.mailgun; import com.agiletec.aps.system.common.AbstractService; import com.agiletec.aps.system.exception.ApsSystemException; import com.agiletec.aps.system.services.baseconfig.ConfigInterface; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.WebResource; import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; import com.sun.jersey.core.util.MultivaluedMapImpl; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import javax.ws.rs.core.MediaType; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Level; import org.entando.entando.plugins.jpmailgun.aps.system.JpMailgunSystemConstants; import org.entando.entando.plugins.jpmailgun.aps.system.services.mailgun.logs.MailgunLog; import org.entando.entando.plugins.jpmailgun.aps.system.services.mailgun.parse.MailgunConfigDOM; import org.json.JSONArray; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Alberto Piras */ public class MailGunManager extends AbstractService implements IMailgunManager { private static final Logger _logger = LoggerFactory.getLogger(MailGunManager.class); @Override public void init() throws Exception { this.loadConfig(); _logger.debug("{}: initialized ", this.getClass().getName()); } /** * Loads Mailgun settings from DB * @throws ApsSystemException */ protected void loadConfig() throws ApsSystemException { try{ String xmlConfig = this.getConfigManager().getConfigItem(JpMailgunSystemConstants.CONFIG_ITEM_MAILGUN); MailgunConfig config = this.parseXML(xmlConfig); this.setConfig(config); } catch (Throwable t) { _logger.error("Error loading Config"); throw new ApsSystemException("Error loading Config", t); } } /** * Transforms XML into MailgunConfig Object * @param xmlConfig The xml to parse * @return the MailgunConfig by the xml stored in DB * @throws ApsSystemException */ private MailgunConfig parseXML(String xmlConfig) throws ApsSystemException { MailgunConfig config=null; try{ MailgunConfigDOM dom=new MailgunConfigDOM(); config=dom.extractConfig(xmlConfig); } catch (Throwable t) { _logger.error("Error parsing XML {}",xmlConfig); throw new ApsSystemException("Error parsing XML", t); } return config; } /** * Changes an Object MailgunConfig into XML format * @param newConfig The MailgunConfig to convert * @return The xml of the MailgunConfig to store in DB * @throws ApsSystemException */ private String buildXml(MailgunConfig newConfig) throws ApsSystemException { String result=null; try{ MailgunConfigDOM dom=new MailgunConfigDOM(); result = dom.createConfigXml(newConfig); } catch (Throwable t) { _logger.error("Error building XML {}",newConfig); throw new ApsSystemException("Error building XML", t); } return result; } /** * Updates the Mailgun config * @param newConfig The new config to update * @throws ApsSystemException */ @Override public void updateConfig(MailgunConfig newConfig) throws ApsSystemException { try{ String xml = this.buildXml(newConfig); this.getConfigManager().updateConfigItem(JpMailgunSystemConstants.CONFIG_ITEM_MAILGUN, xml); this.setConfig(newConfig); } catch (Throwable t) { _logger.error("Error updating Mailgun Config {}",newConfig); throw new ApsSystemException("Error updating Mailgun Config", t); } } /** * Sends a test email to verify settings' Mailgun * @param from this has to be made with a correct domain * @param to the recipient * @return MailgunMailResponse * @throws ApsSystemException */ @Override public MailgunMailResponse sendTestMail(String from, String to)throws ApsSystemException{ if (!this.isActive()) { _logger.info("The mailgun service is not active!: sendSimpleSingleMessage from:{} to:{} of the following email:{} - {}", from, to); return null; } MailgunMailResponse response = null; try { Client client = Client.create(); client.addFilter(new HTTPBasicAuthFilter("api",this.getConfig().getApiKey())); WebResource webResource = client.resource(this.getConfig().getAPIMessagesURL()); MultivaluedMapImpl formData = new MultivaluedMapImpl(); formData.add("from",from); formData.add("to", to); formData.add("subject", "Mailgun Settings"); formData.add("text", "Domain and APIKEY are correctly configured"); ClientResponse resp= webResource.type(MediaType.APPLICATION_FORM_URLENCODED).post(ClientResponse.class, formData); if(resp!=null) response= new MailgunMailResponse(resp); } catch (Throwable t) { _logger.error("Error sending Test message from:{} to:{}",from, to); throw new ApsSystemException("Error sending Test message from", t); } return response; } /** * Sends a Simple Message to a recipient, tracking default is true * @param from a valid email address registered on mailgun * @param subject the subject of the email * @param text the body of the email * @param to the recipient * @return {@link MailgunMailResponse} * @throws ApsSystemException if an error occurs */ @Override public MailgunMailResponse sendMessage(String from, String subject, String text, String to) throws ApsSystemException{ if (!this.isActive()) { _logger.info("The mailgun service is not active!: sendSimpleSingleMessage from:{} to:{} of the following email:{} - {}", from, to, subject, text); return null; } MailgunMailResponse response = null; try { Client client = Client.create(); client.addFilter(new HTTPBasicAuthFilter("api",this.getConfig().getApiKey())); WebResource webResource =client.resource(this.getConfig().getAPIMessagesURL()); MultivaluedMapImpl formData = new MultivaluedMapImpl(); formData.add("from", from); formData.add("to", to); formData.add("subject", subject); formData.add("html", text); ClientResponse resp=webResource.type(MediaType.APPLICATION_FORM_URLENCODED).post(ClientResponse.class, formData); response= new MailgunMailResponse(resp); } catch (Throwable t) { _logger.error("Error sending simple message from:{} to:{} subject:{}",from, to,subject); throw new ApsSystemException("Error in send Simple Single Message", t); } return response; } /** * Sends a Simple Message to a recipient, tracking default is true * @param from a valid email address registered on mailgun * @param subject the subject of the email * @param text the body of the email * @param to the recipient * @param trackingValues map to override tracking options * @return {@link MailgunMailResponse} * @throws ApsSystemException if an error occurs */ @Override public MailgunMailResponse sendMessage(String from, String subject, String text, String to, Map<String, Object> trackingValues) throws ApsSystemException{ if (!this.isActive()) { _logger.info("The mailgun service is not active!: sendSimpleSingleMessage from:{} to:{} of the following email:{} - {}", from, to, subject, text); return null; } MailgunMailResponse response = null; try { Client client = Client.create(); client.addFilter(new HTTPBasicAuthFilter("api",this.getConfig().getApiKey())); WebResource webResource =client.resource(this.getConfig().getAPIMessagesURL()); MultivaluedMapImpl formData = new MultivaluedMapImpl(); initializeCustomizedMapValues(formData,trackingValues); formData.add("from", from); formData.add("to", to); formData.add("subject", subject); formData.add("html", text); ClientResponse resp=webResource.type(MediaType.APPLICATION_FORM_URLENCODED).post(ClientResponse.class, formData); response= new MailgunMailResponse(resp); } catch (Throwable t) { _logger.error("Error sending simple message from:{} to:{} subject:{}",from, to,subject); throw new ApsSystemException("Error in send Simple Single Message", t); } return response; } /** *Sends a Simple Message to a group of recipients, tracking default is true * @param from mail from * @param subject subject of the email * @param text content of the email * @param list list of emails to send the email * @return MailgunMailResponse * @throws ApsSystemException */ @Override public MailgunMailResponse sendSimpleMultipleMessage(String from, String subject, String text, Set<String> list) throws ApsSystemException { if (!this.isActive()) { _logger.info("The mailgun service is not active!: sendSimpleSingleMessage from:{} to:{} of the following email:{} - {}", from, subject, text); return null; } MailgunMailResponse response = null; try { Client client = Client.create(); client.addFilter(new HTTPBasicAuthFilter("api",this.getConfig().getApiKey())); WebResource webResource =client.resource(this.getConfig().getAPIMessagesURL()); MultivaluedMapImpl formData = new MultivaluedMapImpl(); formData.add("from", from); JSONObject ogg= new JSONObject(); for(String temp: list){ ogg.append(temp, "{}"); formData.add("to", temp); } formData.add("subject", subject); formData.add("html", text); formData.add("recipient-variables", ogg.toString()); ClientResponse resp=webResource.type(MediaType.APPLICATION_FORM_URLENCODED).post(ClientResponse.class, formData); response= new MailgunMailResponse(resp); } catch (Throwable t) { _logger.error("Error sending message from:{} to:{} subject:{}",from, StringUtils.join(list, ","), subject, t); throw new ApsSystemException("Error in sendSimpleMultipleMessage", t); } return response; } /** *Sends a Simple Message to a group of recipients, tracking default is true * @param from mail from * @param subject subject of the email * @param text content of the email * @param list list of emails to send the email * @param trackingValues map to override tracking options * @return MailgunMailResponse * @throws ApsSystemException */ @Override public MailgunMailResponse sendSimpleMultipleMessage(String from, String subject, String text, Set<String> list, Map<String, Object> trackingValues) throws ApsSystemException { if (!this.isActive()) { _logger.info("The mailgun service is not active!: sendSimpleSingleMessage from:{} to:{} of the following email:{} - {}", from, subject, text); return null; } MailgunMailResponse response = null; try { Client client = Client.create(); client.addFilter(new HTTPBasicAuthFilter("api",this.getConfig().getApiKey())); WebResource webResource =client.resource(this.getConfig().getAPIMessagesURL()); MultivaluedMapImpl formData = new MultivaluedMapImpl(); initializeCustomizedMapValues(formData,trackingValues); formData.add("from", from); JSONObject ogg= new JSONObject(); for(String temp: list){ ogg.append(temp, "{}"); formData.add("to", temp); } formData.add("subject", subject); formData.add("html", text); formData.add("recipient-variables", ogg.toString()); ClientResponse resp=webResource.type(MediaType.APPLICATION_FORM_URLENCODED).post(ClientResponse.class, formData); response= new MailgunMailResponse(resp); } catch (Throwable t) { _logger.error("Error sending message from:{} to:{} subject:{}",from, StringUtils.join(list, ","), subject, t); throw new ApsSystemException("Error in sendSimpleMultipleMessage", t); } return response; } /** * Sends a Message to a group of recipients, tracking default is true * @param from mail from * @param subject subject of the email * @param body content of the email * @param recipientVariables Map<String, Map<String, Object>> that contains variables of each recipient * @return MailgunMailResponse * @throws ApsSystemException */ @SuppressWarnings("rawtypes") @Override public MailgunMailResponse sendBatchWithRecipientVariables(String from, String subject, String body, Map<String, Map<String, Object>> recipientVariables) throws ApsSystemException { if (!this.isActive()) { _logger.info("The mailgun service is not active!: sendSimpleSingleMessage from:{} to:{} of the following email:{} - {}",from, subject); return null; } MailgunMailResponse response = null; try { Client client = Client.create(); client.addFilter(new HTTPBasicAuthFilter("api",this.getConfig().getApiKey())); WebResource webResource =client.resource(this.getConfig().getAPIMessagesURL()); MultivaluedMapImpl formData = new MultivaluedMapImpl(); formData.add("from", from); Iterator it = recipientVariables.entrySet().iterator(); while (it.hasNext()) { Map.Entry pairs = (Map.Entry)it.next(); formData.add("to",pairs.getKey()); } formData.add("subject", subject); formData.add("html", body); String recipientVars = new JSONObject(recipientVariables).toString(); formData.add("recipient-variables", recipientVars); ClientResponse resp=webResource.type(MediaType.APPLICATION_FORM_URLENCODED).post(ClientResponse.class, formData); response= new MailgunMailResponse(resp); System.out.println("RESPONSE:"+response.getStatus()); } catch (Throwable t) { _logger.error("Error sending message from:{} to:{} subject:{}",from, subject, t); throw new ApsSystemException("Error in sendSimpleMultipleMessage", t); } return response; } /** * Sends a Message to a group of recipients, tracking default is true * @param from mail from * @param subject subject of the email * @param body content of the email * @param recipientVariables Map<String, Map<String, Object>> that contains variables of each recipient * @param trackingValues map to override tracking options * @return MailgunMailResponse * @throws ApsSystemException */ @SuppressWarnings("rawtypes") @Override public MailgunMailResponse sendBatchWithRecipientVariables(String from, String subject, String body, Map<String, Map<String, Object>> recipientVariables, Map<String, Object> trackingValues) throws ApsSystemException { if (!this.isActive()) { _logger.info("The mailgun service is not active!: sendSimpleSingleMessage from:{} to:{} of the following email:{} - {}",from, subject); return null; } MailgunMailResponse response = null; try { Client client = Client.create(); client.addFilter(new HTTPBasicAuthFilter("api",this.getConfig().getApiKey())); WebResource webResource =client.resource(this.getConfig().getAPIMessagesURL()); MultivaluedMapImpl formData = new MultivaluedMapImpl(); initializeCustomizedMapValues(formData,trackingValues); formData.add("from", from); Iterator it = recipientVariables.entrySet().iterator(); while (it.hasNext()) { Map.Entry pairs = (Map.Entry)it.next(); formData.add("to",pairs.getKey()); } formData.add("subject", subject); formData.add("html", body); String recipientVars = new JSONObject(recipientVariables).toString(); formData.add("recipient-variables", recipientVars); ClientResponse resp=webResource.type(MediaType.APPLICATION_FORM_URLENCODED).post(ClientResponse.class, formData); response= new MailgunMailResponse(resp); System.out.println("RESPONSE:"+response.getStatus()); } catch (Throwable t) { _logger.error("Error sending message from:{} to:{} subject:{}",from, subject, t); throw new ApsSystemException("Error in sendSimpleMultipleMessage", t); } return response; } private void initializeCustomizedMapValues(MultivaluedMapImpl formData,Map<String, Object> map){ Iterator iteratorMap = map.entrySet().iterator(); while (iteratorMap.hasNext()) { Map.Entry pairs = (Map.Entry)iteratorMap.next(); formData.add(pairs.getKey().toString(), pairs.getValue()); } } /** * Gets Logs of an element by its own ID * @param id message identifier * @return MailgunMailLog * @throws ApsSystemException */ @Override public MailgunLog getLogById(String id) throws ApsSystemException{ MailgunLog log =null; try{ Client client = new Client(); client.addFilter(new HTTPBasicAuthFilter("api",this.getConfig().getApiKey())); WebResource webResource =client.resource(this.getConfig().getAPIDomainEventsURL()); MultivaluedMapImpl queryParams = new MultivaluedMapImpl(); queryParams.add("begin", 50); queryParams.add("ascending", "yes");; queryParams.add("pretty", "yes"); queryParams.add("message-id", id); ClientResponse resp= webResource.queryParams(queryParams).get(ClientResponse.class); log = new MailgunLog(printRequest(resp)); }catch(Throwable t){ _logger.error("Error getting a log by Id{}",id); throw new ApsSystemException("Error getting a log by Id",t); } return log; } /** * Creates a string contaning the entity of a ClientResponse * @param response A ClientResponse * @return String Entity * @throws ApsSystemException */ public String printRequest(ClientResponse response) throws ApsSystemException{ String body=null; try{ body=IOUtils.toString(response.getEntityInputStream()); }catch(Throwable t){ _logger.error("Error printing Request of ClientResponse"); throw new ApsSystemException("Error printing Request of ClientResponse",t); } return body; } /** * Verifies a specific message status, TO USE WITH A MESSAGE SENT TO A ONE RECIPIENT * @param idMessage message id * @param status status to search * @return true if that message is in that status, false otherwise */ public boolean verifyStatusOfAMessage(String idMessage,String status) throws ApsSystemException{ Client client = new Client(); client.addFilter(new HTTPBasicAuthFilter("api",this.getConfig().getApiKey())); WebResource webResource =client.resource(this.getConfig().getAPIDomainEventsURL()); MultivaluedMapImpl queryParams = new MultivaluedMapImpl(); queryParams.add("pretty", "yes"); queryParams.add("message-id", idMessage); queryParams.add("event", status); ClientResponse resp=webResource.queryParams(queryParams).get(ClientResponse.class); return verifyEventByJSON(resp); } /** * Verifies if JSON contains or not the results (every type of results) * * @param response The response of a query * @return false if the response is void(there is not any items ), true otherwise */ public boolean verifyEventByJSON(ClientResponse response) throws ApsSystemException{ try{ String body=printRequest(response); JSONObject o = new JSONObject(body); JSONArray arrayOfTests =o.getJSONArray("items"); if(arrayOfTests.length()>0) return true; else return false; }catch(Throwable t){ _logger.error("Error verifying Event By JSON"); throw new ApsSystemException("Error verifying Event By JSON",t); } } /** *Creates a new Domain * @param domainName * @param password * @return ClientResponse */ public ClientResponse addDomain(String domainName, String password) { Client client = new Client(); client.addFilter(new HTTPBasicAuthFilter("api", this.getConfig().getApiKey())); WebResource webResource =client.resource("https://api.mailgun.net/v2/domains"); MultivaluedMapImpl formData = new MultivaluedMapImpl(); formData.add("name", domainName); formData.add("smtp_password", password); return webResource.type(MediaType.APPLICATION_FORM_URLENCODED).post(ClientResponse.class, formData); } /** *Gets lasts 10 Domains * @return ClientResponse */ public ClientResponse getDomains() { Client client = Client.create(); client.addFilter(new HTTPBasicAuthFilter("api",this.getConfig().getApiKey())); WebResource webResource =client.resource("https://api.mailgun.net/v2/domains"); MultivaluedMapImpl queryParams = new MultivaluedMapImpl(); queryParams.add("skip", 0); queryParams.add("limit", 10); return webResource.queryParams(queryParams).get(ClientResponse.class); } /** *Removes a Domain * @param domainName * @return ClientResponse */ public ClientResponse deleteDomain(String domainName) { Client client = Client.create(); client.addFilter(new HTTPBasicAuthFilter("api",this.getConfig().getApiKey())); WebResource webResource =client.resource("https://api.mailgun.net/v2/domains/"+domainName); return webResource.delete(ClientResponse.class); } public void setConfig(MailgunConfig config) { this._config = config; } /** * Gets Mailgun configuration * @return MailgunConfig */ @Override public MailgunConfig getConfig() { try { loadConfig(); } catch (ApsSystemException ex) { //TO DO: // java.util.logging.Logger.getLogger(MailGunManager.class.getName()).log(Level.SEVERE, null, ex); _logger.error("Exception: "+ex); } return _config; } /** * @return true fi statusof Mailgun is Active, false otherwise */ public boolean isActive() { return _active; } private MailgunConfigDOM getConfigDOM() { return _configDOM; } public void setConfigDOM(MailgunConfigDOM _configDOM) { this._configDOM = _configDOM; } public ConfigInterface getConfigManager() { return _configManager; } public void setConfigManager(ConfigInterface _configManager) { this._configManager = _configManager; } public void setActive(boolean active) { this._active = active; } private void _logger(String string) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } private MailgunConfigDOM _configDOM; private MailgunConfig _config; private ConfigInterface _configManager; private boolean _active = true; }