package net.curisit.securis.utils; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Map; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import javax.inject.Singleton; import net.curisit.securis.SeCurisException; import org.apache.commons.io.IOUtils; import org.apache.http.HttpResponse; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.entity.ContentType; import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.entity.mime.content.FileBody; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.ssl.SSLContextBuilder; import org.apache.http.ssl.TrustStrategy; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; /** * Component that send emails using Mailgun API: * http://documentation.mailgun.com/user_manual.html#sending-messages * * @author roberto */ @Singleton public class EmailManager { private static final Logger LOG = LogManager.getLogger(EmailManager.class); private final String serverUrl; private final CloseableHttpClient httpClient; /** * * @throws SeCurisException */ public EmailManager() throws SeCurisException { String domain = Params.get(Params.KEYS.MAILGUN_DOMAIN); if (domain == null) { throw new SeCurisException("Please, add '" + Params.KEYS.MAILGUN_DOMAIN + "' parameter to config file"); } serverUrl = String.format("https://api.mailgun.net/v2/%s/messages", domain); httpClient = createHttpClient(); } private CloseableHttpClient createHttpClient() throws SeCurisException { SSLContextBuilder builder = new SSLContextBuilder(); SSLConnectionSocketFactory sslsf = null; try { builder.loadTrustMaterial((KeyStore) null, new TrustStrategy() { @Override public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { return true; } }); sslsf = new SSLConnectionSocketFactory(builder.build()); } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e1) { LOG.error(e1); throw new SeCurisException("Error creating SSL socket factory"); } CredentialsProvider provider = new BasicCredentialsProvider(); UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("api", Params.get(Params.KEYS.MAILGUN_API_KEY)); provider.setCredentials(AuthScope.ANY, credentials); return HttpClientBuilder.create().setDefaultCredentialsProvider(provider).setSSLSocketFactory(sslsf).build(); } /** * Basic method to send emails in text mode with attachment. The method is * synchronous, It waits until server responses. * * @param subject * @param body * @param to * @param file * @throws SeCurisException * @throws UnsupportedEncodingException */ public void sendEmail(String subject, String body, String to, String cc, File file) throws SeCurisException, UnsupportedEncodingException { HttpPost postRequest = new HttpPost(serverUrl); MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.setCharset(Charset.forName("utf-8")); builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); builder.addTextBody("from", Params.get(Params.KEYS.EMAIL_FROM_ADDRESS)); builder.addTextBody("to", to); if (cc != null) builder.addTextBody("cc", cc); builder.addTextBody("subject", subject, ContentType.create(ContentType.TEXT_PLAIN.getMimeType(), Charset.forName("utf-8"))); builder.addTextBody("text", body, ContentType.create(ContentType.TEXT_PLAIN.getMimeType(), Charset.forName("utf-8"))); if (file != null) builder.addPart("attachment", new FileBody(file)); postRequest.setEntity(builder.build()); HttpResponse response; try { response = httpClient.execute(postRequest); String jsonLic = IOUtils.toString(response.getEntity().getContent()); if (response.getStatusLine().getStatusCode() == 200) { LOG.debug("Response content read OK: {}", jsonLic); Map responseBean = JsonUtils.json2map(jsonLic); LOG.debug("Response mail read OK: {}", responseBean); } else { throw new SeCurisException("Error sending email, response estatus: " + response.getStatusLine()); } } catch (IOException e) { LOG.error("Error sending email", e); throw new SeCurisException("Error sending email"); } } /** * Basic method to send emails in text mode with attachment. The method is * asynchronous, It returns immediately * * @param subject * @param body * @param to * @param file * @throws SeCurisException * @throws UnsupportedEncodingException */ public void sendEmailAsync(String subject, String body, String to, String cc, File file, EmailCallback callback) throws SeCurisException, UnsupportedEncodingException { Executor ex = Executors.newSingleThreadExecutor(); ex.execute(new Runnable() { @Override public void run() { try { EmailManager.this.sendEmail(subject, body, to, cc, file); callback.success(); } catch (UnsupportedEncodingException e) { callback.error(new SeCurisException("Error sending email", e)); } catch (SeCurisException e) { callback.error(e); } } }); } public static interface EmailCallback { public void success(); public void error(SeCurisException e); } public static void main(String[] args) throws SeCurisException, UnsupportedEncodingException { // new EmailManager().sendEmail("España así de bien", // "Me gusta esta prueba\nCon varias líneas\n\n\n--\nNo response", // "info@r75.es", new File( // "/Users/rob/Downloads/test.req")); new EmailManager().sendEmailAsync("España así de bien", "Me gusta esta prueba\nCon varias líneas\n\n\n--\nNo response", "info@r75.es", "dev@r75.es", new File("/Users/rob/Downloads/test.req"), new EmailCallback() { @Override public void success() { LOG.info("Success!!!"); } @Override public void error(SeCurisException e) { LOG.error("Error: {} !!!", e); } }); LOG.info("Waiting for email to be sent..."); } }