diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..d4cd657 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "maven" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 0000000..f369e16 --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,33 @@ +# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven + +name: Java CI with Maven + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 1.8 + uses: actions/setup-java@v3 + with: + java-version: '8' + distribution: 'temurin' + cache: maven + - name: Cache local Maven repository + uses: actions/cache@v3.0.11 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + - name: Build with Maven + run: mvn -B package --file pom.xml diff --git a/.travis.yml b/.travis.yml index e1003b4..61998ed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,7 @@ language: java jdk: - - oraclejdk7 - - openjdk7 \ No newline at end of file + - oraclejdk8 + - openjdk8 +cache: + directories: + - $HOME/.m2 diff --git a/README.md b/README.md index 8b41994..b770218 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ The easiest way to install and run MockMock is by downloading the jar file [here `java -jar MockMock.jar` This will run MockMock on the default ports 25 (for SMTP) and 8282 (the web interface). Please note you might need root permissions on some systems to let it listen on port 25. -After it started you can use your internet browser to navigate to [http://localhost:8282] (replace host name and web port if necessary). This will now show you the emails it received (which should be none at the moment). You can now send emails using the built in SMTP server running on port 25 by default. The emails should be visible via the web interface. To run MockMock on another port, you can start it with the following parameters: +After it started you can use your internet browser to navigate to [http://localhost:8282] (replace host name and web port if necessary). This will now show you the emails it received (which should be none at the moment). You can now send emails using the built-in SMTP server running on port 25 by default. The emails should be visible via the web interface. To run MockMock on another port, you can start it with the following parameters: `java -jar MockMock.jar -p 25000 -h 8080` This will run MockMock on SMTP port 25000 and http port 8080. diff --git a/checkstyle.xml b/checkstyle.xml new file mode 100644 index 0000000..1bcbf91 --- /dev/null +++ b/checkstyle.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/extra/init.centos b/extra/init.centos new file mode 100755 index 0000000..6aa1980 --- /dev/null +++ b/extra/init.centos @@ -0,0 +1,88 @@ +#! /bin/sh +### BEGIN INIT INFO +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: MockMock - Mock SMTP Server +### END INIT INFO + +# PATH should only include /usr/* if it runs after the mountnfs.sh script +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="MockMock - Mock SMTP Server" +NAME=mockmock +DAEMON=/opt/mockmock/MockMock.jar +DAEMON_ARGS="-p 25000 -h 8282" +PIDFILE=/var/run/$NAME.pid +SCRIPTNAME=/etc/init.d/$NAME + +# Read configuration variable file if it is present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +# Centos daemon functions +. /etc/init.d/functions + +exe="/usr/bin/java -jar ${DAEMON} ${DAEMON_ARGS}" + +# +# Function that starts the daemon/service +# +do_start() +{ + echo -n "Starting mockmock : ${DAEMON_ARGS}" + #daemon ${exe} # Not working ... + if [ -s ${PIDFILE} ]; then + RETVAL=1 + echo -n "Already running, check '${PIDFILE}'." && warning + echo + else + nohup ${exe} > /var/log/mockmock.log 2>&1 & + RETVAL=$? + PID=$! + [ $RETVAL -eq 0 ] && success || failure + echo + echo $PID > ${PIDFILE} + fi + return "$RETVAL" +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + killproc -p ${PIDFILE} + RETVAL="$?" + if [ "$RETVAL" -ne 0 ]; then + echo -n "Could not stop mockmock with pid file ${PIDFILE}." && error + return "$RETVAL" + fi + + # Many daemons don't delete their pidfiles when they exit. + rm -f ${PIDFILE} + echo "Stopping mockmock." + return "$RETVAL" +} + +case "$1" in + start) + do_start + ;; + stop) + do_stop + ;; + status) + status -p $PIDFILE + ;; + restart|force-reload) + do_stop + do_start + ;; + *) + #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 + echo "Usage: $SCRIPTNAME {start|stop|status|restart}" >&2 + exit 3 + ;; +esac + +: diff --git a/pom.xml b/pom.xml index 88cfb5b..627a418 100644 --- a/pom.xml +++ b/pom.xml @@ -1,117 +1,68 @@ - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.mockmock MockMock - 1.4.0 + 1.4.1-SNAPSHOT jar MockMock Mock SMTP Server - 2012 https://github.com/tweakers-dev/MockMock - - - 3.0 - + 2012 - ISO-8859-15 - ISO-8859-15 - 4.1.2.RELEASE + UTF-8 + UTF-8 + 2.0.9 - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - 1.7 - 1.7 - - - - org.apache.maven.plugins - maven-jar-plugin - 2.3.1 - - - - com.mockmock.AppStarter - - - - - - org.dstovall - onejar-maven-plugin - 1.4.4 - - - - 0.97 - true - onejar - - package - - one-jar - - - - - - - org.apache.maven.plugins - maven-resources-plugin - 2.4.3 - - - copy-resources - package - - copy-resources - - - ${basedir}/target/static - - - src/main/resources - true - - - - - - - - - - - - onejar-maven-plugin.googlecode.com - http://onejar-maven-plugin.googlecode.com/svn/mavenrepo - - - - - - repository.springframework.maven.release - Spring Framework Maven Release Repository - http://maven.springframework.org/release - - + + + + org.springframework + spring-framework-bom + 5.3.23 + pom + import + + + org.eclipse.jetty + jetty-bom + 9.4.49.v20220914 + pom + import + + + javax.mail + mail + 1.4.7 + + + org.slf4j + slf4j-api + ${slf4j.version} + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + javax.activation + activation + 1.1.1 + + + commons-cli commons-cli - 1.2 + 1.5.0 @@ -120,40 +71,20 @@ 2.6 - - javax.mail - mail - 1.4 - - - - org.slf4j - slf4j-api - 1.7.2 - - org.slf4j slf4j-simple - 1.7.2 - - - - javax.activation - activation - 1.1 + ${slf4j.version} org.eclipse.jetty jetty-server - 8.1.8.v20121106 org.eclipse.jetty jetty-webapp - 8.1.8.v20121106 @@ -165,60 +96,169 @@ joda-time joda-time - 2.1 + 2.12.5 com.google.guava guava - 13.0 + 32.1.3-jre org.springframework spring-core - ${spring.version} org.springframework spring-beans - ${spring.version} org.springframework spring-context - ${spring.version} org.springframework spring-context-support - ${spring.version} org.springframework spring-webmvc - ${spring.version} - junit junit - 4.11 + 4.13.2 test org.mockito mockito-core - 1.8.5 + 4.11.0 test - \ No newline at end of file + + + repository.springframework.maven.release + Spring Framework Maven Release Repository + http://maven.springframework.org/release + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.4.1 + + + enforce-maven + + enforce + + + + + 3.0.5 + + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.3.0 + + + validate + validate + + checkstyle.xml + ${project.build.sourceEncoding} + true + true + + + check + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + 1.7 + 1.7 + + + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + + + com.mockmock.AppStarter + + + + + + com.jolira + onejar-maven-plugin + 1.4.4 + + + + 0.97 + true + onejar + + package + + one-jar + + + + + + + org.apache.maven.plugins + maven-resources-plugin + 3.3.1 + + + copy-resources + package + + copy-resources + + + ${basedir}/target/static + + + src/main/resources + true + + + + + + + + + diff --git a/release/MockMock.jar b/release/MockMock.jar index 12ed6c2..ca6f98c 100644 Binary files a/release/MockMock.jar and b/release/MockMock.jar differ diff --git a/src/main/java/com/mockmock/Util.java b/src/main/java/com/mockmock/Util.java index 2b32188..bcb3d98 100644 --- a/src/main/java/com/mockmock/Util.java +++ b/src/main/java/com/mockmock/Util.java @@ -1,12 +1,9 @@ package com.mockmock; import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.util.Scanner; public class Util { @@ -43,4 +40,4 @@ public String getFile(String fileName) return sb.toString(); } -} \ No newline at end of file +} diff --git a/src/main/java/com/mockmock/console/Parser.java b/src/main/java/com/mockmock/console/Parser.java index d836a4e..4246906 100644 --- a/src/main/java/com/mockmock/console/Parser.java +++ b/src/main/java/com/mockmock/console/Parser.java @@ -1,6 +1,5 @@ package com.mockmock.console; - import com.mockmock.Settings; import org.apache.commons.cli.*; import org.springframework.stereotype.Service; @@ -19,15 +18,15 @@ public Settings parseOptions(String[] args, Settings settings) { // define the possible options Options options = new Options(); - options.addOption("p", true, "The mail port number to use. Default is 25000."); - options.addOption("h", true, "The http port number to use. Default is 8282."); - options.addOption("m", true, "The maximum size of the mail qeueue. Default is 1000."); - options.addOption("c", true, "Comma separated list of channels. Default is #postman."); - options.addOption("ff", true, "Filters out from email addresses (comma separated)."); - options.addOption("ft", true, "Filters out to email addresses (comma separated)."); - options.addOption("s", true, "Full path to the folder containing the static files like images and css."); - options.addOption("ec", false, "Turns on emails printing to console. Default off"); - options.addOption("?", false, "Shows this help information."); + options.addOption("p", "smtp", true, "The mail port number to use. Default is 25."); + options.addOption("h", "http", true, "The http port number to use. Default is 8282."); + options.addOption("m", "queue", true, "The maximum size of the mail queue. Default is 1000."); + options.addOption("c", "channels", true, "Comma separated list of channels. Default is #postman."); + options.addOption("f", "filter-from", true, "Filters out from email addresses (comma separated)."); + options.addOption("t", "filter-to", true, "Filters out to email addresses (comma separated)."); + options.addOption("s", "static", true, "Full path to the folder containing the static files like images and css."); + options.addOption("ec", "console", false, "Turns on emails printing to console. Default off"); + options.addOption("?", "help", false, "Shows this help information."); // parse the given arguments CommandLineParser parser = new PosixParser(); @@ -43,7 +42,7 @@ public Settings parseOptions(String[] args, Settings settings) System.exit(0); } - partseShowEmailInConsoleOption(cmd, settings); + parseShowEmailInConsoleOption(cmd, settings); parseSmtpPortOption(cmd, settings); parseHttpPortOption(cmd, settings); parseMailQueueSizeOption(cmd, settings); @@ -59,19 +58,11 @@ public Settings parseOptions(String[] args, Settings settings) return settings; } - protected void partseShowEmailInConsoleOption(CommandLine cmd, Settings settings) + protected void parseShowEmailInConsoleOption(CommandLine cmd, Settings settings) { if(cmd.hasOption("ec")) { - try - { - // settings.setShowEmailInConsole(Boolean.valueOf(cmd.getOptionValue("ec"))); - settings.setShowEmailInConsole(true); - } - catch(IllegalArgumentException e) - { - System.err.println("Invalid value given, using default " + settings.getShowEmailInConsole()); - } + settings.setShowEmailInConsole(true); } } @@ -81,7 +72,7 @@ protected void parseSmtpPortOption(CommandLine cmd, Settings settings) { try { - settings.setSmtpPort(Integer.valueOf(cmd.getOptionValue("p"))); + settings.setSmtpPort(Integer.parseInt(cmd.getOptionValue("p"))); } catch (NumberFormatException e) { @@ -96,7 +87,7 @@ protected void parseHttpPortOption(CommandLine cmd, Settings settings) { try { - settings.setHttpPort(Integer.valueOf(cmd.getOptionValue("h"))); + settings.setHttpPort(Integer.parseInt(cmd.getOptionValue("h"))); } catch (NumberFormatException e) { @@ -111,7 +102,7 @@ protected void parseMailQueueSizeOption(CommandLine cmd, Settings settings) { try { - settings.setMaxMailQueueSize(Integer.valueOf(cmd.getOptionValue("m"))); + settings.setMaxMailQueueSize(Integer.parseInt(cmd.getOptionValue("m"))); } catch (NumberFormatException e) { @@ -122,9 +113,9 @@ protected void parseMailQueueSizeOption(CommandLine cmd, Settings settings) protected void parseFilterFromEmailAddressesOption(CommandLine cmd, Settings settings) { - if(cmd.hasOption("ff")) + if(cmd.hasOption("f")) { - String input = cmd.getOptionValue("ff"); + String input = cmd.getOptionValue("f"); String[] emailAddresses = input.split(","); settings.setFilterFromEmailAddresses(new HashSet<>(Arrays.asList(emailAddresses))); } @@ -132,9 +123,9 @@ protected void parseFilterFromEmailAddressesOption(CommandLine cmd, Settings set protected void parseFilterToEmailAddressesOption(CommandLine cmd, Settings settings) { - if(cmd.hasOption("ft")) + if(cmd.hasOption("t")) { - String input = cmd.getOptionValue("ft"); + String input = cmd.getOptionValue("t"); String[] emailAddresses = input.split(","); settings.setFilterToEmailAddresses(new HashSet<>(Arrays.asList(emailAddresses))); } diff --git a/src/main/java/com/mockmock/htmlbuilder/AddressesHtmlBuilder.java b/src/main/java/com/mockmock/htmlbuilder/AddressesHtmlBuilder.java index 8b51534..c017cfd 100644 --- a/src/main/java/com/mockmock/htmlbuilder/AddressesHtmlBuilder.java +++ b/src/main/java/com/mockmock/htmlbuilder/AddressesHtmlBuilder.java @@ -12,7 +12,7 @@ public class AddressesHtmlBuilder implements HtmlBuilder public String build() { - String output = ""; + StringBuilder output = new StringBuilder(); StringFromHtmlBuilder fromHtmlBuilder = new StringFromHtmlBuilder(); fromHtmlBuilder.setMockMail(mockMail); @@ -20,26 +20,26 @@ public String build() StringRecipientHtmlBuilder recipientHtmlBuilder = new StringRecipientHtmlBuilder(); recipientHtmlBuilder.setMockMail(mockMail); - output += "From: " + fromHtmlBuilder.build() + "
\n"; + output.append("From: ").append(fromHtmlBuilder.build()).append("
\n"); recipientHtmlBuilder.setRecipientType(MimeMessage.RecipientType.TO); - output += "To: " + recipientHtmlBuilder.build() + "
\n"; + output.append("To: ").append(recipientHtmlBuilder.build()).append("
\n"); recipientHtmlBuilder.setRecipientType(MimeMessage.RecipientType.CC); String ccOutput = recipientHtmlBuilder.build(); if(ccOutput.length() > 0) { - output += "CC: " + ccOutput + "
\n"; + output.append("CC: ").append(ccOutput).append("
\n"); } recipientHtmlBuilder.setRecipientType(MimeMessage.RecipientType.BCC); String bccOutput = recipientHtmlBuilder.build(); if(bccOutput.length() > 0) { - output += "BCC: " + bccOutput + "
\n"; + output.append("BCC: ").append(bccOutput).append("
\n"); } - return output; + return output.toString(); } public void setMockMail(MockMail mockMail) diff --git a/src/main/java/com/mockmock/htmlbuilder/FooterHtmlBuilder.java b/src/main/java/com/mockmock/htmlbuilder/FooterHtmlBuilder.java index 41675f3..16ee4ac 100644 --- a/src/main/java/com/mockmock/htmlbuilder/FooterHtmlBuilder.java +++ b/src/main/java/com/mockmock/htmlbuilder/FooterHtmlBuilder.java @@ -1,6 +1,5 @@ package com.mockmock.htmlbuilder; -import com.mockmock.AppStarter; import com.mockmock.Settings; import com.mockmock.Util; import org.springframework.stereotype.Service; @@ -19,28 +18,20 @@ public void setSettings(Settings settings) public String build() { - String output = ""; + StringBuilder output = new StringBuilder(); Util util = new Util(); if(settings.getStaticFolderPath() != null) { - output += - " \n" + - " \n" + - " \n"; + output.append(" \n" + " \n" + " \n"); } else { - output += - " \n" + - " \n" + - " \n"; + output.append(" \n").append(" \n").append(" \n"); } - output += - " \n" + - "\n"; + output.append(" \n" + "\n"); - return output; + return output.toString(); } } diff --git a/src/main/java/com/mockmock/htmlbuilder/HeaderHtmlBuilder.java b/src/main/java/com/mockmock/htmlbuilder/HeaderHtmlBuilder.java index 808ea67..96e520f 100644 --- a/src/main/java/com/mockmock/htmlbuilder/HeaderHtmlBuilder.java +++ b/src/main/java/com/mockmock/htmlbuilder/HeaderHtmlBuilder.java @@ -19,50 +19,44 @@ public void setSettings(Settings settings) public String build() { - String output = ""; + StringBuilder output = new StringBuilder(); Util util = new Util(); - output += - "\n" + - "\n" + - " \n" + - " MockMock - SMTP Mock Server version " + AppStarter.VERSION_NUMBER + "\n"; - + output.append("\n" + "\n" + " \n" + " MockMock - SMTP Mock Server version " + AppStarter.VERSION_NUMBER + "\n"); if(settings.getStaticFolderPath() != null) { - output += - " \n" + - " \n"; + output.append(" \n") + .append(" \n"); } else { - output += - " \n"; + output.append(" \n"); } - output += - " \n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " MockMock\n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + - "
\n"; - - return output; + output.append(" \n") + .append(" \n") + .append("
\n") + .append("
\n") + .append("
\n") + .append(" \n") + .append(" \n") + .append(" \n") + .append(" \n") + .append(" MockMock\n") + .append("
\n") + .append(" \n") + .append("
\n") + .append("
\n") + .append("
\n") + .append("
\n"); + + return output.toString(); } } diff --git a/src/main/java/com/mockmock/htmlbuilder/HtmlBuilder.java b/src/main/java/com/mockmock/htmlbuilder/HtmlBuilder.java index 7c99841..66057f6 100644 --- a/src/main/java/com/mockmock/htmlbuilder/HtmlBuilder.java +++ b/src/main/java/com/mockmock/htmlbuilder/HtmlBuilder.java @@ -6,5 +6,5 @@ public interface HtmlBuilder * Returns the created html as a String * @return String */ - public String build(); + String build(); } diff --git a/src/main/java/com/mockmock/htmlbuilder/MailListHtmlBuilder.java b/src/main/java/com/mockmock/htmlbuilder/MailListHtmlBuilder.java index cd487f3..e2e7194 100644 --- a/src/main/java/com/mockmock/htmlbuilder/MailListHtmlBuilder.java +++ b/src/main/java/com/mockmock/htmlbuilder/MailListHtmlBuilder.java @@ -19,36 +19,36 @@ public void setMailQueue(ArrayList mailQueue) public String build() { - String output = - "
\n"; + StringBuilder output = + new StringBuilder("
\n"); - if(mailQueue == null || mailQueue.size() == 0) + if(mailQueue == null || mailQueue.isEmpty()) { - output += "

