/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package util;
import java.util.Date;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.mail.Email;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.SimpleEmail;
import play.Logger;
import play.Play;
import play.data.validation.Validation;
public class MailSettingsValidator {
public static class Settings {
public String server;
public String port;
public String username;
public String password;
public String channel;
public String authType;
public String fromAddress;
}
public static void validate(Settings settings, String toEmail) {
SimpleEmail email = new SimpleEmail();
try {
email.setFrom(settings.fromAddress);
} catch (Exception e) {
Logger.error(e, "Failed to parse From email address [%s]", settings.fromAddress);
Validation.addError(null, "MailSettings.failedToParseAddress", settings.fromAddress);
}
try {
email.addTo(toEmail);
} catch (EmailException e) {
Logger.error(e, "Failed to parse To email address [%s]", toEmail);
Validation.addError(null, "MailSettings.failedToParseAddress", toEmail);
}
email.setSubject(MessagesUtils.get("MailSettings.testSubject"));
try {
email.setMsg(MessagesUtils.get("MailSettings.testMessage"));
} catch (EmailException e) {
Logger.error(e, "Failed to set email message");
Validation.addError(null, "MailSettings.failedToSetMessage");
}
if (!Validation.hasErrors()) {
try {
send(email, settings);
} catch (EmailException e) {
Logger.error(e, "Failed to send email");
addExceptionError(e);
} catch (RuntimeException e) {
Logger.error(e, "Failed to send email");
addExceptionError(e);
}
}
}
/**
* Send an email
*/
private static boolean send(Email email, Settings settings) throws EmailException {
email = buildMessage(email, settings);
email.setMailSession(getSession(settings));
return sendMessage(email);
}
private static Email buildMessage(Email email, Settings form) throws EmailException {
String from = form.fromAddress;
if (email.getFromAddress() == null && !StringUtils.isEmpty(from)) {
email.setFrom(from);
}
else if (email.getFromAddress() == null) {
throw new EmailException("Please define a 'from' email address");
}
if ((email.getToAddresses() == null || email.getToAddresses().size() == 0)
&& (email.getCcAddresses() == null || email.getCcAddresses().size() == 0)
&& (email.getBccAddresses() == null || email.getBccAddresses().size() == 0)) {
throw new EmailException("Please define a recipient email address");
}
if (email.getSubject() == null) {
throw new EmailException("Please define a subject");
}
if (email.getReplyToAddresses() == null || email.getReplyToAddresses().size() == 0) {
email.addReplyTo(email.getFromAddress().getAddress());
}
return email;
}
public static Session getSession(Settings form) {
Properties props = new Properties();
String host = form.server;
String port = form.port;
// Put a bogus value even if we are on dev mode, otherwise JavaMail
// will complain
props.put("mail.smtp.host", host);
String channelEncryption = form.channel;
if (channelEncryption.equals("clear")) {
props.put("mail.smtp.port", ConfigPropertyUtils.defaultPort(port, "25"));
}
else if (channelEncryption.equals("ssl")) {
// port 465 + setup yes ssl socket factory (won't verify that
// the server certificate is signed with a root ca.)
props.put("mail.smtp.port", ConfigPropertyUtils.defaultPort(port, "465"));
props.put("mail.smtp.ssl.socketFactory.port", ConfigPropertyUtils.defaultPort(port, "465"));
props.put("mail.smtp.ssl.socketFactory.class", "play.utils.YesSSLSocketFactory");
props.put("mail.smtp.ssl.socketFactory.fallback", "false");
}
else if (channelEncryption.equals("starttls")) {
// port 25 + enable starttls + ssl socket factory
props.put("mail.smtp.port", ConfigPropertyUtils.defaultPort(port, "465"));
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.ssl.socketFactory.port", ConfigPropertyUtils.defaultPort(port, "465"));
props.put("mail.smtp.ssl.socketFactory.class", "play.utils.YesSSLSocketFactory");
props.put("mail.smtp.ssl.socketFactory.fallback", "false");
}
String user = form.username;
String password = form.password;
String authenticator = Play.configuration.getProperty("mail.smtp.authenticator");
Session session = null;
if (authenticator != null) {
props.put("mail.smtp.auth", "true");
try {
session = Session.getInstance(props, (Authenticator) Play.classloader.loadClass(authenticator)
.newInstance());
} catch (Exception e) {
Logger.error(e, "Cannot instantiate custom SMTP authenticator (%s)", authenticator);
addExceptionError(e);
}
}
if (session == null) {
if (StringUtils.isNotBlank(user) && StringUtils.isNotBlank(password)) {
props.put("mail.smtp.auth", "true");
session = Session.getInstance(props, new SMTPAuthenticator(user, password));
}
else {
props.remove("mail.smtp.auth");
session = Session.getInstance(props);
}
}
return session;
}
/**
* Send a JavaMail message
*
* @param message
* the email message
*/
public static boolean sendMessage(Email message) throws EmailException {
message.setSentDate(new Date());
message.send();
return true;
}
public static class SMTPAuthenticator extends Authenticator {
private String user;
private String password;
public SMTPAuthenticator(String user, String password) {
this.user = user;
this.password = password;
}
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user, password);
}
}
private static void addExceptionError(Throwable t) {
if (t.getCause() != null && (t instanceof javax.mail.MessagingException == false)) {
addExceptionError(t.getCause());
}
else {
Validation.addError(null, t.getMessage());
}
}
}