Email Attachments Without the Infrastructure Overhead

Attach, send, and retrieve files through a single API. MultiMail handles storage, signed download URLs, and server-side malware scanning so your agent doesn't have to.


Why this matters

Attachments are a common failure point in agent-driven email systems. Files inflate request payloads, require separate storage backends, and introduce malware vectors that a naive API pass-through won't catch. Most teams bolt on S3, write custom MIME checks, and manually wire presigned URLs — none of which belongs in application logic. When an inbound email carries a .xlsx or a .pdf, the agent needs a safe, structured way to retrieve it without downloading raw bytes into memory or exposing a public URL.


How MultiMail solves this

MultiMail handles attachments inline on the send call and as structured metadata on inbound mail. To send a file, include it in the attachments array of your send request as base64 with a name and content type — MultiMail stores it and links it to the message. On inbound email, the message's attachment metadata (name, content type, size) is returned by the read endpoint, and each file is fetched on demand: download it directly, or request a short-lived signed URL that expires automatically so agents never have to hold raw bytes. The result is a consistent read/write pattern for files that works the same whether you're sending a report or parsing an inbound invoice.

1

Attach inline and send

Include each file in the attachments array of a POST /v1/mailboxes/{mailbox_id}/send call as { name, content_base64, content_type }. MultiMail stores it and links it to the outbound message. Multiple attachments map to multiple objects in the same array.

2

Receive inbound attachment metadata

Inbound emails with attachments trigger an email.received webhook. Read the message via GET /v1/mailboxes/{mailbox_id}/emails/{email_id} to get structured attachment metadata for each file: name, content_type, and size. No binary data is inlined in the read response.

3

Download a file directly or via a signed URL

Fetch the bytes with GET /v1/mailboxes/{mailbox_id}/emails/{email_id}/attachments/{filename}, or request a short-lived signed URL with GET /v1/mailboxes/{mailbox_id}/emails/{email_id}/attachments/{filename}/url. The signed URL is valid for one hour — pass it to downstream tools, storage systems, or a human approver without granting permanent access.

4

Malware scanning runs server-side

Inbound mail is scanned (ClamAV) before it lands in the mailbox. Messages that fail scanning or score as spam are quarantined as a whole — the email status reflects the quarantine, so your agent can branch on it before processing any attachment.


Try it with your agent

Pick your platform, copy the prompt, and paste it to your AI agent — it sets up MultiMail and builds the whole flow. Nothing to fill in.

1. Read https://multimail.dev/llms.txt, connect the MultiMail MCP server, create a free inbox, and set up a verified sender. 2. In Zendesk, use a Trigger with a webhook to notify me when a new or updated ticket contains email-originated attachments on a ticket comment. 3. For each triggered ticket, read the Zendesk ticket and comment attachment details, classify the files by name and content type, and draft the right customer reply or internal handoff without exposing raw files in the prompt. 4. Send or schedule the email through MultiMail in monitored mode, keeping attachment-related context tied to the message and flagging suspicious or unsupported files for review. 5. Ask me only for Zendesk credentials, MultiMail access, and brand voice details before turning this on.

What you get

No file bytes in your application layer

Inbound attachments live in MultiMail storage. Your agent works with metadata and short-lived signed URLs — it never has to hold raw inbound bytes in memory.

Malware scanning before your code runs

Inbound mail is virus-scanned (ClamAV) server-side, and messages that fail scanning or score as spam are quarantined as a whole before they reach your mailbox — not after your agent has already processed them. Content-type metadata is exposed so you can enforce your own type policy in the handler.

Consistent send and receive pattern

Outbound files go inline in the send call ({ name, content_base64, content_type }); inbound files surface as metadata on the read endpoint and are fetched on demand. One predictable pattern covers the full file lifecycle.

Time-limited download URLs

Request a signed URL for any inbound attachment by name; it is valid for one hour. Downstream tools, human approvers, and external systems get temporary access without permanent storage exposure.

Structured metadata on inbound files

Every inbound attachment surfaces with name, content_type, and size on the read endpoint. Your agent can make routing decisions on the metadata before ever fetching the file bytes.


Recommended oversight mode

Recommended
monitored
Attachment workflows typically handle business documents — reports, invoices, contracts — where speed matters more than per-action approval. Monitored mode lets the agent send and retrieve files autonomously while giving the human operator a complete activity log. If your use case involves sensitive document categories (legal, financial, health), consider gated_send to require approval before outbound messages with attachments are delivered.

Common questions

What is the maximum attachment size?
Individual attachments are capped at 25 MB, consistent with standard SMTP limits. Total attachment payload per email is capped at 40 MB. For larger files, upload to your own storage and send a presigned URL in the email body instead.
How does inbound attachment screening work?
Inbound mail is virus-scanned (ClamAV) and spam-scored server-side before it lands in your mailbox. A message that fails scanning or scores as spam is quarantined as a whole — its status becomes spam_quarantined or spam_flagged, so your agent can branch on the email status before touching any attachment. To enforce your own content-type policy, read the message and inspect each attachment's content_type metadata before downloading the bytes.
Can I send the same attachment to multiple recipients without re-encoding?
Attachments are sent inline in the send call as base64 — there is no separate upload-and-reference step. To send the same file to multiple recipients, reuse the same base64-encoded attachment object across your send calls (or list multiple recipients in the to array of a single send).
How long do attachment download URLs remain valid?
Request a signed URL for an inbound attachment via GET /v1/mailboxes/{mailbox_id}/emails/{email_id}/attachments/{filename}/url. The URL is valid for one hour. After it expires, request a fresh one. You can also download the bytes directly from the authenticated attachments endpoint without a signed URL.
Are attachments scanned for malware?
Yes. Inbound mail is virus-scanned with ClamAV before it reaches your mailbox. A message that fails scanning is quarantined as a whole — its status reflects the quarantine and your agent will not process its attachments through the normal path. For outbound mail, content is filtered automatically server-side.
What happens if a send fails?
Because attachments are sent inline with the message, there is no orphaned upload to clean up — a failed send simply doesn't create a message. Pass an idempotency_key on the send so a retry after a timeout returns the original message instead of sending a duplicate.
Can I list or read attachments received by a mailbox?
List inbound messages with GET /v1/mailboxes/{mailbox_id}/emails (filter on has_attachments=true to surface messages that carry files), then read a specific message with GET /v1/mailboxes/{mailbox_id}/emails/{email_id} to get the full attachment metadata (name, content_type, size) for that message.

Explore more use cases

The only agent email with a verifiable sender

Email infrastructure built for AI agents. Verifiable identity, graduated oversight, and a hosted MCP server. Formally verified in Lean 4.