easy-agent-email
This skill provides script-based email operations for an agent. It includes functionalities for managing mailboxes, reading/searching emails, sending/replyin...
Like a lobster shell, security has layers — review code before you run it.
License
SKILL.md
easy-agent-email
1. Overview
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.
2. Configuration
Configure this skill with ./scripts/config.toml. Configuration method see ./scripts/config.sample.toml.
- Start from
./scripts/config.sample.tomland copy it to./scripts/config.toml. - Fill in a real account entry in
config.tomlbefore using the skill.
3. Data Exchange Contract
3.1. Overview
All scripts follow the same JSON-over-stdin contract:
- Agent sends one JSON object to stdin.
- Script writes one JSON object to stdout.
- Logs and diagnostics are written to stderr.
3.2. Request Schema
{
"requestId": "optional-trace-id",
"schemaVersion": "1.0",
"account": "optional-account-name-in-config",
"data": {}
}
3.3. Success Response Schema
{
"ok": true,
"requestId": "same-as-request",
"schemaVersion": "1.0",
"data": {}
}
Response data field definitions in this document describe possible fields; fields that are not applicable to a specific operation may be omitted.
3.4. Error Response Schema
{
"ok": false,
"requestId": "same-as-request",
"schemaVersion": "1.0",
"error": {
"code": "VALIDATION_ERROR",
"message": "Human-readable message",
"details": {}
}
}
4. Scripts
4.1. Overview
All scripts are under scripts/.
4.2. folder_create.py
Create mailbox.
Request data fields:
name: string, required
Response data fields:
account: string - Account name usedname: string - Mailbox name createdcreated: boolean -trueon success
4.3. folder_delete.py
Delete mailbox.
Request data fields:
name: string, required
Response data fields:
account: string - Account name usedname: string - Mailbox name deleteddeleted: boolean -trueon success
4.4. folder_list.py
List mailboxes.
Request data fields: none ({}).
Response data fields:
account: string - Account name usedmailboxes: array of objects - Parsed mailbox listname: string - Mailbox namedelimiter: string or null - Hierarchy delimiter reported by serverflags: string[] - IMAP LIST flags (e.g.,\HasNoChildren,\Noselect)raw: string - Original LIST row for diagnostics/compatibility
4.5. folder_rename.py
Rename mailbox.
Request data fields:
oldName: string, requirednewName: string, required
Response data fields:
account: string - Account name usedoldName: string - Original mailbox namenewName: string - New mailbox namerenamed: boolean -trueon success
4.6. mail_copy.py
Copy email(s) from one mailbox to another.
Request data fields:
uids: string[] or comma-separated string, requiredsourceFolder: string, optional, defaultINBOXtargetFolder: string, required
Response data fields:
account: string - Account name useduids: string[] - UIDs copiedsourceFolder: string - Source mailbox nametargetFolder: string - Target mailbox namecopied: boolean -trueon success
4.7. mail_delete.py
Delete email(s).
Request data fields:
uids: string[] or comma-separated string, requiredfolder: string, optional, defaultINBOXexpunge: boolean, optional, defaultfalse(soft delete)
Response data fields:
account: string - Account name useduids: string[] - UIDs deletedfolder: string - Mailbox name useddeleted: boolean -trueon successexpunged: boolean -trueif hard delete (expunge) was performed; otherwisefalse.
4.8. mail_forward.py
Forward email with optional additional body and attachments.
Behavior notes:
- If
bodyHtmlis provided withoutbodyText, the script derives a plain-text fallback automatically. - When the original message contains HTML, the forwarded message preserves an HTML body alongside the plain-text forwarded content whenever possible.
Request data fields:
uid: string, requiredfolder: string, optional, defaultINBOXto: string or string[], requiredcc: string or string[], optionalbcc: string or string[], optionalbodyText: string, optional (prepended to forwarded content)bodyHtml: string, optionalattachments: array of { filename: string, contentBase64: string }, optional
Response data fields:
account: string - Account name usedforwarded: boolean -trueon successuid: string - UID of original emailsourceFolder: string - Source mailbox nameto: string[] - Recipient listcc: string[] - CC recipient listbccCount: integer - Number of BCC recipientssubject: string - Forwarded subject (withFwd:prefix)originalAttachmentCount: integer - Number of original attachmentsadditionalAttachmentCount: integer - Number of additional attachments
Automatically includes original email and attachments in forwarded message.
4.9. mail_mark.py
Mark email(s) with various flags.
Request data fields:
uids: string[] or comma-separated string, requiredmarkType: string, optional, defaultread. Allowed values:read: Mark as read (\Seenflag)unread: Mark as unread (remove\Seenflag)flag: Add star/flag (\Flaggedflag)unflag: Remove star/flagspam: Mark as spam (\Spamflag)notspam: Mark as not spamjunk: Mark as junk (\Junkflag)notjunk: Mark as not junk
folder: string, optional, defaultINBOX
Response data fields:
account: string - Account name useduids: string[] - UIDs markedfolder: string - Mailbox name usedmarkType: string - Mark type appliedflag: string - IMAP flag namemarked: boolean -trueon success
4.10. mail_move.py
Move email(s) from one mailbox to another.
Request data fields:
uids: string[] or comma-separated string, requiredsourceFolder: string, optional, defaultINBOXtargetFolder: string, required
Response data fields:
account: string - Account name useduids: string[] - UIDs movedsourceFolder: string - Source mailbox nametargetFolder: string - Target mailbox namemoved: boolean -trueon success
4.11. mail_read.py
Read email content and metadata.
Behavior notes:
- If an attachment cannot be decoded, the script returns a structured
MAIL_OPERATION_ERRORinstead of an internal crash.
Request data fields:
uid: string, requiredfolder: string, optional, defaultINBOX
This command attempts to mark the message as read (\Seen) after successful fetch. If marking as read fails, the script will return an error and no content will be returned.
Response data fields:
account: string - Account name useduid: string - Email UIDfolder: string - Mailbox name usedsubject: string - Email subjectfrom: string - Sender addressto: string - Recipient addressescc: string - CC addresses (empty if not present)date: string - Email date header valuemessageId: string - EmailMessage-IDbodyText: string - Plain text body (nullif no text body)bodyHtml: string - HTML body (nullif no HTML body)attachments: array of { filename: string, contentBase64: string, size: integer } - Attachment listattachmentCount: integer - Number of attachmentsflags: string[] - Raw IMAP flags reported by serversystemTags: string[] - System flags such as\Seen,\Answered,\Flaggedkeywords: string[] - Non-system IMAP keywords/tagsgmailLabels: string[] - Gmail labels when server supportsX-GM-LABELStags: string[] - Combined deduplicated list of flags and labels
4.12. mail_reply.py
Reply email.
Behavior notes:
- If
bodyHtmlis provided withoutbodyText, the script derives a plain-text fallback automatically. - The script keeps quoted original content aligned between the plain-text and HTML reply bodies whenever possible.
Request data fields:
uid: string, requiredfolder: string, optional, defaultINBOXbodyText: string, optionalbodyHtml: string, optionalreplyAll: boolean, optional, defaultfalsepriority: string, optional, defaultnormal. Allowed:high,normal,lowreadReceipt: boolean, optional, defaultfalseinReplyTo: string, optional (overrides auto-generated reply thread header)references: string, optional (overrides auto-generated references header)attachments: array of { filename: string, contentBase64: string }, optional
Response data fields:
account: string - Account name useduid: string - UID of original emailfolder: string - Mailbox name usedsent: boolean -trueon successto: string[] - Reply recipientscc: string[] - CC recipientsattachmentCount: integer - Number of attachments sentpriority: string - Priority appliedreadReceipt: boolean - Read receipt setting appliedinReplyTo: string -In-Reply-Toheader usedreferences: string -Referencesheader usedsubject: string - Reply subject (withRe:prefix)
4.13. mail_list.py
List emails using IMAP search query.
Request data fields:
query: string, optional, defaultUNSEEN(IMAP search syntax, e.g., "FROM user@example.com", "SUBJECT test", "ALL")folder: string, optional, defaultINBOXmaxResults: integer, optional, default10
The script first tries UID SEARCH CHARSET UTF-8 <query>, then falls back to UID SEARCH <query> for compatibility.
Response data fields:
account: string - Account name usedfolder: string - Mailbox name searchedquery: string - Search query executeduids: string[] - Matching email UIDscount: integer - Number of results returnedtotalCount: integer - Total number of matches before limiting bymaxResultshasMore: boolean -trueif more results exist beyondmaxResultssummary: array - Summary list:uid: stringsubject: stringfrom: stringdate: stringflags: string[] - Raw IMAP flags reported by serversystemTags: string[] - System flags such as\Seen,\Answered,\Flaggedkeywords: string[] - Non-system IMAP keywords/tagsgmailLabels: string[] - Gmail labels when server supportsX-GM-LABELStags: string[] - Combined deduplicated list of flags and labels
4.14. mail_send.py
Send a new email.
Behavior notes:
- If both
bodyTextandbodyHtmlare provided, clients typically display the HTML part and keep the text part as a compatibility fallback. - If only
bodyHtmlis provided, the script derives a plain-text fallback automatically.
Request data fields:
to: string or string[], requiredsubject: string, requiredbodyText: string, optionalbodyHtml: string, optionalcc: string or string[], optionalbcc: string or string[], optionalfrom: string, optional, defaults to account emailpriority: string, optional, defaultnormal. Allowed:high,normal,lowreadReceipt: boolean, optional, defaultfalseinReplyTo: string, optionalreferences: string, optionalattachments: array of { filename: string, contentBase64: string }, optional
Response data fields:
account: string - Account name usedsent: boolean -trueon successto: string[] - Recipient listcc: string[] - CC recipient listbccCount: integer - Number of BCC recipientsattachmentCount: integer - Number of attachments sentpriority: string - Priority appliedreadReceipt: boolean - Read receipt setting appliedinReplyTo: string -In-Reply-Toheader usedreferences: string -Referencesheader usedsubject: string - Sent email subject
5. Examples
Suppose the mailbox is already configured.
Windows PowerShell
# List new emails
@'
{"requestId":"req-list","schemaVersion":"1.0","data":{"maxResults":10}}
'@ | python scripts/mail_list.py
# Read the new email with UID `2`
@'
{"requestId":"req-read","schemaVersion":"1.0","data":{"uid":"2"}}
'@ | python scripts/mail_read.py
# Reply to the new email with UID `2`
@'
{"requestId":"req-reply","schemaVersion":"1.0","data":{"uid":"2","bodyText":"Thanks. Received and noted."}}
'@ | python scripts/mail_reply.py
Linux/Mac Terminal
# List new emails
echo '{"requestId":"req-list","schemaVersion":"1.0","data":{"maxResults":10}}' | python3 scripts/mail_list.py
# Read the new email with UID `2`
echo '{"requestId":"req-read","schemaVersion":"1.0","data":{"uid":"2"}}' | python3 scripts/mail_read.py
# Reply to the new email with UID `2`
echo '{"requestId":"req-reply","schemaVersion":"1.0","data":{"uid":"2","bodyText":"Thanks. Received and noted."}}' | python3 scripts/mail_reply.py
Files
17 totalComments
Loading comments…
