diff --git a/src/main/java/uk/ac/cam/cares/jps/base/email/EmailSender.java b/src/main/java/uk/ac/cam/cares/jps/base/email/EmailSender.java deleted file mode 100644 index d7955796d..000000000 --- a/src/main/java/uk/ac/cam/cares/jps/base/email/EmailSender.java +++ /dev/null @@ -1,269 +0,0 @@ -package uk.ac.cam.cares.jps.base.email; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.InetAddress; -import java.net.URL; -import java.net.UnknownHostException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Optional; -import java.util.Properties; - -import org.json.JSONObject; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import uk.ac.cam.cares.jps.base.discovery.AgentCaller; - -/** - * This class handles sending HTTP requests to a remote EmailAgent instance to facilitate the - * sending of an automated email. - * - * @author Michael Hillman (mdhillman<@>cmclinnovations.com) - */ -public class EmailSender { - - /** - * Logger for error output. - */ - private static final Logger LOGGER = LogManager.getLogger(EmailSender.class); - - /** - * Contains meta-data to append to email content. - */ - private final Properties metadata; - - /** - * Base URL for remote EmailAgent instance. - */ - private String emailAgentURL; - - /** - * Denotes if the remote EmailAgent is reachable and available. - */ - private boolean isAgentReachable = false; - - /** - * Create a new EmailSender instance. - */ - public EmailSender() { - this(null); - } - - /** - * Create a new EmailSender instance. - * - * @param emailAgentURL URL of remote EmailAgent instance. - */ - public EmailSender(String emailAgentURL) { - this.emailAgentURL = emailAgentURL; - this.metadata = new Properties(); - - // Can we reach the remote EmailAgent? - determineAgentLocation(); - this.isAgentReachable = isReachable(); - - // Generate meta-data to add to email - gatherMetaData(); - } - - /** - * Attempts to send a HTTP request to the remote EmailAgent instance using the input content. - * - * Note: if the remote EmailAgent cannot be reached, or returns an error code, then the message - * content is written to a local file instead. - * - * @param subject email subject - * @param body email body - * - * @return Optionally returns location of log file (if written to). - * - * @throws Exception if not initialised, email cannot be sent or written to local file. - */ - public Optional sendEmail(String subject, String body) throws Exception { - // Append the meta-data to the email body - StringBuilder strBuilder = new StringBuilder(body); - strBuilder.append("

"); - strBuilder.append("The following meta-data was gathered from the machine triggering this notification:"); - strBuilder.append("
"); - - for (Object key : metadata.keySet()) { - strBuilder.append(" ").append(key).append(": ").append(metadata.get(key)); - strBuilder.append("
"); - } - - // Determine whether to send email or write to file - if (!isAgentReachable) { - // Write to file. - LOGGER.warn("Could not reach remote EmailAgent, writing message to a local file instead."); - return Optional.of(writeToFile(subject, strBuilder.toString())); - - } else { - // Send HTTP request - try { - makeRequest(subject, strBuilder.toString()); - return Optional.empty(); - } catch (Exception exception) { - return Optional.of(writeToFile(subject, strBuilder.toString())); - } - } - } - - /** - * Makes the HTTP request to the remote EmailAgent. - * - * @param subject email subject - * @param body email body - */ - private void makeRequest(String subject, String body) { - JSONObject request = new JSONObject(); - request.put("subject", subject); - request.put("body", body); - - try { - // Make the HTTP request - String submitURL = (emailAgentURL.endsWith("/")) ? emailAgentURL + "send" : emailAgentURL + "/send"; - String result = AgentCaller.executeGetWithURLAndJSON(submitURL, request.toString()); - - if (result.contains("Request forwarded")) { - // Success - LOGGER.info("EmailAgent reports successful request, check recipient mailbox."); - - } else { - // Failure - JSONObject resultJSON = new JSONObject(result); - LOGGER.warn("Remote EmailAgent instance reports issues, cannot send email!"); - LOGGER.warn(resultJSON.get("description")); - } - } catch (Exception exception) { - LOGGER.error("Exception when attempting to contact remote EmailAgent instance, will write to file instead.", exception); - } - } - - /** - * Writes the email content to file. - * - * @param subject email subject. - * @param body email body. - * - * @throws IOException if file could not be written to. - */ - private Path writeToFile(String subject, String body) throws IOException { - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss-SSSS"); - String datetime = dateFormat.format(new Date()); - - String fileName = "EmailSender_" + datetime + ".log"; - Path logFile = Paths.get(fileName); - - try ( BufferedWriter writer = new BufferedWriter(new FileWriter(logFile.toFile()))) { - writer.append("Subject: ").append(subject); - writer.append("\n"); - writer.append("Body:\n"); - writer.append(body); - } - - LOGGER.info("Message written to file at {}", logFile.toAbsolutePath()); - return logFile; - } - - /** - * Attempts to contact the remote EmailAgent, returns true if it can be reached and responds as - * available. - * - * @return remote EmailAgent is reachable. - */ - public boolean isReachable() { - try { - // Make the HTTP request - String statusURL = (emailAgentURL.endsWith("/")) ? emailAgentURL + "status" : emailAgentURL + "/status"; - String result = AgentCaller.executeGetWithURL(statusURL); - - // Check result contents - if (result.contains("Ready to serve")) { - return true; - } - } catch (Exception exception) { - LOGGER.error("Exception when trying to determine if remote EmailAgent is reachable.", exception); - } - return false; - } - - /** - * If not already passed in, attempts to read the EmailAgent's URL from an environment variable - * (that should have been set using Docker). - */ - private void determineAgentLocation() { - if(emailAgentURL == null) { - String variable = System.getenv("EMAIL_AGENT_URL"); - - if (variable == null || variable.trim().isEmpty()) { - LOGGER.error("Could not find EMAIL_AGENT_URL variable, cannot continue"); - isAgentReachable = false; - } else { - emailAgentURL = variable; - LOGGER.info("Found EMAIL_AGENT_URL variable, remote location is: {}", emailAgentURL); - } - } - } - - /** - * Gathers meta-data what will be appended to the email content. - */ - private void gatherMetaData() { - // Hostname - String hostname = null; - try { - hostname = InetAddress.getLocalHost().getHostName(); - } catch (UnknownHostException exception) { - hostname = "Unknown"; - } finally { - metadata.put("Hostname", hostname); - } - - // Local IP - String localIP = null; - try { - localIP = InetAddress.getLocalHost().getHostAddress(); - } catch (UnknownHostException exception) { - localIP = "Unknown"; - } finally { - metadata.put("Local IP Address", localIP); - } - - // Public IP - String publicIP = null; - try { - publicIP = getPublicIP(); - } catch (Exception exception) { - publicIP = "Unknown"; - } finally { - metadata.put("Public IP Address", publicIP); - } - - // Submission time - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSS"); - String datetime = dateFormat.format(new Date()); - metadata.put("Submission Time", datetime); - } - - /** - * Uses a remote service to get the current public IP. - * - * @return public IP - */ - private String getPublicIP() throws Exception { - URL url = new URL("http://checkip.amazonaws.com"); - - try ( BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()))) { - return reader.readLine(); - } - } - -} -// End of class. diff --git a/src/main/java/uk/ac/cam/cares/jps/base/email/package-info.java b/src/main/java/uk/ac/cam/cares/jps/base/email/package-info.java deleted file mode 100644 index b6a3bdce3..000000000 --- a/src/main/java/uk/ac/cam/cares/jps/base/email/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * This package contains classes relating to communication with the EmailAgent service. - * - * @author Michael Hillman - */ -package uk.ac.cam.cares.jps.base.email; diff --git a/src/test/java/uk/ac/cam/cares/jps/base/email/EmailSenderTest.java b/src/test/java/uk/ac/cam/cares/jps/base/email/EmailSenderTest.java deleted file mode 100644 index 3ef2cf63e..000000000 --- a/src/test/java/uk/ac/cam/cares/jps/base/email/EmailSenderTest.java +++ /dev/null @@ -1,108 +0,0 @@ -package uk.ac.cam.cares.jps.base.email; - -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Optional; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -/** - * Tests the functionality of the EmailSender class. - * See the EmailAgent source code for details on how to test - * - * @author Michael Hillman (mdhillman<@>cmclinnovations.com) - */ -public class EmailSenderTest { - - /** - * Logger for error output. - */ - private static final Logger LOGGER = LogManager.getLogger(EmailSenderTest.class); - - /** - * Base URL of remote EmailAgent to use in test. - */ - private static final String EMAIL_AGENT_URL = "http://localhost:8080/email_agent"; - - /** - * Tests that an email can be submitted to the EmailSender and is written to a - * local log file. - */ - @Test - public void writeToFile() { - // Initialise new EmailSender - EmailSender sender = new EmailSender("http://fake-website/email-agent/"); - - // Use a junk environment variable so that the EmailSender cannot reach a remote - // EmailAgent instance and falls back to creating a log file. - try { - - // Email contents - String subject = "Test email from the EmailSender_Test.writeToFile() method."; - String body = "This test email should fail and get written to a local log file."; - - // Attempt to send an email - Optional logFile = sender.sendEmail(subject, body); - - // Should return a log file - Assertions.assertTrue(logFile.isPresent(), "Expected an log file to be returned!"); - - // Should exist on disk - Assertions.assertTrue(Files.exists(logFile.get()), "Expected to find log file on disk!"); - - // Remove the generated log file - Assertions.assertTrue(Files.deleteIfExists(logFile.get()), "Could not delete the generated log file!"); - - } catch (Exception exception) { - Assertions.fail("Could not mock environment variables for unit test!", exception); - } - } - - /** - * Attempts to contact a remote EmailAgent instance and submit a message. - */ - @Test - @Disabled("See class documentation") - public void submitJob() { - // Configure a message - String subject = "Testing the EmailAgent"; - String body = "This is a test of the EmailAgent's functionality to recieve job submissions " - + "and forward them to a remote SMTP server for delivery. If you're not the originator of " - + "this job, please ignore this message."; - - // Use JPS base library code to submit job - EmailSender sender = new EmailSender(EMAIL_AGENT_URL); - - try { - Optional logFile = sender.sendEmail(subject, body); - LOGGER.info("Email sent successfully, please check recipient's mailbox."); - if (logFile.isPresent()) { - Files.deleteIfExists(logFile.get()); - } - } catch (Exception exception) { - LOGGER.error("Could not contact remote EmailAgent!", exception); - } - } - - /** - * Attempts to contact a remote EmailAgent instance and get the status - */ - @Test - @Disabled("See class documentation") - public void submitPing() { - // Use JPS base library code to submit job - EmailSender sender = new EmailSender(EMAIL_AGENT_URL); - - try { - boolean reachable = sender.isReachable(); - LOGGER.info("Pinged the remote EmailAgent, status was {}", reachable); - } catch (Exception exception) { - LOGGER.error("Could not contact remote EmailAgent!", exception); - } - } -} -// End of class.