Launch-Free 3 months Builder plan-

Receiving Emails

Create inboxes, wait for emails in real-time, and filter results.

Last updated 2026-03-29

Every LobsterMail inbox is a fully functional email address your agent can receive mail at. This guide covers inbox creation, real-time email delivery, filtering, and the email object structure.

Creating Inboxes#

// Smart naming (recommended) — handles collisions automatically
const inbox = await lm.createSmartInbox({
  name: 'Sarah Shield',
  org: 'Palisade',
  displayName: 'Sarah Shield',
});
// Tries: sarah-shield, sarah-shield-palisade, s-shield, sarah-shield1..5, then random

// Purpose-based
const inbox = await lm.createSmartInbox({
  preferred: ['billing-bot', 'billing'],
  displayName: 'Billing Bot',
});

// Auto-generated address
const inbox = await lm.createInbox();
console.log(inbox.address); // lobster-a7f3@lobstermail.ai

// Custom local part
const inbox = await lm.createInbox({ localPart: 'signup-bot' });
console.log(inbox.address); // signup-bot@lobstermail.ai

Custom local parts are first-come, first-served. If the address is taken, the request will fail with a 409 Conflict. Use createSmartInbox() to handle collisions automatically.

Dots are cosmetic (Gmail-style): sarah.shield and sarahshield are the same mailbox.

Listing Emails with receive()#

receive() returns an array of emails currently in the inbox.

const emails = await inbox.receive();

Options#

OptionTypeDescription
sincestringOnly return emails received after this ISO 8601 timestamp.
limitnumberMaximum number of emails to return. Default: 20, max: 50.
direction'inbound' | 'outbound'Filter by email direction.
const recent = await inbox.receive({
  since: '2026-02-23T00:00:00Z',
  limit: 5,
});

Waiting with waitForEmail()#

waitForEmail() waits for an email matching your filters and returns it as soon as it arrives. Under the hood, it uses server-side long-polling — the server holds the connection open and responds within milliseconds of the email landing, instead of the client polling every few seconds.

const email = await inbox.waitForEmail({
  filter: { from: 'noreply@acme.com', subject: 'Verify' },
  timeout: 60000, // 60 seconds
});

If no matching email arrives within the timeout, waitForEmail() returns null.

Options#

OptionTypeDefaultDescription
filter.fromstringMatch against the sender address (exact match).
filter.subjectstring | RegExpMatch against the subject line.
timeoutnumber60000Max wait time in milliseconds.
sincestringOnly consider emails after this ISO 8601 timestamp.
longPollbooleantrueUse server-side long-polling for real-time delivery. Set to false to use classic exponential-backoff polling.

How Long-Polling Works#

When longPoll is enabled (the default), the SDK calls GET /v1/inboxes/{id}/emails/poll which holds the request open server-side for up to 25 seconds. When an email arrives for that inbox, the server returns it immediately — typically within 200ms of delivery.

If no email arrives within the 25-second window, the server returns 204 No Content and the SDK automatically retries. This means your agent makes ~2-3 HTTP requests per minute while waiting, instead of 10+ with traditional polling.

The SDK automatically falls back to classic polling if the server doesn't support the long-poll endpoint.

The Email Object#

email.id          // string — unique email ID (e.g. eml_...)
email.inboxId     // string — the inbox that received this email
email.direction   // 'inbound' | 'outbound'
email.from        // string — sender address
email.to          // string[] — recipient addresses
email.subject     // string — subject line
email.body        // string | null — full body (null until fetched)
email.preview     // string | null — first 200 characters, text only
email.threadId    // string | null — conversation thread ID
email.receivedAt  // string | null — when the email was received

// Security (see Security guide)
email.isInjectionRisk          // boolean — true if injection risk detected
email.security.injectionRiskScore  // number — 0.0 to 1.0
email.security.flags           // string[] — e.g. ['prompt_injection', 'phishing_url']
email.security.spf             // string | null — 'pass' | 'fail' | 'none'
email.security.dkim            // string | null — 'pass' | 'fail' | 'none'
email.security.dmarc           // string | null — 'pass' | 'fail' | 'none'

Safe Content Access#

For agents passing email content to an LLM, always use safeBodyForLLM() instead of body:

const safeContent = email.safeBodyForLLM();

This wraps the body in boundary markers and strips dangerous patterns. See the Security guide for details.

Searching Across Inboxes#

Need to find an email but don't know which inbox it's in? Use searchEmails() to search across all inboxes at once:

const results = await lm.searchEmails({ q: 'invoice', from: 'billing@' });

See the Cross-Inbox Search guide for full details on filtering, pagination, and query syntax.

Conversation Threads#

Emails are automatically grouped into conversation threads. Use the threadId on any email to find related messages, or browse threads directly:

const { data: threads } = await inbox.listThreads();
const thread = await inbox.getThread(threads[0].id);

See the Threads guide for details on how threading works and how to reply within a thread.

Pagination#

Use the since parameter to paginate through emails. receive() returns an Email[] array — use the timestamp of the last email as the since value for the next page:

const page1 = await inbox.receive({ limit: 10 });
if (page1.length === 10) {
  const lastEmail = page1[page1.length - 1];
  const page2 = await inbox.receive({ limit: 10, since: lastEmail.receivedAt });
}