Test email with Subethamail – Mock email without changing code

Standard

Most of the applications require notifications to be sent to stakeholders (users/administrators/owners) about application events. The notifications may be in the form of SMS, showing popup messages or email. Out of the various notification options described earlier, Email is the most traditional option. In case of Java, the built-in package of javax.mail provides standard APIs to send email including features of Sending attachments, bcc etc.

While there are Open Source / Freeware / Commercial email servers are available, it is always inconvenient to setup a SMTP server for development. On top of that, security policies at Organization level, prevent developers from accessing Enterprise Email server for development testing. This forces, either commenting code responsible for sending email or turning off the feature in development mode. Few, prefer to wrap an exception due to Email server unavailability and ignore it completely. Here is the list of side-effects, one can notice due to ignoring such a crucial functionality.

Silent Failure
Silently suppressing exception raised from Mail API in development mode can delay the exception handling required for genuine issues that might occur at Production environment.

Log Pile-up
Developers tend to execute unfinished code many times a day to achieve desired results. In addition to that, developers prefer the logs are always in verbose mode while coding to trace the code execution path. Exception stack traces from Mail API due to unavailability of Email server, leads to filling up Log files with useless stack trace. Developers have to skip many blocks in the log while doing the analysis and that’s very inconvenient.

Mail Preview
This may not be a real problem, if you are using Email designing tools with preview options. But most of the emails sent out from Enterprise applications are hand coded without using any specialized editor. At the end, developers will have to either wait for actual Email to arrive or trust on what they have coded in the application. This may result in poorly designed Email due to unreadable format.

Delayed issue
Another caveat of ignoring Email failure can lead to delay in fixing the email content. An email may contain link for account activation or password reset or discount coupon. All of these functionalities are not tested due to inability to send email. A developer may have made mistake, while generating these emails and may have missed on one or more data parameters OR the values are incorrect. Such behavior may result into leaking defects to production systems.

To address all the above listed issues, it is necessary to test the entire functionality at the development time without compromising Organization security policy and upsetting System administrators. In addition to that, any mistake on developers part should not result into Spam emails being generated. Also mocking an Email component has all the similar issues described above.

Fortunately, there exists a solution – Subethasmtp. It allows to setup SMTP server using simple Java APIs and provides much finer control over the email contents. Developer can continue to code assuming that an email server is available at the development time. The application can continue to send emails as expected and all emails will be caught by subethasmtp.

Example
Create a maven project and add following dependency to the project.


   org.subethamail
   subethasmtp
   3.1.3

Lets create simple server, which listens on default port – 25. Note that below given code is a simple illustration of how to use subethasmtp. It is possible to accept/reject email based on sender and recipient.

private void setupSMTPServer() {
  SMTPServer server = new SMTPServer(new SimpleMessageListenerAdapter(new SimpleMessageListener() {

  @Override
  public void deliver(String from, String recipient, InputStream data) 
    throws TooMuchDataException, IOException {
    System.out.print("Mail received from : " + from + " \n recipient: " + recipient);
  }

  @Override
  public boolean accept(String from, String recipient) {
    return true;
  }
  }));

  server.setHostName("localhost");
  server.setPort(25);
  server.start();
  System.setProperty("mail.smtp.host", "localhost");
}

Using Java Mail API to send email. Below given code demonstrates simple email sending functionality.

private void sendEmail(){
  Properties props = System.getProperties();
  Session session = Session.getInstance(props);
  MimeMessage message = new MimeMessage(session);
  try {
    message.setFrom(new InternetAddress("[email protected]"));
    message.addRecipient(Message.RecipientType.TO, new InternetAddress("[email protected]"));
    message.setHeader("x-local-message", "Hi there.");
    message.setText("Hi mail using OS solution!!!");
    Transport.send(message);
  } catch (Exception e) {
    e.printStackTrace();
  }	
}

Once above code executes, you will notice the console output

Mail received from : [email protected] 
 recipient: [email protected]
Be Sociable, Share!

Leave a Reply

Your email address will not be published. Required fields are marked *