Guide to Send Emails in Java

Java has been ranking as one of the most popular web programming languages for many years. In this tutorial on sending emails in Java, which was originally published on the Mailtrap blog, we will demonstrate how to build HTML emails with images and attachments and send them using an SMTP server.

The main option is to use a Java API for sending and receiving emails via SMTP, POP3, and IMAP. It is implemented as an optional package compatible with any operating system. At the same time, Jakarta Mail is supplied as a part of Jakarta EE and Java EE platforms. In the earlier releases, the mail package was titled “JavaMail API”. However, since July 2019, the Java software has been further developed by the Eclipse Foundation. This is why the email package also got the new name. All main classes and properties are the same for both JavaMail and Jakarta Mail.

In this article, we will describe the main email package properties and will show how to send different types of messages.

Getting Started with Jakarta Mail (JavaMail)

To start working with Jakarta Mail, first of all, you should insert jakarta.mail.jar file into your CLASSPATH environment. You can download it from the (Jakarta Mail project page on GitHub)[https://javaee.github.io/javamail/].

Besides, you can find Jakarta Mail jar files in the Maven repository and add them to your environment with Maven dependencies:

<dependencies>
    <dependency>
        <groupId>com.sun.mail</groupId>
        <artifactId>jakarta.mail</artifactId>
        <version>1.6.4</version>
    </dependency>
</dependencies>

Please note that if you use JDK 1.5 or older versions, you will also need an implementation of the JavaBeans Activation Framework.

import java.util.*;  
import javax.mail.*;  
import javax.mail.internet.*;  
import javax.activation.*;

Let’s focus on the main steps for preparing HTML email and sending it via an external SMTP server.

Jakarta Mail Classes and Syntax

Before we move to code, let’s review core classes and properties, which are most frequently used for building and sending messages with Jakarta Mail.

Session Class (javax.mail.Session) is the primary one connecting all the properties and defaults. The following methods are used to get the session object:

  • getDefaultInstance() returns the default session

  • public static Session getDefaultInstance/(Properties props)

  • public static Session getDefaultInstance(Properties props, Authenticator auth)

  • getInstance() returns the new session.

  • public static Session getInstance(Properties props)

  • public static Session getInstance(Properties props, Authenticator auth)

Message class (javax.mail.Message) is an abstract class for actually building an email message. We will mostly use its Mime Message (javax.mail.internet.MimeMessage) subclass and its main methods:

  • setFrom(Address[] addresses) sets the “From” header field.

  • public void addFrom(Address[] addresses)

  • addRecipients(Message.RecipientType type, String addresses) adds the given address to the recipient type.

  • public void addRecipient(Message.RecipientType type, Address[] addresses)

  • Message.RecipientType.TO “To”

  • Message.RecipientType.CC “Cc”

  • Message.RecipientType.BCC “Bcc”

  • MimeMessage.RecipientType.NEWSGROUPS “Newsgroups”

  • setSubject(String subject) sets the subject header field.

  • public void setSubject(String subject)

  • setText(String textmessage) sets the text as the message content using text/plain MIME type.

  • public void setText(String textmessage)

  • setContent(Object o, String type) sets this message’s content.

  • public void setContent(Object o, String type)

To send emails via an external SMTP server, use com.sun.mail.smtp package: it is an SMTP protocol provider for the JavaMail API that provides access to an SMTP server.

The main properties are:

  • mail.smtp.user, default username for SMTP.

  • mail.smtp.host, the SMTP server to connect to.

  • mail.smtp.port, the SMTP server port to connect to, if the connect() method doesn’t explicitly specify one. Defaults to 25.

To enable SMTP authentication, set the mail.smtp.auth property or provide the SMTP Transport with a username and password when connecting to the SMTP server.

We will show how to implement it later, when demonstrating code examples.

SMTPMessage class is a specialization of the MimeMessage class for specifying SMTP options and parameters. Simply use this class instead of MimeMessage and set SMTP options using the methods on this class.

  • public SMTPMessage(Session session)

  • Transport ( javax.mail.Transport) is an abstract class for sending messages.

  • Transport.send(message)

To view all classes and their methods, see this section of the Jakarta Mail documentation.

Sending Emails in Java via SMTP

Let’s now review how to implement classes and methods described above and write some Java code to send an email via an external SMTP server.

First of all, we need to define who sends what to whom. So, use the SendEmail public class and set “from” and “to” email addresses and add the subject. With javax.mail.PasswordAuthentication class we will be able to require password authentication to send a message via SMTP server.

In the properties method, we will add the necessary SMTP settings and then create a mail Session object. Afterward, you can create a Message using the MimeMessage.

Finally, send your message with the Transport object.

Don’t forget to add Exceptions. This class enables you to get details on possible errors along with an understanding of how to debug them. The main one is MessagingException. It can be used within javax.mail, javax.mail.internet, and javax.mail.search packages. For example, AddressException for javax.mail.internet will be thrown if you offered a wrongly formatted address.

We will return to debugging a bit later in this post.

How to test emails in Java?

For testing email sending from Java, we will use Mailtrap, an online tool, which helps test, review, and analyze emails sent from dev, QA, or staging environments, without the risk of spamming your customers or colleagues. Once you have tested and verified that everything works properly, change settings for the server you use in production.

Input:

package com.example.smtp;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;

public class SendEmail {
    public static void main(String[] args) {
        // Put recipient’s address
        String to = "[email protected]";

        // Put sender’s address
        String from = "[email protected]";
        final String username = "1a2b3c4d5e6f7g";//username generated by Mailtrap
        final String password = "1a2b3c4d5e6f7g";//password generated by Mailtrap

        // Paste host address from the SMTP settings tab in your Mailtrap Inbox
        String host = "smtp.mailtrap.io";

        Properties props = new Properties();
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");//it’s optional in Mailtrap
        props.put("mail.smtp.host", host);
        props.put("mail.smtp.port", "2525");// use one of the options in the SMTP settings tab in your Mailtrap Inbox

        // Get the Session object.
        Session session = Session.getInstance(props,
            new javax.mail.Authenticator() {
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }
            });

        try {
            // Create a default MimeMessage object.
            Message message = new MimeMessage(session);

            // Set From: header field
            message.setFrom(new InternetAddress(from));

            // Set To: header field
            message.setRecipients(Message.RecipientType.TO,
                InternetAddress.parse(to));

            // Set Subject: header field
            message.setSubject("My first message with JavaMail");

            // Put the content of your message
            message.setText("Hi there, this is my first message sent with JavaMail");

            // Send message
            Transport.send(message);

            System.out.println("Sent message successfully....");

        } catch (MessagingException e) {
            throw new RuntimeException(e);
        }
    }
}

