How to Use Spring Mail against DevNull SMTP

Test your Spring Mail Application without Spamming Anyone

Raise your hand if you’ve ever spammed an entire department or company while testing email functionality in an application.  I think we’ve all done it at one point or another.  So today, we’re going to write a quick application demonstrating how to send our test emails to DevNull SMTP.  There are other options for test SMTP servers.  Many of them seem to be offered as a SAAS product and if you’re testing internal company emails, I feel like this raises security and privacy concerns.  Best to just send these test emails into the ether of your local machine.

The Application

Let’s start by having a look at our email application.  I used the Spring Initializr to create a Spring Boot application using Gradle, the Spring Boot 2.1.6 and Java 8 and added the Web, Java Mail Sender, and Thymeleaf dependencies.

We have a very simple Email class for getting our email information from the front-end.  On a side note, there’s not an ounce of validation here.  Validating email addresses is surprisingly complicated and there’s quite a bit of debate on the topic.  I decided to leave it out of this post entirely because it’s potentially quite distracting.

public class Email {
   private String toAddress = "";
   private String fromAddress = "";
   private String subject = "";
   private String message = "";

   // Standard getters/setters and toString
}

The controller is equally straightforward.

@Controller
public class EmailController {
   @Autowired
   private EmailService emailService;

   @GetMapping("/compose")
   public String composeEmail(@ModelAttribute Email email) {
      return "compose";
   }
   
   @PostMapping("/send")
   public String saveWidget(@Valid Email email, Model model) {
      boolean result = emailService.sendEmail(email);
      model.addAttribute("email", email);
      return "sent";
   }
}

The work of sending our email is done in an EmailService class and just sends the email off.

@Service
public class EmailService {
   @Autowired
   private JavaMailSender mailSender;
   
    public boolean sendEmail(Email email) {
       SimpleMailMessage message = new SimpleMailMessage();
       message.setFrom(email.getFromAddress());
       message.setTo(email.getToAddress());
       message.setSubject(email.getSubject());
       
       message.setText(email.getMessage());
       try {
          mailSender.send(message);
          return true;
       } catch (MailException e) {
          e.printStackTrace();
          return false;
       }
    }
}

We also have Thymeleaf templates for entering the email information and for displaying the sent message afterward.

Running DevNull SMTP

When you download DevNull SMTP and extract it to a directory, you get a jar file and a bat file.  If you’re on Windows like I am, just run the bat file.  I guess if you’re on Mac or *nix you’ve got to fire that jar up yourself.

The application will open, but the SMTP server is not started.  You can change the port here and give it a location to save the email messages.  You can also set it up to only accept emails from specific domains.

DevNullSMTP_NotStarted

Just click Start Server when you’re ready to run.

Configuring Spring Mail

Now that we’ve got DevNull SMTP running, let’s head back to the application and configure Spring Mail in our application.properties.  It’s extremely simple.  We just point it at localhost and set the listening port we chose and that’s it.  We don’t need to configure anything else.

spring.mail.host=localhost
spring.mail.port=25

Sending Email

At this point, we can start our application, point our browser to http://localhost:8080/compose and send an email.

If we go over to DevNull SMTP, we can see our message show up in the SMTP Log.

DevNullSMTP_SMTPLog

The Last Message tab will show us the subject and message of the email.

DevNullSMTP_LastMessage

Saving the incoming messages is useful if you need to check out the formatting.  The emails are saved in a .eml file so you can open them in an email client.  One gotcha is that the directory you specify in Save incoming messages to must already exist.

Conclusion

In this post, we looked at an easy way to avoid the embarrassment of accidentally sending test emails to bewildered recipients in our organization.  We achieved this by using DevNull SMTP, but there are a variety of other options including cloud-based services.

The full example code is available over on GitHub.