Guide
Receive Email Without an SMTP Server
You want an inbox that receives mail — without configuring MX records, installing Postfix, or wiring up spam filters. A Nylas agent account gives you a managed email identity backed by provider=nylas: read messages with the standard email surface and subscribe to webhooks for real-time delivery. No OAuth, no third-party mailbox.
Written by Hazik Director of Product Management
Reviewed by Caleb Geene
The problem with receiving email
Self-hosted inbound email requires at least five separate systems — MX records, an SMTP daemon, spam filtering, TLS certificates, and a MIME parser — each carrying its own maintenance burden and security surface. According to Postfix's own advisory list, the most popular open-source MTA has published 12 security patches since 2020, and each one demands a restart and a smoke test to confirm mail still flows. A managed agent account removes all five layers at once.
Those five systems break down as follows:
- MX records — DNS entries that tell the internet where to deliver your mail
- SMTP daemon — Postfix or Exim to accept the connection and store the message
- Spam filtering — SpamAssassin or rspamd to reject junk before it fills your queue
- TLS certificates — required by senders that enforce opportunistic TLS
- MIME parser — to decode multipart messages, attachments, and encoded headers (the wire format itself is defined in RFC 5322 and the multipart structure in RFC 2045; getting these wrong is a frequent source of CVEs in mail handlers)
A managed agent email account handles all five layers. You get a managed address, a JSON API, and webhook delivery — without touching DNS or a mail daemon.
1. Install
The Nylas CLI installs as a single static binary — under 30 MB on disk — and supports macOS, Linux, and Windows. Homebrew is the fastest method, pulling the latest release from the nylas/nylas-cli tap and linking the binary in one step.
brew install nylas/nylas-cli/nylasFor shell-script, PowerShell, and Go installs, see the getting started guide.
2. Authenticate
Before creating agent accounts, the Nylas CLI needs a valid API key tied to your Nylas application. Authentication takes about 5 seconds: run the config command, paste the key, and the CLI persists the credential locally so every subsequent command inherits it.
The nylas auth config command stores your key in ~/.config/nylas/. The credential is scoped to one Nylas application and never leaves your machine.
nylas auth configPaste your Nylas API key when prompted. The credential file is plain-text, so protect it with chmod 600 on shared machines.
3. Create an agent account
An agent account is a fully managed email identity backed by provider=nylas that can receive (and send) mail without OAuth, MX records, or a third-party mailbox. The Nylas API provisions the address in under 2 seconds and assigns it a grant ID that works with every standard email endpoint. Each Nylas application can hold multiple agent accounts, so a single API key can manage support, no-reply, and test inboxes.
Pick the local-part you want, then create the account. The CLI provisions a managed address under your application's *.nylas.email zone:
nylas agent account create support@yourapp.nylas.email✓ Agent account created successfully!
Email: support@yourapp.nylas.email
Provider: nylas
Status: validThe account is backed by provider=nylas — no OAuth handshake, no third-party mailbox. Share the address wherever you want to receive mail: contact forms, transactional flows, or test automation. For a hands-on walkthrough of the full identity (send + IMAP/SMTP receive), see Create an AI Agent Email Identity.
4. List your agent accounts
Listing agent accounts returns every managed address under the current Nylas application, along with each account's status and grant ID. The default output is a human-readable table; adding --json produces machine-parseable JSON for piping into jq or other tooling. The command completes in roughly 200 ms regardless of how many accounts exist.
# Human-readable table
nylas agent account list
# JSON output (pipe-friendly)
nylas agent account list --jsonAgent Accounts (2)
1. support@yourapp.nylas.email active
ID: 11111111-1111-1111-1111-111111111111
2. noreply@yourapp.nylas.email active
ID: 22222222-2222-2222-2222-2222222222225. Read received messages
The nylas email list command reads messages from any agent account using the same email surface that works with Gmail, Outlook, and IMAP grants. By default, the CLI returns the 10 most recent messages on the active grant. Adding --grant targets a specific agent account by its grant ID, and --unread filters to unread messages only — useful for polling loops in scripts.
Pass --grant to target a specific account explicitly:
# Latest messages on the active grant
nylas email list
# JSON output
nylas email list --json
# Unread only, against a specific agent account
nylas email list \
--grant 11111111-1111-1111-1111-111111111111 \
--unread --json[
{
"id": "msg_a1b2c3d4",
"from": [{ "name": "Alice Smith", "email": "alice@example.com" }],
"to": [{ "email": "support@yourapp.nylas.email" }],
"subject": "Login issue on mobile",
"snippet": "Hi, I can't log in on iOS 17. The button just spins...",
"date": "2026-03-28T09:14:22Z",
"unread": true
}
]6. Set up webhooks for real-time processing
Nylas webhooks push event payloads to your server within seconds of a message arriving, eliminating the latency and wasted API calls of polling. The nylas webhook create command registers an HTTPS endpoint and subscribes it to one or more event triggers. Nylas supports 7 message-level triggers — from message.created for inbound mail to message.link_clicked for engagement tracking — so a single webhook can cover the full message lifecycle.
Register a webhook endpoint and subscribe to the message.created trigger to receive inbound mail notifications:
nylas webhook create \
--url https://example.com/hook \
--triggers message.created✓ Webhook created
Webhook ID: whk_9p0q1r2s3t4u
URL: https://example.com/hook
Triggers: message.created
Status: activeA single webhook can subscribe to multiple event types. Repeat the --triggers flag for each event you want to capture. This is useful when you need to track both inbound delivery and outbound engagement from the same endpoint:
nylas webhook create \
--url https://example.com/hook \
--triggers message.created \
--triggers message.bounce_detected \
--triggers message.link_clickedThe nylas webhook list command shows all active subscriptions, and nylas webhook delete removes one by its ID. Both commands complete in under 500 ms:
# List all webhooks
nylas webhook list
# Delete a webhook
nylas webhook delete whk_9p0q1r2s3t4uAvailable message triggers
| Trigger | Fires when |
|---|---|
| message.created | New email arrives |
| message.updated | Message flags change (e.g., marked read) |
| message.bounce_detected | A sent message bounced |
| message.send_success | A sent message was accepted by the recipient server |
| message.send_failed | A send attempt failed |
| message.opened | Recipient opened the message (pixel tracking) |
| message.link_clicked | Recipient clicked a tracked link |
7. Per-test isolated inboxes
Agent accounts can be created and destroyed programmatically, which makes them ideal for test automation. Provisioning a fresh account takes under 2 seconds via the CLI, so each test run gets its own clean inbox with zero shared state. This pattern eliminates the flaky cross-test contamination that plagues shared mailboxes in CI pipelines — a problem that, according to a 2023 Launchable study, accounts for roughly 30% of flaky end-to-end test failures.
The following Node.js snippet creates a UUID-based agent account before each test and tears it down afterward. The execFileSync call uses argument-array form to avoid shell injection:
import { randomUUID } from 'node:crypto'
import { execFileSync } from 'node:child_process'
const localPart = `e2e-${randomUUID()}`
const email = `${localPart}@yourapp.nylas.email`
// Provision a one-shot agent account for this test (arg-array form, no shell)
const out = execFileSync(
'nylas',
['agent', 'account', 'create', email, '--json'],
{ encoding: 'utf-8' }
)
const { id: grantId } = JSON.parse(out)
// Send your transactional email to `email`.
// Then poll the inbox: execFileSync('nylas', ['email', 'list', '--grant', grantId, '--unread', '--json'])
// Tear down at the end: execFileSync('nylas', ['agent', 'account', 'delete', grantId, '--yes'])Parallel test workers don't interfere with each other, and clean-up is one command per inbox.
8. Clean up
Deleting an agent account revokes its underlying provider=nylas grant, immediately stops accepting inbound mail, and removes the address from your application's account list. Webhooks are separate resources — deleting an account does not automatically remove associated webhooks, so delete those explicitly to avoid orphaned subscriptions.
Both deletions are idempotent. Re-running them against an already-deleted resource returns a 404 but causes no side effects:
# Delete an agent account (revokes the underlying provider=nylas grant)
nylas agent account delete 11111111-1111-1111-1111-111111111111 --yes
# Delete a webhook
nylas webhook delete whk_9p0q1r2s3t4uNext steps
- Getting started with Agent Accounts — architecture diagrams, the workspace model, and how email flows through the policy layer
- Create an AI agent email identity — same agent surface, focused on send + IMAP/SMTP receive
- Send email from the terminal — outbound counterpart to this guide
- E2E email testing with Playwright — full walkthrough using agent accounts in Playwright tests
- Test email webhooks locally — run a local receiver, replay fixtures, and verify signatures before production
- Parse inbound email webhooks — verify message.created events and route message IDs to workers
- Mailtrap alternative for real inbox testing — decide when a managed inbox should replace SMTP capture in tests
- Build an email agent with the CLI — process inbound messages with an AI agent
- Command reference — every flag, subcommand, and example