Output:

Sending HTML Email

To send an HTML email, you should perform the same steps as for sending a simple text message, with only SendHTMLEmail class instead of just SendEmail. Also, you need to set content to the MimeMessage.setContent(Object, String) and indicate text/html type.

Input:

package com.example.smtp;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;

public class SendHTMLEmail {
    public static void main(String[] args) {
        String to = "[email protected]";

        String from = "[email protected]";
        final String username = "1a2b3c4d5e6f7g";//generated by Mailtrap
        final String password = "1a2b3c4d5e6f7g";//generated by Mailtrap

        String host = "smtp.mailtrap.io";

        Properties props = new Properties();
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.smtp.host", host);
        props.put("mail.smtp.port", "2525");

        // Get the Session object.
        Session session = Session.getInstance(props,
            new javax.mail.Authenticator() {
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }
            });

        try {
            // Create a default MimeMessage object.
            Message message = new MimeMessage(session);

            message.setFrom(new InternetAddress(from));

            message.setRecipients(Message.RecipientType.TO,
                InternetAddress.parse(to));

            message.setSubject("My HTML message");

            // Put your HTML content using HTML markup
            message.setContent(
                "<div><span style=\"color:#57aaca;\">c</span><span style=\"color:#57aec5;\">o</span><span style=\"color:#57b2c0;\">l</span><span style=\"color:#57b6ba;\">o</span><span style=\"color:#57bbb5;\">r</span><span style=\"color:#56bfb0;\">f</span><span style=\"color:#56c3ab;\">u</span><span style=\"color:#56c7a5;\">l</span><span style=\"color:#56cba0;\"> </span><span style=\"color:#5ec3ab;\">m</span><span style=\"color:#65bbb6;\">e</span><span style=\"color:#6db3c1;\">s</span><span style=\"color:#75accd;\">s</span><span style=\"color:#7da4d8;\">a</span><span style=\"color:#849ce3;\">g</span><span style=\"color:#8c94ee;\">e</span></div>", "text/html");

            // Send message
            Transport.send(message);

            System.out.println("Sent message successfully....");

        } catch (MessagingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}

Output:

In Mailtrap, you can also check the raw data of your message as well as its HTML source on separate tabs.

If you would like your message to contain both HTML and plain text, you need to build it using a MimeMultipart(“alternative”) object. You should create two different parts manually and insert them separately: text/plain body part as the first part in the multipart the text/html body part as the second one.

HTML Email with Images in Java

To add an image to your HTML emails in Jakarta Mail, you can choose any of three regular options: CID, base64 image, or linked image.

To embed a CID image, you need to create a MIME multipart/related message:

Multipart multipart = new MimeMultipart("related");

MimeBodyPart htmlPart = new MimeBodyPart();
//add reference to your image to the HTML body <img src="cid:some-image-cid" alt="img" />
htmlPart.setText(messageBody, "utf-8", "html");
multipart.addBodyPart(htmlPart);

MimeBodyPart imgPart = new MimeBodyPart();
// imageFile is the file containing the image
imgPart.attachFile(imageFile);
// or, if the image is in a byte array in memory, use
// imgPart.setDataHandler(new DataHandler(
// new ByteArrayDataSource(bytes, "image/whatever")));

imgPart.setContentID("<some-image-cid>");
multipart.addBodyPart(imgPart);

message.setContent(multipart);

For a base64, or inlined image, include the encoded image data in the HTML body:

<img src="data:image/jpeg;base64,base64-encoded-data-here" />

But remember that each Base64 digit represents 6 bits of data, so your actual image code will be pretty long. Besides, it affects the overall size of the HTML message, so it’s better not to inline large images.

The simplest way to add an image is just linking to the image hosted on some external server. Refer to your image as a link in the HTML body with an “img” tag:

<img src="https://blog.mailtrap.io/wp-content/uploads/2018/11/blog-illustration-email-embedding-images.png" alt="img" />

Sending an Email with Attachments

To attach any type of files to your message, you need to build a MIME multipart message and indicate the attachFile method in the MimeBodyPart.

public void attachFile(File file, Multipart multipart, MimeBodyPart messageBodyPart) { 
    DataSource source = new FileDataSource(file);

    messageBodyPart.setDataHandler(new DataHandler(source));
    messageBodyPart.setFileName(file.getName());

    multipart.addBodyPart(messageBodyPart); 
}

Debug Jakarta Mail

Debugging plays a critical role in testing of email sending. In Jakarta Mail it’s pretty straightforward. Set debug to true in the properties of your email code:

props.put("mail.debug", "true");

As a result, you will get a step by step description of how your code is executed. If any problem with sending your message appears, you will instantly understand what happened and at which stage.

Here is how our HTML message debug output looks:

DEBUG: Jakarta Mail version 1.6.4
DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]
DEBUG SMTP: need username and password for authentication
DEBUG SMTP: protocolConnect returning false, host=smtp.mailtrap.io, user=diana, password=<null>
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: trying to connect to host "smtp.mailtrap.io", port 2525, isSSL false
220 mailtrap.io ESMTP ready
DEBUG SMTP: connected to host "smtp.mailtrap.io", port: 2525
EHLO DESKTOP-NLP1GG8
250-mailtrap.io
250-SIZE 5242880
250-PIPELINING
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250-AUTH PLAIN LOGIN CRAM-MD5
250 STARTTLS
DEBUG SMTP: Found extension "SIZE", arg "5242880"
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "DSN", arg ""
DEBUG SMTP: Found extension "AUTH", arg "PLAIN LOGIN CRAM-MD5"
DEBUG SMTP: Found extension "STARTTLS", arg ""
STARTTLS
220 2.0.0 Start TLS
EHLO DESKTOP-NLP1GG8
250-mailtrap.io
250-SIZE 5242880
250-PIPELINING
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250 AUTH PLAIN LOGIN CRAM-MD5
DEBUG SMTP: Found extension "SIZE", arg "5242880"
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "DSN", arg ""
DEBUG SMTP: Found extension "AUTH", arg "PLAIN LOGIN CRAM-MD5"
DEBUG SMTP: protocolConnect login, host=smtp.mailtrap.io, user=1e2b3c4d5e6f7g, password=<non-null>
DEBUG SMTP: Attempt to authenticate using mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM XOAUTH2 
DEBUG SMTP: Using mechanism LOGIN
DEBUG SMTP: AUTH LOGIN command trace suppressed
DEBUG SMTP: AUTH LOGIN succeeded
DEBUG SMTP: use8bit false
MAIL FROM:<[email protected]>
250 2.1.0 Ok
RCPT TO:<[email protected]>
250 2.1.0 Ok
DEBUG SMTP: Verified Addresses
DEBUG SMTP:   [email protected]
DATA
354 Go ahead
Date: Tue, 30 Jul 2019 17:19:31 +0200 (EET)
From: [email protected]
To: [email protected]
Message-ID: <20132171.0.1548256771226@DESKTOP-NLP1GG8>
Subject: My HTML message
MIME-Version: 1.0
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: 7bit

