Skip to main content

IMAP API - REST Interface for IMAP Mailboxes

EmailEngine provides a REST API for IMAP mailboxes, so an application does not have to implement the IMAP protocol itself.

Why Use an IMAP API?

Working with IMAP directly requires:

  • Persistent TCP connections - Managing long-lived socket connections
  • Protocol state machines - Handling IMAP command sequences and states
  • IDLE implementation - Maintaining connections for real-time updates
  • Provider quirks - Dealing with non-standard implementations
  • Connection pooling - Efficiently managing multiple mailbox connections
  • Error recovery - Handling disconnections and reconnections

EmailEngine takes all of this on and exposes the mailbox through REST endpoints and webhook notifications.

IMAP API Operations

List Mailboxes

Get all folders/mailboxes in an account:

curl "https://emailengine.example.com/v1/account/user123/mailboxes?counters=true" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response:

{
"mailboxes": [
{"path": "INBOX", "specialUse": "\\Inbox", "status": {"messages": 1523, "unseen": 12}},
{"path": "Sent", "specialUse": "\\Sent", "status": {"messages": 892, "unseen": 0}},
{"path": "Drafts", "specialUse": "\\Drafts", "status": {"messages": 3, "unseen": 0}}
]
}

Message counts come from status, and only when counters=true is set. Without it the folder tree is returned without per-folder counts, which is much cheaper on an account with many folders.

List Messages

Retrieve messages from a mailbox:

curl "https://emailengine.example.com/v1/account/user123/messages?path=INBOX&page=0&pageSize=20" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response:

{
"messages": [
{
"id": "AAAAAQAACnA",
"uid": 1234,
"date": "2025-01-15T10:30:00Z",
"subject": "Meeting tomorrow",
"from": {"address": "sender@example.com", "name": "John Doe"},
"flags": ["\\Seen"]
}
],
"total": 1523,
"page": 0,
"pages": 77
}

Get Message Content

Fetch a message with its body and attachment list. Body content is left out unless textType asks for it, because fetching it costs a round trip to the mail server:

curl "https://emailengine.example.com/v1/account/user123/message/AAAAAQAACnA?textType=*" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response:

{
"id": "AAAAAQAACnA",
"subject": "Meeting tomorrow",
"from": {"address": "sender@example.com", "name": "John Doe"},
"to": [{"address": "you@example.com"}],
"date": "2025-01-15T10:30:00Z",
"text": {
"plain": "Hi, let's meet tomorrow at 2pm.",
"html": "<p>Hi, let's meet tomorrow at 2pm.</p>"
},
"attachments": [
{
"id": "AAAAAQAACnAy",
"filename": "agenda.pdf",
"contentType": "application/pdf",
"encodedSize": 45231
}
]
}

Search Messages

Search using IMAP search criteria. The search terms go in the request body, so this is a POST:

curl -X POST "https://emailengine.example.com/v1/account/user123/search?path=INBOX" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "search": { "from": "john@example.com", "subject": "invoice" } }'

Or search the message body:

curl -X POST "https://emailengine.example.com/v1/account/user123/search?path=INBOX" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "search": { "body": "quarterly report" } }'

Move/Copy Messages

Move a message to another folder:

curl -X PUT "https://emailengine.example.com/v1/account/user123/message/AAAAAQAACnA/move" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "path": "Archive" }'

Update Flags

Mark messages as read, flagged, etc:

curl -X PUT "https://emailengine.example.com/v1/account/user123/message/AAAAAQAACnA" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "flags": { "add": ["\\Seen"], "delete": ["\\Flagged"] } }'

Delete Messages

Move to trash or permanently delete:

curl -X DELETE "https://emailengine.example.com/v1/account/user123/message/AAAAAQAACnA" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Download Attachments

curl "https://emailengine.example.com/v1/account/user123/attachment/AAAAAQAACnAy" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-o agenda.pdf

Real-Time Updates via Webhooks

EmailEngine maintains IMAP IDLE connections and sends webhooks when changes occur - no polling needed.

