# Read messages and threads with Kotlin/Java

Source: https://developer.nylas.com/docs/v3/sdks/kotlin-java/read-messages-threads/

This page explains how to use the Nylas Kotlin/Java SDK and Email API to read and search your users' messages and threads. For more information, see the [Email documentation](/docs/v3/email/).

## Messages versus Threads


Messages are the fundamental object of the Nylas platform and the core building block for most email applications. Messages contain several pieces of information, such as when the message was sent, the sender's address, to whom it was sent, and the message body. They can also contain files (attachments), calendar event invitations, and more.

Threads are first-class objects that represent collections of messages which are related to each other, and result from people replying to an email conversation. For Gmail and Microsoft Exchange accounts, Nylas threads messages together so that they are as similar as possible to their representation in those environments. For all other providers, including generic IMAP, Nylas threads messages using a custom JWZ-inspired algorithm.

For more information, see the [Messages](/docs/reference/api/messages/) and [Threads](/docs/reference/api/threads/) references.


## Before you begin

Before you start, you must have done the following tasks:

- [Installed and set up the Nylas Kotlin/Java SDK](/docs/v3/sdks/kotlin-java/).
- [Authenticated one or more users](/docs/v3/sdks/kotlin-java/#authenticate-users).

## Read messages from an inbox

This section walks through how to read messages from a user's inbox.

First, create a Message object and pass a query to it. This returns a list containing only the most recent message in the user's inbox.

```java
ListMessagesQueryParams queryParams = new ListMessagesQueryParams.Builder().limit(1).build();
ListResponse<Message> message = nylas.messages().list("<NYLAS_GRANT_ID>", queryParams);
```

```kt
val queryParams : ListMessagesQueryParams = ListMessagesQueryParams.Builder().limit(1).build()
val messages : List<Message> = nylas.messages().list("<NYLAS_GRANT_ID>", queryParams).data
```

Next, print the message subject, unread status, and ID.

```java
System.out.printf("Subject: %s | Unread: %s | Id: %s",
    message.getData().get(0).getSubject(),
    message.getData().get(0).getUnread(),
    message.getData().get(0).getId());
```

```kt
println("Subject: ${messages[0].subject} | " +
    "Unread: ${messages[0].unread} | " +
    "Id: ${messages[0].id}")
```

## Read threads from an inbox

This section shows how to read threads from a user's inbox.

First, create a Threads object and pass a query to it. This returns a list containing only the five most recent unread threads in a user's inbox.

```java
ListThreadsQueryParams queryParams = new ListThreadsQueryParams.Builder().
    limit(5).
    unread(true).
    build();

ListResponse<Thread> thread = nylas.threads().list("<NYLAS_GRANT_ID>", queryParams);
```

```kt
val queryParams = ListThreadsQueryParams(limit = 5, unread = true)
val threads : List<Thread> = nylas.threads().list("<NYLAS_GRANT_ID>", queryParams).data
```

Next, print the threads' subjects and participant email addresses.

```java
for(Thread message : thread.getData()){
  List<EmailName> participants   = message.getParticipants();
  assert participants != null;

  for(EmailName participant : participants) {
    System.out.println("Subject: " + message.getSubject() +
        " | Participant: " + participant.getName());
  }
}
```

```kt
for(message in threads) {
  val participants = message.participants

if (participants != null) {
    for(participant : EmailName in participants) {
      println("Subject: " + message.subject +
          " | Participant: " + participant.name)
    }
  }
}
```

## Search a user's inbox

When Nylas runs a search on a user's inbox, that search is proxied to the account's provider. Nylas matches results with synced objects and returns them. You can search for both messages and threads.

The examples below show how to search for and read messages and threads from a user's inbox.

```java
public class SearchEmail {
  public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
    NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();

    ListMessagesQueryParams messagesQueryParams = new ListMessagesQueryParams.Builder().
        limit(1).
        build();

    ListResponse<Message> messages = nylas.messages().list("<NYLAS_GRANT_ID>", messagesQueryParams);

    for(Message message : messages.getData()) {
      System.out.printf("Subject: %s | Unread: %s | ID: %s\n",
          message.getSubject(),
          message.getUnread(),
          message.getId());
    }

    ListThreadsQueryParams queryParams = new ListThreadsQueryParams.Builder().
        limit(5).
        build();

    ListResponse<Thread> thread = nylas.threads().list("<NYLAS_GRANT_ID>", queryParams);

    for(Thread message : thread.getData()) {
      List<EmailName> participants   = message.getParticipants();
      assert participants != null;

      for(EmailName participant : participants) {
        System.out.println("Subject: " + message.getSubject() +
            " | Participant: " + participant.getName());
      }
    }

    ListMessagesQueryParams searchQueryParams = new ListMessagesQueryParams.Builder().
        searchQueryNative("from:swag@example.com").
        build();

    ListResponse<Message> message = nylas.messages().list("<NYLAS_GRANT_ID>", searchQueryParams);

    System.out.println(message.getData().get(0).getSubject());
  }
}
```

```kt
fun main(args: Array<String>) {
  val nylas: NylasClient = NylasClient(apiKey = "<NYLAS_API_KEY>")

  val listQueryParams : ListMessagesQueryParams = ListMessagesQueryParams.
      Builder().
      limit(1).
      build()

  val messages : ListResponse<Message> = nylas.messages().list("<NYLAS_GRANT_ID>", listQueryParams)

  for (message in messages.data) {
    System.out.printf(
        "Subject: %s | Unread: %s | ID: %s\n",
            message.subject,
            message.unread,
            message.id
    )
  }

  val threadQueryParams : ListThreadsQueryParams = ListThreadsQueryParams.
      Builder().
      limit(5).
      build()

  val threads: List<com.nylas.models.Thread> = nylas.threads().list("<NYLAS_GRANT_ID>", threadQueryParams).data

  for(message in threads) {
    val participants = message.participants

    if (participants != null) {
      for(participant : EmailName in participants) {
          println("Subject: " + message.subject +
              " | Participant: " + participant.name)
      }
    }
  }

  val queryParams = ListMessagesQueryParams(searchQueryNative = "from:swag@example.com")
  val search = nylas.messages().list("<NYLAS_GRANT_ID>", queryParams).data

  println(search[0].subject)
}
```