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

In this guide, I'm going to teach you how to avoid getting scammed.

Yes, I know this isn't a finance blog. But I still need to teach how you to avoid getting ripped off.

Because the Gmail API will do that to you.

If you let it.

So read on if you want to get everything you're supposed to get from the Gmail API.

Or just visit GitHub and get the code.

The Current State of the Transaction

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

The Future State of the Transaction

In this part of the series, you will:

  • Avoid getting ripped off by the Gmail API

I already told you that.

Ya Got Took

Take another look at the getMessageList() method in GmailUtil.

    private List<Message> getMessageList(Gmail service) {
        try {
            Messages messages = service.users().messages();
            Gmail.Users.Messages.List messageList = messages
                                                    .list("me")
                                                    .setQ("in:inbox -category:{social promotions forums}")
                                                    .setMaxResults(20l);
            
            ListMessagesResponse rsp = messageList.execute();
            List<Message> list = rsp.getMessages();
    
            return list;
        } catch (IOException ie) {
            LOG.error("Problem retrieving Gmail messages!", ie);
        }
        
        return null;
    }

Pay particular attention to this line:

List<Message> list = rsp.getMessages();

At the end of the last guide, I said that method gives you a List of Message objects from the ListMessageResponse object.

I lied.

Well, what I said is partially true. Let's spit out the whole List object and see what we've got.

[
   {
      "id":"1787ec438f39bb6e",
      "threadId":"1787ec438f39bb6e"
   },
   {
      "id":"1787ebe70b24ec48",
      "threadId":"1787ebe70b24ec48"
   },
   {
      "id":"1787e5dca489bf24",
      "threadId":"1787e5dca489bf24"
   }
]

That's... it.

So you got back really abbreviated Message objects. All you have for each message is just the ID and the thread ID.

Well that sucks.

So at this point the Gmail API is ripping you off.

And, yeah, it's by design.

Check out the API docs and you'll find this nugget: "Note that each message resource contains only an id and a threadId."

So you didn't do anything wrong.

But the problem still stands: You need full messages.

Fortunately, you can get them.

To do that, you need to retrieve each message individually by its ID.

Yes, I think that sucks, too.

But since that's what you need to do, go ahead and create a getSingleEmailMessageById() method:

    private Email getSingleEmailMessageById(String id, Gmail service) {
        try {
            Message retrievedMessage = service
                                        .users()
                                        .messages()
                                        .get("me", id)
                                        .setFormat("full")
                                        .execute();
            Email email = getEmail(retrievedMessage);
            return email;
        } catch (IOException ie) {
            LOG.error("Problem retrieving individual message!");
        }   
        
        return null;
    }

You'll call that method for each Message object you got back from the getMessageList() method.

That method accepts two parameters: the ID of the message and the Gmail object.

You've already instantiated the Gmail object in the previous guide. I won't need to explain that again.

But this time you'll use the Gmail service a little differently than you did last time. Instead of getting a whole list of very lightweight Message objects, you'll use it to get a single heavyweight Message object.

First, the Gmail service invokes the users() method to get the Users object. You've seen that before.

Then, it invokes the messages() method on the User object to get the Messages object.

As you may recall from the last guide, that's the object you use to get email messages. This time, though, you're going to use it to just get a single email message.

The code gets that ball rolling with the get() method. It takes two parameters: "me" (the current credentialed user) and the ID of the message.

But that's not good enough. That's only going to return a Get object. Still no message.

To get the message, the code first specifies the message format. It uses "full" so it gets back everything and can decide what to keep and what to toss away later on. 

Finally, the code invokes the all-too-familiar execute() method.  And that returns the full Message object.

After getting that object, the code invokes another familiar method: getEmail(). I covered that one a couple of guides ago.

That method translates the Message object into an Email object. That's the object that gets returned by the getSingleEmailMessageById() method.

Wrapping It Up

And that will do it for you. That's how you can avoid letting the Gmail API shortchage you.

In the next guide, you'll use Postman to actually retrieve email messages using your Spring Boot microservice.

Until then, have fun!

Photo by Karolina Grabowska from Pexels