No emails in queue

\n"; + output.append("

No emails in queue

\n"); } else { String mailText = mailQueue.size() == 1 ? "email" : "emails"; - output += "

You have " + mailQueue.size() + " " + mailText + "! Delete all

\n"; - output += " \n"; - output += " \n"; - output += " \n"; - output += " \n"; - output += " \n"; - output += " \n"; - output += " \n"; - output += " \n"; + output.append("

You have ").append(mailQueue.size()).append(" ").append(mailText).append("! Delete all

\n"); + output.append("
FromToSubjectAction
\n"); + output.append(" \n"); + output.append(" \n"); + output.append(" \n"); + output.append(" \n"); + output.append(" \n"); + output.append(" \n"); + output.append(" \n"); for (MockMail mail : mailQueue) { - output += buildMailRow(mail); + output.append(buildMailRow(mail)); } - output += " \n"; - output += "
FromToSubjectAction
\n"; + output.append(" \n"); + output.append(" \n"); } - output += "
\n"; + output.append("
\n"); - return output; + return output.toString(); } private String buildMailRow(MockMail mail) diff --git a/src/main/java/com/mockmock/htmlbuilder/MailViewHeadersHtmlBuilder.java b/src/main/java/com/mockmock/htmlbuilder/MailViewHeadersHtmlBuilder.java index 43b29bb..9d270f1 100644 --- a/src/main/java/com/mockmock/htmlbuilder/MailViewHeadersHtmlBuilder.java +++ b/src/main/java/com/mockmock/htmlbuilder/MailViewHeadersHtmlBuilder.java @@ -14,21 +14,21 @@ public class MailViewHeadersHtmlBuilder implements HtmlBuilder public String build() { - String output = ""; + StringBuilder output = new StringBuilder(); if(mockMail != null) { MimeMessage mimeMessage = mockMail.getMimeMessage(); try { - output += "
\n";
-                Enumeration headers = mimeMessage.getAllHeaderLines();
+                output.append("
\n");
+                Enumeration headers = mimeMessage.getAllHeaderLines();
                 while (headers.hasMoreElements())
                 {
                     String header = (String) headers.nextElement();
-                    output += header + "
"; + output.append(header).append("
"); } - output += "
"; + output.append("
"); } catch (MessagingException e) { @@ -36,7 +36,7 @@ public String build() } } - return output; + return output.toString(); } public void setMockMail(MockMail mockMail) diff --git a/src/main/java/com/mockmock/htmlbuilder/MailViewHtmlBuilder.java b/src/main/java/com/mockmock/htmlbuilder/MailViewHtmlBuilder.java index 12915ef..9e9c3d8 100644 --- a/src/main/java/com/mockmock/htmlbuilder/MailViewHtmlBuilder.java +++ b/src/main/java/com/mockmock/htmlbuilder/MailViewHtmlBuilder.java @@ -36,68 +36,67 @@ public String build() subjectOutput += " Delete"; - String output = "
\n"; - - output += - "

" + subjectOutput + "

\n" + - "
\n"; - - output += - "
\n" + - "

Addresses

\n" + - " " + addressesHtmlBuilder.build() + - "
\n"; - - output += - "
\n" + - "

Mail headers

\n" + - " " + headersBuilder.build() + - "
\n"; + StringBuilder output = new StringBuilder("
\n"); + + output.append("

") + .append(subjectOutput) + .append("

\n") + .append("
\n") + .append("
\n") + .append("

Addresses

\n") + .append(" ") + .append(addressesHtmlBuilder.build()) + .append("
\n") + .append("
\n") + .append("

Mail headers

\n") + .append(" ") + .append(headersBuilder.build()) + .append("
\n"); if(mockMail.getBody() != null) { - output += - "
\n" + - "

Plain text body

\n" + - "
" + StringEscapeUtils.escapeHtml(mockMail.getBody()) + "
\n" + - "
\n"; + output.append("
\n") + .append("

Plain text body

\n") + .append("
") + .append(StringEscapeUtils.escapeHtml(mockMail.getBody())) + .append("
\n") + .append("
\n"); } if(mockMail.getBodyHtml() != null) { - output += - "
\n" + - "

HTML body unformatted

\n" + - "
" + StringEscapeUtils.escapeHtml(mockMail.getBodyHtml()) + "
\n" + - "
\n"; + output.append("
\n") + .append("

HTML body unformatted

\n") + .append("
") + .append(StringEscapeUtils.escapeHtml(mockMail.getBodyHtml())) + .append("
\n") + .append("
\n"); // also show a parsed version via an iframe - output += - "
\n" + - "

HTML body formatted

\n" + - " \n" + - "
"; + output.append("
\n" + "

HTML body formatted

\n") + .append(" \n") + .append("
"); } // just output the raw mail so we're sure everything is on the screen if(mockMail.getRawMail() != null) { // output complete raw mail - output += - "
\n" + - "

Complete raw mail output

\n" + - "
" + StringEscapeUtils.escapeHtml(mockMail.getRawMail()) + "
\n" + - "
\n"; + output.append("
\n") + .append("

Complete raw mail output

\n") + .append("
") + .append(StringEscapeUtils.escapeHtml(mockMail.getRawMail())) + .append("
\n") + .append("
\n"); } - output += - "
\n"; - - output += - "
\n"; + output.append("
\n") + .append("
\n"); - return output; + return output.toString(); } @Autowired @@ -109,4 +108,4 @@ public void setMailViewHeadersHtmlBuilder(MailViewHeadersHtmlBuilder mailViewHea public void setAddressesHtmlBuilder(AddressesHtmlBuilder addressesHtmlBuilder) { this.addressesHtmlBuilder = addressesHtmlBuilder; } -} \ No newline at end of file +} diff --git a/src/main/java/com/mockmock/htmlbuilder/StringFromHtmlBuilder.java b/src/main/java/com/mockmock/htmlbuilder/StringFromHtmlBuilder.java index adea7e7..b92b249 100644 --- a/src/main/java/com/mockmock/htmlbuilder/StringFromHtmlBuilder.java +++ b/src/main/java/com/mockmock/htmlbuilder/StringFromHtmlBuilder.java @@ -13,12 +13,12 @@ public class StringFromHtmlBuilder implements HtmlBuilder public String build() { - String output = ""; + StringBuilder output = new StringBuilder(); MimeMessage mimeMessage = mockMail.getMimeMessage(); if(mimeMessage == null) { - return output; + return output.toString(); } try @@ -29,10 +29,10 @@ public String build() int i = 1; for(Address address : addresses) { - output += StringEscapeUtils.escapeHtml(address.toString()); + output.append(StringEscapeUtils.escapeHtml(address.toString())); if(addresses.length != i) { - output += ", "; + output.append(", "); } i++; @@ -40,7 +40,7 @@ public String build() } else { - output += StringEscapeUtils.escapeHtml(mockMail.getFrom()); + output.append(StringEscapeUtils.escapeHtml(mockMail.getFrom())); } } catch (MessagingException e) @@ -48,7 +48,7 @@ public String build() e.printStackTrace(); } - return output; + return output.toString(); } public void setMockMail(MockMail mockMail) diff --git a/src/main/java/com/mockmock/htmlbuilder/StringRecipientHtmlBuilder.java b/src/main/java/com/mockmock/htmlbuilder/StringRecipientHtmlBuilder.java index 9deb0da..41db72a 100644 --- a/src/main/java/com/mockmock/htmlbuilder/StringRecipientHtmlBuilder.java +++ b/src/main/java/com/mockmock/htmlbuilder/StringRecipientHtmlBuilder.java @@ -16,12 +16,12 @@ public class StringRecipientHtmlBuilder implements HtmlBuilder public String build() { - String output = ""; + StringBuilder output = new StringBuilder(); MimeMessage mimeMessage = mockMail.getMimeMessage(); if(mimeMessage == null) { - return output; + return output.toString(); } try @@ -48,10 +48,10 @@ public String build() int i = 1; for(Address address : addresses) { - output += StringEscapeUtils.escapeHtml(address.toString()); + output.append(StringEscapeUtils.escapeHtml(address.toString())); if(addresses.length != i) { - output += ", "; + output.append(", "); } i++; @@ -69,7 +69,7 @@ public String build() } else { - shortName = output; + shortName = output.toString(); } return "" + shortName + ""; diff --git a/src/main/java/com/mockmock/mail/MailQueue.java b/src/main/java/com/mockmock/mail/MailQueue.java index 43ff309..46e2bed 100644 --- a/src/main/java/com/mockmock/mail/MailQueue.java +++ b/src/main/java/com/mockmock/mail/MailQueue.java @@ -1,7 +1,6 @@ package com.mockmock.mail; import com.google.common.eventbus.Subscribe; -import com.mockmock.AppStarter; import com.mockmock.Settings; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -41,7 +40,7 @@ public ArrayList getMailQueue() /** * Returns the MockMail that belongs to the given ID - * @param id The id of the mail mail that needs to be retrieved + * @param id The id of the mail that needs to be retrieved * @return Returns the MockMail when found or null otherwise */ public MockMail getById(long id) diff --git a/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java b/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java index e45ee0f..943d67b 100644 --- a/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java +++ b/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java @@ -21,7 +21,7 @@ @Service public class MockMockMessageHandlerFactory implements MessageHandlerFactory { - private EventBus eventBus; + private final EventBus eventBus; private Settings settings; @Autowired @@ -51,7 +51,7 @@ class MockMockHandler implements MessageHandler * Constructor * @param context MessageContext */ - public MockMockHandler(MessageContext context) + MockMockHandler(MessageContext context) { this.context = context; this.mockMail = new MockMail(); @@ -61,9 +61,9 @@ public MockMockHandler(MessageContext context) } /** - * Called first, after the MAIL FROM during a SMTP exchange. - * @param from String - * @throws RejectException + * Called first, after the MAIL FROM during an SMTP exchange. + * @param from the email sender + * @throws RejectException never */ @Override public void from(String from) throws RejectException @@ -81,10 +81,10 @@ public void from(String from) throws RejectException } /** - * Called once for every RCPT TO during a SMTP exchange. + * Called once for every RCPT TO during an SMTP exchange. * This will occur after a from() call. - * @param recipient String - * @throws RejectException + * @param recipient the email recipient + * @throws RejectException never */ @Override public void recipient(String recipient) throws RejectException @@ -100,8 +100,8 @@ public void recipient(String recipient) throws RejectException /** * Called when the DATA part of the SMTP exchange begins. * @param data InputStream - * @throws RejectException - * @throws IOException + * @throws RejectException never + * @throws IOException if there is a problem getting the message contents */ @Override public void data(InputStream data) throws RejectException, IOException diff --git a/src/main/java/com/mockmock/server/HttpServer.java b/src/main/java/com/mockmock/server/HttpServer.java index 6738ee8..9c8cb5f 100644 --- a/src/main/java/com/mockmock/server/HttpServer.java +++ b/src/main/java/com/mockmock/server/HttpServer.java @@ -33,7 +33,7 @@ public void start() { Server http = new Server(port); - // get the path to the "static" folder. If it doesn't exists, check if it's in the folder of the file being executed. + // get the path to the "static" folder. If it doesn't exist, check if it's in the folder of the file being executed. String path = "./static"; if(settings.getStaticFolderPath() != null) { diff --git a/src/main/java/com/mockmock/server/Server.java b/src/main/java/com/mockmock/server/Server.java index 3525f95..22176b5 100644 --- a/src/main/java/com/mockmock/server/Server.java +++ b/src/main/java/com/mockmock/server/Server.java @@ -5,6 +5,6 @@ */ public interface Server { - public void setPort(int port); - public void start(); + void setPort(int port); + void start(); } diff --git a/src/test/java/com/mockmock/console/ParserTest.java b/src/test/java/com/mockmock/console/ParserTest.java new file mode 100644 index 0000000..b653f71 --- /dev/null +++ b/src/test/java/com/mockmock/console/ParserTest.java @@ -0,0 +1,226 @@ +package com.mockmock.console; + +import com.mockmock.Settings; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.security.Permission; + +import static org.junit.Assert.*; + +public class ParserTest { + + private static final String EMAIL_LIST_1VALUE = "example@example.com"; + private static final String EMAIL_LIST_2VALUES = EMAIL_LIST_1VALUE + ",nobody@example.com"; + private Parser service; + private Settings settings; + + private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + private final ByteArrayOutputStream errContent = new ByteArrayOutputStream(); + private final PrintStream originalOut = System.out; + private final PrintStream originalErr = System.err; + + @Before + public void setUp() { + service = new Parser(); + settings = new Settings(); + System.setOut(new PrintStream(outContent)); + System.setErr(new PrintStream(errContent)); + System.setSecurityManager(new NoExitSecurityManager()); + } + + @After + public void tearDown() { + System.setOut(originalOut); + System.setErr(originalErr); + System.setSecurityManager(null); // restore security manager + } + + /** + * Writes the std or err output if a test is failed. + * This lets us see any error messages. + */ + @Rule(order = Integer.MIN_VALUE) + public TestWatcher watchman = new TestWatcher() { + @Override + protected void failed(Throwable e, Description description) { + if(outContent.size() != 0) { + originalOut.println("Standard Output:"); + originalOut.print(outContent); + originalOut.println("----------"); + } + if(errContent.size() != 0) { + originalErr.println("Error Output:"); + originalErr.print(errContent); + originalErr.println("----------"); + } + } + }; + + /** + * An {@link Exception} to catch a System.exit() call + */ + protected static class ExitException extends SecurityException + { + public final int status; + public ExitException(int status) + { + super("There is no escape!"); + this.status = status; + } + } + + /** + * A SecurityManager set up to catch a call to System.exit() and throw an {@link ExitException} instead. + */ + private static class NoExitSecurityManager extends SecurityManager + { + @Override + public void checkPermission(Permission perm) + { + // allow anything. + } + @Override + public void checkPermission(Permission perm, Object context) + { + // allow anything. + } + @Override + public void checkExit(int status) + { + super.checkExit(status); + throw new ExitException(status); + } + } + + @Test + public void parseOption_help() { + try { + service.parseOptions(new String[]{"-?"}, settings); + } catch (ExitException e) + { + assertEquals("Exit status", 0, e.status); + } + assertTrue(outContent.toString().contains("java -jar")); + assertTrue(errContent.toString().isEmpty()); + } + + @Test + public void parseOption_valid_P() { + Settings actual = service.parseOptions(new String[]{"-p32"}, settings); + assertEquals(settings, actual); + assertEquals(32, actual.getSmtpPort()); + assertTrue(errContent.toString().isEmpty()); + } + + @Test + public void parseOption_invalid_P() { + int defaultSmtpPort = settings.getSmtpPort(); + Settings actual = service.parseOptions(new String[]{"-pa"}, settings); + assertTrue(errContent.toString().contains("Invalid mail port given")); + assertEquals(defaultSmtpPort, actual.getSmtpPort()); + } + + @Test + public void parseOption_valid_H() { + Settings actual = service.parseOptions(new String[]{"-h32"}, settings); + assertEquals(32, actual.getHttpPort()); + assertTrue(errContent.toString().isEmpty()); + } + + @Test + public void parseOption_invalid_H() { + int defaultHttpPort = settings.getHttpPort(); + Settings actual = service.parseOptions(new String[]{"-ha"}, settings); + assertTrue(errContent.toString().contains("Invalid http port given")); + assertEquals(defaultHttpPort, actual.getHttpPort()); + } + + @Test + public void parseOption_valid_M() { + Settings actual = service.parseOptions(new String[]{"-m32"}, settings); + assertEquals(32, actual.getMaxMailQueueSize()); + assertTrue(errContent.toString().isEmpty()); + } + + @Test + public void parseOption_invalid_M() { + int defaultMaxMailQueueSize = settings.getMaxMailQueueSize(); + Settings actual = service.parseOptions(new String[]{"-ma"}, settings); + assertTrue(errContent.toString().contains("Invalid max mail queue size given")); + assertEquals(defaultMaxMailQueueSize, actual.getMaxMailQueueSize()); + } + + @Test + public void parseOption_valid_showEmail() { + assertFalse(settings.getShowEmailInConsole()); + Settings actual = service.parseOptions(new String[]{"-ec"}, settings); + assertTrue(actual.getShowEmailInConsole()); + assertTrue(errContent.toString().isEmpty()); + } + + @Test + public void parseOption_valid_filterFrom_1long() { + Settings actual = service.parseOptions(new String[]{"--filter-from=" + EMAIL_LIST_1VALUE}, settings); + assertEquals(1, actual.getFilterFromEmailAddresses().size()); + assertTrue(actual.getFilterFromEmailAddresses().contains(EMAIL_LIST_1VALUE)); + } + + @Test + public void parseOption_valid_filterFrom_2long() { + Settings actual = service.parseOptions(new String[]{"--filter-from=" + EMAIL_LIST_2VALUES}, settings); + assertEquals(2, actual.getFilterFromEmailAddresses().size()); + for(String email : EMAIL_LIST_2VALUES.split(",")) { + assertTrue(actual.getFilterFromEmailAddresses().contains(email)); + } + } + + @Test + public void parseOption_valid_filterFrom_1short() { + Settings actual = service.parseOptions(new String[]{"-f" + EMAIL_LIST_1VALUE}, settings); + assertEquals(1, actual.getFilterFromEmailAddresses().size()); + assertTrue(actual.getFilterFromEmailAddresses().contains(EMAIL_LIST_1VALUE)); + } + + @Test + public void parseOption_valid_filterFrom_2short() { + Settings actual = service.parseOptions(new String[]{"-f" + EMAIL_LIST_2VALUES}, settings); + assertEquals(2, actual.getFilterFromEmailAddresses().size()); + } + + @Test + public void parseOption_valid_filterTo_1long() { + Settings actual = service.parseOptions(new String[]{"--filter-to=" + EMAIL_LIST_1VALUE}, settings); + assertEquals(1, actual.getFilterToEmailAddresses().size()); + assertTrue(actual.getFilterToEmailAddresses().contains(EMAIL_LIST_1VALUE)); + } + + @Test + public void parseOption_valid_filterTo_2long() { + Settings actual = service.parseOptions(new String[]{"--filter-to=" + EMAIL_LIST_2VALUES}, settings); + assertEquals(2, actual.getFilterToEmailAddresses().size()); + for(String email : EMAIL_LIST_2VALUES.split(",")) { + assertTrue(actual.getFilterToEmailAddresses().contains(email)); + } + } + + @Test + public void parseOption_valid_filterTo_1short() { + Settings actual = service.parseOptions(new String[]{"-t" + EMAIL_LIST_1VALUE}, settings); + assertEquals(1, actual.getFilterToEmailAddresses().size()); + assertTrue(actual.getFilterToEmailAddresses().contains(EMAIL_LIST_1VALUE)); + } + + @Test + public void parseOption_valid_filterTo_2short() { + Settings actual = service.parseOptions(new String[]{"-t" + EMAIL_LIST_2VALUES}, settings); + assertEquals(2, actual.getFilterToEmailAddresses().size()); + } + +} diff --git a/src/test/java/com/mockmock/http/DeleteHandlerTest.java b/src/test/java/com/mockmock/http/DeleteHandlerTest.java new file mode 100644 index 0000000..f5e99ae --- /dev/null +++ b/src/test/java/com/mockmock/http/DeleteHandlerTest.java @@ -0,0 +1,51 @@ +package com.mockmock.http; + +import com.mockmock.mail.MailQueue; +import org.eclipse.jetty.server.Request; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +import static org.mockito.Mockito.*; + +@RunWith(MockitoJUnitRunner.class) +public class DeleteHandlerTest { + + private DeleteHandler handler; + + @Mock + MailQueue queue; + @Mock + Request request; + @Mock + HttpServletRequest httpServletRequest; + @Mock + HttpServletResponse httpServletResponse; + + @Before + public void setUp() { + handler = new DeleteHandler(); + handler.setMailQueue(queue); + } + + @Test + public void handle_delete_all() throws ServletException, IOException { + doNothing().when(queue).emptyQueue(); + handler.handle("/mail/delete/all", request, httpServletRequest, httpServletResponse); + verify(queue, times(1)).emptyQueue(); + } + + @Test + public void handle_delete_nothing() throws ServletException, IOException { + handler.handle("/mail/delete/nothing", request, httpServletRequest, httpServletResponse); + verify(queue, times(0)).emptyQueue(); + } + +} diff --git a/src/test/java/com/mockmock/http/IndexHandlerTest.java b/src/test/java/com/mockmock/http/IndexHandlerTest.java new file mode 100644 index 0000000..0c43c57 --- /dev/null +++ b/src/test/java/com/mockmock/http/IndexHandlerTest.java @@ -0,0 +1,63 @@ +package com.mockmock.http; + +import com.mockmock.htmlbuilder.FooterHtmlBuilder; +import com.mockmock.htmlbuilder.HeaderHtmlBuilder; +import com.mockmock.htmlbuilder.MailListHtmlBuilder; +import com.mockmock.mail.MailQueue; +import org.eclipse.jetty.server.Request; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; + +import static org.mockito.Mockito.*; + +@RunWith(MockitoJUnitRunner.class) +public class IndexHandlerTest { + + IndexHandler handler; + @Mock private MailQueue queue; + @Mock private FooterHtmlBuilder footerHtmlBuilder; + @Mock private HeaderHtmlBuilder headerHtmlBuilder; + @Mock private MailListHtmlBuilder mailListHtmlBuilder; + @Mock private Request request; + @Mock private HttpServletRequest httpServletRequest; + @Mock private HttpServletResponse httpServletResponse; + + @Before + public void setUp() { + handler = new IndexHandler(); + handler.setMailQueue(queue); + handler.setHeaderHtmlBuilder(headerHtmlBuilder); + handler.setFooterHtmlBuilder(footerHtmlBuilder); + handler.setMailListHtmlBuilder(mailListHtmlBuilder); + } + + @Test + public void handle_notIndex() throws ServletException, IOException { + handler.handle("/test", request, httpServletRequest, httpServletResponse); + verify(headerHtmlBuilder, times(0)).build(); + verify(mailListHtmlBuilder, times(0)).build(); + verify(footerHtmlBuilder, times(0)).build(); + verify(httpServletResponse, times(0)).setStatus(200); + } + + @Test + public void handle_index() throws ServletException, IOException { + when(httpServletResponse.getWriter()).thenReturn(new PrintWriter(new StringWriter())); + handler.handle("/", request, httpServletRequest, httpServletResponse); + verify(headerHtmlBuilder, times(1)).build(); + verify(mailListHtmlBuilder, times(1)).build(); + verify(footerHtmlBuilder, times(1)).build(); + verify(httpServletResponse, times(1)).setStatus(200); + } + +}