New Message Webhook

{
"event": "messageNew",
"account": "my-account",
"data": {
"id": "AAAAAQAACnB",
"uid": 1235,
"path": "INBOX",
"subject": "New inquiry",
"from": {"address": "prospect@example.com"}
}
}

Message Updated Webhook

{
"event": "messageUpdated",
"account": "my-account",
"data": {
"id": "AAAAAQAACnA",
"changes": {
"flags": {
"added": ["\\Seen"],
"value": ["\\Seen"]
}
}
}
}

Message Deleted Webhook

{
"event": "messageDeleted",
"account": "my-account",
"path": "INBOX",
"data": {
"id": "AAAAAQAACnA",
"uid": 1234
}
}

Full webhooks documentation →

Supported IMAP Providers

EmailEngine works with any IMAP server:

ProviderAuthenticationNotes
GmailOAuth2 or App PasswordFull support including labels
Google WorkspaceOAuth2Domain-wide delegation available
Microsoft 365OAuth2Or use Microsoft Graph API
Outlook.comOAuth2Consumer accounts
Yahoo MailApp PasswordIncluding AOL and Verizon; native threading via the OBJECTID extension
FastMailApp PasswordFull IMAP support
Proton MailVia BridgeRequires the Proton Mail Bridge
Zoho MailApp PasswordIMAP enabled accounts
Custom IMAPUser/Password or OAuth2Any standard IMAP server

IMAP API vs Direct IMAP

AspectDirect IMAPEmailEngine IMAP API
Connection ManagementYou handleAutomatic
Real-time UpdatesImplement IDLEWebhooks
AuthenticationHandle OAuth2 flowsBuilt-in
Error RecoveryBuild yourselfAutomatic reconnection
Protocol ComplexityFull IMAP knowledgeREST calls
ScalingConnection poolingManaged per-account

Performance Considerations

Data Fetching

EmailEngine fetches message content on-demand from the IMAP server:

  • Metadata (subject, from, date, flags) - Cached in Redis
  • Body content - Fetched from IMAP when requested
  • Attachments - Streamed from IMAP server

This means:

  • First fetch may be slower than cached solutions
  • No email content stored on your servers
  • Always up-to-date with mailbox state

Connection Handling

  • One IMAP connection per registered account, plus one for each configured sub-connection
  • IDLE on the watched folder for real-time updates
  • Reconnection with backoff after a dropped connection

Get Started with IMAP API

The examples above address a deployed instance at emailengine.example.com. The walkthrough below runs one locally, so it calls http://localhost:3000.

1. Install EmailEngine

# Using Docker
docker run -p 3000:3000 \
--env EENGINE_REDIS="redis://host.docker.internal:6379/8" \
postalsys/emailengine:v2

Full installation guide →

2. Register an IMAP Account

curl -X POST http://localhost:3000/v1/account \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"account": "my-mailbox",
"name": "My Mailbox",
"email": "user@example.com",
"imap": {
"host": "imap.example.com",
"port": 993,
"secure": true,
"auth": {
"user": "user@example.com",
"pass": "your-password"
}
}
}'

3. List Messages

curl "http://localhost:3000/v1/account/my-mailbox/messages?path=INBOX" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

4. Configure Webhooks

webhookEvents is an allowlist with no default: name the events you want, or ["*"] for all of them.

curl -X POST http://localhost:3000/v1/settings \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"webhooks": "https://yourapp.com/webhooks",
"webhooksEnabled": true,
"webhookEvents": ["messageNew", "messageUpdated", "messageDeleted"]
}'

IMAP API Documentation

Alternative: Native Provider APIs

For Gmail and Microsoft 365, EmailEngine also supports native APIs:

  • Gmail API - Direct Google API integration with Pub/Sub
  • Microsoft Graph API - Native Microsoft 365 integration

These provide additional features like native threading and can be faster for some operations.

Gmail API setup → | Microsoft Graph setup →

See Also