<div><span style="color:#57aaca;">c</span><span style="color:#57aec5;">o</span><span style="color:#57b2c0;">l</span><span style="color:#57b6ba;">o</span><span style="color:#57bbb5;">r</span><span style="color:#56bfb0;">f</span><span style="color:#56c3ab;">u</span><span style="color:#56c7a5;">l</span><span style="color:#56cba0;"> </span><span style="color:#5ec3ab;">m</span><span style="color:#65bbb6;">e</span><span style="color:#6db3c1;">s</span><span style="color:#75accd;">s</span><span style="color:#7da4d8;">a</span><span style="color:#849ce3;">g</span><span style="color:#8c94ee;">e</span></div>
.
250 2.0.0 Ok: queued
DEBUG SMTP: message successfully delivered to mail server
QUIT
221 2.0.0 Bye
Sent message successfully....

Need More Options?

In this post, we have guided you through the main Jakarta Mail use cases and options. Should you experience any difficulties with installing, implementing, or using this package, refer to the Jakarta Mail FAQ.

Indeed, constructing transactional emails to send from your Java app with Jakarta Mail API takes time. Alternatively, you can consider options for simplified email sending in Java. For example, the Spring Framework or Apache Common Emails are quite popular, while the Play Framework offers a plugin for sending emails. Simple Java Mail is one of the simplest libraries ever – in fact, it is a wrapper around JavaMail API.

