Summary
Add support for large outgoing attachments by uploading them to R2 and inserting a secure download link into the email, similar to Gmail’s large-file link fallback.
Problem
Large attachments can hit email provider limits and Worker request body limits. Instead of forcing every file into the email payload, oversized files should be stored in R2 and shared as links.
Proposed behavior
- Small files continue as normal email attachments.
- Files above a configurable limit are uploaded to R2.
- The email body gets a secure download link.
- The UI shows filename, size, upload state, and link status.
- The agent can reference attachment metadata without loading the full file.
Suggested config
MAX_INLINE_ATTACHMENT_MB=25
MAX_R2_LINK_ATTACHMENT_MB=500
R2_ATTACHMENT_LINK_TTL_DAYS=30
Implementation idea
Store files in R2 under a scoped key like:
mailboxes/{mailboxId}/outgoing-attachments/{draftId}/{attachmentId}
Store metadata with the draft/message:
- filename
- content type
- size
- R2 key
- expiry
- download token/hash
Downloads should go through the Worker using an unguessable or signed URL, instead of exposing raw R2 URLs.
For very large files, multipart/chunked upload should be supported.
Acceptance criteria
References
Summary
Add support for large outgoing attachments by uploading them to R2 and inserting a secure download link into the email, similar to Gmail’s large-file link fallback.
Problem
Large attachments can hit email provider limits and Worker request body limits. Instead of forcing every file into the email payload, oversized files should be stored in R2 and shared as links.
Proposed behavior
Suggested config
Implementation idea
Store files in R2 under a scoped key like:
mailboxes/{mailboxId}/outgoing-attachments/{draftId}/{attachmentId}Store metadata with the draft/message:
Downloads should go through the Worker using an unguessable or signed URL, instead of exposing raw R2 URLs.
For very large files, multipart/chunked upload should be supported.
Acceptance criteria
References