Use Java Mail API to send Email with Gmail SMTP example

In this article, we’re going to see how to send an email with and without attachments using pure Java Mail API. Java (since version 1.2) provides a set of classes and interfaces for sending an email as a part of Java Mail API. 

There are various email protocols used by a client and a server to exchange emails. SMTP, POP3, and IMAP among the most popular email protocols that are widely used today. Java mail API supports all of these protocols. 

sending email with Java Mail API

In this article, we are going to use the SMTP protocol. For this, we will use Gmail as an SMTP server. You can use any private (host provided) SMTP server though.

Configuration

To use Java mail API, you need to add the following depedency to your maven project. Always check the latest version from the maven site and add the dependency accordingly.

<dependency>
      <groupId>com.sun.mail</groupId>
      <artifactId>javax.mail</artifactId>
      <version>1.6.2</version>
</dependency>

Sending an Email With Java Mail API

We are going to send an email in the following 3 steps.

Preparing session ( Java Mail API )

The very first step is to get the mail session object. The javax.mail.Session class represents a mail session. It’s a singleton class. So you can’t directly create an instance of it. You need to call one of the overloaded static methods getInstance()/getDefaultInstance() as follows.

NoMethodDescription
1getDefaultInstance(Properties props)Get default Session without Authenticator. The default Session object is available across the same JVM. It contains security-sensitive information. It internally calls getDefaultInstance(Properties props, Authenticator authenticator) by passing null to Authenticator
2getDefaultInstance(Properties props,Authenticator authenticator)Synchronized method to get default Session with Authenticator. Access to the Session object is restricted.
3getInstance(Properties props)Get a new Session object without Authenticator. It internally calls getInstance(Properties props, Authenticator authenticator) by passing null to Authenticator
3getInstance(Properties props, Authenticator authenticator)Get a new Session object with Authenticator. Access to the Session object is restricted.

The difference between getDefaultInstance() and getInstance() method is as follows.

  • The getDefaultInstance() always returns the same object that is created the first time. On the other hand, the getInstance() method returns a fresh new object every time upon calling.
  • Additionally, the getDefaultInstance() is synchronized method while getInstance() is not.

Let’s create the session object with the above method.

final Properties prop = new Properties();
prop.put("mail.smtp.username", "[email protected]");
prop.put("mail.smtp.password", "wffggfzvvbwbiaeh");
prop.put("mail.smtp.host", "smtp.gmail.com");
prop.put("mail.smtp.port", "587");
prop.put("mail.smtp.auth", "true");
prop.put("mail.smtp.starttls.enable", "true"); // TLS

Session mailSession = Session.getInstance(prop, new javax.mail.Authenticator() {
    @Override
    protected javax.mail.PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(prop.getProperty("mail.smtp.username"), 
                    prop.getProperty("mail.smtp.password"));
    }
});

Explanation

  • Firstly, we created the Session object with properties and the Authenticator object.
  • The properties are as follows.
    • mail.smtp.username – Username of SMTP server
    • mail.smtp.password – Password of SMTP server
    • mail.smtp.host – Host of SMTP server
    • mail.smtp.port – Port
    • mail.smtp.auth – Is Authentication is required.
    • mail.smtp.starttls.enable – TLS enable.
  • The Authenticator is an abstract class. Its object is created by providing an anonymous implementation of getPasswordAuthentication() method. The PasswordAuthentication class is used as a placeholder for storing user credentials.

Message composition ( Java Mail API )

Next, we will compose the email message. The javax.mail.Message class represents a message in Java mail API. Since it’s an abstract class, we will use its concrete implementation – javax.mail.internet.MimeMessage class. Java Mail API allows sending mail either in plain text or in HTML content. Let’s see both of the flavors.

Compose a mail with plain text

Below is the snippet to compose a plain text email.

Message message = new MimeMessage(mailSession);
message.setFrom(new InternetAddress("[email protected]"));
message.setSubject("Sending Mail with pure Java Mail API ");

/* Mail body with plain Text */
message.setText("Hello User," 
        + "\n\n If you read this, means mail sent with Java Mail API is successful");

InternetAddress[] toEmailAddresses = 
        InternetAddress.parse("[email protected], [email protected]");
InternetAddress[] ccEmailAddresses = 
        InternetAddress.parse("[email protected], [email protected]");
InternetAddress[] bccEmailAddresses = 
        InternetAddress.parse("[email protected]");
            
message.setRecipients(Message.RecipientType.TO,toEmailAddresses);
message.setRecipients(Message.RecipientType.CC,ccEmailAddresses);
message.setRecipients(Message.RecipientType.BCC,bccEmailAddresses);
  • First, we created the object of MimeMessage by passing a Session object that we created in step.
  • Then we set from address and mail subject.
  • To send an email in plain text, just pass the text in the message.setText() method.
  • Then, we created an array of To, Cc, and Bcc users. the InternetAddress.parse() method is used to form a user array. You need to pass comma-separated email addresses.
  • In the end, we attached them to the message with the message.setRecipients() method with respective types (Message.RecipientType.TO, CC and BCC).

This will send an email in plain text format.

Compose a mail with HTML content.