How do I set the time of java.util.Date instance to 00:00:00?

The following code snippet shows you how to remove time information from the java.util.Date object. The static method removeTime() in the code snippet below will take a Date object as parameter and will return a new Date object where the hour, minute, second and millisecond information hasbeen reset to zero. To do this, we use the java.util.Calendar. To remove time information, we set the calendar fields of Calendar.HOUR_OF_DAY, Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND to zero.

package org.kodejava.util;

import java.util.Calendar;
import java.util.Date;

public class DateRemoveTime {
    public static void main(String[] args) {
        System.out.println("Now = " + removeTime(new Date()));
    }

    private static Date removeTime(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }
}

The result of the code snippet above is:

Now = Sat Nov 20 00:00:00 CST 2021

In the above code:

  1. An instance of Calendar is created using Calendar.getInstance().
  2. We set the Calendar time using setTime() method and pass the date object.
  3. The time fields (HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND) are set to zero. Calendar.HOUR_OF_DAY is used for 24-hour clock.
  4. The resulting Calendar instances time value is printed which should now represent the start of the day.

How to Install Consolas Font in Mac OS X?

Here are the instructions to install Microsoft Consolas Font on Mac OS X.

  • You need to install brew first.
  • Type-in the following commands.
brew install cabextract
cd ~/Downloads
mkdir Consolas
cd Consolas
curl -LO https://sourceforge.net/projects/mscorefonts2/files/cabs/PowerPointViewer.exe
cabextract PowerPointViewer.exe
cabextract ppviewer.cab
open CONSOLA*.TTF
  • Press Install Font button to install the fonts.

