Search code examples
springspring-bootsmtpspring-testgreenmail

Springboot Testing via Greenmail


I tried to test my Gmail smtp in my Spring-Application and followed this Tutorial. I have implemented it as specified in the tutorial, but my EmailService throws a MailSendException:

org.springframework.mail.MailSendException: Mail server connection failed; nested exception is com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 2525; timeout 5000;
  nested exception is:
    java.net.ConnectException: Connection refused: connect. Failed messages: com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 2525; timeout 5000;
  nested exception is:
    java.net.ConnectException: Connection refused: connect
; message exception details (1) are:
Failed message 1:
com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 2525; timeout 5000;
  nested exception is:
    java.net.ConnectException: Connection refused: connect
    at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2210)
    at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:722)
    at javax.mail.Service.connect(Service.java:342)

Has anyone a tip how to solve this? (Never tested something like SMTP/Email and therefore just followed the tutorial above. EDIT: I can send emails without any problem manually, but I need to test it. my application.yml:

spring.mail.host: smtp.gmail.com
spring.mail.port: 587
spring.mail.properties.mail.smtp.starttls.enable: true
spring.mail.username: ************@gmail.com
spring.mail.password: ***************
spring.mail.properties.mail.smtp.starttls.required: true
spring.mail.properties.mail.smtp.auth: true
spring.mail.properties.mail.smtp.connectiontimeout: 5000
spring.mail.properties.mail.smtp.timeout: 5000
spring.mail.properties.mail.smtp.writetimeout: 5000

Solution

  • From the log you can see, that Spring is trying to connect to port 2525 but can't make connection. That means that there's no running mail server on this port, during test execution - which should be provided by JUnit Rule implementation (If you're using JUnit5 use Extensions)

    Make sure that your test configuration is properly setup. That means, check whether your test code, e.g.

    @Rule
    public SmtpServerRule smtpServerRule = new SmtpServerRule(2525);
    

    matches

    src/test/resources/application.yml

    spring:
      mail:
        default-encoding: UTF-8
        host: localhost
        jndi-name:
        username: username
        password: secret
        port: 2525
        properties:
          mail:
            debug: false
            smtp:
              debug: false
              auth: true
              starttls: true
        protocol: smtp
        test-connection: false
    

    I would also recommend to update the code from the Tutorial and add test user - as it could be used with secured protocols.

    public class SmtpServerRule extends ExternalResource {
    // omitted for brevity
    @Override
    protected void before() throws Throwable {
       super.before();
       smtpServer = new GreenMail(new ServerSetup(port, null, "smtp"));
       smtpServer.addUser("username", "secret");
       smtpServer.start();
    }
    // omitted for brevity
    }
    

    Also, refer to the official GreenMail documentation for more specific setup.