Skip to main content

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

FieldTypeDefaultDescription
imap_hoststrIMAP server hostname
imap_portint993IMAP port
smtp_hoststrSMTP server hostname
smtp_portint587SMTP port
usernamestrEmail address / login
passwordstrPassword or app password
use_sslboolTrueUse SSL for IMAP

Common Resource Settings

ResourceIMAP HostSMTP HostNotes
Outlook/365outlook.office365.comsmtp.office365.comApp password or OAuth2
Yahooimap.mail.yahoo.comsmtp.mail.yahoo.comApp password required
Fastmailimap.fastmail.comsmtp.fastmail.comApp password
iCloudimap.mail.me.comsmtp.mail.me.comApp password
ProtonMail127.0.0.1 (Bridge)127.0.0.1 (Bridge)Requires ProtonMail Bridge
Self-hostedYour server hostnameYour server hostnameWhatever 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:
CommandNotes
lsList folders, dates, messages, attachments
catRead message JSON or attachment content
head / tailFirst/last N lines
grep / rgPattern search (file or directory level)
jqQuery message JSON fields
wcLine/word/byte counts
statFile metadata (name, size, type)
findRecursive search with -name, -maxdepth
treeDirectory tree view
basenameExtract filename from path
dirnameExtract directory from path
realpathResolve path to absolute form
nlNumber lines of output
Resource-specific commands:

email-send

Send a new email.
email-send --to "user@example.com" --subject "Hello" --body "Hi there"
OptionRequiredDescription
--toyesRecipient email address
--subjectyesEmail subject line
--bodyyesEmail 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"
OptionRequiredDescription
--uidyesMessage UID
--foldernoIMAP folder (default: INBOX)
--bodyyesReply 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"
OptionRequiredDescription
--uidyesMessage UID
--foldernoIMAP folder (default: INBOX)
--bodyyesReply 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"
OptionRequiredDescription
--uidyesMessage UID
--foldernoIMAP folder (default: INBOX)
--toyesRecipient email address
Returns the forwarded message JSON.

email-triage

Search and triage emails.
email-triage --folder INBOX --unseen --max 10
OptionRequiredDescription
--foldernoIMAP folder (default: INBOX)
--maxnoMax results (default: 20)
--unseennoOnly show unread messages
Returns matching messages as JSON.

email-read

Read a message by its UID.
email-read --uid 12345 --folder INBOX
OptionRequiredDescription
--uidyesMessage UID
--foldernoIMAP folder (default: INBOX)
Returns the full message JSON.