QQ邮箱(QQ Mail)全功能操作技能。触发场景:看邮箱、查邮件、收件箱、看看邮件、有没有新邮件、未读邮件、帮我看看邮箱、打开邮箱、最近的邮件、邮件列表、发邮件、写邮件、发一封邮件、回复邮件、转发邮件、删除邮件、搜邮件、找邮件、搜索邮箱、下载附件、邮件附件、check email、inbox、send email、reply、forward、search mail、attachments。覆盖:收发邮件、搜索、附件下载、回复转发删除等所有邮箱操作。All QQ Mail operations MUST go through the qq-mail MCP server tools.
Scanned 9/8/2026
Install to Claude Code
npx -y skills add infometa/workbuddyskills --skill skills --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of qq-mail?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/infometa-qq-mail)More formats (shields.io, HTML) on the badges page.
---
name: qq-mail
description: "QQ邮箱(QQ Mail)全功能操作技能。触发场景:看邮箱、查邮件、收件箱、看看邮件、有没有新邮件、未读邮件、帮我看看邮箱、打开邮箱、最近的邮件、邮件列表、发邮件、写邮件、发一封邮件、回复邮件、转发邮件、删除邮件、搜邮件、找邮件、搜索邮箱、下载附件、邮件附件、check email、inbox、send email、reply、forward、search mail、attachments。覆盖:收发邮件、搜索、附件下载、回复转发删除等所有邮箱操作。All QQ Mail operations MUST go through the qq-mail MCP server tools."
---
# QQ Mail Skill
This skill enables the agent to operate QQ Mail on behalf of the user via the **qqmail MCP server**. All email operations MUST be performed by calling qqmail MCP tools directly.
The qqmail MCP server and its authorization are managed by the QQ Mail Connector — token management is handled by the Connector, not by this skill.
---
## Required Call Sequence
### Always call GetMe first (at session start)
Before any operation, call `GetMe` to obtain the `alias_id` required by all other tools, and to understand available permissions and limits.
```
Tool: GetMe
Arguments: (none)
```
Example response (based on real API):
```json
{
"data": {
"scopes": ["alias:read", "mail:read", "mail:send"],
"aliases": [
{ "alias_id": "alias_q8Mxe-...", "email": "darranadamchou@qq.com", "name": "darranadamchou", "is_primary": true },
{ "alias_id": "alias_2XZMj...", "email": "609709286@qq.com", "is_primary": false }
],
"rate_limits": {
"requests_per_minute": 10,
"requests_per_hour": 200,
"daily_send_quota": 2000
},
"constraints": {
"max_attachment_size_bytes": 1048576,
"max_total_attachments_size_bytes": 3145728,
"max_attachment_count": 3
}
}
}
```
Key fields:
- `aliases[].alias_id` — required for all other tool calls; use the one where `is_primary: true` by default unless the user specifies otherwise
- `aliases[].email` — the actual email address of this alias
- `scopes` — confirms which operations are permitted; check before calling tools:
- `mail:read` → ListMessages, GetMessage, SearchMessages, ListAttachments, DownloadAttachment
- `mail:send` → SendMessage, ReplyMessage, ForwardMessage
- `mail:delete` → DeleteMessage (if missing, DeleteMessage will return 403)
- `constraints` — actual attachment limits to enforce: max 3 files, 1 MB per file, ~3 MB total
---
## Tool Reference
### GetMe
Bootstrap endpoint. Call this first in every session.
```
Tool: GetMe
Required: (none)
```
---
### ListMessages
List emails in a folder with optional filters.
```
Tool: ListMessages
Required:
alias_id: "alias_abc123" # from GetMe
Optional:
dir: "inbox" # inbox | sent | trash | spam
limit: 20 # max 50, default 10
cursor: "<cursor>" # omit for first page; use value from previous response for next page
after: "2026-01-01T00:00:00Z" # ISO 8601, only messages after this time
before: "2026-04-01T00:00:00Z" # ISO 8601, only messages before this time
has_attachments: true # true = with attachments only
is_read: false # true = read only, false = unread only
```
---
### GetMessage
Retrieve full content of a single email.
```
Tool: GetMessage
Required:
alias_id: "alias_abc123" # from GetMe
message_id: "msg_xxxxxxxx" # from ListMessages or SearchMessages
```
Note: Returns attachment metadata (id, filename, size) but NOT file content. To get file content, call `DownloadAttachment` separately.
---
### SearchMessages
Search emails by keyword, sender, recipient, date, or folder.
```
Tool: SearchMessages
Required:
alias_id: "alias_abc123" # from GetMe
Optional:
q: "project report" # search keyword or phrase
search_in: "SEARCH_IN_ALL" # SEARCH_IN_ALL (default) | SEARCH_IN_SUBJECT | SEARCH_IN_CONTENT
# Use SEARCH_IN_SUBJECT when user says "search in subject/title"
# Use SEARCH_IN_CONTENT when user says "search in body/content"
from: "boss@example.com" # filter by sender email
to: "me@qq.com" # filter by recipient email
dir: "inbox" # inbox | sent | trash | spam
after: "2026-01-01T00:00:00Z"
before: "2026-04-01T00:00:00Z"
has_attachments: true
is_read: false
limit: 20 # max 50, default 10
cursor: "<cursor>"
```
---
### ListAttachments
List attachment metadata for an email without downloading content.
```
Tool: ListAttachments
Required:
alias_id: "alias_abc123" # from GetMe
message_id: "msg_xxxxxxxx"
```
Returns: attachment IDs (`att_`-prefixed), filenames, MIME types, file sizes. Use before `DownloadAttachment` to confirm attachment IDs.
---
### DownloadAttachment
Download attachment content as Base64-encoded data.
```
Tool: DownloadAttachment
Required:
alias_id: "alias_abc123" # from GetMe
message_id: "msg_xxxxxxxx"
attachment_id: "att_xxxxxxxx" # from GetMessage or ListAttachments
```
After download, verify data integrity using the SHA-1 checksum if provided.
---
### SendMessage
Send a new email. **Requires two-phase confirmation — see section below.**
```
Tool: SendMessage
Required:
alias_id: "alias_abc123" # from GetMe; identifies the sender
to: # at least one recipient required
- email: "recipient@example.com"
name: "Name" # optional
subject: "Email subject" # max 998 characters
body: "Email body content"
Optional:
cc:
- email: "cc@example.com"
bcc:
- email: "bcc@example.com"
body_format: "PLAIN" # PLAIN (default) | HTML
confirmation_token: "<token>" # ONLY include after user confirms; obtained from Phase 1 response
attachments: # max 3 files, 1MB each, 3MB total
- filename: "report.pdf"
content_type: "application/pdf"
content: "<base64-encoded>"
size: 102400 # original file size in bytes
sha1: "abc123..." # SHA-1 hex hash of original file
```
---
### ReplyMessage
Reply to an existing email. **Requires two-phase confirmation.**
```
Tool: ReplyMessage
Required:
alias_id: "alias_abc123" # from GetMe
message_id: "msg_xxxxxxxx" # the message being replied to
body: "Reply content"
Optional:
body_format: "PLAIN" # PLAIN (default) | HTML
reply_all: false # true = reply to all original recipients; false = reply to sender only
cc:
- email: "cc@example.com"
bcc:
- email: "bcc@example.com"
confirmation_token: "<token>" # ONLY include after user confirms
attachments: # max 3 files, 1MB each
- filename: "file.pdf"
content_type: "application/pdf"
content: "<base64-encoded>"
size: 102400
sha1: "abc123..."
```
---
### ForwardMessage
Forward an email to new recipients. **Requires two-phase confirmation.**
```
Tool: ForwardMessage
Required:
alias_id: "alias_abc123" # from GetMe
message_id: "msg_xxxxxxxx" # the message to forward
to:
- email: "newrecipient@example.com"
Optional:
cc:
- email: "cc@example.com"
bcc:
- email: "bcc@example.com"
body: "FYI — see below" # optional note prepended to the forwarded content
body_format: "PLAIN" # PLAIN (default) | HTML
include_attachments: true # true = include original attachments; false = text only
confirmation_token: "<token>" # ONLY include after user confirms
attachments: # additional attachments beyond original (max 3, 1MB each)
- filename: "extra.pdf"
content_type: "application/pdf"
content: "<base64-encoded>"
size: 102400
sha1: "abc123..."
```
---
### DeleteMessage
Move an email to trash. **Requires two-phase confirmation.**
> ⚠️ **Permission note**: DeleteMessage requires the `mail:delete` scope. If `GetMe` shows only `alias:read, mail:read, mail:send` (no `mail:delete`), the API will return HTTP 403. In this case, inform the user that the current authorization does not include delete permission and guide them to re-authorize with the `mail:delete` scope.
```
Tool: DeleteMessage
Required:
alias_id: "alias_abc123" # from GetMe
message_id: "msg_xxxxxxxx"
Optional:
confirmation_token: "<token>" # ONLY include after user confirms
```
Soft delete only — messages remain in trash for 30 days before permanent deletion.
---
## Two-Phase Confirmation (Critical)
`SendMessage`, `ReplyMessage`, `ForwardMessage`, and `DeleteMessage` all require explicit user confirmation before execution.
### Phase 1 — Get preview
Call the tool **without** `confirmation_token`. The API returns HTTP 428 with:
```json
{
"confirmation_token": "ctk_xxxxxxxx",
"operation_summary": {
"from": "user@qq.com",
"to": ["recipient@example.com"],
"subject": "Email subject",
"attachment_count": 1
}
}
```
Display the full `operation_summary` in an `AskUserQuestion` confirmation card and ask for explicit confirmation. Do NOT ask for confirmation in plain chat text.
### Actual MCP error shape in WorkBuddy
In WorkBuddy connector mode, the first call may be returned as a tool error with
business code `42801` instead of a plain top-level `confirmation_token` response.
Example:
```json
{
"error": {
"code": 42801,
"message": "confirmation required",
"details": {
"confirmation_token": "ctk_xxxxxxxx",
"expires_at": "2026-07-09T12:00:00Z",
"operation_summary": {
"from": "user@qq.com",
"to": ["recipient@example.com"],
"subject": "Email subject",
"attachment_count": 1
}
},
"_hints": {
"suggested_action": "confirm_with_token"
}
}
}
```
When this happens:
- Your next action MUST be to call `AskUserQuestion`.
- Do NOT ask for confirmation in plain chat text.
- Do NOT say the email was sent until the second tool call succeeds.
- Do NOT retry automatically without explicit user confirmation.
- If the user selects the confirmation option in the `AskUserQuestion` card, retry the same QQ Mail tool with the same arguments plus:
```json
{
"confirmation_token": "ctk_xxxxxxxx"
}
```
If the user cancels or does not confirm, do not retry and tell the user the email operation was not executed.
### Phase 2 — Execute after confirmation
If the user selects the confirmation option in the `AskUserQuestion` card, **immediately** call the same tool again with the identical arguments, adding `confirmation_token`:
```
confirmation_token: "ctk_xxxxxxxx"
```
### Rules
- `confirmation_token` expires in ~5 minutes — get user confirmation promptly
- NEVER auto-retry without explicit user approval
- NEVER persist or reuse a token across operations
- If the token expires before the user responds, restart from Phase 1
- If the user cancels or switches topics, abort entirely and discard the token
- Confirmation MUST be collected through an `AskUserQuestion` card; plain chat replies such as "确认" / "yes" are not sufficient unless they are selected in the card.
- The `AskUserQuestion` card SHOULD provide exactly two options: `确认发送` and `取消`.
### Example
```
User: "Send email to alice@example.com"
Agent: [Calls SendMessage without confirmation_token]
← API returns 428 with confirmation_token + operation_summary
Agent: [Calls AskUserQuestion with one confirmation question]
Question:
"是否确认发送这封 QQ 邮箱邮件?
发件人:user@qq.com
收件人:alice@example.com
主题:Hello
附件数:0"
Options:
- 确认发送
- 取消
User: [selects "确认发送" in the AskUserQuestion card]
Agent: [Immediately calls SendMessage again with the same arguments plus confirmation_token="ctk_xxxxxxxx"]
```
---
## Attachment Limits
| Constraint | Value |
|-----------|-------|
| Max files per email | 3 |
| Max size per file | 1 MB |
| Max total per email | 3 MB |
Attachment `content` must be Base64-encoded. Required fields per attachment: `filename`, `content_type`, `content`, `size`, `sha1`.
---
## Email Display Format
When showing an email to the user:
```
发件人:sender@qq.com
收件人:recipient@example.com
主题:Email subject
时间:2026-04-01 10:30:00
邮件正文:
Email body content here...
附件:
report.pdf (2.3 MB)
photo.png (500 KB)
```
- Use Chinese field labels
- Indent body and attachment list with a tab
- If no attachments: `附件:无`
- Multiple recipients: comma-separated
- Time format: YYYY-MM-DD HH:MM:SS
---
## Email Content Rules
- Do NOT add automated signatures or footers (e.g., "Sent via QQ Mail")
- Only include a signature if the user explicitly requests it
---
## Disconnecting / Switching Accounts
If the user wants to disconnect QQ Mail or re-authorize with a different account, revoke the stored OAuth token by deleting the entry from the OAuth credentials file.
### Where the credentials are stored
The QQ Mail OAuth token is stored in a JSON file. The location depends on the environment:
| Environment | Platform | Path |
|-------------|----------|------|
| WorkBuddy / CodeBuddy IDE extension | macOS | `~/Library/Application Support/WorkBuddyExtension/Data/default/VSCode_mcp_ide_oauth.json` |
| WorkBuddy / CodeBuddy IDE extension | Windows | `%LOCALAPPDATA%\WorkBuddyExtension\Data\default\VSCode_mcp_ide_oauth.json` |
| WorkBuddy / CodeBuddy IDE extension | Linux | `~/.local/share/WorkBuddyExtension/Data/default/VSCode_mcp_ide_oauth.json` |
| CodeBuddy Code (CLI) | all platforms | `~/.codebuddy/.credentials.json` |
> If you cannot determine the environment, assume IDE extension (macOS path above) as the default.
>
> Note: The `Data/default/` path is the common case. There may also be UUID-named subdirectories (e.g., `Data/dc5dbbc6-.../`) containing the same file if multiple profiles exist — check both.
### How to revoke
1. Read the credentials file to find the QQ Mail entry (look for a key containing `qq` or `mail.qq.com`).
2. Remove only the QQ Mail entry from the `tokens` object — leave other connectors intact.
3. Save the file.
4. Restart WorkBuddy / CodeBuddy for the change to take effect. The QQ Mail Connector will show as unauthorized and can be re-authorized by scanning the QR code again.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!