claw-mail

v1.0.0

Multi-account email management skill for IMAP/SMTP. Fetches, reads, searches, composes, sends, replies, forwards, and organizes emails across multiple accoun...

0· 386·0 current·0 all-time
byKamau Wanguhu@borgcube
Security Scan
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Suspicious
medium confidence
Purpose & Capability
The name/description (multi-account IMAP/SMTP mail manager) matches the included scripts and libraries (imap_client, smtp_client, account_manager, outbox, composer, S/MIME, OAuth2, etc.). The number and nature of files are proportionate to the claimed feature set (fetch, send, draft, outbox, rules, mail-merge, webhooks, S/MIME).
Instruction Scope
Runtime instructions and scripts stay within the mail-management domain (reading config, connecting to IMAP/SMTP, staging to Outbox, processing rules, saving attachments). However, the rule pipeline supports a 'webhook' action that POSTs JSON payloads including message fields (subject, message_id, sender, matched_rules, tags). If rules/config include external webhook URLs, the skill will transmit email contents to those endpoints. The credential resolution supports op://, keychain://, and env:// URIs, meaning scripts may read environment variables or OS keychain entries if the config references them. These behaviors are plausible for an email processing tool but have data-exfiltration implications depending on configuration.
Install Mechanism
No install spec is provided (instruction-only install), and the package includes the Python scripts directly. That reduces supply-chain risk from remote downloads. The skill requires Python 3.11+ at runtime per SKILL.md but does not attempt to fetch or install arbitrary third-party code during install.
!
Credentials
The registry metadata shows no required env vars, but the code and SKILL.md explicitly support credential URIs: env://VAR_NAME (reads environment variables), keychain://... (macOS Keychain), and op://... (1Password CLI). While this is reasonable for an email client, it means a config file can cause the skill to read arbitrary environment variables or keychain items. Combined with the webhook action, a misconfigured or malicious rules/config can exfiltrate secrets or message contents. The skill therefore has capabilities to access high-value secrets if the user provides URIs in config; that access is not enforced/limited by the metadata.
Persistence & Privilege
always:false and model invocation not disabled (default) — normal. The skill does not claim to modify other skills or system-wide settings. It writes attachments and can create/modify IMAP folders and a local Outbox via IMAP; these are expected for an email client. Because the skill can be invoked autonomously and performs outbound network operations, misconfiguration could increase risk — but autonomous invocation alone is not a disqualifier.
What to consider before installing
This skill seems to implement a full-featured email client and is internally consistent with its description, but it can access credentials (env://, keychain://, op://) and can POST processed message data to arbitrary webhook URLs via rule actions. Before installing: - Review any config.yaml you will use: do not store secrets inline in the skill root. Prefer 1Password or a secure vault over env:// for very sensitive variables. - Inspect rules that include webhook_url and ensure endpoints are trusted; webhook actions will send message metadata (and potentially message content) to external services. - Audit scripts/lib/credential_store.py and references to env:///op:///keychain:// in the repository to confirm exactly how credentials are read and resolved. - If you must test, run the skill in an isolated environment or sandbox and avoid pointing it at production accounts or sensitive environment variables until you are comfortable with its behavior. - If you need stricter guarantees: require that configs do not contain env:// references for secrets, disable webhook rules, or restrict webhook endpoints to known internal services. I judged this 'suspicious' (not 'malicious') because the code and SKILL.md align with an email-management purpose, but the combination of credential resolution and webhook rule actions creates a plausible avenue for data exfiltration if misconfigured or if the config originates from an untrusted source. Additional review of the omitted files (credential_store, processor, webhook implementation) would increase confidence.

Like a lobster shell, security has layers — review code before you run it.

latestvk975wy0sdxqbwztn4zww26rqth81z76v
386downloads
0stars
1versions
Updated 1mo ago
v1.0.0
MIT-0

clawMail Skill

You are an email management agent with multi-account IMAP/SMTP support. You can fetch, read, search, process, compose, send, reply, forward, move, and manage emails, drafts, and folders across multiple email accounts.

Multi-Account Model

  • Account profiles: Each account has its own IMAP/SMTP credentials, mailboxes, fetch limits, archival settings, and processing rules.
  • Default account: One account is designated as the default. Any script invoked without --account uses the default automatically.
  • SMTP fallback: If an account's SMTP server fails, the system automatically retries via a configured fallback relay.
  • IMAP Outbox: Messages are staged in a temporary Outbox folder before SMTP delivery. If SMTP fails, the message stays in Outbox for retry by the heartbeat.
  • Per-account + global rules: Each account has its own rules, plus global rules that apply to all accounts.
  • OAuth2: Accounts can use OAuth2 (XOAUTH2) authentication instead of passwords.
  • Dated-folder archival: archive_mail.py and the heartbeat honor per-account archive_root/archive_frequency defaults so messages routed to the archive action land in folders such as Archive-202603, Archive-W09, or Archive-20260315.

Security

  • TLS 1.2+: All IMAP and SMTP connections enforce TLS 1.2 or higher.
  • Hardened ciphers: Only ECDHE+AESGCM, ECDHE+CHACHA20, DHE+AESGCM, and DHE+CHACHA20 cipher suites are allowed. Weak ciphers (MD5, RC4, 3DES, DSS) are explicitly blocked.
  • Certificate verification: Hostname checking and certificate validation are always enabled.
  • RFC 5322 compliance: All outgoing emails include required Date, Message-ID, and MIME-Version headers automatically.
  • Secure credential storage: Passwords in config support 1Password CLI (op://vault/item/field), macOS Keychain (keychain://service/account), and environment variables (env://VAR_NAME).

Available Scripts

All scripts are in the scripts/ directory. Run with python3 scripts/<name>.py from the skill root. Every script accepts --account <name> to target a specific account.

Core Scripts

ScriptPurpose
scripts/fetch_mail.pyFetch emails from an IMAP folder
scripts/read_mail.pyRead/render an email by Message-ID; save attachments to disk
scripts/search_mail.pySearch emails by subject, sender, body, date, flags
scripts/send_mail.pySend rich HTML emails via SMTP (Outbox + fallback); attach files
scripts/compose_mail.pyCompose rich HTML emails from templates; attach files
scripts/reply_mail.pyReply to an email with original-message quoting
scripts/forward_mail.pyForward an email inline-quoted or with attachments
scripts/draft_mail.pySave, list, resume, or send drafts via IMAP Drafts folder
scripts/process_mail.pyRun emails through the rule-based processing pipeline
scripts/manage_folders.pyList, create, delete, rename, and move IMAP folders
scripts/move_mail.pyMove emails between IMAP folders (batch support)
scripts/heartbeat.pyRun a full heartbeat cycle (drains Outbox, fetches, processes)
scripts/idle_monitor.pyMonitor a mailbox via IMAP IDLE (push notifications)
scripts/retry_send.pyRetry sending messages stuck in the IMAP Outbox
scripts/calendar_invite.pyCompose and send iCalendar meeting invitations
scripts/mail_merge.pyBatch personalised sends from template + CSV/JSON data
scripts/thread_mail.pyGroup messages into conversation threads
scripts/archive_mail.pyAuto-archive old messages into dated folders (daily/weekly/monthly/yearly)

Library Modules

ModulePurpose
scripts/lib/imap_client.pyIMAP client with IDLE, search, folder management, TLS 1.2+
scripts/lib/smtp_client.pySMTP client with TLS 1.2+, RFC 5322, OAuth2, MIME building
scripts/lib/composer.pyRich HTML email composer with templates, reply, forward
scripts/lib/processor.pyRule-based processing pipeline with webhook actions
scripts/lib/account_manager.pyMulti-account manager with SMTP fallback and Outbox
scripts/lib/outbox.pyIMAP Outbox — temporary folder for reliable delivery
scripts/lib/credential_store.pySecure credential storage (1Password, Keychain, env)
scripts/lib/pool.pyConnection pool for IMAP/SMTP reuse
scripts/lib/send_queue.pyLegacy file-backed send queue (superseded by Outbox)
scripts/lib/smime.pyS/MIME signing and encryption
scripts/lib/oauth2.pyOAuth2 (XOAUTH2) token management
scripts/lib/models.pyData models (EmailMessage, EmailAddress, etc.)

Reference Documents

ReferenceWhen to read
references/REFERENCE.mdAPI overview, all script arguments and output formats
references/TEMPLATES.mdAvailable email templates and template variables
references/RULES.mdHow to configure processing rules
ROADMAP.mdFeature roadmap and progress tracker

Quick Start

Fetching Mail

python3 scripts/fetch_mail.py --config config.yaml

python3 scripts/fetch_mail.py --account personal --unread-only --format cli --config config.yaml

Sending Rich Emails

Messages are staged in a temporary IMAP Outbox folder, sent via SMTP (with automatic fallback), then removed from Outbox on success.

python3 scripts/send_mail.py \
  --to "recipient@example.com" \
  --subject "Weekly Report" \
  --body "<p>Here are this week's results.</p>" \
  --template default \
  --attach report.pdf \
  --config config.yaml

Replying and Forwarding

python3 scripts/reply_mail.py --message-id "<id@example.com>" --body "Thanks!" --config config.yaml

python3 scripts/forward_mail.py --message-id "<id@example.com>" --to "colleague@x.com" --config config.yaml

Searching Emails

python3 scripts/search_mail.py --subject "invoice" --unseen --config config.yaml

python3 scripts/search_mail.py --criteria '(FROM "alice@x.com" SINCE 01-Jan-2026)' --config config.yaml

Working with Drafts

python3 scripts/draft_mail.py --action save --to "user@x.com" --subject "WIP" --body "..." --config config.yaml
python3 scripts/draft_mail.py --action list --format cli --config config.yaml
python3 scripts/draft_mail.py --action send --message-id "<draft@x.com>" --config config.yaml

Outbox & Send Retry

python3 scripts/retry_send.py --config config.yaml
python3 scripts/retry_send.py --config config.yaml --list

Heartbeat Cycle

The heartbeat drains each account's Outbox, then fetches and processes mail:

python3 scripts/heartbeat.py --config config.yaml
python3 scripts/heartbeat.py --config config.yaml --account work

Archiving Old Messages

python3 scripts/archive_mail.py --config config.yaml --days 90 --frequency monthly
python3 scripts/archive_mail.py --config config.yaml --days 30 --frequency daily --archive-root "Old Mail" --dry-run --format cli

Archiving honors archive_root / archive_frequency settings (defaults: Archive, monthly). The heartbeat and any rule with the archive action move the message into folders named Archive-202603, Archive-W09, or Archive-20260315 based on the configured cadence.

Calendar Invitations

python3 scripts/calendar_invite.py \
  --to "bob@example.com" --subject "Standup" \
  --start "2026-03-01T09:00:00" --end "2026-03-01T09:30:00" \
  --location "Zoom" --config config.yaml

Mail Merge

python3 scripts/mail_merge.py \
  --data contacts.csv --subject "Hello {{name}}" \
  --body "<p>Dear {{name}}, your code is {{code}}.</p>" \
  --to-field email --config config.yaml

Configuration

Create a config.yaml from assets/config.example.yaml:

default_account: work

accounts:
  work:
    label: "Work"
    sender_address: "alice@company.com"
    sender_name: "Alice Smith"
    imap:
      host: imap.company.com
      port: 993
      username: "alice@company.com"
      password: "op://Work/IMAP/password"          # 1Password CLI
      ssl: true
    smtp:
      host: smtp.company.com
      port: 587
      username: "alice@company.com"
      password: "op://Work/SMTP/password"          # 1Password CLI
      tls: true
    mailboxes: [INBOX, Projects]
    fetch_limit: 50
    rules:
      - name: flag_urgent
        sender_pattern: "boss@company\\.com"
        actions: [flag, tag]
        tag: urgent

  personal:
    label: "Personal"
    sender_address: "alice@gmail.com"
    imap:
      host: imap.gmail.com
      password: "keychain://imap.gmail.com/alice@gmail.com"  # macOS Keychain
    smtp:
      host: smtp.gmail.com
      password: "keychain://smtp.gmail.com/alice@gmail.com"  # macOS Keychain

You can also define archive_root (e.g., Archive) and archive_frequency (daily, weekly, monthly, yearly) either globally or per- account. These defaults drive both the archive_mail.py script and the heartbeat's handling of the archive rule action so that archived messages consistently live under folders like Archive-202603, Archive-W09, or Archive-20260315.

Secure Credential Storage

Passwords in config support four backends:

SchemeBackendExample
op://1Password CLI"op://Work/IMAP/password"
keychain://macOS Keychain"keychain://imap.gmail.com/alice"
env://Environment variable"env://GMAIL_APP_PASSWORD"
(plain text)Literal value"my-password" (logs a warning)

OAuth2 Authentication (Gmail, Outlook 365)

For providers that require OAuth2, set auth: oauth2 on the IMAP/SMTP block:

imap:
  host: imap.gmail.com
  username: "user@gmail.com"
  auth: oauth2
  oauth2:
    client_id: "your-client-id"
    client_secret: "your-client-secret"
    refresh_token: "your-refresh-token"
    token_uri: "https://oauth2.googleapis.com/token"

Legacy Single-Account Config

Flat imap: / smtp: at root is automatically treated as a single account named "default".

Comments

Loading comments...