/* * Copyright (c) 2015 EMC Corporation * All Rights Reserved */ package com.emc.storageos.security.mail; import com.emc.storageos.coordinator.client.service.CoordinatorClient; import com.emc.storageos.svcs.errorhandling.resources.APIException; import com.google.common.collect.Maps; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.text.StrLookup; import org.apache.commons.lang.text.StrSubstitutor; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.springframework.mail.MailException; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.JavaMailSenderImpl; import org.springframework.mail.javamail.MimeMessageHelper; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import java.io.IOException; import java.io.InputStream; import java.util.Map; import java.util.Properties; public class MailHelper { private static final Logger log = Logger.getLogger(MailHelper.class); private CoordinatorClient coordinatorClient; private JavaMailSenderImpl mailSender; public static final String SMTP_PROPERTY_PREFIX = "system_connectemc_smtp_"; public static final String ZERO_PORT = "0"; public static final String DEFAULT_SMTP_TLS_PORT = "465"; public static final String DEFAULT_SMTP_PORT = "25"; public static final String SMTP_CONNECTION_TIMEOUT = "10000"; // 10 seconds public static final String SMTP_WRITE_TIMEOUT = "10000"; // 10 seconds public static final String SMTP_READ_TIMEOUT = "10000"; //10 seconds public static final String SMTP_SERVER = "system_connectemc_smtp_server"; public static final String SMTP_PORT = "system_connectemc_smtp_port"; public static final String SMTP_ENABLE_TLS = "system_connectemc_smtp_enabletls"; public static final String SMTP_AUTH_TYPE = "system_connectemc_smtp_authtype"; public static final String SMTP_USERNAME = "system_connectemc_smtp_username"; public static final String SMTP_PASSWORD = "system_connectemc_smtp_password"; // NOSONAR // ("Suppressing: removing this hard-coded password since it's just the name of attribute") public static final String SMTP_FROM_ADDRESS = "system_connectemc_smtp_from"; private String smtpServer; private String smtpPort; private String smtpEnableTls; private String fromAddress; private String smtpAuthType; private String username; private String password; public MailHelper(CoordinatorClient coordinatorClient) { this.coordinatorClient = coordinatorClient; } public void sendMailMessage(String to, String subject, String html) { try { JavaMailSender mailSender = getMailSender(); if (mailSender != null) { MimeMessage mimeMessage = mailSender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, false, "utf-8"); helper.setText(html, true); String[] addresses = StringUtils.split(to, ","); for (String address : addresses) { address = StringUtils.trimToNull(address); if (address != null) { helper.addTo(address); } } helper.setSubject(subject); mailSender.send(mimeMessage); } else { log.warn("Unable to send notification email. Email settings not configured."); } } catch (MailException | MessagingException ex) { String message = String.format("Failed to notify user by email"); log.error(message, ex); throw APIException.internalServerErrors.genericApisvcError(message, ex); } } private JavaMailSender getMailSender() { if (smtpSettingsUpdated()) { this.mailSender = createJavaMailSender(); } return this.mailSender; } private boolean smtpSettingsUpdated() { Map<String, String> properties = getPropertiesFromCoordinator(); if (this.mailSender == null && containsSmtpSettings(properties)) { return StringUtils.isNotBlank(properties.get(SMTP_SERVER)); } else if (this.mailSender != null) { String newSmtpServer = properties.get(SMTP_SERVER); String newSmtpPort = properties.get(SMTP_PORT); String newSmtpEnableTls = properties.get(SMTP_ENABLE_TLS); String newFromAddress = properties.get(SMTP_FROM_ADDRESS); String newSmtpAuthType = properties.get(SMTP_AUTH_TYPE); String newUsername = properties.get(SMTP_USERNAME); String newPassword = properties.get(SMTP_PASSWORD); if (StringUtils.equalsIgnoreCase(this.smtpServer, newSmtpServer) == false) { return true; } if (StringUtils.equalsIgnoreCase(this.smtpPort, newSmtpPort) == false) { return true; } if (StringUtils.equalsIgnoreCase(this.smtpEnableTls, newSmtpEnableTls) == false) { return true; } if (StringUtils.equalsIgnoreCase(this.fromAddress, newFromAddress) == false) { return true; } if (StringUtils.equalsIgnoreCase(this.smtpAuthType, newSmtpAuthType) == false) { return true; } if (StringUtils.equalsIgnoreCase(this.username, newUsername) == false) { return true; } if (StringUtils.equalsIgnoreCase(this.password, newPassword) == false) { return true; } } return false; } private JavaMailSenderImpl createJavaMailSender() { Map<String, String> properties = getPropertiesFromCoordinator(); smtpServer = properties.get(SMTP_SERVER); smtpPort = properties.get(SMTP_PORT); smtpEnableTls = properties.get(SMTP_ENABLE_TLS); fromAddress = properties.get(SMTP_FROM_ADDRESS); smtpAuthType = properties.get(SMTP_AUTH_TYPE); username = properties.get(SMTP_USERNAME); password = properties.get(SMTP_PASSWORD); boolean enableTls = StringUtils.equalsIgnoreCase("yes", smtpEnableTls); boolean authEnabled = StringUtils.isNotBlank(smtpAuthType) && !StringUtils.equalsIgnoreCase(smtpAuthType, "none"); Properties javaMailProperties = new Properties(); javaMailProperties.setProperty("mail.smtp.host", smtpServer); javaMailProperties.setProperty("mail.smtp.connectiontimeout", SMTP_CONNECTION_TIMEOUT); javaMailProperties.setProperty("mail.smtp.timeout", SMTP_READ_TIMEOUT); javaMailProperties.setProperty("mail.smtp.writetimeout", SMTP_WRITE_TIMEOUT); if (enableTls) { javaMailProperties.setProperty("mail.smtp.channel", "starttls"); smtpPort = defaultPort(smtpPort, DEFAULT_SMTP_TLS_PORT); } else { smtpPort = defaultPort(smtpPort, DEFAULT_SMTP_PORT); } javaMailProperties.setProperty("mail.smtp.port", smtpPort); javaMailProperties.setProperty("mail.smtp.from", fromAddress); if (authEnabled) { javaMailProperties.setProperty("mail.smtp.auth", "true"); javaMailProperties.setProperty("mail.smtp.user", username); javaMailProperties.setProperty("mail.smtp.pass", password); } JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); mailSender.setHost(smtpServer); try { mailSender.setPort(Integer.parseInt(smtpPort)); } catch (NumberFormatException e) { log.error(String.format("Failed to parse smtp port [%s]", smtpPort), e); } // this.mailSender.setProtocol(protocol); if (authEnabled) { mailSender.setUsername(username); mailSender.setPassword(password); } mailSender.setJavaMailProperties(javaMailProperties); log.debug(String.format(" mail.smtp.host = %s", mailSender.getJavaMailProperties().get("mail.smtp.host"))); log.debug(String.format(" mail.smtp.port = %s", mailSender.getJavaMailProperties().get("mail.smtp.port"))); log.debug(String.format(" mail.smtp.channel = %s", mailSender.getJavaMailProperties().get("mail.smtp.channel"))); log.debug(String.format(" mail.smtp.auth = %s", mailSender.getJavaMailProperties().get("mail.smtp.auth"))); log.debug(String.format(" mail.smtp.user = %s", mailSender.getJavaMailProperties().get("mail.smtp.user"))); log.debug(String.format(" mail.smtp.from = %s", mailSender.getJavaMailProperties().get("mail.smtp.from"))); return mailSender; } private Map<String, String> getPropertiesFromCoordinator() { com.emc.storageos.model.property.PropertyInfo propertyInfo = coordinatorClient.getPropertyInfo(); if (propertyInfo != null) { return propertyInfo.getAllProperties(); } return Maps.newHashMap(); } private boolean containsSmtpSettings(Map<String, String> properties) { for (String key : properties.keySet()) { if (key.startsWith(SMTP_PROPERTY_PREFIX)) { return true; } } return false; } private String defaultPort(String port, String defaultPort) { if (StringUtils.isBlank(port) || port.equalsIgnoreCase(ZERO_PORT)) { return defaultPort; } return port; } /** * read template html * * @param resource * @return */ public static String readTemplate(String resource) { InputStream in = MailHelper.class.getResourceAsStream(resource); try { return IOUtils.toString(in, "UTF-8"); } catch (IOException e) { throw new Error(e); } } /** * substitute parameters into template * * @param parameters * @param input * @return */ public static String parseTemplate(Map parameters, String input) { if (parameters == null) { return input; } StrSubstitutor substitutor = new StrSubstitutor(StrLookup.mapLookup(parameters)); return substitutor.replace(input); } }