Welcome to Part 18 of this series of guides on how to integrate Gmail with Angular and Spring Boot.

Now it's time to send a fancy shmancy email.

Yes, you already learned how to send an email. But that was a plain text email.

In this guide, you'll learn how to add HTML to your email.

It's easy. But you need to know how to populate the MimeMessage properties.

And that's exactly what I'll show you.

Or, if you prefer, you can just go view the source code on GitHub.

You Are Here

Thus far in the series, you have:

  • Created an OAuth2 client ID and secret on Google Cloud Console
  • Enabled the Gmail API via Google Cloud Console
  • Set the necessary properties in your Spring Boot application.properties file 
  • Set up a DataStore implementation with its associated factory
  • Set up a refresh listener
  • Created a utility class that handles the Google authorization code flow
  • Set up proper Gmail consent with the Google Cloud Platform
  • Created a controller that handles a request to get the Google authorization code flow URL
  • Used Postman to get the Google authorization code URL
  • Used that URL to authorize your application to access your Gmail inbox
  • Updated the controller so it handles a token request
  • Updated the utility class so it creates the credential from a token
  • Persisted that credential
  • Used Postman to retrieve the token
  • Learned why you didn't actually need to retrieve the token
  • Learned about the structure of the Message object
  • Learned about MIME
  • Created an Email type that gets sent back to the client
  • Wrote code that converts a Message object to an Email object
  • Instantiated the Gmail service
  • Used the Gmail service to retrieve just the messages you want to retrieve
  • Used the Gmail service to extracted full Message objects from very lightweight objects
  • Added a new endpoint to listen for inbox requests
  • Used that endpoint to send back the user's most recent emails
  • Learned how to disallow your application from accessing your inbox
  • Created a new component on the Angular side that shows emails from the user's inbox
  • Created a new service on the Angular side that retrieves emails from the Spring Boot microservice
  • Optimized the payload response from the microservice
  • Displayed HTML reference characters as they should be displayed
  • Got rid of whitespace that isn't whitespace
  • Designed a user-friendly, responsive inbox
  • Created a UI so people can read individual email messages
  • Learned about the security risks associated with displaying full HTML messages from the Gmail API
  • Added code to support sending emails
  • Sent a simple plain text email via Postman

And if you haven't done those things, Part 1 is waiting for you.

You Will Be There

In this guide, you will:

  • Construct a MimeMessage with an HTML email body
  • Test out sending an HTML message via Postman

And then you can go back to watching professional wrestling.

A New Method in an Old Utility

Edit EmailUtil. Add this method:

    public static MimeMessage convertHtmlEmailToMimeMessage(Email email) throws MessagingException {
        Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);

        MimeMessage mimeMessage = new MimeMessage(session);

        setMetadata(mimeMessage, email);
        
        MimeBodyPart htmlBodyPart = new MimeBodyPart();
        htmlBodyPart.setContent(email.getHtml(), MediaType.TEXT_HTML_VALUE);

        Multipart multipart = new MimeMultipart();
        multipart.addBodyPart(htmlBodyPart);
        
        mimeMessage.setContent(multipart);

        return mimeMessage;
    }

The method takes an Email object and converts it to a MimeMessage object with an HTML body.

I'll explain it line-by-line.

The code begins by instantiating an empty Properties object. If you were using "straight" JavaMail, you'd populate that properties object with info like your SMTP server IP address and credentials.

Here, the Gmail API is doing all that heavy lifting. So the Properties object stays empty.

But it's required to instantiate the Session object which represents an email session.

And that Session object, in turn, is required to create a MimeMessage object.

So it's a long trip just to get to the point where the code instantiates MimeMessage. But it's worth it.

That setMetaData() method you see is a new method that populates the from, to, and subject attributes for the email.

Then comes the good stuff. The code instantiates a MimeBodyPart object. You will be shocked to learn that MimeBodyPart represents a MIME body part.

Although the class name contains the word "body," don't let that fool you. It doesn't mean that the class is always associated with the "body" of the email.

In fact, you would use MimeBodyPart to attach a file to an email message as well.

But here, the code is, in fact, using it to populate the body of the email.

It does that with the setContent() method that you see above. The content itself comes from the html property of the Email object.

The second parameter in setContent() sets the media type. In this case, it's "text/html" which happens to be the value of that MediaType constant you see in the code.

But just creating MimeBodyPart isn't good enough. You see, it's only one part of what could be many parts.

In this case, you only need one part (the body of the email message). But in other cases, you might have attachments you'd like to add as well.

So that's why the code instantiates MimeMultipart. Then, it adds the MimeBodyPart instance via the addBodyPart() method.

Finally, the code sets the content of the email message via the setContent() method on the MimeMessage object.

Back in the Service

Now that you've created that new method in EmailUtil, use it.

Edit GmailService and update the createGmailMessageFromEmail() method to this:

    private Message createGmailMessageFromEmail(Email email) throws MessagingException, IOException {
       MimeMessage mimeMessage = EmailUtil.convertHtmlEmailToMimeMessage(email);
       
       ByteArrayOutputStream buffer = new ByteArrayOutputStream();
       mimeMessage.writeTo(buffer);
       
       byte[] bytes = buffer.toByteArray();
       String encodedEmail = Base64.getEncoder().encodeToString(bytes);
       
       Message message = new Message();
       message.setRaw(encodedEmail);
       
       return message;
    }

The only change there is in the first line. It's using the new method you just created.

Everything else stays the same. 

Testing Once More

Back to testing.

Fire up your User API, your Email API, and Postman.

When everything is finished loading, POST a request to http://localhost:32050/email/messages. Make the request body look like this:

{
    "html" : "<html><body><h1>Header 1</h1><h2>Header 2</h2><h3>Header 3</h3></body></html>",
    "subject" : "Look for a recruit",
    "from" : "emailaddress@xmail.com",
    "to" : "emailaddress@spacelysprockets.com"
}

Of course, you'll want to substitute legit email address in to the "from" and "to" properties.

Here's what the whole thing should look like on Postman:

 

As you can see, the "html" property includes bona fide HTML. So you can check to make sure the message came through in HTML format when you view it in your email client.

Now click that big blue Send button. Wait a couple of seconds to get the ID back. Then, check the inbox associated with the "to" property.

In my testing, this is what I see:

 

And that's exactly what I should see. The text is displayed as HTML instead of plain text.

It's a success!

Wrapping It Up

That's it. Now you know how to send emails with HTML message bodies.

Stay tuned to this space for more great guides.

Have fun!