Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
IMAP/SMTP mail client for OpenClaw agents. Use when: (1) reading or listing emails from a mailbox, (2) searching emails by sender, subject, date or text, (3)...
IMAP/SMTP mail client for OpenClaw agents. Use when: (1) reading or listing emails from a mailbox, (2) searching emails by sender, subject, date or text, (3)...
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete.
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run.
IMAP read/search + SMTP send for any standard mail server. Python stdlib only, zero external dependencies.
"check my email" "do I have unread messages" "read the email from Alice" "search emails about invoice" "send an email to Bob" "move that email to the Archive folder" "mark that as read" "delete that message" "list my mail folders"
python3 scripts/setup.py # interactive setup: credentials + permissions python3 scripts/init.py # validate all configured capabilities python3 scripts/mail.py config # show current config (no secrets)
python3 scripts/setup.py The wizard collects: SMTP host/port, IMAP host/port Mail user and app key (application password) Which capabilities to enable (all false by default) Default folder and max results
python3 scripts/init.py Expected output: all checks OK or SKIP (none FAIL).
Edit ~/.openclaw/config/mail-client/config.json: { "allow_send": true, "allow_read": true, "allow_search": true, "allow_delete": false, "smtp_port": 587, "imap_port": 993, "mail_from": "you@example.com", "default_folder": "INBOX", "max_results": 20 }
PathWritten byPurposeContains secrets~/.openclaw/secrets/mail_credssetup.pySMTP/IMAP credentials + app keyYES - chmod 600, never committed~/.openclaw/config/mail-client/config.jsonsetup.pyBehavior restrictions, folder/limit defaultsNO - behavior only, not in skill dir - survives clawhub updates
Written by setup.py, chmod 600, never committed to git. Contains: MAIL_SMTP_HOST=mail.example.com MAIL_IMAP_HOST=mail.example.com MAIL_USER=user@example.com MAIL_APP_KEY=app-password-here Ports (smtp_port, imap_port) and sender address (mail_from) are set in config.json - they are configuration, not credentials. Credentials can also be provided via environment variables (MAIL_USER, MAIL_APP_KEY, MAIL_SMTP_HOST, MAIL_IMAP_HOST). Environment variables take precedence over file values. The skill checks env vars first, then falls back to the creds file.
Written by setup.py. Controls behavior restrictions (which capabilities are enabled). Contains no secrets. Not in the skill directory - survives clawhub updates. Start from config.example.json in the skill dir if you prefer to create it manually. Cleanup on uninstall: clawhub uninstall mail-client removes the skill directory. To also remove credentials and config: python3 scripts/setup.py --cleanup On reinstall, any existing config at ~/.openclaw/config/mail-client/config.json is picked up automatically.
Import MailClient directly in Python: from scripts.mail import MailClient client = MailClient() # List 5 unread messages msgs = client.list_messages(limit=5, unseen_only=True) for m in msgs: print(m["from"], m["subject"]) # Read a message msg = client.read_message("42") print(msg["body"]) # Send a message result = client.send( to="alice@example.com", subject="Hello", body="Hi Alice, how are you?", ) print(result) # Send with attachments result = client.send( to="alice@example.com", subject="Report Q1", body="Please find attached the Q1 report.", attachments=["report.pdf", "data.xlsx"], ) print(result) # Search found = client.search_messages(from_addr="bob@example.com", unseen_only=True)
python3 scripts/mail.py <subcommand> [options] SubcommandRequiresDescriptionlistallow_readList messages (newest first)read <uid>allow_readRead a full message by UIDsearchallow_searchSearch with filterssendallow_sendSend an email (with optional --attachment)move <uid> <folder>allow_deleteMove message to foldermark-read <uid>allow_readMark as readmark-unread <uid>allow_readMark as unreaddelete <uid>allow_deleteDelete a messagefoldersallow_readList IMAP foldersquotanoneGet mailbox quotaconfignoneShow current config
# List last 10 messages python3 scripts/mail.py list --limit 10 # List unread only python3 scripts/mail.py list --unseen # Read message UID 42 python3 scripts/mail.py read 42 # Search from a sender since a date python3 scripts/mail.py search --from-addr alice@example.com --since 01-Jan-2026 # Search by subject containing "invoice" python3 scripts/mail.py search --subject "invoice" # Send with CC python3 scripts/mail.py send \ --to recipient@example.com \ --subject "Report" \ --body "Please find attached." \ --cc manager@example.com # Send with attachments python3 scripts/mail.py send \ --to recipient@example.com \ --subject "Report Q1" \ --body "See attached." \ --attachment report.pdf data.xlsx # Move UID 42 to Archive python3 scripts/mail.py move 42 Archive # Mark as unread python3 scripts/mail.py mark-unread 42 # Delete UID 42 python3 scripts/mail.py delete 42 # List folders python3 scripts/mail.py folders # Check quota python3 scripts/mail.py quota
from scripts.mail import MailClient client = MailClient() msgs = client.list_messages(unseen_only=True, limit=10) if not msgs: print("No unread messages.") else: for m in msgs: print(f"[{m['uid']}] From: {m['from']} | {m['subject']}")
from scripts.mail import MailClient client = MailClient() client.send( to="admin@example.com", subject="Alert: disk usage high", body="Disk usage has exceeded 90% on server prod-01.", )
from scripts.mail import MailClient client = MailClient() invoices = client.search_messages(subject="invoice", since="01-Jan-2025") for msg in invoices: client.move_message(msg["uid"], "Archive/Invoices")
Daily digest: list unread messages each morning and summarize senders + subjects Auto-archive: move messages matching certain criteria to archive folders Send alerts from monitoring scripts (disk, backups, errors) Draft-style send: compose body via LLM then send via this skill Combined with calendar skill: send meeting summaries by email
nextcloud-files - attach or save email attachments to Nextcloud ghost-admin - email notification when a Ghost post is published Any monitoring or automation skill for alert delivery
See references/troubleshooting.md for: Connection refused Authentication failed IMAP folder not found SMTP relay rejected Self-signed certificate workaround (local servers only)
Code helpers, APIs, CLIs, browser automation, testing, and developer operations.
Largest current source with strong distribution and engagement signals.