Build Email Inbox Management and Search Features With Nylas

Learn how the Nylas Email API makes it easy to organize an email inbox and search message content.

Ben Lloyd Pearson | September 25, 2020

If you’re integrating email functionality into your app, there’s a good chance you’ll need to perform common inbox management functions like marking emails as unread and organizing messages into folders and labels. There’s also a good chance that you want to implement email inbox search functionality to help your users quickly find relevant emails.

These features are table stakes for any application that leverages email data and functionality, and the Nylas Email API is the easiest way to accomplish this task. The Nylas Communications Platform provides a single point of integration that instantly connects 100% of email, calendar and contacts providers to your app, via simple REST APIs.  This article will show you how to use Nylas to manage a user’s inbox and search for email messages.

Want a PDF of this article?

Share it with a friend or save it for later reading.

Getting Started with Inbox Zero

Inbox Zero is a demo inbox application that you can use to explore and understand the Nylas API. It’s built using:
  • Next.js, a framework for making server-rendered React apps
  • Express.js to create RESTful endpoints on the server
  • JSON Web Tokens (JWT) for authentication
  • Lowdb, a lightweight key-value database powered by Lodash, for storing user information

Organize an Email Inbox

Manage Emails with Inbox Zero

There are two primary ways that an email inbox can be organized: labels or folders. Gmail is the only provider that uses labels, and every other provider, including Exchange, Office 365, and IMAP providers all user folders. This article will focus specifically on working with labels for Gmail accounts, but all of this functionality can be adapted for providers that use folders if necessary. The only functional difference between labels and folders is that an email message can have multiple labels applied to it, while alternatively it can only be contained in a single folder.

Since labels are only available for Gmail accounts, the first thing you need to do is identify the provider for the user account. The Nylas Account endpoint provides two fields to help accomplish this

  • provider indicates which of the supported provider types the account is.
  • organization_unit indicates if the account uses labels for folders for organization.

Here’s how to check for each of these attributes with the Nylas Node SDK:

const account = await nylas.account.get();
if (account.provider === "gmail") {
        // This account uses labels!
}
if (account.organizationUnit === "label") {
        // This account uses labels!
}

Inbox Zero checks the organization_unit attribute when the individual thread page is rendered, and when creating new labels.

How to Create a Label

The only thing you need to define to create a label is the display name. Inbox Zero takes the input from the user in the label component, and when they click create, the app sends a request to the label creation route. From there, all that’s left is to use the Nylas Node SDK to create a new label, set the name, and save!

const displayName = req.body.displayName;
const label = nylas.labels.build();
label.displayName = displayName;
await label.save();

After saving, the label object is automatically updated with the ID for the new label. Inbox Zero sends that back to the user interface to be used for tagging emails.

res.json({
        id: label.id,
        displayName: label.displayName
});

Retrieve all Labels for an Email Thread

When the user retrieves an email thread, they’ll also want to know which of their labels have been applied to that specific thread. The Thread object contains a labels attribute that provides data for all of the labels that are applied to the thread. However, in Inbox Zero, we want to show the user all of their labels with a checkbox that indicates which labels have been applied to the specific thread the user is viewing. The label component handles this for Inbox Zero by returning all labels for the user account and displaying their names.

const accountLabels = await nylas.labels.list();

Most email accounts include default labels that aren’t really relevant for this use case, so Inbox Zero defines this list so they can be handled appropriately.

const DEFAULT_LABELS = [
        "inbox",
        "all",
        "trash",
        "archive",
        "drafts",
        "sent",
        "spam",
        "important"
];

Finally, the app iterates through the list to find any custom labels that have been applied to the thread the user is viewing, and sets a checked property that’s used to determine which labels should have a checkmark next to them in the user interface.

const labels = accountLabels
        .filter(label => !DEFAULT_LABELS.includes(label.name))
        .map(label => ({
                id: label.id,
                displayName: label.displayName,
                checked: !!thread.labels.find(({ id }) => id === label.id)
        }));

Set and Clear Labels

When an Inbox Zero user wants to change the labels that are applied to a thread, they can check/uncheck a checkbox in the label component which triggers the thread update route. To handle this request, the app first gets the data for the thread, and returns it in expanded view which includes all of the data for the associated messages.

const id = req.params.id;
const thread = await nylas.threads.find(id, null, { view: "expanded" });

Next, the app sets the thread object’s labels property to an array with all the labels for that thread. We don’t want to overwrite the thread’s default labels, so they also need to be reapplied. 

const threadDefaultLabels = thread.labels.filter(label =>
        DEFAULT_LABELS.includes(label.name)
);

thread.labels = [
        ...threadDefaultLabels,
        ...req.body.labels.filter(label => label.checked)
];
The last step is to save the thread.
await thread.save();

Search an Email Inbox

Another essential tool for email productivity is the ability to search an email inbox for specific messages. When an Inbox Zero user puts a search term into the SearchForm component on the threads overview page, that term is appended in the query portion of the URL, causing the request to the thread overview route to be reissued. From there, the app captures the search term and use the Nylas SDK to get matching results.  This request uses a limit and offset to control pagination of results.

const PAGE_LIMIT = 6; // Limit the number of results to make the request faster
const page = req.query.page >= 1 ? req.query.page : 1;
const search = req.query.search;

const threads = await nylas.threads.search(search, {
        limit: PAGE_LIMIT + 1,
        offset: (page - 1) * PAGE_LIMIT
});

Inbox Zero uses the IDs returned in the search results to get the necessary data for displaying all the relevant information from the email threads. To speed up the performance of these requests, Inbox Zero uses Bluebird to make the requests for these threads asynchronously. 

const Promise = require("bluebird");
const results = Promise.map(threads, async thread => {
        const messages = await nylas.messages.list({
                thread_id: thread.id
        });
        thread.messages = messages;
        return thread;
}, { concurrency: 5 });

Once that’s done, the app handles the threads and displays the threads in the same manner as the standard threaded email view.

res.status(200).json({
        hasPrevious: page > 1,
        hasNext: threads.length > PAGE_LIMIT,
        threads: threads.slice(0, PAGE_LIMIT).map(thread => ({
                id: thread.id,
                subject: thread.subject,
                from: thread.from,
                date: thread.lastMessageTimestamp,
                snippet: thread.snippet,
                unread: thread.unread,
                hasAttachments: thread.hasAttachments
        }))
});

Extend Your Email Functionality With Nylas

This article outlines what it takes to build email inbox management and search features, but why stop there? With Nylas, developers also unlock the full capability of users’ calendars and contact books too, and these combined with email functionality allow you to turn your app into a scheduling powerhouse. With Nylas, you can build deeply contextual experiences that let your users access their email, calendar, and contacts seamlessly from within your app. Get started today!

Ben Lloyd Pearson

Ben is the Developer Advocate for Nylas. He is a triathlete, musician, avid gamer, and loves to seek out the best breakfast tacos in Austin, Texas.