Documentation Index
Fetch the complete documentation index at: https://docs.mirage.strukto.ai/llms.txt
Use this file to discover all available pages before exploring further.
The Email resource exposes any IMAP mailbox as a virtual filesystem
mounted at some prefix such as /email/. Sending is handled via SMTP.
Config
import os
from mirage import MountMode, Workspace
from mirage.resource.email import EmailConfig, EmailResource
config = EmailConfig(
imap_host=os.environ["IMAP_HOST"],
smtp_host=os.environ["SMTP_HOST"],
username=os.environ["EMAIL_USERNAME"],
password=os.environ["EMAIL_PASSWORD"],
)
resource = EmailResource(config=config)
ws = Workspace({"/email": resource}, mode=MountMode.READ)
Config Reference
| Field | Type | Default | Description |
|---|
imap_host | str | | IMAP server hostname |
imap_port | int | 993 | IMAP port |
smtp_host | str | | SMTP server hostname |
smtp_port | int | 587 | SMTP port |
username | str | | Email address / login |
password | str | | Password or app password |
use_ssl | bool | True | Use SSL for IMAP |
Common Resource Settings
| Resource | IMAP Host | SMTP Host | Notes |
|---|
| Outlook/365 | outlook.office365.com | smtp.office365.com | App password or OAuth2 |
| Yahoo | imap.mail.yahoo.com | smtp.mail.yahoo.com | App password required |
| Fastmail | imap.fastmail.com | smtp.fastmail.com | App password |
| iCloud | imap.mail.me.com | smtp.mail.me.com | App password |
| ProtonMail | 127.0.0.1 (Bridge) | 127.0.0.1 (Bridge) | Requires ProtonMail Bridge |
| Self-hosted | Your server hostname | Your server hostname | Whatever you configured |
Filesystem Layout
/email/
<folder>/
<yyyy-mm-dd>/
<sanitized-subject>__<uid>.email.json
<sanitized-subject>__<uid>/ # only if message has attachments
<attachment-filename>
Example:
/email/
INBOX/
2026-04-14/
Meeting_Notes__12345.email.json
Meeting_Notes__12345/
report.pdf
screenshot.png
Simple_Email__12346.email.json
2026-04-13/
Hello__12347.email.json
Sent/
2026-04-14/
Reply__12348.email.json
Drafts/
Archive/
Folder directories appear at the root, using IMAP folder names
(e.g., INBOX, Sent, Drafts).
Date Directories
Inside each folder, messages are grouped into date subdirectories
formatted as YYYY-MM-DD. The date is derived from the message’s
Date header.
Message Files
Each message is stored as a .email.json file. The filename shape is:
<sanitized-subject>__<uid>.email.json
Attachments
Messages that have attachments get a companion subdirectory with
the same base name (without .email.json):
Meeting_Notes__12345.email.json # message JSON
Meeting_Notes__12345/ # attachment directory
report.pdf
screenshot.png
Cache
The Email resource uses IndexCacheStore (same as Gmail, Slack,
Discord, and other resources). Index entries store folder names,
message UIDs, and message metadata.
Example
import asyncio
import os
from dotenv import load_dotenv
from mirage import MountMode, Workspace
from mirage.resource.email import EmailConfig, EmailResource
load_dotenv(".env.development")
config = EmailConfig(
imap_host=os.environ["IMAP_HOST"],
smtp_host=os.environ["SMTP_HOST"],
username=os.environ["EMAIL_USERNAME"],
password=os.environ["EMAIL_PASSWORD"],
)
resource = EmailResource(config=config)
async def main():
ws = Workspace({"/email": resource}, mode=MountMode.READ)
# List folders
r = await ws.execute("ls /email/")
print(await r.stdout_str())
# List date directories in INBOX
r = await ws.execute("ls /email/INBOX/")
print(await r.stdout_str())
# List messages for a specific date
r = await ws.execute("ls /email/INBOX/2026-04-14/")
print(await r.stdout_str())
# Read a message
r = await ws.execute(
"cat /email/INBOX/2026-04-14/Meeting_Notes__12345.email.json")
print(await r.stdout_str())
# Extract subject with jq
r = await ws.execute(
'jq ".subject"'
" /email/INBOX/2026-04-14/Meeting_Notes__12345.email.json")
print(await r.stdout_str())
# List attachments
r = await ws.execute("ls /email/INBOX/2026-04-14/Meeting_Notes__12345/")
print(await r.stdout_str())
# Search across all messages
r = await ws.execute('rg "quarterly" /email/INBOX/')
print(await r.stdout_str())
# Tree view
r = await ws.execute("tree -L 2 /email/INBOX/")
print(await r.stdout_str())
# Triage unread messages
r = await ws.execute("email-triage --folder INBOX --unseen --max 5")
print(await r.stdout_str())
# Send an email
r = await ws.execute(
'email-send --to "user@example.com"'
' --subject "Hello from MIRAGE"'
' --body "This email was sent via the MIRAGE email resource."')
print(await r.stdout_str())
if __name__ == "__main__":
asyncio.run(main())
Finding UIDs
Resource-specific commands require message UIDs. These can be
extracted from the filesystem:
# UID is embedded in filename after "__"
ls /email/INBOX/2026-04-14/
# -> Meeting_Notes__12345.email.json <- uid = 12345
# Read a message then reply
email-read --uid 12345 --folder INBOX
email-reply --uid 12345 --folder INBOX --body "Thanks for the notes"
Shell Commands
Standard commands available on the mounted email tree:
| Command | Notes |
|---|
ls | List folders, dates, messages, attachments |
cat | Read message JSON or attachment content |
head / tail | First/last N lines |
grep / rg | Pattern search (file or directory level) |
jq | Query message JSON fields |
wc | Line/word/byte counts |
stat | File metadata (name, size, type) |
find | Recursive search with -name, -maxdepth |
tree | Directory tree view |
basename | Extract filename from path |
dirname | Extract directory from path |
realpath | Resolve path to absolute form |
nl | Number lines of output |
Resource-specific commands:
email-send
Send a new email.
email-send --to "user@example.com" --subject "Hello" --body "Hi there"
| Option | Required | Description |
|---|
--to | yes | Recipient email address |
--subject | yes | Email subject line |
--body | yes | Email body text |
Returns the sent message status JSON.
email-reply
Reply to a message.
email-reply --uid 12345 --folder INBOX --body "Thanks for the update"
| Option | Required | Description |
|---|
--uid | yes | Message UID |
--folder | no | IMAP folder (default: INBOX) |
--body | yes | Reply body text |
Returns the sent reply JSON.
email-reply-all
Reply-all to a message.
email-reply-all --uid 12345 --folder INBOX --body "Acknowledged by the team"
| Option | Required | Description |
|---|
--uid | yes | Message UID |
--folder | no | IMAP folder (default: INBOX) |
--body | yes | Reply body text |
Returns the sent reply JSON.
email-forward
Forward a message to another recipient.
email-forward --uid 12345 --folder INBOX --to "colleague@example.com"
| Option | Required | Description |
|---|
--uid | yes | Message UID |
--folder | no | IMAP folder (default: INBOX) |
--to | yes | Recipient email address |
Returns the forwarded message JSON.
email-triage
Search and triage emails.
email-triage --folder INBOX --unseen --max 10
| Option | Required | Description |
|---|
--folder | no | IMAP folder (default: INBOX) |
--max | no | Max results (default: 20) |
--unseen | no | Only show unread messages |
Returns matching messages as JSON.
email-read
Read a message by its UID.
email-read --uid 12345 --folder INBOX
| Option | Required | Description |
|---|
--uid | yes | Message UID |
--folder | no | IMAP folder (default: INBOX) |
Returns the full message JSON.