This is an automated email from the ASF dual-hosted git repository. btellier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 62f0ba34ae60b51fd7830fac4359450f0c5604a2 Author: Tran Tien Duc <[email protected]> AuthorDate: Thu Aug 22 14:36:15 2019 +0700 JAMES-2865 Implement default behavior of MockSMTPServer mock server acts like a normal server, received mails from smtp clients --- .../james/mock/smtp/server/MockMessageHandler.java | 78 ++++++++++++ .../james/mock/smtp/server/MockSMTPServer.java | 56 +++++++++ .../james/mock/smtp/server/MockSMTPServerTest.java | 138 +++++++++++++++++++++ 3 files changed, 272 insertions(+) diff --git a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockMessageHandler.java b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockMessageHandler.java new file mode 100644 index 0000000..7322fa7 --- /dev/null +++ b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockMessageHandler.java @@ -0,0 +1,78 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.mock.smtp.server; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +import javax.mail.internet.AddressException; + +import org.apache.commons.io.IOUtils; +import org.apache.james.core.MailAddress; +import org.apache.james.mock.smtp.server.model.Mail; +import org.subethamail.smtp.MessageHandler; +import org.subethamail.smtp.RejectException; +import org.subethamail.smtp.TooMuchDataException; + +public class MockMessageHandler implements MessageHandler { + + private static final int ARGUMENT_SYNTAX_ERROR_501 = 501; + + private final Mail.Envelope.Builder envelopeBuilder; + private final Mail.Builder mailBuilder; + private final ReceivedMailRepository mailRepository; + + MockMessageHandler(ReceivedMailRepository mailRepository) { + this.mailRepository = mailRepository; + this.envelopeBuilder = new Mail.Envelope.Builder(); + this.mailBuilder = new Mail.Builder(); + } + + @Override + public void from(String from) throws RejectException { + try { + envelopeBuilder.from(new MailAddress(from)); + } catch (AddressException e) { + throw new RejectException(ARGUMENT_SYNTAX_ERROR_501, "invalid email address supplied"); + } + } + + @Override + public void recipient(String recipient) throws RejectException { + try { + envelopeBuilder.addRecipient(new MailAddress(recipient)); + } catch (AddressException e) { + throw new RejectException(ARGUMENT_SYNTAX_ERROR_501, "invalid email address supplied"); + } + } + + @Override + public void data(InputStream data) throws RejectException, TooMuchDataException, IOException { + mailBuilder.message(IOUtils.toString(data, StandardCharsets.UTF_8)); + } + + @Override + public void done() { + Mail mail = mailBuilder.envelope(envelopeBuilder.build()) + .build(); + mailRepository.store(mail); + } +} diff --git a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockSMTPServer.java b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockSMTPServer.java new file mode 100644 index 0000000..96246c4 --- /dev/null +++ b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockSMTPServer.java @@ -0,0 +1,56 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.mock.smtp.server; + +import java.util.List; + +import org.apache.james.mock.smtp.server.model.Mail; +import org.apache.james.util.Port; +import org.subethamail.smtp.server.SMTPServer; + +class MockSMTPServer { + + private final SMTPServer server; + private final ReceivedMailRepository mailRepository; + + MockSMTPServer() { + this.mailRepository = new ReceivedMailRepository(); + this.server = new SMTPServer(ctx -> new MockMessageHandler(mailRepository)); + this.server.setPort(0); + } + + List<Mail> listReceivedMails() { + return mailRepository.list(); + } + + void start() { + if (!server.isRunning()) { + server.start(); + } + } + + Port getPort() { + return Port.of(server.getPort()); + } + + void stop() { + server.stop(); + } +} diff --git a/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/MockSMTPServerTest.java b/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/MockSMTPServerTest.java new file mode 100644 index 0000000..c2c5bdc --- /dev/null +++ b/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/MockSMTPServerTest.java @@ -0,0 +1,138 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.mock.smtp.server; + +import static org.apache.james.mock.smtp.server.Fixture.ALICE; +import static org.apache.james.mock.smtp.server.Fixture.BOB; +import static org.apache.james.mock.smtp.server.Fixture.DOMAIN; +import static org.apache.james.mock.smtp.server.Fixture.JACK; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.net.ConnectException; +import java.util.List; + +import javax.mail.internet.MimeMessage; + +import org.apache.james.core.MailAddress; +import org.apache.james.core.builder.MimeMessageBuilder; +import org.apache.james.mock.smtp.server.model.Mail; +import org.apache.james.mock.smtp.server.model.Response; +import org.apache.james.util.MimeMessageUtil; +import org.apache.james.util.Port; +import org.apache.james.utils.SMTPMessageSender; +import org.apache.mailet.base.test.FakeMail; +import org.awaitility.Awaitility; +import org.awaitility.Duration; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.testcontainers.shaded.com.google.common.collect.ImmutableList; + +import com.github.fge.lambdas.Throwing; + +class MockSMTPServerTest { + + private static final Response.SMTPStatusCode SERVICE_NOT_AVAILABLE_421 = Response.SMTPStatusCode.of(421); + + @Nested + class NormalBehaviorTests { + private MockSMTPServer mockServer; + + @BeforeEach + void setUp() { + mockServer = new MockSMTPServer(); + mockServer.start(); + } + + @AfterEach + void tearDown() { + mockServer.stop(); + } + + @Test + void serverShouldReceiveMessageFromClient() throws Exception { + SMTPMessageSender sender = new SMTPMessageSender(DOMAIN) + .connect("localhost", mockServer.getPort()); + + MimeMessage message = MimeMessageBuilder.mimeMessageBuilder() + .setSubject("test") + .setText("any text") + .build(); + + FakeMail mail = FakeMail.builder() + .name("name") + .sender(BOB) + .recipients(ALICE, JACK) + .mimeMessage(message) + .build(); + + sender.sendMessage(mail); + + Awaitility.await().atMost(Duration.TEN_SECONDS) + .untilAsserted(() -> { + List<Mail> mails = mockServer.listReceivedMails(); + Mail.Envelope expectedEnvelope = new Mail.Envelope( + new MailAddress(BOB), + ImmutableList.of(new MailAddress(ALICE), new MailAddress(JACK))); + assertThat(mails) + .hasSize(1) + .allSatisfy(Throwing.consumer(assertedMail -> { + assertThat(assertedMail.getEnvelope()).isEqualTo(expectedEnvelope); + assertThat(assertedMail.getMessage()).contains(MimeMessageUtil.asString(message)); + })); + }); + } + } + + @Test + void serverStartShouldOpenASmtpPort() { + MockSMTPServer mockServer = new MockSMTPServer(); + mockServer.start(); + + assertThatCode(() -> new SMTPMessageSender(DOMAIN) + .connect("localhost", mockServer.getPort())) + .doesNotThrowAnyException(); + } + + @Test + void serverShouldBeAbleToStop() { + MockSMTPServer mockServer = new MockSMTPServer(); + mockServer.start(); + Port port = mockServer.getPort(); + + mockServer.stop(); + assertThatThrownBy(() -> new SMTPMessageSender(DOMAIN) + .connect("localhost", port)) + .isInstanceOf(ConnectException.class) + .hasMessage("Connection refused (Connection refused)"); + } + + @Test + void serverStartShouldBeIdempotent() { + MockSMTPServer mockServer = new MockSMTPServer(); + mockServer.start(); + + assertThatCode(() -> mockServer.start()) + .doesNotThrowAnyException(); + } +} \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
