SkillHub

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 accounts. Features IMAP Outbox for reliable delivery, secure credential storage via 1Password and macOS Keychain, TLS 1.2+ with hardened ciphers, OAu...

Sourced from ClawHub, Authored by Kamau Wanguhu

Installation

Please help me install the skill `claw-mail` from SkillHub official store. npx skills add borgcube/claw-mail

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

Script Purpose
scripts/fetch_mail.py Fetch emails from an IMAP folder
scripts/read_mail.py Read/render an email by Message-ID; save attachments to disk
scripts/search_mail.py Search emails by subject, sender, body, date, flags
scripts/send_mail.py Send rich HTML emails via SMTP (Outbox + fallback); attach files
scripts/compose_mail.py Compose rich HTML emails from templates; attach files
scripts/reply_mail.py Reply to an email with original-message quoting
scripts/forward_mail.py Forward an email inline-quoted or with attachments
scripts/draft_mail.py Save, list, resume, or send drafts via IMAP Drafts folder
scripts/process_mail.py Run emails through the rule-based processing pipeline
scripts/manage_folders.py List, create, delete, rename, and move IMAP folders
scripts/move_mail.py Move emails between IMAP folders (batch support)
scripts/heartbeat.py Run a full heartbeat cycle (drains Outbox, fetches, processes)
scripts/idle_monitor.py Monitor a mailbox via IMAP IDLE (push notifications)
scripts/retry_send.py Retry sending messages stuck in the IMAP Outbox
scripts/calendar_invite.py Compose and send iCalendar meeting invitations
scripts/mail_merge.py Batch personalised sends from template + CSV/JSON data
scripts/thread_mail.py Group messages into conversation threads
scripts/archive_mail.py Auto-archive old messages into dated folders (daily/weekly/monthly/yearly)

Library Modules

Module Purpose
scripts/lib/imap_client.py IMAP client with IDLE, search, folder management, TLS 1.2+
scripts/lib/smtp_client.py SMTP client with TLS 1.2+, RFC 5322, OAuth2, MIME building
scripts/lib/composer.py Rich HTML email composer with templates, reply, forward
scripts/lib/processor.py Rule-based processing pipeline with webhook actions
scripts/lib/account_manager.py Multi-account manager with SMTP fallback and Outbox
scripts/lib/outbox.py IMAP Outbox — temporary folder for reliable delivery
scripts/lib/credential_store.py Secure credential storage (1Password, Keychain, env)
scripts/lib/pool.py Connection pool for IMAP/SMTP reuse
scripts/lib/send_queue.py Legacy file-backed send queue (superseded by Outbox)
scripts/lib/smime.py S/MIME signing and encryption
scripts/lib/oauth2.py OAuth2 (XOAUTH2) token management
scripts/lib/models.py Data models (EmailMessage, EmailAddress, etc.)

Reference Documents

Reference When to read
references/REFERENCE.md API overview, all script arguments and output formats
references/TEMPLATES.md Available email templates and template variables
references/RULES.md How to configure processing rules
ROADMAP.md Feature 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 "[email protected]" 
  --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 "<[email protected]>" --body "Thanks!" --config config.yaml

python3 scripts/forward_mail.py --message-id "<[email protected]>" --to "[email protected]" --config config.yaml

Searching Emails

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

python3 scripts/search_mail.py --criteria '(FROM "[email protected]" SINCE 01-Jan-2026)' --config config.yaml

Working with Drafts

python3 scripts/draft_mail.py --action save --to "[email protected]" --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 "<[email protected]>" --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 "[email protected]" --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: "[email protected]"
    sender_name: "Alice Smith"
    imap:
      host: imap.company.com
      port: 993
      username: "[email protected]"
      password: "op://Work/IMAP/password"          # 1Password CLI
      ssl: true
    smtp:
      host: smtp.company.com
      port: 587
      username: "[email protected]"
      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: "[email protected]"
    imap:
      host: imap.gmail.com
      password: "keychain://imap.gmail.com/[email protected]"  # macOS Keychain
    smtp:
      host: smtp.gmail.com
      password: "keychain://smtp.gmail.com/[email protected]"  # 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:

Scheme Backend Example
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: "[email protected]"
  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".