Give autonomous AI agents real two-way email inboxes, incoming SMTP reception, upstream relay sending, cryptographic SPF/DKIM/DMARC evidence, prompt-injection screening, and human-in-the-loop review gates.
- π¬ Real Inbound SMTP Daemon: Binds TCP port
2525(dev) or25(production) to accept incoming emails directly from standard Mail Transfer Agents (MTAs) and external servers. - β‘ Upstream Outbound SMTP Relay: Agents send real emails over the internet through upstream providers (AWS SES, Resend, SendGrid, Postmark, or Gmail SMTP with App Passwords).
- π Domains & DNS Record Verification: Configure custom domains (e.g.
agents.yourdomain.com) with auto-generated MX, SPF, DKIM (RSA), and DMARC records and real-time DNS status checks. - π§΅ Standards-Compliant RFC Threading: Automatically preserves RFC
Message-ID,In-Reply-To, andReferencesheaders so agents participate seamlessly in long Gmail or Outlook conversation threads. - π‘οΈ Inbound Threat & Prompt-Injection Screening: Built-in heuristic detector intercepts indirect prompt injections, hidden CSS / zero-point font tricks, ChatML delimiters (
<|im_start|>), and Markdown data exfiltration. - π€ Human-in-the-Loop (HITL) Approval Queue: Configurable policy holds sensitive or suspicious inbound and outbound emails in
pending_reviewuntil an operator approves or quarantines them. - π€ Model Context Protocol (MCP) Gateway: Out-of-the-box MCP endpoint (
http://localhost:8000/mcp/rpc) enables coding agents in Cursor, Claude Code, Claude Desktop, and Windsurf to read inboxes, reply, and send emails autonomously. - π Bearer API Keys: Manage tokens (
oae_live_...) with fine-grained permission scopes for Python / TypeScript agent frameworks (LangChain, CrewAI, PydanticAI, OpenAI Agents SDK).
Real External Inboxes (Gmail / Outlook) Β· Another AI Agent
β β²
Inbound SMTP β β Outbound Upstream SMTP
(Port 2525) βΌ β (AWS SES / Resend / Gmail)
βββββββββββββββββββββββββββββββββββββββββββββββββββββ΄ββββββββββββββββββββββββ
β Open Agent Email Gateway (FastAPI) β
β β
β 1. Inbound SMTP Receiver (RFC 5321 / 5322) β
β 2. Threat Scanner (Prompt Injection / Hidden Text / Exfiltration) β
β 3. Human-in-the-Loop (HITL) Review Gate β
β 4. Local Loopback Relay (Agent-to-Agent) & Upstream SMTP Relay β
β 5. SQLite / PostgreSQL Store with RFC Header Thread Tracking β
βββββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββ
β WebSockets / MCP / REST
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Next.js Dashboard (:3000) Β· Coding Agents (Cursor / Claude) β
β β’ Live Inboxes & Thread View β’ list_messages, get_message β
β β’ Domains & DNS Verification β’ send_message, reply_to_message β
β β’ Upstream SMTP Configuration β’ list_reviews, approve_review β
β β’ HITL Review Queue & API Keys β’ WebSocket stream listener β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Python 3.11+
- Node.js 18+ & npm
cd server
# Create and activate virtual environment
python -m venv .venv
# On Windows:
.\.venv\Scripts\activate
# On Linux/macOS:
source .venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Start server
python run.pyThe server initializes:
- FastAPI HTTP API & MCP:
http://127.0.0.1:8000 - Interactive OpenAPI Docs:
http://127.0.0.1:8000/docs - Inbound SMTP Listener:
127.0.0.1:2525
cd client
npm install
npm run devOpen http://localhost:3000 in your browser.
Run the complete gateway stack with Docker Compose:
docker compose up -d --build- Web Dashboard:
http://localhost:3000 - REST API & MCP:
http://localhost:8000 - SMTP Listener: Port
2525(or map to25for direct internet MX delivery)
To let your agents send real emails to external people over the internet:
- Navigate to Upstream SMTP in the dashboard.
- Enter your provider details:
- Gmail: Host
smtp.gmail.com, Port587, STARTTLS enabled, Username, and Google App Password. - AWS SES: Host
email-smtp.us-east-1.amazonaws.com, Port587, SMTP credentials. - Resend / SendGrid / Postmark: Standard SMTP relay credentials.
- Gmail: Host
- Test delivery instantly with the built-in Send Live Test Email tool.
- Add your agent domain (e.g.,
agents.yourdomain.com). - Add the generated DNS records to your DNS registrar (Cloudflare, Route53, Namecheap):
MX:10 mx.yourdomain.compointing to your server IP.TXT (SPF):v=spf1 include:_spf.openagent.dev ~allTXT (DKIM):default._domainkeywith RSA public key.TXT (DMARC):_dmarcwithp=quarantineorp=reject.
- Click Verify DNS to confirm records.
When an agent has hitl_enabled: true or when the Threat Scanner detects suspicious prompt injection payloads:
- Inbound mail is quarantined before reaching the agent.
- Outbound mail is held before dispatching to upstream SMTP.
- Operators review reason, threat score, and diffs in the review queue and click Approve or Reject.
Connect any Model Context Protocol compatible client to control agent inboxes.
Add to .cursor/mcp.json (or ~/.cursor/mcp.json):
{
"mcpServers": {
"open-agent-email": {
"url": "http://127.0.0.1:8000/mcp/rpc"
}
}
}claude mcp add open-agent-email http://127.0.0.1:8000/mcp/rpc| Tool | Description |
|---|---|
list_agents |
Lists all configured agent inboxes and their operational status. |
list_messages |
Fetches inbound and outbound messages with status and threat scores. |
get_message |
Retrieves full RFC headers, body text, HTML, and security verification verdicts. |
send_message |
Dispatches outbound email from the agent address (relays via upstream SMTP). |
reply_to_message |
Replies in-thread preserving In-Reply-To and References. |
list_reviews |
Lists emails held in the Human-in-the-Loop approval queue. |
approve_review |
Approves a held email and triggers delivery. |
reject_review |
Rejects and quarantines an email. |
Connect an autonomous agent to stream incoming emails over WebSockets without opening firewall ports or using ngrok:
import asyncio
import websockets
import json
AGENT_EMAIL = "assistant@agents.local"
WS_URL = f"ws://127.0.0.1:8000/v1/agents/{AGENT_EMAIL}/ws"
async def listen():
async with websockets.connect(WS_URL) as ws:
print(f"Connected to live stream for {AGENT_EMAIL}")
while True:
msg = await ws.recv()
event = json.loads(msg)
if event.get("event") == "email.received":
data = event["data"]
print(f"New email from: {data['sender']} - Subject: {data['subject']}")
asyncio.run(listen())The built-in scanner guards agent inboxes against:
- Direct Instruction Overrides:
Ignore previous instructions,Disregard system prompts,System Override. - CSS / Font Smuggling:
display:none,font-size:0px,visibility:hidden, zero-width Unicode tags. - ChatML & Prompt Delimiters:
<|im_start|>,[INST],### System:,<|endoftext|>. - Exfiltration Attacks: Markdown image credential leaks (
). - Base64 Payload Obfuscation: Automatic decoding and heuristic recursion.
Apache 2.0. Open-source for developers and autonomous AI agent systems.