How do I clear the current command line in terminal?

Terminal

You have typed a long line of command in terminal. But now you want to clear or delete the entire line. Deleting each character in the command will take sometime and bored you. So are there any keyboard shortcuts that allow you to do this? Yes there are some hotkeys to the rescue.

Hotkeys Description
CTRL + u Delete the current command.
The deleted command will be stored into a buffer.
CTRL + w Delete a word.
CTRL + c Abort what you are typing.
CTRL + d Delete current character.

Other hotkeys that might help you work faster in the terminal.

Hotkeys Description
CTRL + e Move to the end of line.
CTRL + a Move to the start of line.
CTRL + k Cut text from the cursor to the end of line.
CTRL + y Paste the last cut text or buffer.
CTRL + - Undo.
CTRL + b Backward one character.
CTRL + f Forward one character.
ALT + Backward one word.
ALT + Forward one word.

How do I generate random alphanumeric strings?

The following code snippet demonstrates how to use RandomStringGenerator class from the Apache Commons Text library to generate random strings. To create an instance of the generator we can use the RandomStringGenerator.Builder() class build() method. The builder class also helps us to configure the properties of the generator. Before calling the build() method we can set the properties of the builder using the following methods:

  • withinRange() to specifies the minimum and maximum code points allowed in the generated string.
  • filteredBy() to limits the characters in the generated string to those that match at least one of the predicates supplied. Some enum for the predicates: CharacterPredicates.DIGITS, CharacterPredicates.LETTERS.
  • selectFrom() to limits the characters in the generated string to those who match at supplied list of Character.
  • usingRandom() to overrides the default source of randomness.

After configuring and building the generator based the properties defined, we can generate the random strings using the generate() methods of the RandomStringGenerator. There are two methods available:

  • generate(int length) generates a random string, containing the specified number of code points.
  • generate(int minLengthInclusive, int maxLengthInclusive) generates a random string, containing between the minimum (inclusive) and the maximum (inclusive) number of code points.

And here is your code snippet:

package org.kodejava.commons.text;

import org.apache.commons.text.CharacterPredicates;
import org.apache.commons.text.RandomStringGenerator;

public class RandomStringDemo {
    public static void main(String[] args) {
        RandomStringGenerator generator = new RandomStringGenerator.Builder()
                .withinRange('0', 'z')
                .filteredBy(CharacterPredicates.DIGITS, CharacterPredicates.LETTERS)
                .build();

        for (int i = 0; i < 10; i++) {
            System.out.println(generator.generate(10, 20));
        }
    }
}

Below are examples of generated random alphanumeric strings:

weJDtVARLIFS96WXje
FYrNzTR3Q3dUrLT3Xsc
4F1fu8nSsA
nIQi3a4Oyv9
l6QcsP9bejdbaLd2jd
Cc9YgTfgwo
2B8un8YCcxn9m2
RAN2dZAWalUIWeZeoS
jPQspicyaKfAzS14twH
GTurc0lWkSid03rG0JZ

Apache Logo

Maven Dependencies

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-text</artifactId>
    <version>1.12.0</version>
</dependency>

Maven Central