Docs navigationBrowse documentation216
OverviewStart here

OpenSend docs

Agent Email Inbox Skill

Build an agent inbox on top of OpenSend receiving without exposing raw mailbox access to the agent runtime.

Raw markdown

OpenSend provides tenant-scoped APIs for listing stored inbound emails, retrieving parsed body content, and generating short-lived attachment URLs. The standalone ingester can accept provider notifications with raw MIME payloads, parse them, store attachments, and write received_emails rows before agents read mail.

Architecture

  1. Create or choose a verified domain in OpenSend.
  2. Configure inbound MX records with your email provider. For AWS SES receiving, route inbound messages or S3 object notifications to the standalone ingester boundary.
  3. Send the ingester event_id, recipients, sanitized metadata, and raw_mime, raw_mime_base64, or raw_mime_url. The ingester resolves the receiving route, stores attachment bodies through OpenSend storage, and writes received_emails.
  4. Notify the agent through your queue or application workflow using only metadata and the received email ID.
  5. Let the agent call OpenSend read APIs with a least-privilege service token controlled by your application boundary.

Safe agent read flow

ts
const baseUrl = process.env.OPENSEND_BASE_URL ?? "https://opensend.namuh.co";
const token = process.env.OPENSEND_API_KEY;

async function opensend(path: string) {
  const response = await fetch(`${baseUrl}${path}`, {
    headers: { Authorization: `Bearer ${token}` },
  });
  if (!response.ok) throw new Error(`OpenSend request failed: ${response.status}`);
  return response.json();
}

const inbox = await opensend("/emails/receiving?limit=10&to=agent@inbound.example.com");
const latest = inbox.data[0];
const message = await opensend(`/emails/receiving/${latest.id}`);
const attachments = await opensend(`/emails/receiving/${latest.id}/attachments`);

Attachment policy

Do not pass arbitrary files directly to a model. Check filename, content type, size, tenant ownership, and malware-scanning status before downloading a presigned URL. Prefer text extraction or human approval for high-risk file types.

Prompt boundary

Treat email bodies as untrusted user content. Never let an inbound email override system instructions, API keys, tenant IDs, billing actions, or webhook secrets. Give the agent a narrow instruction such as: "Summarize this received email and draft a reply for human review."

Current product status

Supported in this repository: read APIs, attachment URL generation, dashboard receiving entry point, receiving routes, forwarding rules with attempt visibility, ingester MIME parsing/storage, provider-event idempotency, generated outbound reply tokens, inbound reply/thread matching, and an internal durable received event. Operator work still required: MX/provider setup, provider callback authentication, and any public webhook emission for received mail.