NIHVIVO-3489 When setting up the Email session, test to see whether the SMTP host will respond on the SMTP port with a valid SMTP header.
This commit is contained in:
parent
e273bc5f3e
commit
cb5e2362b1
1 changed files with 118 additions and 28 deletions
|
@ -2,7 +2,15 @@
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.email;
|
package edu.cornell.mannlib.vitro.webapp.email;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.net.ConnectException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
import javax.mail.Session;
|
import javax.mail.Session;
|
||||||
import javax.mail.internet.AddressException;
|
import javax.mail.internet.AddressException;
|
||||||
|
@ -53,11 +61,6 @@ public class FreemarkerEmailFactory {
|
||||||
factory.getReplyToAddress());
|
factory.getReplyToAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isConfigured(HttpServletRequest req) {
|
|
||||||
FreemarkerEmailFactory factory = getFactory(req);
|
|
||||||
return (factory != null) && (factory.isConfigured());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client code that does not use the FreemarkerEmailFactory can still use
|
* Client code that does not use the FreemarkerEmailFactory can still use
|
||||||
* it's Email Session.
|
* it's Email Session.
|
||||||
|
@ -69,6 +72,10 @@ public class FreemarkerEmailFactory {
|
||||||
return getFactory(req).getEmailSession();
|
return getFactory(req).getEmailSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isConfigured(HttpServletRequest req) {
|
||||||
|
return (getFactory(req) != null);
|
||||||
|
}
|
||||||
|
|
||||||
private static FreemarkerEmailFactory getFactory(HttpServletRequest req) {
|
private static FreemarkerEmailFactory getFactory(HttpServletRequest req) {
|
||||||
ServletContext ctx = req.getSession().getServletContext();
|
ServletContext ctx = req.getSession().getServletContext();
|
||||||
return (FreemarkerEmailFactory) ctx.getAttribute(ATTRIBUTE_NAME);
|
return (FreemarkerEmailFactory) ctx.getAttribute(ATTRIBUTE_NAME);
|
||||||
|
@ -84,12 +91,14 @@ public class FreemarkerEmailFactory {
|
||||||
|
|
||||||
public FreemarkerEmailFactory(ServletContext ctx) {
|
public FreemarkerEmailFactory(ServletContext ctx) {
|
||||||
this.smtpHost = getSmtpHostFromConfig(ctx);
|
this.smtpHost = getSmtpHostFromConfig(ctx);
|
||||||
|
new SmtpHostTester().test(this.smtpHost);
|
||||||
|
|
||||||
this.replyToAddress = getReplyToAddressFromConfig(ctx);
|
this.replyToAddress = getReplyToAddressFromConfig(ctx);
|
||||||
this.emailSession = createEmailSession(this.smtpHost);
|
this.emailSession = createEmailSession(smtpHost);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isConfigured() {
|
String getSmtpHost() {
|
||||||
return (!smtpHost.isEmpty()) && (replyToAddress != null);
|
return smtpHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
InternetAddress getReplyToAddress() {
|
InternetAddress getReplyToAddress() {
|
||||||
|
@ -104,8 +113,7 @@ public class FreemarkerEmailFactory {
|
||||||
ConfigurationProperties config = ConfigurationProperties.getBean(ctx);
|
ConfigurationProperties config = ConfigurationProperties.getBean(ctx);
|
||||||
String hostName = config.getProperty(SMTP_HOST_PROPERTY, "");
|
String hostName = config.getProperty(SMTP_HOST_PROPERTY, "");
|
||||||
if (hostName.isEmpty()) {
|
if (hostName.isEmpty()) {
|
||||||
log.info("Configuration property for '" + SMTP_HOST_PROPERTY
|
throw new NotConfiguredException(SMTP_HOST_PROPERTY);
|
||||||
+ "' is empty: email is disabled.");
|
|
||||||
}
|
}
|
||||||
return hostName;
|
return hostName;
|
||||||
}
|
}
|
||||||
|
@ -114,22 +122,18 @@ public class FreemarkerEmailFactory {
|
||||||
ConfigurationProperties config = ConfigurationProperties.getBean(ctx);
|
ConfigurationProperties config = ConfigurationProperties.getBean(ctx);
|
||||||
String rawAddress = config.getProperty(REPLY_TO_PROPERTY, "");
|
String rawAddress = config.getProperty(REPLY_TO_PROPERTY, "");
|
||||||
if (rawAddress.isEmpty()) {
|
if (rawAddress.isEmpty()) {
|
||||||
log.info("Configuration property for '" + REPLY_TO_PROPERTY
|
throw new NotConfiguredException(REPLY_TO_PROPERTY);
|
||||||
+ "' is empty: email is disabled.");
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
InternetAddress[] addresses = InternetAddress.parse(rawAddress,
|
InternetAddress[] addresses = InternetAddress.parse(rawAddress,
|
||||||
false);
|
false);
|
||||||
if (addresses.length == 0) {
|
if (addresses.length == 0) {
|
||||||
throw new IllegalStateException(
|
throw new BadPropertyValueException("No Reply-To address",
|
||||||
"No Reply-To address configured in '"
|
REPLY_TO_PROPERTY);
|
||||||
+ REPLY_TO_PROPERTY + "'");
|
|
||||||
} else if (addresses.length > 1) {
|
} else if (addresses.length > 1) {
|
||||||
throw new IllegalStateException(
|
throw new BadPropertyValueException(
|
||||||
"More than one Reply-To address configured in '"
|
"More than one Reply-To address", REPLY_TO_PROPERTY);
|
||||||
+ REPLY_TO_PROPERTY + "'");
|
|
||||||
} else {
|
} else {
|
||||||
return addresses[0];
|
return addresses[0];
|
||||||
}
|
}
|
||||||
|
@ -147,9 +151,93 @@ public class FreemarkerEmailFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
// Setup class
|
// Helper classes
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
public static class NotConfiguredException extends RuntimeException {
|
||||||
|
public NotConfiguredException(String property) {
|
||||||
|
super("Configuration property for '" + property
|
||||||
|
+ "' is empty - Email functions are disabled.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BadPropertyValueException extends RuntimeException {
|
||||||
|
public BadPropertyValueException(String problem, String property) {
|
||||||
|
super(problem + " configured in '" + property
|
||||||
|
+ "' - Email functions are disabled.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class InvalidSmtpHost extends RuntimeException {
|
||||||
|
public InvalidSmtpHost(String smtpHost, String reason) {
|
||||||
|
super("Invalid SMTP host: '" + smtpHost + "': " + reason
|
||||||
|
+ " - Email functions are disabled.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks to see whether the SMTP host will talk to us.
|
||||||
|
*/
|
||||||
|
public static class SmtpHostTester {
|
||||||
|
private static final int SMTP_PORT = 25;
|
||||||
|
private static final int SMTP_SUCCESS_CODE = 220;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to open a connection to the SMTP host and conduct an "empty"
|
||||||
|
* conversation using SMTP.
|
||||||
|
*
|
||||||
|
* @throws InvalidSmtpHost
|
||||||
|
* If anything goes wrong.
|
||||||
|
*/
|
||||||
|
public void test(String smtpHost) throws InvalidSmtpHost {
|
||||||
|
Socket socket = null;
|
||||||
|
PrintStream out = null;
|
||||||
|
Scanner in = null;
|
||||||
|
try {
|
||||||
|
InetAddress hostAddr = InetAddress.getByName(smtpHost);
|
||||||
|
socket = new Socket(hostAddr, SMTP_PORT);
|
||||||
|
|
||||||
|
out = new PrintStream(socket.getOutputStream());
|
||||||
|
in = new Scanner(new InputStreamReader(socket.getInputStream()));
|
||||||
|
|
||||||
|
int smtpCode = in.nextInt();
|
||||||
|
if (smtpCode != SMTP_SUCCESS_CODE) {
|
||||||
|
throw new InvalidSmtpHost(smtpHost,
|
||||||
|
"host will not converse: "
|
||||||
|
+ "SMTP initialization code is " + smtpCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
out.println("QUIT");
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
throw new InvalidSmtpHost(smtpHost,
|
||||||
|
"host name is not recognized");
|
||||||
|
} catch (ConnectException e) {
|
||||||
|
throw new InvalidSmtpHost(smtpHost,
|
||||||
|
"refused connection on port " + SMTP_PORT);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("unrecognized problem: ", e);
|
||||||
|
} finally {
|
||||||
|
if (in != null) {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
if (out != null) {
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
if ((socket != null) && (!socket.isClosed())) {
|
||||||
|
try {
|
||||||
|
socket.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("failed to close socket", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to create a FreemarkerEmailFactory bean and store it in the servlet
|
||||||
|
* context.
|
||||||
|
*/
|
||||||
public static class Setup implements ServletContextListener {
|
public static class Setup implements ServletContextListener {
|
||||||
@Override
|
@Override
|
||||||
public void contextInitialized(ServletContextEvent sce) {
|
public void contextInitialized(ServletContextEvent sce) {
|
||||||
|
@ -159,14 +247,16 @@ public class FreemarkerEmailFactory {
|
||||||
try {
|
try {
|
||||||
FreemarkerEmailFactory factory = new FreemarkerEmailFactory(ctx);
|
FreemarkerEmailFactory factory = new FreemarkerEmailFactory(ctx);
|
||||||
ctx.setAttribute(ATTRIBUTE_NAME, factory);
|
ctx.setAttribute(ATTRIBUTE_NAME, factory);
|
||||||
|
ss.info(this,
|
||||||
if (factory.isConfigured()) {
|
"The system will send email from '"
|
||||||
ss.info(this, "The system is configured to "
|
+ factory.getReplyToAddress() + "' through '"
|
||||||
+ "send mail to users.");
|
+ factory.getSmtpHost() + "'.");
|
||||||
} else {
|
} catch (NotConfiguredException e) {
|
||||||
ss.info(this, "Configuration parameters are missing: "
|
ss.info(this, e.getMessage());
|
||||||
+ "the system will not send mail to users.");
|
} catch (BadPropertyValueException e) {
|
||||||
}
|
ss.warning(this, e.getMessage());
|
||||||
|
} catch (InvalidSmtpHost e) {
|
||||||
|
ss.warning(this, e.getMessage());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ss.warning(this,
|
ss.warning(this,
|
||||||
"Failed to initialize FreemarkerEmailFactory. "
|
"Failed to initialize FreemarkerEmailFactory. "
|
||||||
|
|
Loading…
Add table
Reference in a new issue