/install ai-agent-email-skill
\r \r
AI Agent Email Skill (aaes)\r
\r
Overview\r
\r This skill provides script-based email operations for an agent. It includes functionalities for managing mailboxes, reading/searching emails, sending/replying/forwarding emails, and managing attachments, allowing agents to perform comprehensive email-related tasks programmatically.\r \r
Features\r
\r
- IMAP operations: Read, list, mark, move, delete, copy emails\r
- SMTP operations: Send, reply, forward emails with attachments\r
- Folder management: Create, delete, rename, list mailboxes\r
- Dual-format bodies: Supports both plain-text and HTML, with automatic fallback generation\r
- Attachment handling: Supports base64-encoded attachments\r
- Multi-account support: Configure multiple accounts\r
- Authentication: Password or OAuth2 via environment variables (auto-detected)\r
- Signatures: Automatic signature appending to outgoing emails\r
- Thread support: Proper In-Reply-To and References header handling\r \r
When to use\r
\r Use this skill when you need an agent to:\r \r
- Check inbox for new emails and summarize them\r
- Read specific emails and extract content\r
- Send new emails with attachments\r
- Reply to or forward emails\r
- Organize emails by moving/copying between folders\r
- Create or manage mailbox folders\r
- Mark emails as read/unread, flagged, spam, or junk\r \r
Requirements\r
\r
- Python 3.14+\r
- IMAP/SMTP access to your email provider\r
- Network access to email servers\r \r
Configuration\r
\r
Basic Setup\r
\r
Configure this skill with ./scripts/config.toml:\r
\r
- Copy
./config.default.tomlto./scripts/config.toml.\r - Edit
./scripts/config.toml- fill in email address and server addresses.\r \r
Authentication Setup\r
\r
Only one authentication method is required, configured via environment variables. \r
\r
Password-based authentication\r
\r
| Variable | Description |\r
| ---------------- | ------------------------------------- |\r
| EMAIL_USERNAME | Login username (required) |\r
| EMAIL_PASSWORD | User password or app password |\r
\r
# Linux/Mac\r
export EMAIL_USERNAME="me"\r
export EMAIL_PASSWORD="my-password"\r
\r
# Windows (PowerShell)\r
$env:EMAIL_USERNAME="me"\r
$env:EMAIL_PASSWORD="my-password"\r
\r
# Windows (CMD)\r
set EMAIL_USERNAME=me\r
set EMAIL_PASSWORD=my-password\r
```\r
\r
**OAuth2 authentication**\r
\r
| Variable | Description |\r
| ---------------------------- | ------------------------- |\r
| `EMAIL_OAUTH2_CLIENT_ID` | OAuth2 client ID |\r
| `EMAIL_OAUTH2_CLIENT_SECRET` | OAuth2 client secret |\r
| `EMAIL_OAUTH2_REFRESH_TOKEN` | OAuth2 refresh token |\r
| `EMAIL_OAUTH2_TOKEN_URL` | OAuth2 token endpoint URL |\r
\r
```bash\r
# Linux/Mac\r
export EMAIL_OAUTH2_CLIENT_ID="xxx"\r
export EMAIL_OAUTH2_CLIENT_SECRET="xxx"\r
export EMAIL_OAUTH2_REFRESH_TOKEN="xxx"\r
export EMAIL_OAUTH2_TOKEN_URL="https://oauth2.example.com/token"\r
\r
# Windows (PowerShell)\r
$env:EMAIL_OAUTH2_CLIENT_ID="xxx"\r
$env:EMAIL_OAUTH2_CLIENT_SECRET="xxx"\r
$env:EMAIL_OAUTH2_REFRESH_TOKEN="xxx"\r
$env:EMAIL_OAUTH2_TOKEN_URL="https://oauth2.example.com/token"\r
\r
# Windows (CMD)\r
set EMAIL_OAUTH2_CLIENT_ID=xxx\r
set EMAIL_OAUTH2_CLIENT_SECRET=xxx\r
set EMAIL_OAUTH2_REFRESH_TOKEN=xxx\r
set EMAIL_OAUTH2_TOKEN_URL="https://oauth2.example.com/token"\r
```\r
\r
### Test\r
\r
```bash\r
# Linux/Mac\r
echo '{"requestId":"test","schemaVersion":"1.0","data":{"maxResults":5}}' | python3 scripts/mail_list.py\r
\r
# Windows (PowerShell)\r
echo '{"requestId":"test","schemaVersion":"1.0","data":{"maxResults":5}}' | python scripts/mail_list.py\r
\r
# Windows (CMD)\r
echo "{\"requestId\":\"test\",\"schemaVersion\":\"1.0\",\"data\":{\"maxResults\":5}}" | python scripts/mail_list.py\r
```\r
\r
## Data Exchange Contract\r
\r
### Overview\r
\r
All scripts follow the same JSON-over-stdin contract:\r
\r
1. Agent sends one JSON object to stdin\r
2. Script writes one JSON object to stdout\r
3. Logs and diagnostics are written to stderr\r
\r
### Request Schema\r
\r
```json\r
{\r
"requestId": "optional-trace-id",\r
"schemaVersion": "1.0",\r
"account": "optional-account-name-in-config",\r
"data": {}\r
}\r
```\r
\r
### Success Response Schema\r
\r
```json\r
{\r
"ok": true,\r
"requestId": "same-as-request",\r
"schemaVersion": "1.0",\r
"data": {}\r
}\r
```\r
\r
### Error Response Schema\r
\r
```json\r
{\r
"ok": false,\r
"requestId": "same-as-request",\r
"schemaVersion": "1.0",\r
"error": {\r
"code": "ERROR_CODE",\r
"message": "Human-readable message",\r
"details": {}\r
}\r
}\r
```\r
\r
| Error Code | Description |\r
| ---------------------- | -------------------------------------- |\r
| `VALIDATION_ERROR` | Invalid input data or parameters |\r
| `CONFIG_ERROR` | Configuration file missing or invalid |\r
| `AUTH_ERROR` | Authentication failed |\r
| `NETWORK_ERROR` | Network connection failed |\r
| `MAIL_OPERATION_ERROR` | IMAP/SMTP operation failed |\r
| `MAILBOX_ERROR` | Mailbox selection or management failed |\r
| `INTERNAL_ERROR` | Unexpected internal error |\r
\r
## Scripts\r
\r
### `folder_create.py`\r
\r
Create mailbox folder.\r
\r
| Request fields | |\r
| -------------- | ---------------- |\r
| `name` | string, required |\r
\r
| Response fields | |\r
| --------------- | ------------------- |\r
| `account` | Account name used |\r
| `name` | Folder name created |\r
| `created` | `true` on success |\r
\r
### `folder_delete.py`\r
\r
Delete mailbox folder.\r
\r
| Request fields | |\r
| -------------- | ---------------- |\r
| `name` | string, required |\r
\r
| Response fields | |\r
| --------------- | ------------------- |\r
| `account` | Account name used |\r
| `name` | Folder name deleted |\r
| `deleted` | `true` on success |\r
\r
### `folder_list.py`\r
\r
List mailbox folders.\r
\r
| Request fields | |\r
| -------------- | --- |\r
| (none) | |\r
\r
| Response fields | |\r
| --------------- | ----------------------- |\r
| `account` | Account name used |\r
| `mailboxes` | Array of folder objects |\r
\r
### `folder_rename.py`\r
\r
Rename mailbox folder.\r
\r
| Request fields | |\r
| -------------- | ---------------- |\r
| `oldName` | string, required |\r
| `newName` | string, required |\r
\r
| Response fields | |\r
| --------------- | -------------------- |\r
| `account` | Account name used |\r
| `oldName` | Original folder name |\r
| `newName` | New folder name |\r
| `renamed` | `true` on success |\r
\r
### `mail_copy.py`\r
\r
Copy email(s) between folders.\r
\r
| Request fields | |\r
| -------------- | ---------------------------------- |\r
| `uids` | string[] or comma-separated string |\r
| `sourceFolder` | optional, default `INBOX` |\r
| `targetFolder` | required |\r
\r
| Response fields | |\r
| --------------- | ----------------- |\r
| `account` | Account name used |\r
| `uids` | UIDs copied |\r
| `sourceFolder` | Source folder |\r
| `targetFolder` | Target folder |\r
| `copied` | `true` on success |\r
\r
### `mail_delete.py`\r
\r
Delete email(s).\r
\r
| Request fields | |\r
| -------------- | ---------------------------------- |\r
| `uids` | string[] or comma-separated string |\r
| `folder` | optional, default `INBOX` |\r
| `expunge` | boolean, default `false` |\r
\r
| Response fields | |\r
| --------------- | ---------------------- |\r
| `account` | Account name used |\r
| `uids` | UIDs deleted |\r
| `folder` | Folder name |\r
| `deleted` | `true` on success |\r
| `expunged` | `true` if hard deleted |\r
\r
### `mail_forward.py`\r
\r
Forward email with optional additions.\r
\r
| Request fields | |\r
| -------------- | ---------------------------------------- |\r
| `uid` | string, required |\r
| `folder` | optional, default `INBOX` |\r
| `to` | string or string[], required |\r
| `cc` | optional |\r
| `bcc` | optional |\r
| `bodyText` | optional, prepended to forwarded content |\r
| `bodyHtml` | optional |\r
| `attachments` | optional |\r
\r
| Response fields | |\r
| --------------- | ------------------ |\r
| `account` | Account name used |\r
| `forwarded` | `true` on success |\r
| `uid` | Original email UID |\r
| `to` | Recipients |\r
| `cc` | CC recipients |\r
| `subject` | Forwarded subject |\r
\r
Automatically includes original email and attachments.\r
\r
### `mail_mark.py`\r
\r
Mark email(s) with flags.\r
\r
| Request fields | |\r
| -------------- | ---------------------------------------------------------------------------------- |\r
| `uids` | string[] or comma-separated string, required |\r
| `markType` | `read`, `unread`, `flag`, `unflag`, `spam`, `notspam`, `junk`, `notjunk`, required |\r
| `folder` | optional, default `INBOX` |\r
\r
| Response fields | |\r
| --------------- | ----------------- |\r
| `account` | Account name used |\r
| `uids` | UIDs marked |\r
| `markType` | Mark type applied |\r
| `marked` | `true` on success |\r
\r
### `mail_move.py`\r
\r
Move email(s) between folders.\r
\r
| Request fields | |\r
| -------------- | ---------------------------------- |\r
| `uids` | string[] or comma-separated string |\r
| `sourceFolder` | optional, default `INBOX` |\r
| `targetFolder` | required |\r
\r
| Response fields | |\r
| --------------- | ----------------- |\r
| `account` | Account name used |\r
| `uids` | UIDs moved |\r
| `sourceFolder` | Source folder |\r
| `targetFolder` | Target folder |\r
| `moved` | `true` on success |\r
\r
### `mail_read.py`\r
\r
Read email content and metadata.\r
\r
| Request fields | |\r
| -------------- | ------------------------- |\r
| `uid` | string, required |\r
| `folder` | optional, default `INBOX` |\r
\r
| Response fields | |\r
| --------------- | ------------------------- |\r
| `account` | Account name used |\r
| `uid` | Email UID |\r
| `subject` | Email subject |\r
| `from` | Sender |\r
| `to` | Recipients |\r
| `cc` | CC recipients |\r
| `date` | Email date |\r
| `bodyText` | Plain text body |\r
| `bodyHtml` | HTML body |\r
| `attachments` | Attachment list |\r
| `tags` | Combined flags and labels |\r
\r
Marks message as read after fetch.\r
\r
### `mail_reply.py`\r
\r
Reply to email.\r
\r
| Request fields | |\r
| -------------- | ------------------------- |\r
| `uid` | string, required |\r
| `folder` | optional, default `INBOX` |\r
| `bodyText` | optional |\r
| `bodyHtml` | optional |\r
| `replyAll` | boolean, default `false` |\r
| `priority` | `high`, `normal`, `low` |\r
| `attachments` | optional |\r
\r
| Response fields | |\r
| ----------------- | ---------------------------------------- |\r
| `account` | Account name used |\r
| `uid` | Original email UID |\r
| `folder` | Original email folder |\r
| `sent` | `true` on success |\r
| `to` | Reply recipients |\r
| `cc` | CC recipients |\r
| `attachmentCount` | Number of attachments |\r
| `priority` | Priority level (`high`, `normal`, `low`) |\r
| `readReceipt` | `true` if read receipt requested |\r
| `inReplyTo` | In-Reply-To message ID |\r
| `references` | References header value |\r
| `subject` | Reply subject |\r
\r
### `mail_list.py`\r
\r
List emails using IMAP search.\r
\r
| Request fields | |\r
| -------------- | -------------------------- |\r
| `query` | optional, default `UNSEEN` |\r
| `folder` | optional, default `INBOX` |\r
| `maxResults` | optional, default `10` |\r
\r
| Response fields | |\r
| --------------- | ---------------------- |\r
| `account` | Account name used |\r
| `folder` | Folder searched |\r
| `query` | Search query |\r
| `uids` | Matching UIDs |\r
| `count` | Results returned |\r
| `totalCount` | Total matches |\r
| `hasMore` | More results available |\r
| `summary` | Email summaries |\r
\r
| Query | Description |\r
| ----------------------- | ---------------- |\r
| `UNSEEN` | Unread messages |\r
| `FROM [email protected]` | From sender |\r
| `SUBJECT "keyword"` | Subject contains |\r
| `SINCE 2024-01-01` | Since date |\r
| `ALL` | All messages |\r
\r
### `mail_send.py`\r
\r
Send new email.\r
\r
| Request fields | |\r
| -------------- | ---------------------------- |\r
| `to` | string or string[], required |\r
| `subject` | string, required |\r
| `bodyText` | optional |\r
| `bodyHtml` | optional |\r
| `cc` | optional |\r
| `bcc` | optional |\r
| `priority` | `high`, `normal`, `low` |\r
| `attachments` | optional |\r
\r
| Response fields | |\r
| ----------------- | ---------------------------------------- |\r
| `account` | Account name used |\r
| `sent` | `true` on success |\r
| `to` | Recipients |\r
| `cc` | CC recipients |\r
| `bccCount` | Number of BCC recipients |\r
| `attachmentCount` | Number of attachments |\r
| `priority` | Priority level (`high`, `normal`, `low`) |\r
| `readReceipt` | `true` if read receipt requested |\r
| `inReplyTo` | In-Reply-To message ID |\r
| `references` | References header value |\r
| `subject` | Sent subject |\r
\r
## Examples\r
\r
### List new emails\r
\r
```bash\r
echo '{"requestId":"test","schemaVersion":"1.0","data":{"maxResults":10}}' | python3 scripts/mail_list.py\r
```\r
\r
### Read email by UID\r
\r
```json\r
{ "requestId": "read", "schemaVersion": "1.0", "data": { "uid": "123" } }\r
```\r
\r
### List from sender\r
\r
```json\r
{\r
"requestId": "search",\r
"schemaVersion": "1.0",\r
"data": { "query": "FROM [email protected]" }\r
}\r
```\r
\r
### Send email\r
\r
```json\r
{\r
"requestId": "send",\r
"schemaVersion": "1.0",\r
"data": {\r
"to": ["[email protected]"],\r
"subject": "Hello",\r
"bodyText": "Hello world!"\r
}\r
}\r
```\r
\r
### Reply to email\r
\r
```json\r
{\r
"requestId": "reply",\r
"schemaVersion": "1.0",\r
"data": { "uid": "123", "bodyText": "Thanks!" }\r
}\r
```\r
\r
### Mark and move\r
\r
```json\r
{"requestId":"mark","schemaVersion":"1.0","data":{"uids":"123","markType":"read"}}\r
{"requestId":"move","schemaVersion":"1.0","data":{"uids":"123","targetFolder":"Archive"}}\r
```\r
\r
## Troubleshooting\r
\r
### AUTH_ERROR\r
\r
- If password auth: Ensure both `EMAIL_USERNAME` and `EMAIL_PASSWORD` are set\r
- If OAuth2 auth: All four variables required: `EMAIL_OAUTH2_CLIENT_ID`, `EMAIL_OAUTH2_CLIENT_SECRET`, `EMAIL_OAUTH2_REFRESH_TOKEN`, `EMAIL_OAUTH2_TOKEN_URL`\r
- For 2FA accounts, use app password for `EMAIL_PASSWORD`\r
- OAuth2 takes priority if all four `EMAIL_OAUTH2_*` variables are set\r
\r
### NETWORK_ERROR\r
\r
- Verify IMAP port 993 (SSL) or 143 (STARTTLS)\r
- Verify SMTP port 465 (SSL) or 587 (STARTTLS)\r
- Check firewall settings\r
\r
### CONFIG_ERROR\r
\r
- Ensure `config.toml` exists and is valid TOML\r
- Check `email`, `imap.host`, `smtp.host` are configured\r
\r
### Security Warnings\r
\r
⚠️ **SSL Verification**: Setting `ssl_verify = false` in config disables certificate validation and exposes connections to man-in-the-middle attacks. Only disable for local development/testing.\r
\r
⚠️ **IMAP Injection Protection**: User-provided search queries are validated against a whitelist of safe commands. Custom queries containing `()";` characters will be rejected.\r
\r
### Debugging\r
\r
Check stderr for detailed error logs with `code`, `message`, and `details`.\r
- Make sure OpenClaw is installed (local or Docker)
- Run the install command in chat:
/install ai-agent-email-skill - After installation, invoke the skill by name or use
/ai-agent-email-skill - Provide required inputs per the skill's parameter spec and get structured output
What is ai-agent-email-skill?
This skill provides script-based email operations for an agent. It includes functionalities for managing mailboxes, reading/searching emails, sending/replyin... It is an AI Agent Skill for Claude Code / OpenClaw, with 139 downloads so far.
How do I install ai-agent-email-skill?
Run "/install ai-agent-email-skill" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.
Is ai-agent-email-skill free?
Yes, ai-agent-email-skill is completely free, licensed under MIT-0. You can download, install and use it at no cost.
Which platforms does ai-agent-email-skill support?
ai-agent-email-skill is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).
Who created ai-agent-email-skill?
It is built and maintained by Tyxiang (@tyxiang); the current version is v1.0.6.