In terms of usability, HTML content is far superior to plain text. So, most of the time, we send emails in HTML content. Java Mail API supports sending emails in HTML content. To send an email with HTML content, you need to replace the message.setText() method with below code.

/* Step 1: Create MimeBodyPart and set content and its Mime Type */
BodyPart mimeBody = new MimeBodyPart();
mimeBody.setContent("<h1> This is HTML content </h1><br> Hello <b> User </b>", "text/html");

/* Step 2: Create MimeMultipart and  wrap the mimebody to it */
Multipart multiPart = new MimeMultipart();
multiPart.addBodyPart(mimeBody);

/* Step 3: set the multipart content to Message in caller method*/
message.setContent(multiPart);
  • Firstly, we created a mime body and set the content and its type (text/html). The javax.mail.internet.MimeBodyPart class represents mime body part. You can set HTML content here.
  • Secondly, we created a mime multipart object that we can use to wrap the mime body object.
  • In the end, we set the mime multipart object as the content of javax.mail.Message. The setContent() method is used here.

Sending Email ( Java Mail API )

So far, we created a session and compose the message. Now it’s time to send the message to the recipients. We will use javax.mail.Transport class for the same. It provides overloaded send() methods as follows. 

NoMethodDescription
1static void send(Message msg)A static method to send a message
2static void send(Message msg, Address[] addresses)A static method to send a message to given recipients
3static void send(Message msg, String user, String password)A static method to send a message with an SMTP server credential
4static void send(Message msg, Address[] addresses, String user, String password)A static method to send a message to given recipients with SMTP server credential

  • The javax.mail.Transport is an abstract class so we can’t directly create an instance of it. 
  • However, all the above methods are static so obviously, we can call them with direct class notation.
  • Internally all the above methods call a common private method – send0(Message msg, Address[] addresses, String user, String password) to send an email.
  • For simplicity, you can call the first method from the above table.

Send an Email With an Attachment

Now, it’s time to send a mail with an attachment. Java Mail API supports sending an email with an attachment. To do so, there won’t be much change in the existing code that we saw in the previous section. To attach the file to an email, create a separate mime body part as follows.

MimeBodyPart attachmentBodyPart = new MimeBodyPart();
attachmentBodyPart.attachFile(new File("<<Path to file>>"));

In the last, add the object of MimeBodyPart ( attachmentBodyPart ) to the MimeMultipart object as follows.

multiPart.addBodyPart(attachmentBodyPart);

Quick notes

  • For mail attachment, we have used the reference type as MimeBodyPart instead of the abstract class BodyPart. The reason is attachFile() method is not available in BodyPart but it’s in the MimeBodyPart class.
  • Moreover, to attach multiple files to email, call the above codes multiple times. Meaning creating MimeBodyPart objects with the file path and attach them all to the MimeMultipart object by calling addBodyPart() method.

And you are done. 

Common Exception in Java Mail API when using Gmail SMTP

While sending an email with any of the above methods, you might get the following exception even your Gmail password is correct.

javax.mail.AuthenticationFailedException: 534-5.7.9 Application-specific password required. Learn more at
534 5.7.9  https://support.google.com/mail/?p=InvalidSecondFactor r10sm12002263pga.48 - gsmtp

    at com.sun.mail.smtp.SMTPTransport$Authenticator.authenticate(SMTPTransport.java:965)
    at com.sun.mail.smtp.SMTPTransport.authenticate(SMTPTransport.java:876)
    at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:780)
    at javax.mail.Service.connect(Service.java:388)
    at javax.mail.Service.connect(Service.java:246)
    at javax.mail.Service.connect(Service.java:195)
    at javax.mail.Transport.send0(Transport.java:254)
    at javax.mail.Transport.send(Transport.java:124)
    at com.opensource.techblog.javamail.EmailWithPlainTextContent.main(EmailWithPlainTextContent.java:54)

The exception (javax.mail.AuthenticationFailedException) talks about the Application-specific password required. This is because your Gmail account is configured for 2-step verification so your direct Gmail password won’t work here due to security reasons. To rectify this, you need to follow the below steps.

  • Sign in with your Google account
  • Go to your Google account or just click on the link – https://myaccount.google.com/?pli=1
  • Click on Security from the left menu.
  • Scroll a bit down to reach the “Signing in to Google” section – most probably 3rd section from the top.
  • Here you can see 2-Step Verification is turned On.
  • Click on App Password just below it. Google will ask you to re-enter the password.
  • On the next screen, you need to select the App and Device.
  • From the “Select app” dropdown, just select Other (Custom name).
  • Give an appropriate name like “Web” and press Generate button.
  • You will a generated password on the screen with a popup.
  • Save and use this password for all your Java mail code.

Summing Up

  • Java email API provides a convenient way to send email programmatically.
  • Java allows you to send mail in plain text, HTML, or any other supported mime type.
  • In fact, attaching files to your email is also possible with just a few lines of code.
  • You can find the complete source code on GitHub. It contains the code for plain text content, HTML content, and attachment in a separate file.

Recommended For You

About the Author: Nilang

Nilang Patel is a technology evangelist who loves to spread knowledge and helping people in all possible ways. He is an author of two technical books - Java 9 Dependency and Spring 5.0 Projects.

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.