Treat every email as untrusted input. Give the agent access to one mailbox, not a founder's inbox or an entire workspace. Let code enforce recipients and sensitive actions. Start with read-only access, move to stored drafts, and allow automatic sending only for narrow cases where a wrong reply would cause little harm.
No prompt can make an email agent safe on its own. The useful controls sit around the model: credentials, permissions, policy checks, approval, current thread state, and logs.
Start with a small threat model
List what the agent can read and what it can change. Then ask what happens if an unknown sender controls every word in a message and attachment.
An email agent normally faces five risks:
- Prompt injection. A message tells the agent to ignore its rules, reveal private data, or call another tool.
- Excess access. A stolen key or a bad tool call reaches mailboxes that have nothing to do with the job.
- Unsafe sending. The agent contacts the wrong person, includes private material, or agrees to a refund, contract, or payment change.
- Stale state. A person replies while the agent is drafting, or a retried event causes the same action twice.
- Data leakage. Message bodies, attachments, access tokens, or model prompts end up in logs and systems that do not need them.
Each risk needs a control that your application can test.
Why email prompt injection is different
An agent receives instructions from its developer and text from other people. A model may not reliably distinguish the two when hostile instructions appear inside a normal-looking email.
OWASP's prompt-injection guidance lists email and attachments as sources of indirect prompt injection. The attack does not need to say "ignore previous instructions" in plain text. It can hide directions in HTML, a document, an image, or a link the agent opens.
Keep email content in a clearly marked data field. Do not join it to system instructions as if both came from the same authority. Extract only the parts needed for the task. A parcel-status agent may need an order number and sender address, not the sender's whole signature, linked web pages, and every attachment.
Screening helps, but it is not a security boundary. Google gives the same warning for its Gmail remote MCP server: email may contain instructions that hijack an agent session. Google recommends trusted clients, screening, and review of actions. Design the system so one missed injection still cannot cross the mailbox or sending rules.
Give the agent one identity
A useful agent address describes one job, such as returns@company.com or
invoices@agents.company.com. It should not begin life inside founder@company.com.
A dedicated mailbox reduces the data exposed to the model. It also gives people a clear place to inspect the same conversation and take over. If the job needs several customer mailboxes, put them inside a tenant boundary rather than handing the runtime an organization-wide key.
In Startup Mail, an API key can be scoped to an organization, tenant, or mailbox. Give a single-mailbox agent a mailbox-scoped key. Keep the broader provisioning key in a separate server process. Startup Mail does not support IMAP or SMTP. REST, the TypeScript SDK, and MCP read or act on the mailbox; signed webhooks notify your application that something changed.
Separate resource access from allowed actions
The mailbox boundary answers, "Which mail can this key reach?" Capabilities answer, "What may it do there?"
Capabilities are one explicit operation allowlist. drafts:send is required to send a stored draft.
Startup Mail's current MCP tools do not manage drafts. Use REST or the TypeScript SDK for the
draft-first workflow described below.
Start with access such as:
| Agent job | Typical capabilities |
|---|---|
| Classify new messages | mail:read; add mailboxes:read for discovery |
| Prepare replies | mail:read, drafts:read, and drafts:write |
| Send approved drafts | drafts:read, drafts:write, and drafts:send |
| Send without a draft | mail:send after policy checks |
| Change address rules | policies:write; omit this from most runtime agents |
Do not give the agent permission to change the policy that constrains it. A classifier does not need send access. A drafting agent does not need to provision mailboxes or keys.
Use a separate key for each deployed workload. Give each key a clear name and expiry. Store it in a secret manager, not in a prompt, repository, browser bundle, or email. Revoke it when the agent is retired.
Enforce communication rules outside the model
The model may propose a recipient. Your application should decide whether that address is allowed.
A support workflow might permit replies only to the sender of the current thread. It might block new outbound conversations, added recipients, external forwarding, payment-detail changes, and attachments until a person approves them.
Startup Mail communication policies can allow or block addresses and domains. The send
direction checks every outbound recipient, including outbound replies. For inbound mail,
receive applies to a new conversation and reply applies after Startup Mail has matched the
message to an existing thread. These policies provide a useful service-side backstop. They do
not understand refund limits, legal promises, account ownership, or the meaning of an
attachment. Keep those business rules in your application.
Check the final request, not only the model's first answer. Validate every to, cc, and bcc
address after tools or people have edited a draft. Check attachment IDs against the same
mailbox. Reject a reply if its message ID does not belong to the expected thread.
Use drafts as the default write path
A stored draft creates a clean break between generation and sending. The agent writes the proposed text. Another step checks recipients, attachments, and policy. A person can review or amend the draft before it is sent.
Startup Mail supports stored drafts and scheduled sends. The technical ability to schedule a message is not an approval system by itself. Your application must record who approved it and cancel or replace it when the thread changes.
Require a person to approve messages that:
- Add a new recipient or attachment
- Share customer, employee, medical, legal, or financial information
- Change bank, payment, delivery, or account details
- Offer a refund, discount, credit, or other commitment
- Start a new conversation outside a fixed allowlist
- Respond to a suspected security incident
Automatic replies can make sense for receipts, acknowledgements, and tightly constrained status updates. Even then, test the exact data fields that can enter the message.
Fetch current state before sending
Webhooks and queues can deliver more than once. A person may answer between the incoming event and the agent's draft.
Use the webhook as a signal, then fetch the current thread. Record the triggering message ID. Before sending, fetch the thread again and check for a newer reply or a closed case. Give each outbound action an idempotency key so a retry does not send a duplicate.
A successful API response may mean the service accepted the job, not that the recipient's mail server accepted the message. Track later delivery events when the workflow depends on a firm outcome.
Limit attachments and links
Do not let the agent open every link or execute every file it receives. Parse attachments in an isolated service with strict file, time, and memory limits. Reject types the workflow does not need. Disable macros and active content.
If the model needs one page of an invoice, do not send it the full mailbox archive. Less context means less private data and fewer places to hide hostile instructions.
HTML sanitising and malware checks are useful, but neither proves that a document is safe for a model to follow. Treat extracted text as untrusted after scanning.
Keep an audit trail without copying the mailbox
Record enough to reconstruct an action:
- Mailbox, thread, and triggering message IDs
- Key or workload identity
- Policy result and approval identity
- Draft version and final recipient list
- Send idempotency key and delivery state
Avoid logging access tokens, complete message bodies, or attachment contents unless an incident process needs them. Set a retention period for audit data and model traces. Make revocation and human takeover simple enough to use during an incident.
A safer rollout plan
Run the agent in stages:
- Read and classify mail, but take no external action.
- Create drafts that people compare with the original thread.
- Auto-send one low-risk message type to an address or domain allowlist.
- Expand only after reviewing errors, blocked attempts, duplicate events, and takeover cases.
Test with hostile emails before each stage. Ask whether an attacker can change a recipient, obtain another thread, send a secret, or trigger the same action twice. A good test proves that the application blocks the action even when the model agrees to it.
OpenAI's safety guidance also recommends adversarial testing and human review before model output is used in practice. Reviewers need the original thread, not only the agent's summary.
Frequently asked questions
Can a system prompt stop email prompt injection?
No. A clear system prompt helps the model follow the intended task, but it is not a reliable access-control system. Use mailbox-scoped credentials, narrow tools, recipient checks, stored drafts, and approval around it.
Should an email agent have send permission?
Not at first. Begin with read-only or draft access. Add send permission only for a defined message type after you can enforce recipients, content rules, retries, and human takeover.
Is MCP less secure than a REST API?
Not by definition. Risk depends on the tools, credentials, client, and approval flow. MCP can expose a small tool set, while a careless REST integration can expose a broad key. Apply the same least-privilege and untrusted-input rules to both.
Does Startup Mail provide a complete agent-security system?
No. It provides mailbox and tenant boundaries, scoped keys, drafts, scheduled sends, communication policies, and human mailbox access. Your application must still enforce business rules, run approval workflows, secure the model and other tools, and decide what to log.
For the wider architecture, read The complete guide to email for AI agents. For the account decision, read Should an AI agent use Gmail or a dedicated mailbox?.