undo
Go Beyond the Code
arrow_forward_ios

Integrating IMAP and SMTP in Java using Jakarta-Mail API

May 29, 2024

Introduction

At Ensolvers, we have been working for a long time in developing a custom Application Tracking System project. In that context, the initial requirement was to integrate it with GMail, so we proceeded to implement that integration via their Java SDK. However, when the platform started to grow, we decided to migrate to a platform-independent implementation of the Internet Messaging Access Protocol, thus allowing us to connect different email providers to implement our automations.

This article outlines the steps to integrate IMAP in Java using the jakarta-mail API, covering the addition of the library, fetching emails, retrieving specific messages, sending emails, and replying to emails.

Solution

In terms of our service, the main use cases are the following:

  • Fetch unread messages from a concrete email account: The service should be able to read new messages and keep track of them locally.
  • Send a new message to a specific email address: Given an email address, the service should allow the user of the application to send emails to it.
  • Reply to a received message: Given an existing email, the service should reply to its address while maintaining the message thread.

Adding the Library

In order to fetch and send emails in Java, we can make use of the jakarta-mail-api library and Eclipse’s angus-mail for the implementation. For a Maven project, this can be done by adding the following dependency in the pom.xml file:

Now, let's proceed to the operation implementation

Creating the service class

Let’s start by defining a class that will encapsulate the methods described above. For this example, we are explicitly using Gmail as the provider and we will receive the username and password for instantiating the IMAP client. This class also includes some useful methods that we are going to use in the future.

Fetching Email Messages

We can now implement our first method which takes care of email fetching. The basic steps are the following:

  1. Get and connect to the email store using the credentials defined in the properties object. The try-with-resources construct takes care of closing the store for us after we are done.
  2. Open the inbox folder.
  3. Fetch all messages from the open folder.
  4. Cast every message to MimeMessage class; the call to the constructor fetches most of the fields of the message that we need into memory, so we can access them after closing the folder. Keep in mind this might be an expensive operation if there are a lot of messages.

Also note that we are logging the errors here as a matter of simplicity. A better approach may be to throw a custom exception.

Fetching a Particular Email

To fetch a particular email, we can use the MIME Message-Id string, this can be achieved by applying the MessageIDTerm filter:

We can also fetch a message by its position in the inbox:

We can also limit the email listing based on some criteria, we can use and combine SearchTerm objects:

Sending an Email

Sending an email involves creating a MimeMessage and using the Transport class to send it. We also need to configure the SMTP parameters depending on the provider we connect to.

Responding to a Specific Email

When replying to a specific email, if we have the original message object, we can call the reply()  method of the MimeMessage instance to build a reply message. The library takes care of adding the required attributes. If we are crafting the message manually, we need to set the References and In-Reply-To headers explicitly to maintain the message as part of a thread.

The replyToMessage function shown below does the following:

  1. Takes an originalMessageId as an argument.
  2. Fetches the message matching that id from the Inbox folder.

Creates and sends a response using the retrieved message. The body argument represented the body of the reply.

Conclusion

Integrating a service to interact with IMAP and SMTP providers in Java using the jakarta-mail API provides a flexible and provider-independent solution for email handling. By following the steps outlined in this article, developers can easily add the necessary library, fetch emails, retrieve specific messages, send emails, and reply to emails with appropriate references. This approach ensures that the implementation remains adaptable to various email providers, promoting long-term maintainability and scalability.

To learn more about this topic, click here.
Facundo Juárez
Software Engineer & Solver

Start Your Digital Journey Now!

Which capabilities are you interested in?
You may select more than one.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.