Skip to main content

Overview

The imap_search_messages tool provides powerful search capabilities with cursor-based pagination for efficient retrieval of messages from large mailboxes.
1

Specify account and mailbox

Every search requires an account_id and mailbox name:
{
  "account_id": "default",
  "mailbox": "INBOX"
}
2

Set result limit

Control how many messages are returned per page (1-50, default 10):
{
  "account_id": "default",
  "mailbox": "INBOX",
  "limit": 25
}
3

Process search results

The response includes message summaries and pagination info:
{
  "summary": "25 message(s) returned",
  "data": {
    "total": 1250,
    "returned": 25,
    "messages": [...],
    "next_cursor": "cursor-abc123",
    "has_more": true
  }
}

Search Filters

Combine multiple filters to narrow your search:

Text Search Filters

Full-text search across message content:
{
  "account_id": "default",
  "mailbox": "INBOX",
  "query": "quarterly report"
}
Search messages from specific senders:
{
  "account_id": "work",
  "mailbox": "INBOX",
  "from": "[email protected]"
}
Search messages sent to specific addresses:
{
  "account_id": "default",
  "mailbox": "Sent",
  "to": "[email protected]"
}
Search by subject line:
{
  "account_id": "default",
  "mailbox": "INBOX",
  "subject": "Invoice"
}

Date Filters

Search messages from the last N days:
{
  "account_id": "default",
  "mailbox": "INBOX",
  "last_days": 7
}
Search messages within a specific date range:
{
  "account_id": "default",
  "mailbox": "INBOX",
  "start_date": "2024-01-01",
  "end_date": "2024-01-31"
}
Dates must be in YYYY-MM-DD format. start_date is inclusive, end_date is exclusive (before the date).

Flag Filters

Filter to show only unread messages:
{
  "account_id": "default",
  "mailbox": "INBOX",
  "unread_only": true
}

Combining Filters

Filters can be combined for precise searches:
{
  "account_id": "work",
  "mailbox": "INBOX",
  "from": "[email protected]",
  "unread_only": true,
  "last_days": 3
}

Message Snippets

Include message body snippets in search results for quick preview:
1

Enable snippets

{
  "account_id": "default",
  "mailbox": "INBOX",
  "include_snippet": true
}
2

Configure snippet length

Set snippet character limit (50-500):
{
  "account_id": "default",
  "mailbox": "INBOX",
  "include_snippet": true,
  "snippet_max_chars": 200
}
snippet_max_chars requires include_snippet=true
3

Use snippets in results

Each message includes a snippet field:
{
  "message_id": "imap:default:INBOX:1234:567",
  "subject": "Quarterly Report",
  "from": "[email protected]",
  "snippet": "Please find attached the Q1 financial report showing 23% growth..."
}

Cursor-Based Pagination

For large result sets, use cursor pagination to retrieve messages in chunks:
1

Initial search

Perform your first search without a cursor:
{
  "account_id": "default",
  "mailbox": "INBOX",
  "last_days": 30,
  "limit": 20
}
2

Check pagination status

The response indicates if more results are available:
{
  "summary": "20 message(s) returned",
  "data": {
    "total": 150,
    "returned": 20,
    "messages": [...],
    "next_cursor": "c_1234567890_abcdef",
    "has_more": true
  }
}
3

Fetch next page

Use the next_cursor from the previous response:
{
  "account_id": "default",
  "mailbox": "INBOX",
  "cursor": "c_1234567890_abcdef",
  "limit": 20
}
When using a cursor, search filters from the original request are preserved. Only include account_id, mailbox, cursor, and optionally limit.
4

Continue until complete

Repeat step 3 until has_more is false:
{
  "total": 150,
  "returned": 10,
  "messages": [...],
  "next_cursor": null,
  "has_more": false
}

Search Result Structure

Each search returns consistent metadata and a list of message summaries:
{
  "summary": "25 message(s) returned",
  "data": {
    "status": "ok",
    "account_id": "default",
    "mailbox": "INBOX",
    "total": 150,
    "attempted": 25,
    "returned": 25,
    "failed": 0,
    "messages": [
      {
        "message_id": "imap:default:INBOX:1234:567",
        "message_uri": "imap://default/INBOX/1234/567",
        "message_raw_uri": "imap://default/INBOX/1234/567/raw",
        "mailbox": "INBOX",
        "uidvalidity": 1234,
        "uid": 567,
        "date": "2024-02-26T10:30:00Z",
        "from": "[email protected]",
        "subject": "Important Message",
        "flags": ["\\Seen"],
        "snippet": "This is the beginning of the message..."
      }
    ],
    "next_cursor": "c_1234567890_abcdef",
    "has_more": true
  },
  "meta": {
    "now_utc": "2024-02-26T10:30:45.123Z",
    "duration_ms": 245
  }
}

Field Descriptions

  • total - Total messages matching search criteria
  • attempted - Messages the server tried to fetch details for
  • returned - Messages successfully included in response
  • failed - Messages that failed to fetch (see issues array)
  • next_cursor - Opaque cursor token for next page
  • has_more - Boolean indicating more results available

Search Limits and Constraints

The limit parameter accepts values from 1 to 50. Default is 10.
{
  "mailbox": "INBOX",
  "limit": 50
}
Searches matching more than 20,000 messages will be rejected:
{
  "error": {
    "code": "invalid_input",
    "message": "search matched 25000 messages; narrow filters to at most 20000 results"
  }
}
Solution: Add more specific filters:
  • Reduce last_days value
  • Add from, to, or subject filters
  • Use date ranges instead of last_days
Cursors expire after the configured TTL (default: 300 seconds).
{
  "error": {
    "code": "invalid_input",
    "message": "cursor is invalid or expired"
  }
}
Solution: Restart the search without a cursor.
If the mailbox UIDVALIDITY changes mid-pagination, you’ll receive a conflict error:
{
  "error": {
    "code": "conflict",
    "message": "mailbox snapshot changed; rerun search"
  }
}
Solution: Start a new search without a cursor. The mailbox was modified (messages deleted, mailbox rebuilt, etc.).

Common Search Patterns

{
  "account_id": "default",
  "mailbox": "INBOX",
  "unread_only": true,
  "last_days": 1
}
{
  "account_id": "work",
  "mailbox": "INBOX",
  "from": "[email protected]",
  "limit": 50
}
{
  "account_id": "default",
  "mailbox": "Archive",
  "start_date": "2024-01-01",
  "end_date": "2024-02-01",
  "include_snippet": true,
  "snippet_max_chars": 150
}
{
  "account_id": "default",
  "mailbox": "INBOX",
  "limit": 50
}
Without filters, results are returned in reverse chronological order (newest first).

Performance Tips

Use specific filters - The more specific your filters, the faster the search:
  • Prefer last_days over date ranges
  • Use from or subject filters when possible
  • Set limit to the minimum you need
Enable snippets selectively - Snippets require fetching message bodies, which is slower:
  • Only enable when you need message previews
  • Keep snippet_max_chars as small as practical
Reuse cursors efficiently - Cursors store search state to avoid re-querying:
  • Complete pagination quickly before cursor expiration
  • Don’t mix different search parameters when using cursors

Next Steps

Error Handling

Learn how to handle search errors and edge cases

API Reference

View complete search tool documentation

Build docs developers (and LLMs) love