Building on my previous tutorial about sending emails with PHPMailer, this guide explores the nuances of email delivery using Java and SMTP.
We will learn how to send emails using Java and choose the proper library and SMTP service for your email implementations. We will look at how to send emails using the following methods and libraries:
- Jakarta email
- Java Spring Mail
- Apache Common Mail
- Simple Java Mail
- Spring Mail + UniOne SMTP
Without wasting much time, let’s gear up and get right in!
SMTP vs. ESP-provided APIs: Differences, Benefits, and Drawbacks
When sending emails from applications or websites, developers typically choose between two methods: traditional SMTP and modern Email APIs from Email Service Providers. While both are used to deliver emails, they are different in how they are implemented and are aimed at different use cases. Let's take the time to understand their differences, benefits, and drawbacks in the coming subsections.
Understanding SMTP
SMTP has been the foundation of email communication since the 1980s, operating through a direct connection between sender (an email client app or an intermediate SMTP server) and recipient (always an SMTP server, either final destination or intermediate) with a structured command-response workflow. Its widespread adoption makes it relatively easy to set up with minimal technical expertise.
SMTP's greatest strengths include platform independence (working consistently across different systems) and straightforward troubleshooting due to the fact that the protocol commands are human-readable.
However, using a plain SMTP connection in your app doesn’t work very well for bulk emails due to its sequential process, which can create performance issues. If you need advanced features like mass sending, variable substitution, or delivery status tracking, you’ll have to implement them by yourself.
The Rise of Email APIs
Email APIs came in as a modern solution to email delivery, allowing applications to send emails using standard HTTP API requests. Email APIs are usually offered by Email Service Providers (ESPs) such as Mailchimp, SendGrid, or UniOne.
This method offers notably faster delivery for bulk emails by handling multiple requests in parallel without establishing new connections for each email. API methods provide easy template management, personalisation and message manipulation. You also get better security through API keys for authentication, providing protection beyond basic username/password combinations. Besides, ESPs completely remove the headaches of managing your own email infrastructure.
Most ESP APIs also offer comprehensive email analytics functions, allowing developers to track important metrics like delivery, open, and click-through rates and receive event notifications in real time.
The flexibility of Email APIs allows for sophisticated workflows, flexible content customization, and easy integration with other services. However, implementation requires programming knowledge and creates a dependency on third-party services, which may experience disruptions or updates affecting your application.
How do you make the right choice?
Well, this greatly depends on your use case. SMTP remains excellent for straightforward setups without extensive development needs. Organizations with minimal email requirements or those needing platform independence across diverse systems often find SMTP the perfect choice.
Email APIs excel at large-scale operations and complex flows but require more technical expertise to set up, as mentioned earlier.
Luckily, some providers offer both Email API and SMTP Service options, allowing you to select the best method for your project's requirements.
Main Java Email Libraries for sending emails via Java
This section will cover the different Java email libraries highlighted in the introduction, discussing their distinct features and benefits, and basic usage. Note that the code samples provided relate to the plain SMTP connection option described above.
Sending emails using Jakarta Mail (Formerly JavaMail)
Jakarta Mail is a comprehensive Java framework that allows you to send emails via SMTP or receive them via IMAP or POP. You’ll find it helpful if you run enterprise applications that require advanced email capabilities.
Main features
- Integration with Jakarta EE ecosystem
- Support for various message types (plain text, HTML, multipart, etc.)
- STARTTLS and implicit SSL/TLS support
- Attachment handling
- Asynchronous sending
- OAuth2 support
Setting up Jakarta Mail
There are multiple options for new users to set up Jakarta Mail. Let’s examine them:
1. Download the latest version from the official GitHub Page.
Note: The latest version is 2.1.3 as of the time of writing; you may need to view the changelog for a summary of new features in later versions.
2. Use dependency managers like Maven or Gradle (recommended):
-
Maven
Get started by creating a folder, cd into it, and run the command below to generate a pom.xml file:
mvn archetype:generate |
Once the installation is concluded, you get this build success message on your terminal:
Now, in the pom.xml file, you'll find the dependencies below automatically generated for you:
<?xml version="1.0" encoding="UTF-8"?> |
-
Gradle
Get started by creating a folder, cd into it, and run the command below to generate a basic project structure:
gradle init |
Once the installation is completed, you get this build success message on your terminal:
When you open the file in your IDE, you’ll see the project structure. Navigate to the build.gradle file and paste in the code below:
plugins { |
Sending an email using Jakarta
Now that we have the installation complete, it’s time for your favorite part: sending out emails :). To do this, navigate to the App.java file, as shown below:
Next, paste in the code below:
package org.unione; |
For our email host, you can either use UniOne (as shown in the code comment) or any other email hosting provider of your choice.
You can run the code using the Main.java command. Alternatively, use the following commands if you installed Maven or Gradle:
# Maven |
Sending emails using Java Spring Mail
Spring Mail is a module within the Spring Framework that provides a higher-level abstraction over Jakarta Mail. It's ideal for Spring-based applications and offers easy integration with other Spring components.
Main features
- Integration with Spring Boot
- Support for template engines (Thymeleaf, Freemarker, etc.)
- Simplified configuration via application properties
- Asynchronous email sending
- Exception handling through Spring's exception hierarchy
Setting up Spring Mail
To get started, create a new folder in your local machine, cd into it, open it on your command line, and run the command spring init. Add the spring-boot-starter-mail when running the command:
spring init -d=mail --package-name=org.unione <directory> |
The current Spring Boot version is 3.4.4 and this may be subject to change in the future.
Note: Another approach is using the Spring Initializr web tool to generate your project structure and include relevant dependencies, such as the Java Email Sender library.
Sending plain texts using Spring Mail
To send plain-text emails, navigate to the main application file and rename the file to match your use case (I named mine EmailSending.java), then paste in the code below:
package org.mailtrap.sendemail; |
Next, navigate to application.properties file and add the code:
spring.mail.host=smtp.us1.unione.io |
Running your Spring Email Application
To run your application, update your code:
package org.unione.sendemail; |
This code above bootstraps the Spring Boot application and calls the run method to execute the email-sending functionality. Now, run your app using mvn spring-boot:run command.
Sending emails using Apache Commons Email
Apache Commons Email provides a simplified programming interface built on top of Jakarta Mail, making it easier to use for basic email tasks. It also serves as a foundation for other email-sending tools. Developers have leveraged it to create things like mailR (for sending emails in R) and email components for the Play Framework.
Main features
- Simpler API compared to Jakarta Mail
- Support for HTML emails
- Attachment handling
- Embedded image support
- Multipart message support
Setting up Apache Commons Email
According to this Apache Commons user guide, you must choose between Javax org.apache.commons:commons-email2-javax , or Jakarta org.apache.commons:commons-email2-jakarta implementation. Anyone you choose installs the org.apache.commons:commons-email2-core module. Installation is done using Maven.
Adding Dependencies
In your Maven project, locate the pom.xml file and add the dependency:
# Javax |
The latest Apache Commons Email version is 2.0.0-M1 and this may be subject to change in the future.
Adding email with SMTP details to the main application file
To send a plain text email, use the code below:
Package app; |
To send an HTML email, change setMsg() to setHtmlMsg().
Sending emails using Simple Java Mail
This library lives up to its name. It is simple to use and better suited for small projects.
Main features
- Extremely clean and fluent API
- Support for HTML emails with inline images
- Attachment handling
- DKIM signing
- Support for multiple recipients
- SSL/TLS encryption
Setting up Simple Java Mail
To set up Simple Java Mail, add the dependency below to your project:
Maven
#pom.xml <dependency> |
Gradle
implementation 'org.simplejavamail:simple-java-mail:8.12.2' |
Sending a basic email
To send a basic email, navigate to your Main.java file and paste in the code:
import org.simplejavamail.api.email.Email; |
To send emails in HTML, change the .withPlainText to .withHTMLText.
Comparison and Use Cases
Here's a quick comparison table for the libraries described above:
Library |
Complexity |
Best For |
Jakarta Mail |
High |
Enterprise applications requiring advanced email features |
Spring Mail |
Medium |
Spring-based applications |
Apache Commons Email |
Low |
Applications requiring basic email functionality |
Simple Java Mail |
Very Low |
Quick implementation with minimal code |
How to configure and set up email sending in Java using SMTP
Let's look at how to configure and set up email functionality using Spring Mail as a Java backend and UniOne as an email service provider. I chose this library due to its ease of use and compatibility with Spring Boot.
Prerequisites
- JDK 8 or higher
- Maven or Gradle for dependency management
- SMTP server access credentials (see below)
- Spring Boot (recommended for easier configuration)
- UniOne account
Setting up a UniOne Account
To set up a UniOne account, follow the steps below:
1. Create a free UniOne account. This is what your account dashboard looks like after signing up:
2. Verify your sender domain. Learn how to do this in this video.
3. Next, get your SMTP credentials. In UniOne, they include your username (user ID) and password (API key)
Note: keep your API Key private, and DO NOT share it with anyone.
You can find your user ID at the top left of your dashboard. For your password (API Key), navigate to “Account – Security” on the left navigation panel as shown below:
4. Use our dedicated SMTP debug tool to test out your connection.
Now that we have our SMTP credentials, it‘s time to set it up in our code.
Basic Java Configuration
For Spring Boot applications, configure your SMTP settings in application.properties or application.yml:
# properties spring.mail.host=smtp.us1.unione.io |
If you're not using Spring Boot, you can configure JavaMailSender programmatically:
@Configuration |
Sending Different Types of Emails
Now, let's explore how to send various types of emails using Spring Mail.
Sending Plain Text Emails
The simplest form of email contains only plain text:
@Service |
Sending HTML Emails
For more visually appealing emails, you can send HTML content:
public void sendHtmlEmail(String to, String subject, String htmlContent) throws MessagingException { |
Example HTML content:
String htmlContent = "<html>" |
Sending Emails with Attachments
Adding attachments is common for sharing documents, reports, or images:
public void sendEmailWithAttachment(String to, String subject, String text, |
Let’s break down the code above a little. The code sends an email with an attachment by creating a MimeMessage and using a MimeMessageHelper to set the basic email fields (from, to, subject, and text content), then attaches a file by converting the physical file at the provided path into a FileSystemResource and adding it to the message with a specified name, before finally sending the email through the mailSender and logging the successful operation.
Sending Emails with Embedded Images
Embedding images directly in the email body can be useful for branding and rich content:
public void sendEmailWithEmbeddedImage(String to, String subject, String htmlContent, |
Example usage:
String htmlContent = "<html><body>" |
Handling Multiple Recipients
There are several ways to send emails to multiple recipients using Spring Mail.
Sending to Multiple TO Recipients
Code implementation for sending to multiple TO recipients:
public void sendToMultipleRecipients(String[] to, String subject, String text) { |
Using CC and BCC Recipients
Code implementation for sending to cc and bcc recipients:
public void sendWithCcAndBcc(String to, String[] cc, String[] bcc, String subject, String text) |
Using Address Objects for Complex Scenarios
This code works well in complex scenarios:
public void sendWithPersonalNames(String to, String toPersonal, |
Implementing Bulk Email Sending
When sending emails in bulk, it's important to consider performance, resource usage, and deliverability.
Batch Sending with Spring Mail
Code implementation for sending batch emails with Spring Mail:
@Service |
The BulkEmailService class is a Spring service designed for sending large volumes of emails in batches. It divides the full list of emails into smaller batches of 100 emails each (defined by BATCH_SIZE), then processes each batch separately with a one-second pause between batches to prevent overwhelming the SMTP server.
Best Practices for Bulk Sending
Here are some of the best practices I'd recommend for sending bulk emails:
- Throttle your sending rate: Respect SMTP server limits to avoid getting flagged as a spammer.
- Monitor bounces and invalid addresses: Maintain a clean recipient list to get better deliverability.
- Use BCC for privacy: When sending the same content to multiple recipients, use Blind Carbon Copy to hide selected addressees.
- Consider using an ESP API: For very large volumes, an Email Service Provider API might be more efficient. The good news is that UniOne offers a powerful Email API for more large-scale requirements.
- Implement retry logic: ESPs usually handle temporary failures for you, but for permanent errors with SMTP code 5XX, you must implement retry strategies on your own, depending on the reason of failure.
Implementing Asynchronous Email Sending
Email operations can be time-consuming. To prevent them from blocking your application, implement asynchronous sending.
Using Spring's @Async Annotation
First, enable asynchronous processing in your Spring Boot application:
@Configuration |
Then implement asynchronous email methods:
@Service |
Example usage:
@RestController |
How to test email functionality in a development environment
Now you are done with your email implementation, how do you test your emails?
For basic testing, it is recommended to set up a local SMTP server. Use either a production grade server software like Exim or Postfix, or install a “fake” server like smtp4dev, SMTP Bucket or similar.
For more comprehensive testing, especially in CI/CD pipelines, consider using Email Testing services that provide virtual inboxes and detailed analytics.
How UniOne Can Help
UniOne offers solutions for Java developers that address many of the challenges discussed in this article. You’ll certainly be impressed with our dedicated Email API, which provides a single interface for all your email needs.
But if you prefer the SMTP approach, UniOne's SMTP Service is here for you!
This tutorial isn't exhaustive but offers an insight into what is possible with sending emails using Java. Consult the documentation for each of the libraries to learn more about their strengths.
Conclusion
Implementing email functionality in Java requires careful consideration of the available libraries, configuration options, and best practices. Since I have covered those in this tutorial, I am positive you'll be able to find the right one for your use case.
For instance, if you work with simple applications, Jakarta Mail or Spring Mail provides everything you need. For more complex scenarios, especially those involving high volumes or marketing emails, considering an ESP like UniOne can save development time and improve deliverability.
Whatever approach you choose, remember to focus on security, reliability, and maintainability.
Frequently Asked Questions
How can I handle email bounces and delivery failures?
If using SMTP directly, implement bounce handling via log analysis, however your options will be limited. If using an ESP like UniOne, use the built-in webhooks feature to monitor and react to delivery issues.
Which Java email library should I choose for my project?
The best library depends on your requirements:
- For Spring applications, Spring Mail is the obvious choice
- For standalone applications, Jakarta Mail provides the most flexibility
- For simple use cases, Apache Commons Email or Simple Java Mail can reduce boilerplate
How can I prevent my emails from being marked as spam?
Follow these best practices:
- Authenticate your emails with SPF, DKIM, and DMARC
- Use a consistent sender address
- Ensure your HTML is well-formed
- Include both HTML and plain text versions, maintain text-to-image ratio
- Monitor bounce rates and complaints