Source: https://cli.nylas.com/guides/imap-idle-explained

# IMAP IDLE Explained (RFC 2177)

IMAP IDLE is the extension that lets a mail client receive new-message notifications without polling. This reference explains what RFC 2177 defines, the 29-minute re-issue rule, why IDLE needs a persistent socket per mailbox, and the webhook push alternative the CLI exposes.

Written by [Nick Barraclough](https://cli.nylas.com/authors/nick-barraclough) Product Manager

Reviewed by [Qasim Muhammad](https://cli.nylas.com/authors/qasim-muhammad)

Updated June 9, 2026

> **TL;DR:** IMAP IDLE (RFC 2177) gives you near-real-time mail by holding one socket open per mailbox and re-issuing the command every 29 minutes. That socket count is the catch at scale. There's a push model that keeps zero connections open — the last section shows how to wire it from the terminal with a `message.created` webhook.

## What is IMAP IDLE?

IMAP IDLE is an extension defined in [RFC 2177](https://datatracker.ietf.org/doc/html/rfc2177) (June 1997) that lets a mail client receive new-message notifications in near real time instead of polling. The client issues the `IDLE` command, the server holds the connection open, and it pushes untagged responses the moment a mailbox changes.

Before IDLE, clients polled with a `NOOP` or re-selected the folder on a timer, typically every 60 seconds, which wasted requests and still left a delivery gap. RFC 2177 calls this out directly: the spec exists because clients otherwise “poll the server for changes” on a fixed interval. IDLE replaces that poll loop with a server-driven push, so a message that lands is announced within seconds rather than at the next poll tick.

## How does the IMAP IDLE command work?

The IDLE command works as a two-state handshake on an authenticated IMAP connection. The client sends `IDLE`, the server replies with a continuation line, and the connection enters a waiting state where the server streams untagged `EXISTS` and `EXPUNGE` updates as they happen.

A client must first `SELECT` a mailbox, because IDLE reports changes for exactly one folder per connection. To run any other command, the client sends `DONE` to leave the idle state. The raw protocol exchange against a server like Dovecot looks like the trace below — four lines that map directly to the [RFC 3501](https://datatracker.ietf.org/doc/html/rfc3501) IMAP4rev1 command grammar.

```text
a01 SELECT INBOX
a02 IDLE
+ idling
* 4 EXISTS          <- server pushes: a new message arrived
DONE
a02 OK IDLE terminated
```

## Why must IMAP IDLE be re-issued every 29 minutes?

IMAP IDLE must be re-issued at least every 29 minutes because RFC 2177 tells clients to do exactly that. The spec states a server may terminate an idle connection after 30 minutes of inactivity, so it advises clients to “terminate the IDLE and re-issue it at least every 29 minutes to avoid being logged off.” That single sentence drives every production IDLE keepalive loop.

The mechanism is a timer. Your client sends `DONE`, re-issues `IDLE`, and resets the 29-minute countdown before the server's 30-minute window closes. Gmail enforces the tighter end of this: Google's IMAP extensions documentation recommends re-issuing IDLE every few minutes, and idle sessions are dropped well before 30 minutes under load. Miss the re-issue and the server logs you off, you miss the `EXISTS` push for any mail that arrives during the gap, and your “real-time” inbox silently falls behind until the next reconnect.

## Why does IMAP IDLE need a socket per mailbox?

IMAP IDLE needs one persistent socket per mailbox because IDLE is scoped to a single selected folder on a single authenticated connection. There is no multiplexing in the protocol: 10,000 users watching their inbox means 10,000 long-lived TCP sockets, each one authenticated, selected, idling, and re-issued on its own 29-minute timer.

That fan-out is the real cost of IDLE at scale. Each connection carries OAuth or XOAUTH2 state that you refresh as tokens expire, and when a process restarts, every mailbox it owned re-handshakes at once — a reconnect storm that can hammer the provider and trip rate limits. You also rebalance sockets across worker processes as users come and go. This is weeks of connection-pool plumbing before you read a single message body, and it is the part that pages an on-call engineer at 3 a.m. rather than the feature the product needed.

## How do I replace IMAP IDLE with webhook push?

You replace IDLE by subscribing to a push notification instead of holding a socket. A `message.created` webhook delivers a small notification when new mail arrives, and your app reads the message on demand. You keep zero persistent connections, which is how Gmail's push and Microsoft Graph change notifications work underneath.

The `nylas webhook create` command registers the subscription in one call, and `nylas webhook server` runs a local receiver so you can watch the exact payload shape before you write a handler. One webhook replaces the per-mailbox socket pool, the 29-minute timer, and the reconnect logic.

```bash
# Subscribe to new mail across every connected mailbox
nylas webhook create \
  --url https://your-app.example.com/inbound \
  --triggers message.created \
  --description "imap idle replacement"

# Watch payloads land locally while you build the handler
nylas webhook server --port 9000 --no-tunnel
```

When a notification arrives it carries the message ID, not the body. The `nylas email read` command fetches just that message as JSON — the only request you make, and only when you need the content. A mailbox that gets 50 messages a day costs 50 reads, not 24 hours of held socket.

```bash
# In your handler: fetch only the message the webhook pointed at
nylas email read "$MESSAGE_ID" --json | jq '{from: .from, subject: .subject}'
```

## Next steps

- [Add email sync without IMAP](https://cli.nylas.com/guides/add-email-sync-without-imap) — the full push-plus-on-demand-read pattern, end to end
- [List IMAP emails from the terminal](https://cli.nylas.com/guides/list-imap-emails) — read a generic IMAP mailbox without writing a client
- [Gmail push notifications](https://cli.nylas.com/guides/gmail-push-notifications) — the provider-native push the webhook path rides on
- [Email to Telegram notifications](https://cli.nylas.com/guides/email-to-telegram-notifications) — route the message.created webhook to a chat channel
- [Email to Mattermost notifications](https://cli.nylas.com/guides/email-to-mattermost-notifications) — push new mail into a team channel from the same webhook
- [Command reference](https://cli.nylas.com/docs/commands) — every flag, subcommand, and example
- [RFC 2177 — IMAP IDLE](https://datatracker.ietf.org/doc/html/rfc2177) — the spec behind the 29-minute re-issue rule
- [RFC 3501 — IMAP4rev1](https://datatracker.ietf.org/doc/html/rfc3501) — the base IMAP grammar IDLE extends
- [Microsoft Graph change notifications](https://learn.microsoft.com/en-us/graph/change-notifications-overview) — the Outlook-side push model behind the webhook path
