JAMES-2262 Add integration testing for SpamAssassin
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/0be23436 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/0be23436 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/0be23436 Branch: refs/heads/master Commit: 0be23436f7df9ac735a27f0be0dbf09c64d33b05 Parents: 4d9d568 Author: quynhn <qngu...@linagora.com> Authored: Thu Dec 14 16:54:19 2017 +0700 Committer: benwa <btell...@linagora.com> Committed: Mon Dec 25 11:24:28 2017 +0700 ---------------------------------------------------------------------- .../james/util/streams/ContainerNames.java | 1 + .../transport/mailets/SpamAssassinTest.java | 158 ++++++++++++------- 2 files changed, 104 insertions(+), 55 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/0be23436/server/container/util-java8/src/test/java/org/apache/james/util/streams/ContainerNames.java ---------------------------------------------------------------------- diff --git a/server/container/util-java8/src/test/java/org/apache/james/util/streams/ContainerNames.java b/server/container/util-java8/src/test/java/org/apache/james/util/streams/ContainerNames.java index 908cea2..2328431 100644 --- a/server/container/util-java8/src/test/java/org/apache/james/util/streams/ContainerNames.java +++ b/server/container/util-java8/src/test/java/org/apache/james/util/streams/ContainerNames.java @@ -25,4 +25,5 @@ public interface ContainerNames { String ELASTICSEARCH = "elasticsearch:2.2.2"; String NGINX = "nginx:1.7.1"; String TIKA = "logicalspark/docker-tikaserver:1.15rc2"; + String SPAMASSASSIN = "dinkel/spamassassin:3.4.0"; } http://git-wip-us.apache.org/repos/asf/james-project/blob/0be23436/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java ---------------------------------------------------------------------- diff --git a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java index 34c9a36..8eb6fea 100644 --- a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java +++ b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java @@ -18,24 +18,21 @@ ****************************************************************/ package org.apache.james.transport.mailets; -import static net.javacrumbs.jsonunit.fluent.JsonFluentAssert.assertThatJson; +import static org.apache.james.MemoryJamesServerMain.SMTP_AND_IMAP_MODULE; +import static org.apache.james.MemoryJamesServerMain.SMTP_ONLY_MODULE; import static org.assertj.core.api.Assertions.assertThat; -import java.util.Optional; - import javax.mail.internet.MimeMessage; import org.apache.james.core.MailAddress; -import org.apache.james.jmap.mailet.VacationMailet; import org.apache.james.mailets.TemporaryJamesServer; import org.apache.james.mailets.configuration.CommonProcessors; import org.apache.james.mailets.configuration.MailetConfiguration; import org.apache.james.mailets.configuration.MailetContainer; import org.apache.james.mailets.configuration.ProcessorConfiguration; -import org.apache.james.transport.mailets.amqp.AmqpRule; import org.apache.james.transport.matchers.All; import org.apache.james.transport.matchers.RecipientIsLocal; -import org.apache.james.transport.matchers.SMTPAuthSuccessful; +import org.apache.james.util.scanner.SpamAssassinInvoker; import org.apache.james.util.streams.ContainerNames; import org.apache.james.util.streams.SwarmGenericContainer; import org.apache.james.utils.DataProbeImpl; @@ -49,36 +46,37 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.RuleChain; import org.junit.rules.TemporaryFolder; +import org.testcontainers.containers.wait.HostPortWaitStrategy; import com.jayway.awaitility.Awaitility; import com.jayway.awaitility.Duration; +import com.jayway.awaitility.core.ConditionFactory; -public class ContactExtractorTest { +public class SpamAssassinTest { + private static final String LOCALHOST_IP = "127.0.0.1"; + private static final int IMAP_PORT = 1143; + private static final int SMTP_PORT = 1025; public static final String JAMES_ORG = "james.org"; public static final String SENDER = "sender@" + JAMES_ORG; public static final String TO = "to@" + JAMES_ORG; - public static final String TO2 = "to2@" + JAMES_ORG; - public static final String CC = "cc@" + JAMES_ORG; - public static final String CC2 = "cc2@" + JAMES_ORG; - public static final String BCC = "bcc@" + JAMES_ORG; - public static final String BCC2 = "bcc2@" + JAMES_ORG; public static final String PASSWORD = "secret"; - public static final String EXCHANGE = "collector:email"; - public static final String ROUTING_KEY = ""; - public SwarmGenericContainer rabbit = new SwarmGenericContainer(ContainerNames.RABBITMQ); - public AmqpRule amqpRule = new AmqpRule(rabbit, EXCHANGE, ROUTING_KEY); - public TemporaryFolder folder = new TemporaryFolder(); + public SwarmGenericContainer spamAssassinContainer = new SwarmGenericContainer(ContainerNames.SPAMASSASSIN) + .withExposedPorts(783) + .withAffinityToContainer() + .waitingFor(new HostPortWaitStrategy()); + + public TemporaryFolder temporaryFolder = new TemporaryFolder(); @Rule - public RuleChain chain = RuleChain.outerRule(rabbit).around(amqpRule).around(folder); + public RuleChain chain = RuleChain.outerRule(temporaryFolder).around(spamAssassinContainer); private TemporaryJamesServer jamesServer; + private ConditionFactory calmlyAwait; @Before public void setup() throws Exception { - String attribute = "ExtractedContacts"; MailetContainer mailets = MailetContainer .builder() .threads(5) @@ -89,16 +87,16 @@ public class ContactExtractorTest { ProcessorConfiguration.builder() .state("transport") .addMailet(MailetConfiguration.builder() - .matcher(SMTPAuthSuccessful.class) - .mailet(ContactExtractor.class) - .addProperty(ContactExtractor.Configuration.ATTRIBUTE, attribute) + .matcher(All.class) + .mailet(SpamAssassin.class) + .addProperty(SpamAssassin.SPAMD_HOST, spamAssassinContainer.getContainerIp()) .build()) .addMailet(MailetConfiguration.builder() .matcher(All.class) - .mailet(AmqpForwardAttribute.class) - .addProperty(AmqpForwardAttribute.URI_PARAMETER_NAME, amqpRule.getAmqpUri()) - .addProperty(AmqpForwardAttribute.EXCHANGE_PARAMETER_NAME, EXCHANGE) - .addProperty(AmqpForwardAttribute.ATTRIBUTE_PARAMETER_NAME, attribute) + .mailet(MailAttributesToMimeHeaders.class) + .addProperty("simplemapping", + SpamAssassinInvoker.FLAG_MAIL_ATTRIBUTE_NAME + ";" + SpamAssassinInvoker.FLAG_MAIL_ATTRIBUTE_NAME + "," + + SpamAssassinInvoker.STATUS_MAIL_ATTRIBUTE_NAME + ";" + SpamAssassinInvoker.STATUS_MAIL_ATTRIBUTE_NAME) .build()) .addMailet(MailetConfiguration.builder() .matcher(All.class) @@ -107,24 +105,20 @@ public class ContactExtractorTest { .build()) .addMailet(MailetConfiguration.builder() .matcher(RecipientIsLocal.class) - .mailet(VacationMailet.class) - .build()) - .addMailet(MailetConfiguration.builder() - .matcher(RecipientIsLocal.class) .mailet(LocalDelivery.class) .build()) .build()) .build(); - jamesServer = TemporaryJamesServer.builder().build(folder, mailets); + jamesServer = TemporaryJamesServer.builder() + .withBase(SMTP_AND_IMAP_MODULE) + .build(temporaryFolder, mailets); + Duration slowPacedPollInterval = Duration.FIVE_HUNDRED_MILLISECONDS; + calmlyAwait = Awaitility.with().pollInterval(slowPacedPollInterval).and().with().pollDelay(slowPacedPollInterval).await(); + DataProbeImpl probe = jamesServer.getProbe(DataProbeImpl.class); probe.addDomain(JAMES_ORG); probe.addUser(SENDER, PASSWORD); probe.addUser(TO, PASSWORD); - probe.addUser(TO2, PASSWORD); - probe.addUser(CC, PASSWORD); - probe.addUser(CC2, PASSWORD); - probe.addUser(BCC, PASSWORD); - probe.addUser(BCC2, PASSWORD); } @After @@ -133,35 +127,89 @@ public class ContactExtractorTest { } @Test - public void recipientsShouldBePublishedToAmqpWhenSendingEmail() throws Exception { + public void spamAssassinShouldAppendNewHeaderOnMessage() throws Exception { + MimeMessage message = MimeMessageBuilder.mimeMessageBuilder() + .setSender(SENDER) + .addToRecipient(TO) + .setSubject("This is the subject") + .setText("This is -SPAM- my email") + .build(); + FakeMail mail = FakeMail.builder() + .mimeMessage(message) + .sender(new MailAddress(SENDER)) + .recipients(new MailAddress(TO)) + .build(); + + try (SMTPMessageSender messageSender = SMTPMessageSender.noAuthentication(LOCALHOST_IP, SMTP_PORT, JAMES_ORG); + IMAPMessageReader imapMessageReader = new IMAPMessageReader(LOCALHOST_IP, IMAP_PORT)) { + + messageSender.sendMessage(mail); + + calmlyAwait.atMost(Duration.ONE_MINUTE).until(messageSender::messageHasBeenSent); + calmlyAwait.atMost(Duration.ONE_MINUTE).until(() -> imapMessageReader.userReceivedMessage(TO, PASSWORD)); + + String receivedHeaders = imapMessageReader.readFirstMessageHeadersInInbox(TO, PASSWORD); + + assertThat(receivedHeaders).contains(SpamAssassinInvoker.FLAG_MAIL_ATTRIBUTE_NAME, SpamAssassinInvoker.STATUS_MAIL_ATTRIBUTE_NAME); + } + } + + @Test + public void spamAssassinShouldAppendNewHeaderWhichDetectIsSpamWhenSpamMessage() throws Exception { + String spamContent = "XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X"; MimeMessage message = MimeMessageBuilder.mimeMessageBuilder() .setSender(SENDER) - .addToRecipient(TO, "John To2 <" + TO2 + ">") - .addCcRecipient(CC, "John Cc2 <" + CC2 + ">") - .addBccRecipient(BCC, "John Bcc2 <" + BCC2 + ">") - .setSubject("Contact collection Rocks") - .setText("This is my email") + .addToRecipient(TO) + .setSubject("This is the subject") + .setText(spamContent) .build(); FakeMail mail = FakeMail.builder() .mimeMessage(message) .sender(new MailAddress(SENDER)) - .recipients(new MailAddress(TO), new MailAddress(TO2), new MailAddress(CC), new MailAddress(CC2), new MailAddress(BCC), new MailAddress(BCC2)) + .recipients(new MailAddress(TO)) .build(); - try (SMTPMessageSender messageSender = SMTPMessageSender.authentication("localhost", 1025, JAMES_ORG, SENDER, PASSWORD); - IMAPMessageReader imap = new IMAPMessageReader("localhost", 1143)) { + + try (SMTPMessageSender messageSender = SMTPMessageSender.noAuthentication(LOCALHOST_IP, SMTP_PORT, JAMES_ORG); + IMAPMessageReader imapMessageReader = new IMAPMessageReader(LOCALHOST_IP, IMAP_PORT)) { messageSender.sendMessage(mail); - Awaitility.await().pollDelay(Duration.FIVE_HUNDRED_MILLISECONDS) - .atMost(Duration.ONE_MINUTE) - .until(() -> imap.userReceivedMessage(TO, PASSWORD)); - - Optional<String> actual = amqpRule.readContent(); - assertThat(actual).isNotEmpty(); - assertThatJson(actual.get()).isEqualTo("{" - + "\"userEmail\" : \"sen...@james.org\", " - + "\"emails\" : [ \"t...@james.org\", \"John To2 <t...@james.org>\", \"c...@james.org\", \"John Cc2 <c...@james.org>\", \"b...@james.org\", \"John Bcc2 <b...@james.org>\" ]" - + "}"); + + calmlyAwait.atMost(Duration.ONE_MINUTE).until(messageSender::messageHasBeenSent); + calmlyAwait.atMost(Duration.ONE_MINUTE).until(() -> imapMessageReader.userReceivedMessage(TO, PASSWORD)); + + String receivedHeaders = imapMessageReader.readFirstMessageInInbox(TO, PASSWORD); + + assertThat(receivedHeaders).contains(SpamAssassinInvoker.FLAG_MAIL_ATTRIBUTE_NAME + ": YES"); + assertThat(receivedHeaders).contains(SpamAssassinInvoker.STATUS_MAIL_ATTRIBUTE_NAME + ": Yes"); } } + @Test + public void spamAssassinShouldAppendNewHeaderWhichNoWhenNonSpamMessage() throws Exception { + MimeMessage message = MimeMessageBuilder.mimeMessageBuilder() + .setSender(SENDER) + .addToRecipient(TO) + .setSubject("This is the subject") + .setText("This is the content") + .build(); + FakeMail mail = FakeMail.builder() + .mimeMessage(message) + .sender(new MailAddress(SENDER)) + .recipients(new MailAddress(TO)) + .build(); + + try (SMTPMessageSender messageSender = SMTPMessageSender.noAuthentication(LOCALHOST_IP, SMTP_PORT, JAMES_ORG); + IMAPMessageReader imapMessageReader = new IMAPMessageReader(LOCALHOST_IP, IMAP_PORT)) { + + messageSender.sendMessage(mail); + + calmlyAwait.atMost(Duration.ONE_MINUTE).until(messageSender::messageHasBeenSent); + calmlyAwait.atMost(Duration.ONE_MINUTE).until(() -> imapMessageReader.userReceivedMessage(TO, PASSWORD)); + + String receivedHeaders = imapMessageReader.readFirstMessageInInbox(TO, PASSWORD); + + assertThat(receivedHeaders).contains(SpamAssassinInvoker.FLAG_MAIL_ATTRIBUTE_NAME + ": NO"); + assertThat(receivedHeaders).contains(SpamAssassinInvoker.STATUS_MAIL_ATTRIBUTE_NAME + ": No"); + } + } } --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org