From 6c697e77dfb826e68493f871534f8c24598897dd Mon Sep 17 00:00:00 2001 From: Marcel May Date: Thu, 29 Sep 2016 22:28:18 +0200 Subject: [PATCH 01/16] Post release 1.5.2 doc updates --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4d23756bbd..1e9a2dbab2 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Go to the [project site][greenmail_project_site] for details: * [JavaDoc][greenmail_javadoc] * [FAQ][greenmail_faq] * [Download][greenmail_download] -* [Maven coordinates][maven_repository_com]: com.icegreen:greenmail:1.5.1 +* [Maven coordinates][maven_repository_com]: com.icegreen:greenmail:1.5.2 The GreenMail project welcomes any contribution, so go ahead and fork/open a pull request! See the guidelines below. From 4951eed6df306581edbb944989e04bbb5ca03b3b Mon Sep 17 00:00:00 2001 From: Marcel May Date: Sun, 20 Nov 2016 08:26:40 +0100 Subject: [PATCH 02/16] Issue #168 : waitForIncomingEmail and CC/BCC Added SmtpServerTest.testSendAndWaitForIncomingMailsInBcc test --- .../greenmail/test/SmtpServerTest.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/greenmail-core/src/test/java/com/icegreen/greenmail/test/SmtpServerTest.java b/greenmail-core/src/test/java/com/icegreen/greenmail/test/SmtpServerTest.java index 8a4b89f556..4cf173952f 100644 --- a/greenmail-core/src/test/java/com/icegreen/greenmail/test/SmtpServerTest.java +++ b/greenmail-core/src/test/java/com/icegreen/greenmail/test/SmtpServerTest.java @@ -18,6 +18,7 @@ import javax.mail.internet.MimeMultipart; import java.io.ByteArrayOutputStream; +import static com.icegreen.greenmail.util.GreenMailUtil.createTextEmail; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -138,4 +139,21 @@ public void testSmtpServerLeadingPeriods() throws MessagingException { assertEquals("subject", emails[0].getSubject()); assertEquals(body, GreenMailUtil.getBody(emails[0])); } + + @Test + public void testSendAndWaitForIncomingMailsInBcc() throws Throwable { + String subject = GreenMailUtil.random(); + String body = GreenMailUtil.random(); + final MimeMessage message = createTextEmail("test@localhost", "from@localhost", subject, body, greenMail.getSmtp().getServerSetup()); + message.addRecipients(Message.RecipientType.BCC, "bcc1@localhost,bcc2@localhost"); + + assertEquals(0, greenMail.getReceivedMessages().length); + + GreenMailUtil.sendMimeMessage(message); + + assertTrue(greenMail.waitForIncomingEmail(1500, 3)); + + MimeMessage[] emails = greenMail.getReceivedMessages(); + assertEquals(3, emails.length); + } } From 7f9a282cb72f2568eae6910ef2ecf595837e2f2d Mon Sep 17 00:00:00 2001 From: Marcel May Date: Mon, 28 Nov 2016 07:19:25 +0100 Subject: [PATCH 03/16] Fixes ##169 : Switch docker base image from java:jdk7 to openjdk:7-jdk-alpine - Updates docker-maven-plugin from 0.16.3 to 0.16.9 - Enabled auto pulling for docker-maven-plugin, for missing images --- greenmail-docker/standalone/Dockerfile | 4 ++-- greenmail-docker/standalone/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/greenmail-docker/standalone/Dockerfile b/greenmail-docker/standalone/Dockerfile index 089b36d725..c8b947e379 100644 --- a/greenmail-docker/standalone/Dockerfile +++ b/greenmail-docker/standalone/Dockerfile @@ -1,4 +1,4 @@ -FROM java:7 +FROM openjdk:7-jdk-alpine MAINTAINER https://github.com/greenmail-mail-test/greenmail (marcel.may.de@gmail.com) # Expose ports: @@ -11,7 +11,7 @@ MAINTAINER https://github.com/greenmail-mail-test/greenmail (marcel.may.de@gmail EXPOSE 3025 3465 3110 3995 3143 3993 # Run as user greenmail -RUN addgroup greenmail && useradd -g greenmail -m greenmail +RUN addgroup greenmail && adduser -G greenmail -D greenmail # Note: If using Dockerfile without Maven, you must manually copy the JAR ADD target/greenmail-standalone.jar /home/greenmail/greenmail-standalone.jar RUN chown greenmail:greenmail /home/greenmail/greenmail-standalone.jar diff --git a/greenmail-docker/standalone/pom.xml b/greenmail-docker/standalone/pom.xml index f8b6bc5bac..9660964976 100644 --- a/greenmail-docker/standalone/pom.xml +++ b/greenmail-docker/standalone/pom.xml @@ -56,7 +56,7 @@ io.fabric8 docker-maven-plugin - false + true true diff --git a/pom.xml b/pom.xml index f41a55021c..e6c6581251 100644 --- a/pom.xml +++ b/pom.xml @@ -193,7 +193,7 @@ io.fabric8 docker-maven-plugin - 0.16.3 + 0.16.9 From aebec142f3216368df3d83d37802e3ae3b1770a4 Mon Sep 17 00:00:00 2001 From: ecrisostomo Date: Mon, 26 Dec 2016 21:55:21 -0400 Subject: [PATCH 04/16] Issue 170 (#171) * Issue 170: Loosening email validation rules to support non ascii utf8 characters on emails. --- .../icegreen/greenmail/mail/MailAddress.java | 39 +++++- .../SendReceiveWithInternationalAddress.java | 127 ++++++++++++++++++ 2 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 greenmail-core/src/test/java/com/icegreen/greenmail/test/SendReceiveWithInternationalAddress.java diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/mail/MailAddress.java b/greenmail-core/src/main/java/com/icegreen/greenmail/mail/MailAddress.java index 0fab545f6a..6a836d30a7 100644 --- a/greenmail-core/src/main/java/com/icegreen/greenmail/mail/MailAddress.java +++ b/greenmail-core/src/main/java/com/icegreen/greenmail/mail/MailAddress.java @@ -8,6 +8,9 @@ import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeUtility; +import java.io.UnsupportedEncodingException; +import java.util.regex.Pattern; public class MailAddress { String host; @@ -15,9 +18,18 @@ public class MailAddress { String email; String name; + static final Pattern RFC6531_VALIDATION_PATTERN = Pattern.compile("[^\\s@]+@[^\\s@]+\\.[^\\s@]+"); + public MailAddress(String str) throws AddressException { - InternetAddress address = new InternetAddress(str); + + // Decoding the mail address in + // case it contains non us-ascii characters + String decoded = decodeStr(str); + + assertValidEmailAddress(decoded); + InternetAddress address = new InternetAddress(); + address.setAddress(decoded); email = address.getAddress(); name = address.getPersonal(); @@ -51,4 +63,29 @@ public String getEmail() { return email; } + private void assertValidEmailAddress(String str) { + + if (str == null || !RFC6531_VALIDATION_PATTERN.matcher(str).matches()) { + new AddressException("Invalid email address!"); + } + } + + /** + * Returns the decoded string, in case it contains non us-ascii characters. + * Returns the same string if it doesn't or the passed value in case + * of an UnsupportedEncodingException. + * + * @param str string to be decoded + * @return the decoded string, in case it contains non us-ascii characters; + * or the same string if it doesn't or the passed value in case + * of an UnsupportedEncodingException. + */ + private String decodeStr(String str) { + + try { + return MimeUtility.decodeText(str); + } catch (UnsupportedEncodingException e) { + return str; + } + } } \ No newline at end of file diff --git a/greenmail-core/src/test/java/com/icegreen/greenmail/test/SendReceiveWithInternationalAddress.java b/greenmail-core/src/test/java/com/icegreen/greenmail/test/SendReceiveWithInternationalAddress.java new file mode 100644 index 0000000000..c1399bec3b --- /dev/null +++ b/greenmail-core/src/test/java/com/icegreen/greenmail/test/SendReceiveWithInternationalAddress.java @@ -0,0 +1,127 @@ +package com.icegreen.greenmail.test; + +import com.icegreen.greenmail.junit.GreenMailRule; +import com.icegreen.greenmail.util.GreenMailUtil; +import com.icegreen.greenmail.util.ServerSetupTest; +import org.junit.Rule; +import org.junit.Test; + +import javax.mail.Message; +import javax.mail.MessagingException; +import javax.mail.Session; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeUtility; + +import java.io.UnsupportedEncodingException; +import java.util.Date; +import java.util.Properties; + +import static org.junit.Assert.assertEquals; + +public class SendReceiveWithInternationalAddress { + + static final Properties properties; + + static { + + properties = new Properties(); + properties.put("mail.mime.address.strict", Boolean.FALSE.toString()); + } + + @Rule + public final GreenMailRule greenMail = new GreenMailRule(ServerSetupTest.SMTP_IMAP); + + @Test + public void testSend() throws MessagingException, UnsupportedEncodingException { + + Session session = GreenMailUtil.getSession(ServerSetupTest.SMTP, properties); + MimeMessage mimeMessage = new MockInternationalizedMimeMessage(session); + mimeMessage.setSubject("subject"); + mimeMessage.setSentDate(new Date()); + mimeMessage.setFrom("múchätįldé@tìldę.oœ"); + mimeMessage.setRecipients(Message.RecipientType.TO, "用户@例子.广告"); + mimeMessage.setRecipients(Message.RecipientType.CC, "θσερεχα@μπλε.ψομ"); + mimeMessage.setRecipients(Message.RecipientType.BCC, "राममो@हन.ईन्फो"); + + // The body text needs to be encoded if it contains non us-ascii characters + mimeMessage.setText(MimeUtility.encodeText("用户@例子")); + + GreenMailUtil.sendMimeMessage(mimeMessage); + + // Decoding the body text to verify equality + String decodedText = MimeUtility.decodeText(GreenMailUtil.getBody(greenMail.getReceivedMessages()[0])); + assertEquals("用户@例子", decodedText); + } + + // This is a mock message that doesn't implement the full functionality from MimeMessage. + // This is only to illustrate the changes needed to make the test work. + private static class MockInternationalizedMimeMessage extends MimeMessage { + + public MockInternationalizedMimeMessage(Session session) { + super(session); + } + + // Current Java Mail version does not respect the "mail.mime.address.strict" + // value when setting email addresses in a MimeMessage object (calls + // InternetAddress.parse(String), which will always validate the + // address based on rfc822) so we need to override this method to + // make this example work. + @Override + public void setRecipients(Message.RecipientType type, String addresses) throws MessagingException { + + InternetAddress address = new InternetAddress(); + address.setAddress(addresses); + setAddressHeader(getHeaderName(type), new InternetAddress[]{address}); + } + + // Current Java Mail version does not respect the "mail.mime.address.strict" + // value when setting email addresses in a MimeMessage object (calls + // InternetAddress.parse(String), which will always validate the + // address based on rfc822) so we need to override this method to + // make this example work. + @Override + public void setFrom(String address) throws MessagingException { + + InternetAddress internetAddress = new InternetAddress(); + internetAddress.setAddress(address); + setAddressHeader("From", new InternetAddress[]{internetAddress}); + } + + // Convenience method to set addresses + private void setAddressHeader(String name, InternetAddress[] addresses) + throws MessagingException { + + try { + + // Encoding the email addresses so they are correctly sent to the mail server. + for (int i = 0; i < addresses.length; i++) { + String addStr = MimeUtility.encodeText(addresses[i].getAddress()); + InternetAddress ia = new InternetAddress(); + ia.setAddress(addStr); + addresses[i] = ia; + } + + String s = InternetAddress.toString(addresses, name.length() + 2); + setHeader(name, s); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + private String getHeaderName(Message.RecipientType type) + throws MessagingException { + String headerName; + + if (type == Message.RecipientType.TO) + headerName = "To"; + else if (type == Message.RecipientType.CC) + headerName = "Cc"; + else if (type == Message.RecipientType.BCC) + headerName = "Bcc"; + else + throw new MessagingException("Invalid Recipient Type"); + return headerName; + } + } +} From 69a3ff4ce8b70ee80106a439c20c3946ee53c987 Mon Sep 17 00:00:00 2001 From: Marcel May Date: Mon, 2 Jan 2017 16:43:53 +0100 Subject: [PATCH 05/16] Spelling and javadoc fix --- .../main/java/com/icegreen/greenmail/util/ServerSetup.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/util/ServerSetup.java b/greenmail-core/src/main/java/com/icegreen/greenmail/util/ServerSetup.java index 14e483645b..5484c91ef1 100644 --- a/greenmail-core/src/main/java/com/icegreen/greenmail/util/ServerSetup.java +++ b/greenmail-core/src/main/java/com/icegreen/greenmail/util/ServerSetup.java @@ -168,6 +168,8 @@ public void setServerStartupTimeout(long timeoutInMs) { *
  • https://javamail.java.net/nonav/docs/api/com/sun/mail/pop3/package-summary.html for valid POP3 properties.
  • * Date: Mon, 2 Jan 2017 16:53:16 +0100 Subject: [PATCH 06/16] Fixes #173 : Use script as entrypoint for GreenMail standalone docker image - Also adds host as 0.0.0.0 for docker exposed port check for docker maven plugin. Localhost would be nicer, but seems not possible with Docker.app at the moment. --- greenmail-docker/standalone/Dockerfile | 11 ++++------- greenmail-docker/standalone/pom.xml | 1 + greenmail-docker/standalone/run_greenmail.sh | 7 +++++++ 3 files changed, 12 insertions(+), 7 deletions(-) create mode 100644 greenmail-docker/standalone/run_greenmail.sh diff --git a/greenmail-docker/standalone/Dockerfile b/greenmail-docker/standalone/Dockerfile index c8b947e379..6ce73fa70e 100644 --- a/greenmail-docker/standalone/Dockerfile +++ b/greenmail-docker/standalone/Dockerfile @@ -14,13 +14,10 @@ EXPOSE 3025 3465 3110 3995 3143 3993 RUN addgroup greenmail && adduser -G greenmail -D greenmail # Note: If using Dockerfile without Maven, you must manually copy the JAR ADD target/greenmail-standalone.jar /home/greenmail/greenmail-standalone.jar -RUN chown greenmail:greenmail /home/greenmail/greenmail-standalone.jar +ADD run_greenmail.sh /home/greenmail/run_greenmail.sh +RUN chown greenmail:greenmail /home/greenmail/greenmail-standalone.jar /home/greenmail/run_greenmail.sh && \ + chmod +x /home/greenmail/run_greenmail.sh USER greenmail WORKDIR /home/greenmail # Run GreenMail Standalone with test setup and disabled authentication -ENTRYPOINT ["java", \ - "-Djava.net.preferIPv4Stack=true", \ - "-Dgreenmail.setup.test.all", \ - "-Dgreenmail.hostname=0.0.0.0", \ - "-Dgreenmail.auth.disabled", \ - "-jar", "greenmail-standalone.jar"] +ENTRYPOINT ["/bin/sh", "-c", "/home/greenmail/run_greenmail.sh"] diff --git a/greenmail-docker/standalone/pom.xml b/greenmail-docker/standalone/pom.xml index 9660964976..761bbd027e 100644 --- a/greenmail-docker/standalone/pom.xml +++ b/greenmail-docker/standalone/pom.xml @@ -82,6 +82,7 @@ + 0.0.0.0 3025 3110 diff --git a/greenmail-docker/standalone/run_greenmail.sh b/greenmail-docker/standalone/run_greenmail.sh new file mode 100644 index 0000000000..784ad1f8f0 --- /dev/null +++ b/greenmail-docker/standalone/run_greenmail.sh @@ -0,0 +1,7 @@ +#/bin/sh +java \ + -Djava.net.preferIPv4Stack=true \ + -Dgreenmail.setup.test.all \ + -Dgreenmail.hostname=0.0.0.0 \ + -Dgreenmail.auth.disabled \ + -jar greenmail-standalone.jar From e11ee9a76a1f832073ea36d765afeb8e0f596fd8 Mon Sep 17 00:00:00 2001 From: Marcel May Date: Mon, 2 Jan 2017 17:04:44 +0100 Subject: [PATCH 07/16] Issue #170 / PR #171 : Postfixed test class with "Test" for consistency with other test classes --- ...ddress.java => SendReceiveWithInternationalAddressTest.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename greenmail-core/src/test/java/com/icegreen/greenmail/test/{SendReceiveWithInternationalAddress.java => SendReceiveWithInternationalAddressTest.java} (98%) diff --git a/greenmail-core/src/test/java/com/icegreen/greenmail/test/SendReceiveWithInternationalAddress.java b/greenmail-core/src/test/java/com/icegreen/greenmail/test/SendReceiveWithInternationalAddressTest.java similarity index 98% rename from greenmail-core/src/test/java/com/icegreen/greenmail/test/SendReceiveWithInternationalAddress.java rename to greenmail-core/src/test/java/com/icegreen/greenmail/test/SendReceiveWithInternationalAddressTest.java index c1399bec3b..afbb369944 100644 --- a/greenmail-core/src/test/java/com/icegreen/greenmail/test/SendReceiveWithInternationalAddress.java +++ b/greenmail-core/src/test/java/com/icegreen/greenmail/test/SendReceiveWithInternationalAddressTest.java @@ -19,7 +19,7 @@ import static org.junit.Assert.assertEquals; -public class SendReceiveWithInternationalAddress { +public class SendReceiveWithInternationalAddressTest { static final Properties properties; From 52092a0335ad23a324e9df8c5aa2f4e60763f044 Mon Sep 17 00:00:00 2001 From: Marcel May Date: Wed, 4 Jan 2017 21:18:02 +0100 Subject: [PATCH 08/16] Fixes #175 : Support verbose mode for GreenMail and standalone runner --- .../greenmail/server/AbstractServer.java | 2 +- .../PropertiesBasedServerSetupBuilder.java | 13 ++++- .../icegreen/greenmail/util/ServerSetup.java | 15 ++++++ ...PropertiesBasedServerSetupBuilderTest.java | 13 +++++ greenmail-site/index.html | 12 +++++ .../standalone/GreenMailStandaloneRunner.java | 48 ++++++++++++------- .../src/main/resources/log4j-verbose.xml | 26 ++++++++++ .../GreenMailStandaloneRunnerTest.java | 12 +++-- 8 files changed, 117 insertions(+), 24 deletions(-) create mode 100644 greenmail-standalone/src/main/resources/log4j-verbose.xml diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/server/AbstractServer.java b/greenmail-core/src/main/java/com/icegreen/greenmail/server/AbstractServer.java index fd2a0be6ef..0bf34586b2 100644 --- a/greenmail-core/src/main/java/com/icegreen/greenmail/server/AbstractServer.java +++ b/greenmail-core/src/main/java/com/icegreen/greenmail/server/AbstractServer.java @@ -308,7 +308,7 @@ public final void stopService() { * @return the session. */ public Session createSession(Properties properties) { - return createSession(properties, false); + return createSession(properties, setup.isVerbose()); } /** diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/util/PropertiesBasedServerSetupBuilder.java b/greenmail-core/src/main/java/com/icegreen/greenmail/util/PropertiesBasedServerSetupBuilder.java index e25ac88cac..5e925c6f11 100644 --- a/greenmail-core/src/main/java/com/icegreen/greenmail/util/PropertiesBasedServerSetupBuilder.java +++ b/greenmail-core/src/main/java/com/icegreen/greenmail/util/PropertiesBasedServerSetupBuilder.java @@ -30,7 +30,7 @@ * *

    *

    Protocol specific setups

    - * Replace PROTOCOL with a value from {@value com.icegreen.greenmail.util.ServerSetup#PROTOCOLS}: + * Replace PROTOCOL with a value from {@link com.icegreen.greenmail.util.ServerSetup#PROTOCOLS}: *
      *
    • greenmail.PROTOCOL.port
    • *
    • greenmail.PROTOCOL.hostname (defaults to {@link ServerSetup#getLocalHostAddress()}
    • @@ -38,6 +38,11 @@ */ public class PropertiesBasedServerSetupBuilder { + /** + * Enables verbose JavaMail debug output by setting JavaMail 'mail.debug' property. + */ + public static final String GREENMAIL_VERBOSE = "greenmail.verbose"; + /** * Creates a server setup based on provided properties. * @@ -60,6 +65,12 @@ public ServerSetup[] build(Properties properties) { addSetup(hostname, protocol, properties, serverSetups); } + for(ServerSetup setup: serverSetups) { + if(properties.containsKey(GREENMAIL_VERBOSE)) { + setup.setVerbose(true); + } + } + return serverSetups.toArray(new ServerSetup[serverSetups.size()]); } diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/util/ServerSetup.java b/greenmail-core/src/main/java/com/icegreen/greenmail/util/ServerSetup.java index 5484c91ef1..cffd05771f 100644 --- a/greenmail-core/src/main/java/com/icegreen/greenmail/util/ServerSetup.java +++ b/greenmail-core/src/main/java/com/icegreen/greenmail/util/ServerSetup.java @@ -72,6 +72,8 @@ public class ServerSetup { private long readTimeout = -1L; private long connectionTimeout = -1L; private long writeTimeout = -1L; + private boolean verbose = false; + /** * Timeout when GreenMail starts a server, in milliseconds. */ @@ -147,6 +149,17 @@ public long getServerStartupTimeout() { return serverStartupTimeout; } + public boolean isVerbose() { + return verbose; + } + + /** + * @param verbose if true enables JavaMail debug output by setting JavaMail property 'mail.debug' + */ + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + /** * Sets the server startup timeout in milliseconds. * @@ -258,6 +271,7 @@ public String toString() { ", connectionTimeout=" + connectionTimeout + ", writeTimeout=" + writeTimeout + ", serverStartupTimeout=" + serverStartupTimeout + + ", verbose=" + isVerbose() + '}'; } @@ -282,6 +296,7 @@ public ServerSetup createCopy(String bindAddress) { setup.setConnectionTimeout(getConnectionTimeout()); setup.setReadTimeout(getReadTimeout()); setup.setWriteTimeout(getWriteTimeout()); + setup.setVerbose(isVerbose()); return setup; } diff --git a/greenmail-core/src/test/java/com/icegreen/greenmail/util/PropertiesBasedServerSetupBuilderTest.java b/greenmail-core/src/test/java/com/icegreen/greenmail/util/PropertiesBasedServerSetupBuilderTest.java index 723b3b9b31..5f44e7d399 100644 --- a/greenmail-core/src/test/java/com/icegreen/greenmail/util/PropertiesBasedServerSetupBuilderTest.java +++ b/greenmail-core/src/test/java/com/icegreen/greenmail/util/PropertiesBasedServerSetupBuilderTest.java @@ -5,6 +5,8 @@ import java.util.Properties; import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; public class PropertiesBasedServerSetupBuilderTest { @Test @@ -35,6 +37,15 @@ public void testCreate() { assert setups != null; assertArrayEquals(setups, new ServerSetup[]{ServerSetupTest.SMTP}); + // With debug + properties.clear(); + properties.setProperty("greenmail.setup.test.smtp", ""); + properties.setProperty(PropertiesBasedServerSetupBuilder.GREENMAIL_VERBOSE, ""); + setups = setupBuilder.build(properties); + assert setups != null; + assertArrayEquals(setups, new ServerSetup[]{ServerSetupTest.SMTP}); + assertTrue(setups[0].isVerbose()); + // With hostname properties.clear(); properties.setProperty("greenmail.setup.test.smtp", ""); @@ -42,6 +53,8 @@ public void testCreate() { setups = setupBuilder.build(properties); assert setups != null; assertArrayEquals(setups, new ServerSetup[]{ServerSetupTest.SMTP.createCopy("0.0.0.0")}); + assertFalse(setups[0].isVerbose()); + // Default test setups for(ServerSetup setup: ServerSetupTest.ALL) { diff --git a/greenmail-site/index.html b/greenmail-site/index.html index 28c2a44002..bea18d5f69 100644 --- a/greenmail-site/index.html +++ b/greenmail-site/index.html @@ -562,6 +562,15 @@

      Starting GreenMail standalone

      + + -Dgreenmail.verbose + Enables verbose mode. + Useful if you want to see debug and protocol level output. +
      + Example: -Dgreenmail.verbose +
      + + -Dlog4j.configuration

      Configures log4j using given configuration file.

      @@ -891,6 +900,9 @@

      How can I create or delete a mail user?

      greenMail.getManagers().getUserManager().deleteUser(user1); // Delete user +

      How can I get more verbose output?

      +

      Enable the verbose mode, which prints debug output and protocol level communication.
      + See ServerSetup.setVerbose(boolean) or GreenMail standalone runner option greenmail.verbose option.

      diff --git a/greenmail-standalone/src/main/java/com/icegreen/greenmail/standalone/GreenMailStandaloneRunner.java b/greenmail-standalone/src/main/java/com/icegreen/greenmail/standalone/GreenMailStandaloneRunner.java index 33a3964a52..83f3994906 100644 --- a/greenmail-standalone/src/main/java/com/icegreen/greenmail/standalone/GreenMailStandaloneRunner.java +++ b/greenmail-standalone/src/main/java/com/icegreen/greenmail/standalone/GreenMailStandaloneRunner.java @@ -15,7 +15,7 @@ /** * Enables GreenMail to run in standalone mode. - * + *

      * Example: java -Dgreenmail.smtp -Dgreenmail.users=test1:pwd1 -jar greenmail.jar * * @see PropertiesBasedServerSetupBuilder @@ -23,6 +23,7 @@ */ public class GreenMailStandaloneRunner { private final Logger log = LoggerFactory.getLogger(GreenMailStandaloneRunner.class); + private GreenMail greenMail; /** * Start and configure GreenMail using given properties. @@ -36,13 +37,32 @@ public void doRun(Properties properties) { printUsage(System.out); } else { - GreenMail greenMail = new GreenMail(serverSetup); + greenMail = new GreenMail(serverSetup); log.info("Starting GreenMail standalone using " + Arrays.toString(serverSetup)); greenMail.withConfiguration(new PropertiesBasedGreenMailConfigurationBuilder().build(properties)) .start(); } } + protected static void configureLogging(Properties properties) { + // Init logging: Try standard log4j configuration mechanism before falling back to + // provided logging configuration + String log4jConfig = System.getProperty("log4j.configuration"); + if (null == log4jConfig) { + if (properties.containsKey(PropertiesBasedServerSetupBuilder.GREENMAIL_VERBOSE)) { + DOMConfigurator.configure(GreenMailStandaloneRunner.class.getResource("/log4j-verbose.xml")); + } else { + DOMConfigurator.configure(GreenMailStandaloneRunner.class.getResource("/log4j.xml")); + } + } else { + if (log4jConfig.toLowerCase().endsWith(".xml")) { + DOMConfigurator.configure(log4jConfig); + } else { + PropertyConfigurator.configure(log4jConfig); + } + } + } + private void printUsage(PrintStream out) { // Don't use logger out.println("Usage: java OPTIONS -jar greenmail.jar"); @@ -58,8 +78,9 @@ private void printUsage(PrintStream out) { {"-Dgreenmail..port=...", "Specifies port. Requires additional hostname parameter."}, {"-Dgreenmail.users=[,...]", "Specifies mail users, eg foo:pwd@bar.com,foo2:pwd@bar2.com."}, {"Note: domain must be DNS resolvable!"}, - {"-Dgreenmail.auth.disabled ","Disables authentication check so that any password works."}, + {"-Dgreenmail.auth.disabled ", "Disables authentication check so that any password works."}, {"Also automatically provisions previously non-existent users."}, + {"-Dgreenmail.verbose ", "Enables verbose mode, including JavaMail debug output"}, }; for (String[] opt : options) { if (opt.length == 1) { @@ -81,20 +102,13 @@ private void printUsage(PrintStream out) { out.println(" Starts SMTP on 0.0.0.0:3025 and IMAP on 0.0.0.0:3143"); } - public static void main(String[] args) { - // Init logging: Try standard log4j configuration mechanism before falling back to - // provided logging configuration - String log4jConfig = System.getProperty("log4j.configuration"); - if (null == log4jConfig) { - DOMConfigurator.configure(GreenMailStandaloneRunner.class.getResource("/log4j.xml")); - } else { - if (log4jConfig.toLowerCase().endsWith(".xml")) { - DOMConfigurator.configure(log4jConfig); - } else { - PropertyConfigurator.configure(log4jConfig); - } - } + GreenMail getGreenMail() { + return greenMail; + } - new GreenMailStandaloneRunner().doRun(System.getProperties()); + public static void main(String[] args) { + final Properties properties = System.getProperties(); + configureLogging(properties); + new GreenMailStandaloneRunner().doRun(properties); } } diff --git a/greenmail-standalone/src/main/resources/log4j-verbose.xml b/greenmail-standalone/src/main/resources/log4j-verbose.xml new file mode 100644 index 0000000000..ebbf33c89d --- /dev/null +++ b/greenmail-standalone/src/main/resources/log4j-verbose.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/greenmail-standalone/src/test/java/com/icegreen/greenmail/standalone/GreenMailStandaloneRunnerTest.java b/greenmail-standalone/src/test/java/com/icegreen/greenmail/standalone/GreenMailStandaloneRunnerTest.java index 8d364d26e9..2b435ee012 100644 --- a/greenmail-standalone/src/test/java/com/icegreen/greenmail/standalone/GreenMailStandaloneRunnerTest.java +++ b/greenmail-standalone/src/test/java/com/icegreen/greenmail/standalone/GreenMailStandaloneRunnerTest.java @@ -2,16 +2,15 @@ import com.icegreen.greenmail.configuration.PropertiesBasedGreenMailConfigurationBuilder; import com.icegreen.greenmail.util.GreenMailUtil; +import com.icegreen.greenmail.util.PropertiesBasedServerSetupBuilder; import com.icegreen.greenmail.util.ServerSetupTest; import org.junit.Test; -import javax.mail.Folder; -import javax.mail.Message; -import javax.mail.MessagingException; -import javax.mail.Store; +import javax.mail.*; import java.util.Properties; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; public class GreenMailStandaloneRunnerTest { @@ -19,6 +18,7 @@ public class GreenMailStandaloneRunnerTest { public void testDoRun() throws MessagingException { GreenMailStandaloneRunner runner = new GreenMailStandaloneRunner(); final Properties properties = new Properties(); + properties.setProperty(PropertiesBasedServerSetupBuilder.GREENMAIL_VERBOSE, ""); properties.setProperty("greenmail.setup.test.smtp", ""); properties.setProperty("greenmail.setup.test.imap", ""); properties.setProperty(PropertiesBasedGreenMailConfigurationBuilder.GREENMAIL_USERS, @@ -28,7 +28,9 @@ public void testDoRun() throws MessagingException { GreenMailUtil.sendTextEmail("test2@localhost", "test1@localhost", "Standalone test", "It worked", ServerSetupTest.SMTP); - Store store = GreenMailUtil.getSession(ServerSetupTest.IMAP).getStore("imap"); + final Session session = runner.getGreenMail().getImap().createSession(); + assertTrue(session.getDebug()); + Store store = session.getStore("imap"); try { store.connect("test2", "pwd2"); final Folder folder = store.getFolder("INBOX"); From d5dd7d204196e5a4eeb4e20d6f398effcf357678 Mon Sep 17 00:00:00 2001 From: Marcel May Date: Thu, 5 Jan 2017 23:29:56 +0100 Subject: [PATCH 09/16] Issue #174 : Support searching by message sequence --- .../greenmail/imap/commands/IdRange.java | 6 +- .../imap/commands/SearchCommandParser.java | 30 +++- .../greenmail/imap/commands/SearchKey.java | 8 +- .../imap/commands/SearchTermBuilder.java | 93 ++++++++-- .../greenmail/store/HierarchicalFolder.java | 6 +- .../greenmail/store/StoredMessage.java | 23 ++- .../imap/commands/ImapProtocolTest.java | 164 ++++++++++++++++-- 7 files changed, 294 insertions(+), 36 deletions(-) diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/imap/commands/IdRange.java b/greenmail-core/src/main/java/com/icegreen/greenmail/imap/commands/IdRange.java index 7431d74ec3..d0f25134f4 100644 --- a/greenmail-core/src/main/java/com/icegreen/greenmail/imap/commands/IdRange.java +++ b/greenmail-core/src/main/java/com/icegreen/greenmail/imap/commands/IdRange.java @@ -8,12 +8,14 @@ import java.io.Serializable; import java.util.*; +import java.util.regex.Pattern; /** * Represents a range of UID values. */ public class IdRange implements Serializable { - + /** Matches a sequence of a single id or id range */ + public static final Pattern SEQUENCE = Pattern.compile("\\d+|\\d+\\:\\d+"); private long lowVal; private long highVal; @@ -48,7 +50,7 @@ public boolean includes(long uid) { * @return a list of ranges, never null. */ public static List parseRangeSequence(String idRangeSequence) { - StringTokenizer tokenizer = new StringTokenizer(idRangeSequence, ","); + StringTokenizer tokenizer = new StringTokenizer(idRangeSequence, " "); List ranges = new ArrayList<>(); while (tokenizer.hasMoreTokens()) { ranges.add(parseRange(tokenizer.nextToken())); diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/imap/commands/SearchCommandParser.java b/greenmail-core/src/main/java/com/icegreen/greenmail/imap/commands/SearchCommandParser.java index e87d66eee1..a56a6391ca 100644 --- a/greenmail-core/src/main/java/com/icegreen/greenmail/imap/commands/SearchCommandParser.java +++ b/greenmail-core/src/main/java/com/icegreen/greenmail/imap/commands/SearchCommandParser.java @@ -15,6 +15,8 @@ import javax.mail.search.NotTerm; import javax.mail.search.SearchTerm; +import static com.icegreen.greenmail.imap.commands.IdRange.SEQUENCE; + /** * Handles processing for the SEARCH imap command. * @@ -50,7 +52,7 @@ public SearchTerm searchTerm(ImapRequestLineReader request) continue; } } - if (!quoted && (next == 32 || next == '\n')) { + if (!quoted && (next == 32 || next == '\n') && sb.length()>0) { if (log.isDebugEnabled()) { log.debug("Search request is '" + sb.toString() + '\''); } @@ -65,11 +67,29 @@ public SearchTerm searchTerm(ImapRequestLineReader request) && keyValue.charAt(keyValue.length() - 1) == ')') { keyValue = keyValue.substring(1, keyValue.length() - 1); } - SearchKey key = SearchKey.valueOf(keyValue); - if (SearchKey.NOT == key) { - negated = true; + + // Message set? + if (SEQUENCE.matcher(keyValue).matches()) { + b = SearchTermBuilder.create(SearchKey.SEQUENCE_SET); + + // Try to get additional number sequences. + // Sequence can be a whitespace separated list of either a number or number range + // Example: '2 5:9 9' + next = request.nextChar(); + while(next == 32 || (next >= '0' && next <= '9') || next == ':') { + request.consume(); + sb.append(next); + next = request.nextChar(); + } + b.addParameter(sb.toString()); } else { - b = SearchTermBuilder.create(key); + // Term? + SearchKey key = SearchKey.valueOf(keyValue); + if (SearchKey.NOT == key) { + negated = true; + } else { + b = SearchTermBuilder.create(key); + } } } catch (IllegalArgumentException ex) { // Ignore for now instead of breaking. See issue#35 . diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/imap/commands/SearchKey.java b/greenmail-core/src/main/java/com/icegreen/greenmail/imap/commands/SearchKey.java index a3a64698c0..6a62b7caa3 100644 --- a/greenmail-core/src/main/java/com/icegreen/greenmail/imap/commands/SearchKey.java +++ b/greenmail-core/src/main/java/com/icegreen/greenmail/imap/commands/SearchKey.java @@ -10,6 +10,7 @@ * Read more: https://tools.ietf.org/html/rfc3501 *

      *
        + *
      • SEQUENCE_SET <SEQUENCE SET> of message ids
      • *
      • ALL All messages in the mailbox; the default initial key for ANDing
      • *
      • ANSWERED Messages with the \Answered flag set.
      • *
      • BCC Messages that contain the specified string in the envelope structure's BCC field.
      • @@ -88,7 +89,12 @@ public enum SearchKey { UNDRAFT(), UNFLAGGED(), UNKEYWORD(1), - UNSEEN(); + UNSEEN(), + /** + * <sequence set> - Messages with message sequence numbers corresponding + * to the specified message sequence number set. + */ + SEQUENCE_SET(1); private int minArgs = 0; // expected additional arguments private boolean operator = false; // Is an operator, such as AND, OR, NOT ... diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/imap/commands/SearchTermBuilder.java b/greenmail-core/src/main/java/com/icegreen/greenmail/imap/commands/SearchTermBuilder.java index 3d4423a6e1..b20f5590c5 100644 --- a/greenmail-core/src/main/java/com/icegreen/greenmail/imap/commands/SearchTermBuilder.java +++ b/greenmail-core/src/main/java/com/icegreen/greenmail/imap/commands/SearchTermBuilder.java @@ -100,6 +100,9 @@ public static SearchTermBuilder create(final SearchKey key) { case UNKEYWORD: builder = createKeywordSearchTermBuilder(key); break; + case SEQUENCE_SET: + builder = createSequenceSetTermBuilder(); + break; default: throw new IllegalStateException("Unsupported search term '" + key + '\''); } @@ -225,6 +228,16 @@ public SearchTerm build() { }; } + private static SearchTermBuilder createSequenceSetTermBuilder() { + return new SearchTermBuilder() { + @Override + public SearchTerm build() { + final List idRanges = IdRange.parseRangeSequence(getParameter(0)); + return new MessageNumberSearchTerm(idRanges); + } + }; + } + private static javax.mail.Flags.Flag toFlag(String pFlag) { if (pFlag == null || pFlag.trim().length() < 1) { throw new IllegalArgumentException("Can not convert empty string to mail flag"); @@ -271,14 +284,73 @@ public boolean match(Message msg) { } } - // Not very efficient due to underlying JavaMail based impl. - // The term compares each mail if matching. - public static class UidSearchTerm extends SearchTerm { + /** + * Supports general searching by id sequences such as MSN or UID. + * + * Note: + * Not very efficient due to underlying JavaMail based impl. + * The term compares each mail if matching. + * + * @see MessageNumberSearchTerm + * @see UidSearchTerm + */ + public abstract static class AbstractIdSearchTerm extends SearchTerm { + private static final long serialVersionUID = -5935470270189992292L; + private final List idRanges; + + public AbstractIdSearchTerm(final List idRanges) { + this.idRanges = idRanges; + } + + @Override + public abstract boolean match(Message msg); + + /** + * Matches id against sequence numbers. + * + * @param id the identifier + * @return true, if matching + */ + public boolean match(final long id) { + for (IdRange idRange : idRanges) { + if (idRange.includes(id)) { + return true; + } + } + return false; + } + } + + /** + * Term for searching by message number ids. + */ + public static class MessageNumberSearchTerm extends AbstractIdSearchTerm { + private static final long serialVersionUID = -2792493451441320161L; + + /** + * @param idRanges the MSNs to search for. + */ + public MessageNumberSearchTerm(List idRanges) { + super(idRanges); + } + + @Override + public boolean match(Message msg) { + return match(msg.getMessageNumber()); + } + } + + /** + * Term for searching uids. + */ + public static class UidSearchTerm extends AbstractIdSearchTerm { private static final long serialVersionUID = 1135219503729412087L; - private final List uidSetList; - public UidSearchTerm(List uidSetList) { - this.uidSetList = uidSetList; + /** + * @param idRanges the UIDs to search for. + */ + public UidSearchTerm(List idRanges) { + super(idRanges); } @Override @@ -292,14 +364,5 @@ public boolean match(Message msg) { return false; } } - - public boolean match(long uid) { - for (IdRange uidSet : uidSetList) { - if (uidSet.includes(uid)) { - return true; - } - } - return false; - } } } diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/store/HierarchicalFolder.java b/greenmail-core/src/main/java/com/icegreen/greenmail/store/HierarchicalFolder.java index 8e381e07c2..dc0a9bc6dc 100644 --- a/greenmail-core/src/main/java/com/icegreen/greenmail/store/HierarchicalFolder.java +++ b/greenmail-core/src/main/java/com/icegreen/greenmail/store/HierarchicalFolder.java @@ -311,7 +311,11 @@ public long[] search(SearchTerm searchTerm) { List matchedMessages = new ArrayList<>(); synchronized (mailMessages) { - for (StoredMessage mailMessage : mailMessages) { + for (int i = 0; i 0); // At least UID and SIZE + assertEquals(2, fetchResponse.getItemCount()); // UID and SIZE + RFC822SIZE size = fetchResponse.getItem(RFC822SIZE.class); + assertNotNull(size); + assertTrue(size.size > 0); + UID uid = fetchResponse.getItem(UID.class); + assertEquals(folder.getUID(folder.getMessage(1)), uid.uid); } finally { store.close(); } } + + @Test + public void testSearchSequenceSet() throws MessagingException { + store.connect("foo@localhost", "pwd"); + try { + IMAPFolder folder = (IMAPFolder) store.getFolder("INBOX"); + folder.open(Folder.READ_ONLY); + Response[] ret = (Response[]) folder.doCommand(new IMAPFolder.ProtocolCommand() { + @Override + public Object doCommand(IMAPProtocol protocol) throws ProtocolException { + return protocol.command("SEARCH 1", null); + } + }); + IMAPResponse response = (IMAPResponse) ret[0]; + assertFalse(response.isBAD()); + assertEquals("1", response.getRest()); + + ret = (Response[]) folder.doCommand(new IMAPFolder.ProtocolCommand() { + @Override + public Object doCommand(IMAPProtocol protocol) throws ProtocolException { + return protocol.command("SEARCH 2:2", null); + } + }); + response = (IMAPResponse) ret[0]; + assertFalse(response.isBAD()); + assertTrue(ret[1].isOK()); + assertEquals("2", response.getRest()); + + ret = (Response[]) folder.doCommand(new IMAPFolder.ProtocolCommand() { + @Override + public Object doCommand(IMAPProtocol protocol) throws ProtocolException { + return protocol.command("SEARCH 2:4", null); + } + }); + response = (IMAPResponse) ret[0]; + assertFalse(response.isBAD()); + assertEquals("2 3 4", response.getRest()); + assertTrue(ret[1].isOK()); + + ret = (Response[]) folder.doCommand(new IMAPFolder.ProtocolCommand() { + @Override + public Object doCommand(IMAPProtocol protocol) throws ProtocolException { + return protocol.command("SEARCH 1 2:4 8", null); + } + }); + response = (IMAPResponse) ret[0]; + assertFalse(response.isBAD()); + assertEquals("1 2 3 4 8", response.getRest()); + assertTrue(ret[1].isOK()); + } finally { + store.close(); + } + } + + @Test + public void testUidSearchSequenceSet() throws MessagingException { + store.connect("foo@localhost", "pwd"); + try { + IMAPFolder folder = (IMAPFolder) store.getFolder("INBOX"); + folder.open(Folder.READ_ONLY); + + final Message[] messages = folder.getMessages(); + Map uids = new HashMap<>(); + for (Message msg : messages) { + uids.put(msg.getMessageNumber(), folder.getUID(msg)); + } + + Response[] ret = (Response[]) folder.doCommand(new IMAPFolder.ProtocolCommand() { + @Override + public Object doCommand(IMAPProtocol protocol) throws ProtocolException { + return protocol.command("UID SEARCH 1", null); + } + }); + IMAPResponse response = (IMAPResponse) ret[0]; + assertFalse(response.isBAD()); + assertEquals(uids.get(1).toString(), response.getRest()); + + ret = (Response[]) folder.doCommand(new IMAPFolder.ProtocolCommand() { + @Override + public Object doCommand(IMAPProtocol protocol) throws ProtocolException { + return protocol.command("UID SEARCH 2:2", null); + } + }); + response = (IMAPResponse) ret[0]; + assertFalse(response.isBAD()); + assertTrue(ret[1].isOK()); + assertEquals(uids.get(2).toString(), response.getRest()); + + ret = (Response[]) folder.doCommand(new IMAPFolder.ProtocolCommand() { + @Override + public Object doCommand(IMAPProtocol protocol) throws ProtocolException { + return protocol.command("UID SEARCH 2:4", null); + } + }); + response = (IMAPResponse) ret[0]; + assertFalse(response.isBAD()); + assertEquals(msnListToUidString(uids, 2, 3, 4), response.getRest()); + assertTrue(ret[1].isOK()); + + ret = (Response[]) folder.doCommand(new IMAPFolder.ProtocolCommand() { + @Override + public Object doCommand(IMAPProtocol protocol) throws ProtocolException { + return protocol.command("UID SEARCH 1 2:4 8", null); + } + }); + response = (IMAPResponse) ret[0]; + assertFalse(response.isBAD()); + assertEquals(msnListToUidString(uids, 1, 2, 3, 4, 8), response.getRest()); + assertTrue(ret[1].isOK()); + } finally { + store.close(); + } + } + + private String msnListToUidString(Map uids, int... msnList) { + StringBuilder buf = new StringBuilder(); + for (int msn : msnList) { + if (buf.length() > 0) { + buf.append(' '); + } + buf.append(uids.get(msn)); + } + return buf.toString(); + } } From d209e0e639ecc6ae9c02716b0aadf40f18f06d81 Mon Sep 17 00:00:00 2001 From: Marcel May Date: Sun, 8 Jan 2017 02:00:50 +0100 Subject: [PATCH 10/16] Fixes #177 : Enhance service greeting with GreenMail project version --- greenmail-core/pom.xml | 25 +++++++++++++++++++ .../icegreen/greenmail/imap/ImapHandler.java | 4 ++- .../icegreen/greenmail/pop3/Pop3Handler.java | 3 ++- .../icegreen/greenmail/server/BuildInfo.java | 17 +++++++++++++ .../icegreen/greenmail/smtp/SmtpHandler.java | 3 ++- .../standalone/GreenMailStandaloneRunner.java | 4 ++- pom.xml | 6 +++++ 7 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 greenmail-core/src/main/java/com/icegreen/greenmail/server/BuildInfo.java diff --git a/greenmail-core/pom.xml b/greenmail-core/pom.xml index 50afdec890..e838b25464 100644 --- a/greenmail-core/pom.xml +++ b/greenmail-core/pom.xml @@ -62,4 +62,29 @@ + + + + de.m3y.maven + inject-maven-plugin + + + + ${project.version} + com.icegreen.greenmail.server.BuildInfo.getProjectVersion + + + + + + process-classes + + inject + + + + + + + diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/imap/ImapHandler.java b/greenmail-core/src/main/java/com/icegreen/greenmail/imap/ImapHandler.java index 4fe3715938..fbcc7a0bfa 100644 --- a/greenmail-core/src/main/java/com/icegreen/greenmail/imap/ImapHandler.java +++ b/greenmail-core/src/main/java/com/icegreen/greenmail/imap/ImapHandler.java @@ -6,6 +6,7 @@ */ package com.icegreen.greenmail.imap; +import com.icegreen.greenmail.server.BuildInfo; import com.icegreen.greenmail.server.ProtocolHandler; import com.icegreen.greenmail.user.UserManager; import org.slf4j.Logger; @@ -58,7 +59,8 @@ public void run() { response = new ImapResponse(outs); // Write welcome message - String responseBuffer = VERSION + " Server GreenMail ready"; + String responseBuffer = VERSION + " Server GreenMail v" + + BuildInfo.INSTANCE.getProjectVersion() + " ready"; response.okResponse(null, responseBuffer); session = new ImapSessionImpl(imapHost, diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/pop3/Pop3Handler.java b/greenmail-core/src/main/java/com/icegreen/greenmail/pop3/Pop3Handler.java index 733c64ea19..fa6bda06f8 100644 --- a/greenmail-core/src/main/java/com/icegreen/greenmail/pop3/Pop3Handler.java +++ b/greenmail-core/src/main/java/com/icegreen/greenmail/pop3/Pop3Handler.java @@ -9,6 +9,7 @@ import com.icegreen.greenmail.pop3.commands.Pop3Command; import com.icegreen.greenmail.pop3.commands.Pop3CommandRegistry; +import com.icegreen.greenmail.server.BuildInfo; import com.icegreen.greenmail.server.ProtocolHandler; import com.icegreen.greenmail.user.UserManager; @@ -63,7 +64,7 @@ public void run() { } void sendGreetings() { - _conn.println("+OK POP3 GreenMail Server ready"); + _conn.println("+OK POP3 GreenMail Server v" + BuildInfo.INSTANCE.getProjectVersion() + " ready"); } void handleCommand() diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/server/BuildInfo.java b/greenmail-core/src/main/java/com/icegreen/greenmail/server/BuildInfo.java new file mode 100644 index 0000000000..a49c2ac3a3 --- /dev/null +++ b/greenmail-core/src/main/java/com/icegreen/greenmail/server/BuildInfo.java @@ -0,0 +1,17 @@ +package com.icegreen.greenmail.server; + +/** + * Defines project build info such as version. + * + * Note: Actual values will be replaced by build compilation + */ +public enum BuildInfo { + INSTANCE; + + /** + * @return the project version + */ + public String getProjectVersion() { + return ""; + } +} diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/smtp/SmtpHandler.java b/greenmail-core/src/main/java/com/icegreen/greenmail/smtp/SmtpHandler.java index f5acd72c1a..83a3cfe083 100644 --- a/greenmail-core/src/main/java/com/icegreen/greenmail/smtp/SmtpHandler.java +++ b/greenmail-core/src/main/java/com/icegreen/greenmail/smtp/SmtpHandler.java @@ -7,6 +7,7 @@ package com.icegreen.greenmail.smtp; import com.icegreen.greenmail.foedus.util.Workspace; +import com.icegreen.greenmail.server.BuildInfo; import com.icegreen.greenmail.server.ProtocolHandler; import com.icegreen.greenmail.smtp.commands.SmtpCommand; import com.icegreen.greenmail.smtp.commands.SmtpCommandRegistry; @@ -73,7 +74,7 @@ public void run() { protected void sendGreetings() { _conn.send("220 " + _conn.getServerGreetingsName() + - " GreenMail SMTP Service Ready at port " + _conn.sock.getLocalPort()); + " GreenMail SMTP Service v" + BuildInfo.INSTANCE.getProjectVersion() + " ready"); } protected void handleCommand() diff --git a/greenmail-standalone/src/main/java/com/icegreen/greenmail/standalone/GreenMailStandaloneRunner.java b/greenmail-standalone/src/main/java/com/icegreen/greenmail/standalone/GreenMailStandaloneRunner.java index 83f3994906..8f6e047a00 100644 --- a/greenmail-standalone/src/main/java/com/icegreen/greenmail/standalone/GreenMailStandaloneRunner.java +++ b/greenmail-standalone/src/main/java/com/icegreen/greenmail/standalone/GreenMailStandaloneRunner.java @@ -1,6 +1,7 @@ package com.icegreen.greenmail.standalone; import com.icegreen.greenmail.configuration.PropertiesBasedGreenMailConfigurationBuilder; +import com.icegreen.greenmail.server.BuildInfo; import com.icegreen.greenmail.util.GreenMail; import com.icegreen.greenmail.util.PropertiesBasedServerSetupBuilder; import com.icegreen.greenmail.util.ServerSetup; @@ -38,7 +39,8 @@ public void doRun(Properties properties) { } else { greenMail = new GreenMail(serverSetup); - log.info("Starting GreenMail standalone using " + Arrays.toString(serverSetup)); + log.info("Starting GreenMail standalone v" + BuildInfo.INSTANCE.getProjectVersion() + + " using " + Arrays.toString(serverSetup)); greenMail.withConfiguration(new PropertiesBasedGreenMailConfigurationBuilder().build(properties)) .start(); } diff --git a/pom.xml b/pom.xml index e6c6581251..a044859162 100644 --- a/pom.xml +++ b/pom.xml @@ -282,6 +282,12 @@ maven-shade-plugin 2.4.3 + + + de.m3y.maven + inject-maven-plugin + 1.0 + From ed3a7fd8c3bf467bb26e57690de2210cb681911b Mon Sep 17 00:00:00 2001 From: Marcel May Date: Sun, 8 Jan 2017 19:18:01 +0100 Subject: [PATCH 11/16] Fixes #178 : Forwarding an attached message RFC822 message causes NPE --- .../greenmail/store/SimpleMessageAttributes.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/store/SimpleMessageAttributes.java b/greenmail-core/src/main/java/com/icegreen/greenmail/store/SimpleMessageAttributes.java index 29f0db5e4b..98a501b2ca 100644 --- a/greenmail-core/src/main/java/com/icegreen/greenmail/store/SimpleMessageAttributes.java +++ b/greenmail-core/src/main/java/com/icegreen/greenmail/store/SimpleMessageAttributes.java @@ -78,11 +78,13 @@ public class SimpleMessageAttributes SimpleMessageAttributes(MimeMessage msg, Date receivedDate) throws MessagingException { Date sentDate = getSentDate(msg, receivedDate); - this.receivedDate = receivedDate; if(null != receivedDate) { + this.receivedDate = receivedDate; receivedDateString = new MailDateFormat().format(receivedDate); } - sentDateEnvelopeString = new MailDateFormat().format(sentDate); + if(null != sentDate) { + sentDateEnvelopeString = new MailDateFormat().format(sentDate); + } if (msg != null) { parseMimePart(msg); @@ -253,7 +255,9 @@ void parseMimePart(MimePart part) throws MessagingException { parts = new SimpleMessageAttributes[1]; try { MimeMessage wrappedMessage = (MimeMessage) part.getContent(); - log.error("message type : "+wrappedMessage.getContentType()); + if(log.isDebugEnabled()) { + log.debug("message type : " + wrappedMessage.getContentType()); + } parts[0] = new SimpleMessageAttributes(wrappedMessage, null); } catch (Exception e) { throw new IllegalStateException("Can not extract part for "+primaryType+"/"+secondaryType, e); From 79bbf7f9d3dc56d40e23eefb4b54d527e068f8fa Mon Sep 17 00:00:00 2001 From: Marcel May Date: Sun, 8 Jan 2017 20:28:05 +0100 Subject: [PATCH 12/16] Issue #172 : IMAP fails to fetch message when content type is text/html - Better text handling --- .../com/icegreen/greenmail/imap/commands/FetchCommand.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/imap/commands/FetchCommand.java b/greenmail-core/src/main/java/com/icegreen/greenmail/imap/commands/FetchCommand.java index 1354e7e238..22676d8df4 100644 --- a/greenmail-core/src/main/java/com/icegreen/greenmail/imap/commands/FetchCommand.java +++ b/greenmail-core/src/main/java/com/icegreen/greenmail/imap/commands/FetchCommand.java @@ -221,11 +221,11 @@ private void handleBodyFetch(MimeMessage mimeMessage, } else if ("TEXT".equalsIgnoreCase(sectionSpecifier)) { handleBodyFetchForText(mimeMessage, partial, response); } else { - String contentType = mimeMessage.getContentType(); - if (contentType.toLowerCase().startsWith("text/plain") && "1".equals(sectionSpecifier)) { + Object content = mimeMessage.getContent(); + if (content instanceof String) { handleBodyFetchForText(mimeMessage, partial, response); } else { - MimeMultipart mp = (MimeMultipart) mimeMessage.getContent(); + MimeMultipart mp = (MimeMultipart) content; BodyPart part = null; // Find part by number spec, eg "1" or "2.1" or "4.3.1" ... From 1c49dc0e6b3c5b41c9b30dfbe398842bb627bfe8 Mon Sep 17 00:00:00 2001 From: Marcel May Date: Mon, 9 Jan 2017 22:52:58 +0100 Subject: [PATCH 13/16] Fixed #179 : Support configuration options for GreenMail standalone Docker image --- greenmail-docker/standalone/Dockerfile | 11 +++++++++++ greenmail-docker/standalone/README.md | 17 +++++++++++++++-- greenmail-docker/standalone/run_greenmail.sh | 8 ++------ greenmail-site/index.html | 16 ++++++++++++++-- 4 files changed, 42 insertions(+), 10 deletions(-) diff --git a/greenmail-docker/standalone/Dockerfile b/greenmail-docker/standalone/Dockerfile index 6ce73fa70e..d5a8bae8f1 100644 --- a/greenmail-docker/standalone/Dockerfile +++ b/greenmail-docker/standalone/Dockerfile @@ -1,6 +1,7 @@ FROM openjdk:7-jdk-alpine MAINTAINER https://github.com/greenmail-mail-test/greenmail (marcel.may.de@gmail.com) +####################### # Expose ports: # - smtp : 3025 # - smtps : 3465 @@ -8,8 +9,18 @@ MAINTAINER https://github.com/greenmail-mail-test/greenmail (marcel.may.de@gmail # - pop3s : 3995 # - imap : 3143 # - imaps : 3993 +####################### EXPOSE 3025 3465 3110 3995 3143 3993 +####################### +# Configuration options +####################### +ENV JAVA_OPTS -Djava.net.preferIPv4Stack=true +ENV GREENMAIL_OPTS -Dgreenmail.setup.test.all \ + -Dgreenmail.hostname=0.0.0.0 \ + -Dgreenmail.auth.disabled + +####################### # Run as user greenmail RUN addgroup greenmail && adduser -G greenmail -D greenmail # Note: If using Dockerfile without Maven, you must manually copy the JAR diff --git a/greenmail-docker/standalone/README.md b/greenmail-docker/standalone/README.md index affb255006..6764353716 100644 --- a/greenmail-docker/standalone/README.md +++ b/greenmail-docker/standalone/README.md @@ -13,10 +13,10 @@ How to build via docker CLI `docker build -t greenmail/standalone .` 2. Test - `docker run -t -i -p 3025:3025 -p 3110:3110 -p 3143:3143 -p 3465:3465 -p 3993:3993 -p 3995:3995 greenmail/standalone` + `docker run -t -i -p 3025:3025 -p 3110:3110 -p 3143:3143 -p 3465:3465 -p 3993:3993 -p 3995:3995 greenmail/standalon:` `telnet ``docker-machine ip`` 3025` The telnet command should produce a GreenMail ready output, - similiar to this: `220 /172.17.0.2 GreenMail SMTP Service Ready at port 3025` + similiar to this: `220 /172.17.0.2 GreenMail SMTP Service ready` 3. Deploy to [Docker Hub](https://hub.docker.com/r/greenmail/standalone/) `docker push greenmail/standalone` @@ -42,3 +42,16 @@ A quickstart when using Maven from this module: Note: For running from GreenMail top level Maven root, use the docker profile which is not active by default: `mvn clean install -Pdocker` + +How to configure running Docker image +------------------------------------- + +You can pass in JVM and GreenMail configuration options when running the Docker image by +setting the Docker environment options JAVA\_OPTS and GREENMAIL\_OPTS. For defaults, see the [Dockerfile](Dockerfile). + +Example running GreenMail in verbose mode by setting GREENMAIL\_OPTS: +``` +docker run -t -i \ + -e GREENMAIL_OPTS='-Dgreenmail.setup.test.all -Dgreenmail.hostname=0.0.0.0 -Dgreenmail.auth.disabled -Dgreenmail.verbose' \ + -p 3025:3025 -p 3110:3110 -p 3143:3143 -p 3465:3465 -p 3993:3993 -p 3995:3995 greenmail/standalon:` +``` diff --git a/greenmail-docker/standalone/run_greenmail.sh b/greenmail-docker/standalone/run_greenmail.sh index 784ad1f8f0..36ef0f1568 100644 --- a/greenmail-docker/standalone/run_greenmail.sh +++ b/greenmail-docker/standalone/run_greenmail.sh @@ -1,7 +1,3 @@ #/bin/sh -java \ - -Djava.net.preferIPv4Stack=true \ - -Dgreenmail.setup.test.all \ - -Dgreenmail.hostname=0.0.0.0 \ - -Dgreenmail.auth.disabled \ - -jar greenmail-standalone.jar +echo "Executing 'java $JAVA_OPTS $GREENMAIL_OPTS -jar greenmail-standalone.jar' ..." +java $JAVA_OPTS $GREENMAIL_OPTS -jar greenmail-standalone.jar diff --git a/greenmail-site/index.html b/greenmail-site/index.html index bea18d5f69..189559d90f 100644 --- a/greenmail-site/index.html +++ b/greenmail-site/index.html @@ -666,10 +666,10 @@

        Using docker to run the image

        docker pull greenmail/standalone:1.5.2 docker run -t -i -p 3025:3025 -p 3110:3110 -p 3143:3143 \ -p 3465:3465 -p 3993:3993 -p 3995:3995 \ - greenmail/standalone + greenmail/standalone:1.5.3

        If you want to test it, you can do a quick check with telnet (or any other mail program) @@ -678,6 +678,18 @@

        Using docker to run the image

        Connecting with telnet to GreenMail docker SMTP service +
        Passing configuration options to GreenMail Standalone Docker image
        +

        You can also configure the JVM and GreenMail configuration options via the Docker environment + variables JAVA_OPTS and GREENMAIL_OPTS: +

        +
        
        +docker run -t -i \
        +           -e GREENMAIL_OPTS='-Dgreenmail.setup.test.all -Dgreenmail.hostname=0.0.0.0 -Dgreenmail.auth.disabled -Dgreenmail.verbose' \
        +           -e JAVA_OPTS='-Djava.net.preferIPv4Stack=true -Xmx512m' \
        +           -p 3025:3025 -p 3110:3110 -p 3143:3143 \
        +           -p 3465:3465 -p 3993:3993 -p 3995:3995 \
        +           greenmail/standalone:1.5.3
        +                

        Deploy as a webapp (WAR)

        From bed1fd4c4f1cf7d9b49a7cb253538230bfd89f1d Mon Sep 17 00:00:00 2001 From: Marcel May Date: Tue, 10 Jan 2017 23:49:18 +0100 Subject: [PATCH 14/16] Fixes #181 : Provide client test setup for Rainloop --- greenmail-docker/clients/rainloop/Dockerfile | 8 +++++ greenmail-docker/clients/rainloop/README.md | 35 +++++++++++++++++++ .../clients/rainloop/docker-compose.yml | 17 +++++++++ .../clients/rainloop/domains/default.ini | 15 ++++++++ .../clients/rainloop/domains/disabled | 1 + 5 files changed, 76 insertions(+) create mode 100644 greenmail-docker/clients/rainloop/Dockerfile create mode 100644 greenmail-docker/clients/rainloop/README.md create mode 100644 greenmail-docker/clients/rainloop/docker-compose.yml create mode 100644 greenmail-docker/clients/rainloop/domains/default.ini create mode 100644 greenmail-docker/clients/rainloop/domains/disabled diff --git a/greenmail-docker/clients/rainloop/Dockerfile b/greenmail-docker/clients/rainloop/Dockerfile new file mode 100644 index 0000000000..31f19b5db6 --- /dev/null +++ b/greenmail-docker/clients/rainloop/Dockerfile @@ -0,0 +1,8 @@ +FROM solidnerd/rainloop:1.10.5.192 +MAINTAINER https://github.com/greenmail-mail-test/greenmail (marcel.may.de@gmail.com) + +EXPOSE 80 + +# Replace domains with preconfigured GreenMail domain +RUN rm $RAINLOOP_HOME/rainloop/v/1.10.5.192/app/domains/* +ADD domains/* $RAINLOOP_HOME/rainloop/v/1.10.5.192/app/domains/ diff --git a/greenmail-docker/clients/rainloop/README.md b/greenmail-docker/clients/rainloop/README.md new file mode 100644 index 0000000000..a079236d43 --- /dev/null +++ b/greenmail-docker/clients/rainloop/README.md @@ -0,0 +1,35 @@ +GreenMail test setup with Rainloop +========= + +Extends [solidnerd/rainloop:1.10.5.192](https://github.com/solidnerd/docker-rainloop) Docker image with a configured GreenMail domain. + +Run `docker-compose up .` and access Rainloop in your browser. + +|Port|Description| +|----|-----------| +|3080| Rainloop | +|3025| GreenMail SMTP | +|3143| GreenMail IMAP | + +How to run with docker (instead of docker-compose) +-------- + +1. Build configured Rainloop image + `docker build -t greenmail/client-rainloop .` + +2. Start GreenMail +``` +docker run -t -i --name greenmail \ + -e GREENMAIL_OPTS='-Dgreenmail.setup.test.all -Dgreenmail.hostname=0.0.0.0 -Dgreenmail.auth.disabled -Dgreenmail.verbose' \ + -p 3025:3025 -p 3143:3143 greenmail/standalon:` +``` + +3. Start configured Rainloop image + +`docker run -t -i --link greenmail -p 3080:80 greenmail/client-rainloop` + +How to run with docker-compose +-------- + +You can - as a As an alternative to starting each container individually you can use docker-compose. +Check and modify the greenmail image version in [docker-compose.yml] and run `docker-compose up`. diff --git a/greenmail-docker/clients/rainloop/docker-compose.yml b/greenmail-docker/clients/rainloop/docker-compose.yml new file mode 100644 index 0000000000..6b2814226c --- /dev/null +++ b/greenmail-docker/clients/rainloop/docker-compose.yml @@ -0,0 +1,17 @@ +version: '2' +services: + greenmail: + image: greenmail/standalone:1.6.0-SNAPSHOT + environment: + # Enable GreenMail verbose mode + - GREENMAIL_OPTS=-Dgreenmail.setup.test.all -Dgreenmail.hostname=0.0.0.0 -Dgreenmail.auth.disabled -Dgreenmail.verbose + ports: + - "3025:3025" + - "3143:3143" + rainloop: + build: + context: . + ports: + - "3080:80" + links: + - greenmail diff --git a/greenmail-docker/clients/rainloop/domains/default.ini b/greenmail-docker/clients/rainloop/domains/default.ini new file mode 100644 index 0000000000..15989448a0 --- /dev/null +++ b/greenmail-docker/clients/rainloop/domains/default.ini @@ -0,0 +1,15 @@ +imap_host = "greenmail" +imap_port = 3143 +imap_secure = "None" +imap_short_login = Off +sieve_use = Off +sieve_allow_raw = Off +sieve_host = "" +sieve_port = 4190 +sieve_secure = "None" +smtp_host = "greenmail" +smtp_port = 3025 +smtp_secure = "None" +smtp_short_login = Off +smtp_auth = Off +smtp_php_mail = Off diff --git a/greenmail-docker/clients/rainloop/domains/disabled b/greenmail-docker/clients/rainloop/domains/disabled new file mode 100644 index 0000000000..129d87b1dc --- /dev/null +++ b/greenmail-docker/clients/rainloop/domains/disabled @@ -0,0 +1 @@ +outlook.com,qq.com,yahoo.com,gmail.com From 6594d81cced80b239261e85d1268f84e6fad17fa Mon Sep 17 00:00:00 2001 From: Marcel May Date: Tue, 10 Jan 2017 23:52:37 +0100 Subject: [PATCH 15/16] Issue #181 : Provide client test setup for Rainloop Fix documentation --- greenmail-docker/clients/rainloop/README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/greenmail-docker/clients/rainloop/README.md b/greenmail-docker/clients/rainloop/README.md index a079236d43..5aca0fc313 100644 --- a/greenmail-docker/clients/rainloop/README.md +++ b/greenmail-docker/clients/rainloop/README.md @@ -28,8 +28,3 @@ docker run -t -i --name greenmail \ `docker run -t -i --link greenmail -p 3080:80 greenmail/client-rainloop` -How to run with docker-compose --------- - -You can - as a As an alternative to starting each container individually you can use docker-compose. -Check and modify the greenmail image version in [docker-compose.yml] and run `docker-compose up`. From 0c12abb08209255aaf382d096122e73db2037d56 Mon Sep 17 00:00:00 2001 From: Marcel May Date: Sun, 15 Jan 2017 17:33:12 +0100 Subject: [PATCH 16/16] Issue #183 : Provide client test setup for Roundcube client --- greenmail-docker/clients/rainloop/README.md | 4 +- greenmail-docker/clients/roundcube/Dockerfile | 18 +++++ greenmail-docker/clients/roundcube/LICENSE | 21 +++++ greenmail-docker/clients/roundcube/README.md | 36 +++++++++ greenmail-docker/clients/roundcube/config.php | 77 +++++++++++++++++++ .../clients/roundcube/docker-compose.yml | 17 ++++ greenmail-docker/clients/roundcube/php.ini | 6 ++ greenmail-docker/clients/roundcube/run.sh | 53 +++++++++++++ 8 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 greenmail-docker/clients/roundcube/Dockerfile create mode 100644 greenmail-docker/clients/roundcube/LICENSE create mode 100644 greenmail-docker/clients/roundcube/README.md create mode 100644 greenmail-docker/clients/roundcube/config.php create mode 100644 greenmail-docker/clients/roundcube/docker-compose.yml create mode 100644 greenmail-docker/clients/roundcube/php.ini create mode 100755 greenmail-docker/clients/roundcube/run.sh diff --git a/greenmail-docker/clients/rainloop/README.md b/greenmail-docker/clients/rainloop/README.md index 5aca0fc313..2010805626 100644 --- a/greenmail-docker/clients/rainloop/README.md +++ b/greenmail-docker/clients/rainloop/README.md @@ -3,11 +3,11 @@ GreenMail test setup with Rainloop Extends [solidnerd/rainloop:1.10.5.192](https://github.com/solidnerd/docker-rainloop) Docker image with a configured GreenMail domain. -Run `docker-compose up .` and access Rainloop in your browser. +Run `docker-compose up` and access Rainloop in your browser. |Port|Description| |----|-----------| -|3080| Rainloop | +|3080| Rainloop Client| |3025| GreenMail SMTP | |3143| GreenMail IMAP | diff --git a/greenmail-docker/clients/roundcube/Dockerfile b/greenmail-docker/clients/roundcube/Dockerfile new file mode 100644 index 0000000000..a1f52ff3fb --- /dev/null +++ b/greenmail-docker/clients/roundcube/Dockerfile @@ -0,0 +1,18 @@ +# Based on https://github.com/konstantinj/docker-roundcube +FROM alpine:3.5 +MAINTAINER https://github.com/greenmail-mail-test/greenmail (marcel.may.de@gmail.com) + +ENV VERSION=1.1.7 + +RUN apk add --no-cache bash curl \ + php5-common php5-iconv php5-imap php5-xml php5-json php5-dom php5-mcrypt php5-intl php5-zip \ + php5-pear php5-pdo php5-sqlite3 php5-pdo_sqlite \ + php5-pear-mail_mime php5-pear-net_smtp \ + php5-fpm \ + && curl --location https://github.com/roundcube/roundcubemail/releases/download/${VERSION}/roundcubemail-${VERSION}.tar.gz | tar xzf - \ + && mv roundcubemail* /www \ + && curl --remote-name http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types \ + && mkdir /config + +COPY config.php php.ini run.sh / +CMD /run.sh diff --git a/greenmail-docker/clients/roundcube/LICENSE b/greenmail-docker/clients/roundcube/LICENSE new file mode 100644 index 0000000000..d9a2e0648b --- /dev/null +++ b/greenmail-docker/clients/roundcube/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Konstantin Jakobi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/greenmail-docker/clients/roundcube/README.md b/greenmail-docker/clients/roundcube/README.md new file mode 100644 index 0000000000..74836db565 --- /dev/null +++ b/greenmail-docker/clients/roundcube/README.md @@ -0,0 +1,36 @@ +# Roundcube Docker image + +Docker container for testing [Roundcube](https://github.com/roundcube/roundcubemail) with GreenMail. + +## Features - why using this image instead of several others? + +- Uses [alpine](https://registry.hub.docker.com/_/alpine/) base image +- Derived from [konstantinj/docker-roundcube](https://github.com/konstantinj/docker-roundcube) + +## Usage + +Run `docker-compose up` and access Roundcube in your browser. + +|Port|Description| +|----|-----------| +|4080| Roundcube Client| +|3025| GreenMail SMTP | +|3143| GreenMail IMAP | + +How to run with docker (instead of docker-compose) +-------- + +1. Build configured Roundcube image + `docker build -t greenmail/client-roundcube .` + +2. Start GreenMail +``` +docker run -t -i --name greenmail \ + -e GREENMAIL_OPTS='-Dgreenmail.setup.test.all -Dgreenmail.hostname=0.0.0.0 -Dgreenmail.auth.disabled -Dgreenmail.verbose' \ + -p 3025:3025 -p 3143:3143 greenmail/standalon:` +``` + +3. Start configured Roundcube image + +`docker run -t -i --link greenmail -p 4080:80 greenmail/client-roundcube` + diff --git a/greenmail-docker/clients/roundcube/config.php b/greenmail-docker/clients/roundcube/config.php new file mode 100644 index 0000000000..ba04848581 --- /dev/null +++ b/greenmail-docker/clients/roundcube/config.php @@ -0,0 +1,77 @@ +/imap or to syslog +$config['imap_debug'] = true; + +// TCP port used for IMAP connections +$config['default_port'] = 3143; + +// SMTP server host (for sending mails). +// To use SSL/TLS connection, enter hostname with prefix ssl:// or tls:// +// If left blank, the PHP mail() function is used +// Supported replacement variables: +// %h - user's IMAP hostname +// %n - hostname ($_SERVER['SERVER_NAME']) +// %t - hostname without the first part +// %d - domain (http hostname $_SERVER['HTTP_HOST'] without the first part) +// %z - IMAP domain (IMAP hostname without the first part) +// For example %n = mail.domain.tld, %t = domain.tld +$config['smtp_server'] = 'greenmail'; + +// SMTP port (default is 25; use 587 for STARTTLS or 465 for the +// deprecated SSL over SMTP (aka SMTPS)) +$config['smtp_port'] = 3025; + +// SMTP username (if required) if you use %u as the username Roundcube +// will use the current username for login +$config['smtp_user'] = ''; + +// SMTP password (if required) if you use %p as the password Roundcube +// will use the current user's password for login +$config['smtp_pass'] = ''; + +$config['smtp_debug'] = true; + +// provide an URL where a user can get support for this Roundcube installation +// PLEASE DO NOT LINK TO THE ROUNDCUBE.NET WEBSITE HERE! +$config['support_url'] = ''; + +// Name your service. This is displayed on the login screen and in the window title +$config['product_name'] = 'Roundcube Webmail'; + +// this key is used to encrypt the users imap password which is stored +// in the session record (and the client cookie if remember password is enabled). +// please provide a string of exactly 24 chars. +// YOUR KEY MUST BE DIFFERENT THAN THE SAMPLE VALUE FOR SECURITY REASONS +$config['des_key'] = 'rcmail-!24ByteDESkey*Str'; + +// List of active plugins (in plugins/ directory) +$config['plugins'] = array( + 'archive', + 'zipdownload', +); + +// skin name: folder from skins/ +$config['skin'] = 'larry'; + diff --git a/greenmail-docker/clients/roundcube/docker-compose.yml b/greenmail-docker/clients/roundcube/docker-compose.yml new file mode 100644 index 0000000000..4d7d9ae590 --- /dev/null +++ b/greenmail-docker/clients/roundcube/docker-compose.yml @@ -0,0 +1,17 @@ +version: '2' +services: + greenmail: + image: greenmail/standalone:1.6.0-SNAPSHOT + environment: + # Enable GreenMail verbose mode + - GREENMAIL_OPTS=-Dgreenmail.setup.test.all -Dgreenmail.hostname=0.0.0.0 -Dgreenmail.auth.disabled -Dgreenmail.verbose + ports: + - "3025:3025" + - "3143:3143" + roundcube: + build: + context: . + ports: + - "4080:80" + links: + - greenmail diff --git a/greenmail-docker/clients/roundcube/php.ini b/greenmail-docker/clients/roundcube/php.ini new file mode 100644 index 0000000000..a63a39fe9e --- /dev/null +++ b/greenmail-docker/clients/roundcube/php.ini @@ -0,0 +1,6 @@ +error_reporting=E_ALL & ~E_NOTICE +memory_limit=128M +upload_max_filesize=128M +post_max_size=128M +max_execution_time=60 +date.timezone=Europe/Berlin diff --git a/greenmail-docker/clients/roundcube/run.sh b/greenmail-docker/clients/roundcube/run.sh new file mode 100755 index 0000000000..583e93cede --- /dev/null +++ b/greenmail-docker/clients/roundcube/run.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +cmd_php="php -S 0.0.0.0:80 -c php.ini -t /www" + +genpasswd() { + export LC_CTYPE=C + local l=$1 + [ "$l" == "" ] && l=16 + cat /dev/urandom | tr -dc A-Za-z0-9_ | head -c ${l} +} + +wait_for_php() { + until curl --output /dev/null --silent --get --fail "http://localhost"; do + echo "waiting for php to start..." + sleep 2 + done +} + +init_config() { + :>/www/logs/errors + export DES_KEY=$(genpasswd 24) + cat config.php>/www/config/config.inc.php + echo "/config/__config.php + for e in $(env); do + case $e in + RC_*) + e1=$(expr "$e" : 'RC_\([A-Z_]*\)') + e2=$(expr "$e" : '\([A-Z_]*\)') + echo "\$config['${e1,,}'] = getenv('$e2');">>/config/__config.php + esac + done +} + +init_db() { + $cmd_php & + wait_for_php + pid_php=$! + echo "/config/___setup.php + curl --silent --output /dev/null --data "initdb=Initialize+database" http://localhost/installer/index.php?_step=3 + kill $pid_php + wait $pid_php 2>/dev/null + rm -rf /www/installer /config/___setup.php +} + +init_config + +if [ ! -f .initialized ]; then + init_db + touch .initialized +fi + +$cmd_php & +tail -f /www/logs/errors