package testutil.testrules;
import org.assertj.core.util.Preconditions;
import org.junit.rules.ExternalResource;
import org.junit.rules.TestRule;
import org.subethamail.smtp.TooMuchDataException;
import org.subethamail.smtp.server.SMTPServer;
import org.subethamail.wiser.Wiser;
import org.subethamail.wiser.WiserMessage;
import javax.annotation.Nonnull;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.List;
import static java.lang.String.format;
import static org.assertj.core.api.Assertions.assertThat;
/**
* SmtpServerRule - a TestRule wrapping a Wiser instance (a SMTP server in Java) started and stoped right before and after each test.
* <br/>
* SmtpServerRule exposes the same methods as the {@link Wiser} instance by delegating the implementation to the instance. These methods, however, can not be
* used outside a JUnit statement (otherwise a {@link IllegalStateException} is raised).
* <br/>
* The {@link Wiser} instance can be directly retrieved but also only from inside a JUnit statement.
*
* @author Sébastien Lesaint
*/
public class SmtpServerRule extends ExternalResource implements TestRule {
private final SmtpServerSupport SmtpServerSupport;
private Wiser wiser;
public SmtpServerRule(@Nonnull SmtpServerSupport SmtpServerSupport) {
this.SmtpServerSupport = Preconditions.checkNotNull(SmtpServerSupport);
}
@Override
protected void before()
throws Throwable {
this.wiser = new Wiser();
this.wiser.setPort(SmtpServerSupport.getPort());
this.wiser.setHostname(SmtpServerSupport.getHostname());
this.wiser.start();
}
@Override
protected void after() {
this.wiser.stop();
}
@Nonnull
public Wiser getWiser() {
checkState("getWiser()");
return this.wiser;
}
@Nonnull
public List<WiserMessage> getMessages() {
checkState("getMessages()");
return wiser.getMessages();
}
@Nonnull
public MimeMessage getOnlyMessage()
throws MessagingException {
checkState("getMessages()");
List<WiserMessage> messages = getMessages();
assertThat(messages).hasSize(1);
MimeMessage mimeMessage = messages.iterator().next().getMimeMessage();
mimeMessage.removeHeader("Message-ID");
return mimeMessage;
}
@Nonnull
public SMTPServer getServer() {
checkState("getServer()");
return wiser.getServer();
}
public boolean accept(String from, String recipient) {
checkState("accept(String, String)");
return wiser.accept(from, recipient);
}
public void deliver(String from, String recipient, InputStream data)
throws TooMuchDataException, IOException {
checkState("deliver(String, String, InputStream)");
wiser.deliver(from, recipient, data);
}
public void dumpMessages(PrintStream out)
throws MessagingException {
checkState("dumpMessages(PrintStream)");
wiser.dumpMessages(out);
}
private void checkState(String method) {
if (this.wiser == null) {
throw new IllegalStateException(format("%s must not be called outside of a JUnit statement", method));
}
}
}