Skip to content

Expose user allowlist and blocklist sender commands - #2261

Open
sysuljx wants to merge 1 commit into
larksuite:mainfrom
sysuljx:feat/c60b367
Open

Expose user allowlist and blocklist sender commands#2261
sysuljx wants to merge 1 commit into
larksuite:mainfrom
sysuljx:feat/c60b367

Conversation

@sysuljx

@sysuljx sysuljx commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Adds mail sender allowlist and blocklist management to the CLI.

  • Documents list, get, set, and delete commands for both lists.
  • Adds generated request-shape tests covering mailbox and sender arguments.

Summary by CodeRabbit

  • Documentation

    • Expanded mail guidance for recipient search, help discovery, delivery-status checks, scheduled sending, send-as addresses, recall, sharing, invitations, templates, and HTML formatting.
    • Added clearer instructions for shortcuts, batch operations, permissions, template workflows, and supported mail resources.
    • Consolidated HTML validation and batch-reading guidance into integrated workflows.
  • Tests

    • Added comprehensive coverage validating mail-sending commands, required fields, preview behavior, permissions, request formatting, and resource naming.

Refresh the generated Mail skill metadata for allow and block sender resources. Add focused contract tests for generated commands, scopes, request shapes, and dry-run routing.
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Added generated tests for mail sender allow-list and block-list resources. Expanded the mail skill with recipient discovery, sending safeguards, HTML linting, templates, shortcuts, API documentation, and permissions.

Changes

Mail sender resource tests

Layer / File(s) Summary
Sender contracts and metadata
cmd/service/mail_sender_generated_test.go
Defines expected sender methods and validates transport metadata, parameters, scopes, request fields, and response fields.
Command and request validation
cmd/service/mail_sender_generated_test.go
Validates generated commands, required mailbox errors, and dry-run request serialization.
Scope preflight and command names
cmd/service/mail_sender_generated_test.go
Tests scope preflight behavior and preserves dotted allow-sender and blocked-sender resource names.

Mail skill guidance

Layer / File(s) Summary
Mail workflows and discovery
skills/lark-mail/SKILL.md
Expands intent coverage, help discovery, recipient search, draft editing, rule actions, and delivery-status procedures.
Sending, HTML, and templates
skills/lark-mail/SKILL.md
Documents sending safeguards, scheduled delivery, recall, sharing, calendar invitations, HTML linting, style rules, and templates.
Shortcuts, APIs, and permissions
skills/lark-mail/SKILL.md
Expands shortcut behavior, HTML linting, API resources and methods, and permission requirements.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • larksuite/cli#2224: Adds tests for sender allow-list and block-list CLI resources documented by that PR.

Suggested labels: documentation

Suggested reviewers: liangshuo-1

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the primary change: exposing user allowlist and blocklist sender commands.
Description check ✅ Passed The description explains the CLI scope, documents the main changes, and identifies generated request-shape tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added domain/mail PR touches the mail domain size/L Large or sensitive change across domains or core paths labels Aug 10, 2026
@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown

PR Quality Summary

CI did not complete successfully. Use the failed check links below to decide whether this PR needs a code change or a rerun.

Failed checks

@github-actions

Copy link
Copy Markdown

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@f3eb37181b26b0cb1bc446d919316019567c9286

🧩 Skill update

npx skills add sysuljx/cli#feat/c60b367 -y -g

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmd/service/mail_sender_generated_test.go`:
- Around line 232-260: Update the dry-run assertions in the contract test around
the envelope API call to project list parameters, create bodies, and remove
bodies into distinct typed structs instead of inspecting generic maps. Assert
the exact expected create sender and sender_type values, and the exact remove
sender list, while preserving the existing list keyword and page_size checks.
- Around line 196-204: The error-path tests must assert typed metadata in both
affected locations: in cmd/service/mail_sender_generated_test.go lines 196-204,
retain errors.As and validationErr.Param == "user_mailbox_id", then assert
Category and Subtype via errs.ProblemOf(err) without using it for Param; in
lines 288-294, assert the permission error’s Category and Subtype via
errs.ProblemOf(err) before checking MissingScopes.
- Line 162: Update cmd/service/mail_sender_generated_test.go at lines 162-162
and 310-310 to use cmdutil.TestFactory(t, config) instead of raw
&cmdutil.Factory{} values. At lines 188-188 and 214-214, call
t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir()) before creating the factory,
and ensure all affected tests use isolated TestFactory setup.

In `@skills/lark-mail/SKILL.md`:
- Line 4: Update the skill description trigger list and the sender-list
documentation near the API method section to cover allowlist and blocklist
operations in Chinese and English. Add concrete user-facing examples for
listing, getting, setting, and deleting entries for both sender-list resources,
including mailbox identity, sender type, pagination, and required confirmation
behavior; retain the existing API method references.
- Around line 115-117: Update the workflow around the `user_mailboxes profile`
step so the relevant `-h` command runs first, or explicitly state that the
numbered workflow begins after the mandatory initial help check. Keep the
existing `profile` operation and first-use ordering consistent with the
documented requirement.
- Around line 299-309: Update the example command’s --event-start and
--event-end values to use a clearly future calendar date relative to August 10,
2026, while preserving the one-hour meeting duration and timezone.
- Around line 207-216: Update the mail write examples for public-mailbox and
alias sends, cancel_scheduled_send, and all +draft-* shortcuts to include the
required --as user option, consistent with the guidance on lines 88-91. If these
shortcuts intentionally enforce user identity instead, document that behavior
explicitly.
- Around line 555-561: The permission table entries for
user_mailbox.allow_senders.list and user_mailbox.blocked_senders.list currently
omit a required scope. Update both rows to document
mail:user_mailbox.message:readonly and mail:user_mailbox.message:modify,
matching the generated contract and preserving the existing endpoint
descriptions.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 94d46c28-ed0b-4e6f-8769-1fabdf500eaa

📥 Commits

Reviewing files that changed from the base of the PR and between 2016120 and f3eb371.

📒 Files selected for processing (2)
  • cmd/service/mail_sender_generated_test.go
  • skills/lark-mail/SKILL.md

func TestGeneratedMailUserSenderCommandsHelpAndRequiredMailbox(t *testing.T) {
service := generatedMailService(t)
root := &cobra.Command{Use: "lark-cli"}
registerService(root, service, &cmdutil.Factory{})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Initialize and isolate each test factory.

Raw factories bypass the standard test fixture setup. The TestFactory calls also lack the required isolated configuration directory.

  • cmd/service/mail_sender_generated_test.go#L162-L162: Replace &cmdutil.Factory{} with a factory from cmdutil.TestFactory.
  • cmd/service/mail_sender_generated_test.go#L188-L188: Set LARKSUITE_CLI_CONFIG_DIR to t.TempDir() before creating the factory.
  • cmd/service/mail_sender_generated_test.go#L214-L214: Set LARKSUITE_CLI_CONFIG_DIR to t.TempDir() before creating the factory.
  • cmd/service/mail_sender_generated_test.go#L310-L310: Replace &cmdutil.Factory{} with a factory from cmdutil.TestFactory.

As per coding guidelines, tests must use cmdutil.TestFactory(t, config) and isolate configuration state with t.Setenv.

📍 Affects 1 file
  • cmd/service/mail_sender_generated_test.go#L162-L162 (this comment)
  • cmd/service/mail_sender_generated_test.go#L188-L188
  • cmd/service/mail_sender_generated_test.go#L214-L214
  • cmd/service/mail_sender_generated_test.go#L310-L310
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/service/mail_sender_generated_test.go` at line 162, Update
cmd/service/mail_sender_generated_test.go at lines 162-162 and 310-310 to use
cmdutil.TestFactory(t, config) instead of raw &cmdutil.Factory{} values. At
lines 188-188 and 214-214, call t.Setenv("LARKSUITE_CLI_CONFIG_DIR",
t.TempDir()) before creating the factory, and ensure all affected tests use
isolated TestFactory setup.

Source: Coding guidelines

Comment on lines +196 to +204
var validationErr *errs.ValidationError
if !errors.As(err, &validationErr) {
t.Fatalf("missing mailbox error = %T %v, want *errs.ValidationError", err, err)
}
if validationErr.Param != "user_mailbox_id" ||
!strings.Contains(validationErr.Hint, "--user-mailbox-id") ||
!strings.Contains(validationErr.Hint, "lark-cli schema mail."+contract.resource+"."+contract.method) {
t.Fatalf("missing mailbox error is not actionable: %+v", validationErr)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert typed metadata for both error paths.

These tests can pass if the error category or subtype changes. Assert Category and Subtype through errs.ProblemOf(err).

  • cmd/service/mail_sender_generated_test.go#L196-L204: Also retain errors.As and assert validationErr.Param == "user_mailbox_id". Do not use errs.ProblemOf for Param.
  • cmd/service/mail_sender_generated_test.go#L288-L294: Assert the permission error category and subtype before checking MissingScopes.

As per coding guidelines, error-path tests must assert typed metadata. Based on learnings, errs.ProblemOf does not expose Param.

📍 Affects 1 file
  • cmd/service/mail_sender_generated_test.go#L196-L204 (this comment)
  • cmd/service/mail_sender_generated_test.go#L288-L294
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/service/mail_sender_generated_test.go` around lines 196 - 204, The
error-path tests must assert typed metadata in both affected locations: in
cmd/service/mail_sender_generated_test.go lines 196-204, retain errors.As and
validationErr.Param == "user_mailbox_id", then assert Category and Subtype via
errs.ProblemOf(err) without using it for Param; in lines 288-294, assert the
permission error’s Category and Subtype via errs.ProblemOf(err) before checking
MissingScopes.

Sources: Coding guidelines, Learnings

Comment on lines +232 to +260
var envelope struct {
OK bool `json:"ok"`
DryRun bool `json:"dry_run"`
Data struct {
API []struct {
Method string `json:"method"`
URL string `json:"url"`
Params map[string]interface{} `json:"params"`
Body map[string]interface{} `json:"body"`
} `json:"api"`
} `json:"data"`
}
if err := json.Unmarshal(stdout.Bytes(), &envelope); err != nil {
t.Fatalf("dry-run output is not JSON: %v\n%s", err, stdout.String())
}
if !envelope.OK || !envelope.DryRun || len(envelope.Data.API) != 1 {
t.Fatalf("unexpected dry-run envelope: %s", stdout.String())
}
call := envelope.Data.API[0]
wantURL := "/open-apis/mail/v1/" + strings.Replace(contract.path, "{user_mailbox_id}", "me", 1)
if call.Method != contract.httpMethod || call.URL != wantURL {
t.Fatalf("dry-run transport = %s %s, want %s %s", call.Method, call.URL, contract.httpMethod, wantURL)
}
if contract.method == "list" {
if call.Params["keyword"] != "example" || call.Params["page_size"] != float64(20) {
t.Fatalf("list params = %#v, want keyword and page_size", call.Params)
}
} else if _, ok := call.Body[contract.bodyField]; !ok {
t.Fatalf("write body = %#v, want %q", call.Body, contract.bodyField)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Assert typed create and remove request bodies.

The test only checks that the body contains items or senders. It does not verify the supplied sender values. A regression that drops sender, changes sender_type, or changes the remove list can still pass.

Decode each request shape into a typed struct. Assert the exact create and remove values. Use distinct structs for list parameters, create bodies, and remove bodies.

As per coding guidelines, contract tests must assert changed fields directly, and JSON maps must be projected into typed structures at the boundary.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/service/mail_sender_generated_test.go` around lines 232 - 260, Update the
dry-run assertions in the contract test around the envelope API call to project
list parameters, create bodies, and remove bodies into distinct typed structs
instead of inspecting generic maps. Assert the exact expected create sender and
sender_type values, and the exact remove sender list, while preserving the
existing list keyword and page_size checks.

Source: Coding guidelines

Comment thread skills/lark-mail/SKILL.md
name: lark-mail
version: 1.0.0
description: "飞书邮箱Use when user mentions 起草邮件、写邮件、草稿、发送/回复/转发邮件、查阅邮件、看邮件搜索邮件邮件文件夹邮件标签邮件联系人监听新邮件、邮件收信规则等;use for mail/email intent only. Do not use for docs/sheets/calendar/auth setup/pure contact lookup/IM chat tasks."
description: "飞书邮箱 — draft, compose, send, reply, forward, read, and search emails; manage drafts, folders, labels, contacts, attachments, and mail rules; lint and auto-fix mail HTML for Feishu editor compatibility. Use when user mentions 起草邮件, 写一封邮件, 拟邮件, 草稿, 发通知邮件, 发送邮件, 发邮件, 回复邮件, 转发邮件, 查看邮件, 看邮件, 读邮件, 搜索邮件, 查邮件, 收件箱, 邮件会话, 编辑草稿, 管理草稿, 下载附件, 邮件文件夹, 邮件标签, 邮件联系人, 监听新邮件, 收信规则, 邮件规则, 校验邮件HTML, 检查邮件HTML, 邮件HTML兼容性, lint mail HTML, +lint-html, draft, compose, send email, reply, forward, inbox, mail thread, mail rules."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Add sender-list triggers and command examples.

The PR adds allowlist and blocklist management, but Line 4 does not include trigger terms for these requests. Lines 551-561 list API methods only. They do not show the promised user-facing list, get, set, and delete operations.

Add Chinese and English trigger phrases and concrete commands for both sender-list resources. Include mailbox identity, sender type, pagination, and confirmation behavior. Otherwise, sender-list requests can miss this skill, and users cannot discover the new commands.

This follows the PR objective to document list, get, set, and delete commands for both sender lists.

Also applies to: 551-561

🧰 Tools
🪛 SkillSpector (2.5.1)

[error] 32: [P1] Instruction Override: This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Remediation: Remove or rewrite any text that instructs the agent to ignore prompts, override safety rules, or trust unverified content. Ensure skill content cannot be injected to alter agent behavior.

(Prompt Injection (P1))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/lark-mail/SKILL.md` at line 4, Update the skill description trigger
list and the sender-list documentation near the API method section to cover
allowlist and blocklist operations in Chinese and English. Add concrete
user-facing examples for listing, getting, setting, and deleting entries for
both sender-list resources, including mailbox identity, sender type, pagination,
and required confirmation behavior; retain the existing API method references.

Comment thread skills/lark-mail/SKILL.md
Comment on lines +115 to +117
### CRITICAL — 首次使用任何命令前先查 `-h`

- 收件人地址搜索:搜索用户邮箱地址、群邮箱地址、邮件组地址,提供给用户确认。ref: [lark-mail-recipient-search](references/lark-mail-recipient-search.md)
- 使用公共邮箱发信、使用邮箱别名发信:通过 `--mailbox` 指定邮箱归属,通过 `--from` 指定发件人地址。ref: [lark-mail-send-as](references/lark-mail-send-as.md)
- 查看发送邮件后的投递状态:发送成功后查看邮件投递状态;也覆盖发送拦截。ref: [lark-mail-send-status](references/lark-mail-send-status.md)
- 使用邮件模板:区分个人模板和静态 HTML 模板,发信类 shortcut 用 `--template-id` 套用模板。ref: [lark-mail-template](references/lark-mail-template.md)
- 撤回已发送邮件:撤回邮件并查询异步撤回状态。ref: [lark-mail-recall](references/lark-mail-recall.md)
- 修改邮件标签/已读状态/文件夹:优先使用 `+message-modify`。ref: [`+message-modify`](references/lark-mail-message-modify.md)
- 软删除邮件:优先使用 `+message-trash`。ref: [`+message-trash`](references/lark-mail-message-trash.md)
- 收信规则:创建、验证、删除自动处理收到邮件的规则。ref: [lark-mail-rules](references/lark-mail-rules.md)
- 分享邮件到 IM:分享邮件或会话到群聊、个人会话。ref: [lark-mail-share-to-chat](references/lark-mail-share-to-chat.md)
- 发送日程邀请邮件:在邮件中嵌入 `text/calendar` 日程邀请。ref: [lark-mail-calendar-invite](references/lark-mail-calendar-invite.md)
- 编写复杂 HTML 正文:复杂 HTML、本地图片、安全不确定时读取规范或运行 `+lint-html`;普通正文无需预读。ref: [lark-mail-html](references/lark-mail-html.md)
- 读取邮件:按场景选择 triage、单封、批量或会话读取。ref: [`+triage`](references/lark-mail-triage.md)、[`+message`](references/lark-mail-message.md)、[`+messages`](references/lark-mail-messages.md)、[`+thread`](references/lark-mail-thread.md)
- 写信、草稿、回复、转发:先判断新邮件、回复或转发,再决定创建草稿、直接发送或定时发送。命令选择见下方;公共邮箱/别名、发送状态等见相关 ref。

### 参数不确定时先查 `-h`

已有明确示例或已确认 flag 时可直接执行;参数、资源名或 raw API 结构不确定时,先运行 `-h` 查看可用参数,不要猜测参数名称:
无论是 Shortcut(`+triage`、`+send` 等)还是原生 API,**首次调用前必须先运行 `-h` 查看可用参数**,不要猜测参数名称:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make the first-use order consistent.

The workflow says that user_mailboxes profile is the first mailbox command. Lines 115-117 require -h before any command.

Run the relevant -h command before profile, or state that the numbered workflow starts after the required help check.

🧰 Tools
🪛 SkillSpector (2.5.1)

[error] 32: [P1] Instruction Override: This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Remediation: Remove or rewrite any text that instructs the agent to ignore prompts, override safety rules, or trust unverified content. Ensure skill content cannot be injected to alter agent behavior.

(Prompt Injection (P1))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/lark-mail/SKILL.md` around lines 115 - 117, Update the workflow around
the `user_mailboxes profile` step so the relevant `-h` command runs first, or
explicitly state that the numbered workflow begins after the mandatory initial
help check. Keep the existing `profile` operation and first-use ordering
consistent with the documented requirement.

Comment thread skills/lark-mail/SKILL.md
Comment on lines +207 to +216
lark-cli mail +send --mailbox shared@example.com \
--to bob@example.com --subject '通知' --body '<p>你好</p>'
```

**别名发信:**

```bash
# --mailbox 指定所属邮箱,--from 指定别名地址
lark-cli mail +send --mailbox me --from alias@example.com \
--to bob@example.com --subject '测试' --body '<p>你好</p>'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Files:"
git ls-files | rg '(^|/)SKILL\.md$|skill|lark-mail|capabilities|commands' || true

echo
echo "Relevant file sections:"
file="skills/lark-mail/SKILL.md"
if [ -f "$file" ]; then
  wc -l "$file"
  sed -n '70,105p' "$file"
  echo "--- "
  sed -n '200,218p' "$file"
  echo "--- "
  sed -n '225,237p' "$file"
  echo "--- "
  sed -n '510,530p' "$file"
fi

echo
echo "Search for --as user/--as auto and lark-cli mail send in repo:"
rg -n 'lark-cli mail .*mailbox|--as user|--as auto|--from alias|cancel_scheduled_send|\+draft-(create|send)|user_access_token|Feishu|open.feishu\.cn' . --glob '!node_modules' --glob '!dist' --glob '!build' || true

Repository: larksuite/cli

Length of output: 50372


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="skills/lark-mail/SKILL.md"
wc -l "$file"

echo "--- lines 1-110 ---"
sed -n '1,110p' "$file"
echo "--- lines 180-218 ---"
sed -n '180,218p' "$file"
echo "--- lines 225-237 ---"
sed -n '225,237p' "$file"
echo "--- lines 505-525 ---"
sed -n '505,525p' "$file"

echo "--- mail shortcut definitions ---"
for f in shortcuts/mail/mail_send.go shortcuts/mail/mail_draft_create.go shortcuts/mail/mail_draft_send.go; do
  [ -f "$f" ] && { echo "### $f"; sed -n '1,90p' "$f"; }
done

Repository: larksuite/cli

Length of output: 26478


Keep mail write examples on the user identity.

Lines 88-91 require --as user for mail writes, but the public-mailbox and alias send examples, cancel_scheduled_send, and +draft-* examples still omit it. Add --as user to these examples, or document that the shortcuts enforce user identity.

🧰 Tools
🪛 SkillSpector (2.5.1)

[error] 32: [P1] Instruction Override: This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Remediation: Remove or rewrite any text that instructs the agent to ignore prompts, override safety rules, or trust unverified content. Ensure skill content cannot be injected to alter agent behavior.

(Prompt Injection (P1))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/lark-mail/SKILL.md` around lines 207 - 216, Update the mail write
examples for public-mailbox and alias sends, cancel_scheduled_send, and all
+draft-* shortcuts to include the required --as user option, consistent with the
guidance on lines 88-91. If these shortcuts intentionally enforce user identity
instead, document that behavior explicitly.

Comment thread skills/lark-mail/SKILL.md
Comment on lines +299 to +309
```bash
# 发送带日程邀请的新邮件(先保存草稿,确认后发送)
lark-cli mail +send --as user \
--to alice@example.com --cc bob@example.com \
--subject '产品评审' \
--body '<p>请参加本次产品评审会议。</p>' \
--event-summary '产品评审' \
--event-start '2026-05-10T14:00+08:00' \
--event-end '2026-05-10T15:00+08:00' \
--event-location '5F 大会议室' \
--confirm-send

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use a future calendar timestamp.

The example uses 2026-05-10T14:00+08:00 through 15:00. This date is before August 10, 2026.

Replace it with a clearly future date, or instruct the user to calculate a future Unix timestamp.

Proposed fix
-    --event-start '2026-05-10T14:00+08:00' \
-    --event-end '2026-05-10T15:00+08:00' \
+    --event-start '2030-05-10T14:00+08:00' \
+    --event-end '2030-05-10T15:00+08:00' \
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
```bash
# 发送带日程邀请的新邮件(先保存草稿,确认后发送)
lark-cli mail +send --as user \
--to alice@example.com --cc bob@example.com \
--subject '产品评审' \
--body '<p>请参加本次产品评审会议。</p>' \
--event-summary '产品评审' \
--event-start '2026-05-10T14:00+08:00' \
--event-end '2026-05-10T15:00+08:00' \
--event-location '5F 大会议室' \
--confirm-send
🧰 Tools
🪛 SkillSpector (2.5.1)

[error] 32: [P1] Instruction Override: This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Remediation: Remove or rewrite any text that instructs the agent to ignore prompts, override safety rules, or trust unverified content. Ensure skill content cannot be injected to alter agent behavior.

(Prompt Injection (P1))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/lark-mail/SKILL.md` around lines 299 - 309, Update the example
command’s --event-start and --event-end values to use a clearly future calendar
date relative to August 10, 2026, while preserving the one-hour meeting duration
and timezone.

Comment thread skills/lark-mail/SKILL.md
Comment on lines +555 to +561
- `list` — 列表/搜索指定用户邮箱的「信任发件人」白名单。支持按发件人地址或域名前缀搜索 (keyword)。返回列表按创建时间倒序,使用 page_token + page_size 进行分页。

### user_mailbox.blocked_senders

- `batch_create` — 批量将发件人加入指定用户邮箱的「屏蔽发件人」黑名单。支持按邮箱地址 (sender_type=1) 或域名 (sender_type=2) 添加。单次最多 100 项,单用户黑白名单合计最多 2000 项;与白名单互斥(添加黑名单会从白名单删除对侧记录)。
- `batch_remove` — 批量从指定用户邮箱的「屏蔽发件人」黑名单中删除发件人。senders 中每项可以是邮箱地址或域名(与添加时一致)。批量删除按字面值哈希匹配,可兼容历史大写数据。单次最多 100 项。
- `list` — 列表/搜索指定用户邮箱的「屏蔽发件人」黑名单。支持按发件人地址或域名前缀搜索 (keyword)。返回列表按创建时间倒序,使用 page_token + page_size 进行分页。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

test -f cmd/service/mail_sender_generated_test.go

rg -n -C 5 \
  'allow_senders|blocked_senders|message:(modify|readonly)|scope' \
  cmd/service/mail_sender_generated_test.go \
  skills/lark-mail/SKILL.md

Repository: larksuite/cli

Length of output: 23783


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
import re

skill = Path("skills/lark-mail/SKILL.md").read_text()
contracts = Path("cmd/service/mail_sender_generated_test.go").read_text()

permission_tab = False
permission_lines = []
for line in skill.splitlines():
    if re.match(r"\| 方法 \| 所需 scope \|", line):
        permission_tab = True
        continue
    if permission_tab:
        if re.match(r"\|--+", line):
            continue
        if re.match(r"\| [A-Za-z]", line):
            permission_lines.append(line)
        else:
            permission_tab = False

print("permission rows involving allow_senders or blocked_senders:")
for row in permission_lines:
    if "allow_senders" in row or "blocked_senders" in row:
        print(row.strip())

print("\nrequired scopes from generated test:")
match = re.search(r"var mailSenderMethodContracts = \[\]mailSenderMethodContract\{(.*?)\};", contracts, re.S)
import ast
contract_block = match.group(1)
items = re.split(r"\},\s*\{", contract_block)
for item in items:
    if "user_mailbox.allow_senders" in item or "user_mailbox.blocked_senders" in item:
        resource = re.search(r"resource:\s*\"([^\"]+)\"", item).group(1)
        method = re.search(r"method:\s*\"([^\"]+)\"", item).group(1)
        scopes = re.search(r"requiredScopes:\s*\[\]string\{(.*)\?}", item, re.S).group(1)
        scopes = re.sub(r"//.*", "", scopes)
        scopes = [str.strip().strip('"') for str.strip().strip('"') in scopes.split(",") if str.strip().strip('"')]
        print(f"{resource}.{method}: {scopes}")
PY

Repository: larksuite/cli

Length of output: 376


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
import re

skill = Path("skills/lark-mail/SKILL.md").read_text()
contracts = Path("cmd/service/mail_sender_generated_test.go").read_text()

permission_tab = False
permission_lines = []
for line in skill.splitlines():
    if re.match(r"\| 方法 \| 所需 scope \|", line):
        permission_tab = True
        continue
    if permission_tab:
        if re.match(r"\|--+", line):
            continue
        if re.match(r"\| [A-Za-z]", line):
            permission_lines.append(line)
        else:
            permission_tab = False

print("permission rows involving allow_senders or blocked_senders:")
for row in permission_lines:
    if "allow_senders" in row or "blocked_senders" in row:
        print(row.strip())

print("\nrequired scopes from generated test:")
match = re.search(r"var mailSenderMethodContracts = \[\]mailSenderMethodContract\{(.*?)\};", contracts, re.S)
contract_block = match.group(1)
items = re.split(r"\},\s*\{", contract_block)
for item in.items for item in items:
    if "user_mailbox.allow_senders" in item or "user_mailbox.blocked_senders" in item:
        resource = re.search(r"resource:\s*\"([^\"]+)\"", item).group(1)
        method = re.search(r"method:\s*\"([^\"]+)\"", item).group(1)
        scopes = re.search(r"requiredScopes:\s*\[\]string\{(.*)\?}", item, re.S).group(1)
        scopes = re.sub(r"//.*", "", scopes)
        scopes = [tok.strip().strip('"') for tok in scopes.split(",") if tok.strip()]
        print(f"{resource}.{method}: {scopes}")
PY

Repository: larksuite/cli

Length of output: 263


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
import re

skill = Path("skills/lark-mail/SKILL.md").read_text()
contracts = Path("cmd/service/mail_sender_generated_test.go").read_text()

permission_tab = False
permission_lines = []
for line in skill.splitlines():
    if re.match(r"\| 方法 \| 所需 scope \|", line):
        permission_tab = True
        continue
    if permission_tab:
        if re.match(r"\|--+", line):
            continue
        if re.match(r"\| [A-Za-z]", line):
            permission_lines.append(line)
        else:
            permission_tab = False

print("permission_rows")
for row in permission_lines:
    if "allow_senders" in row or "blocked_senders" in row:
        print(row.strip())

print("\nrequired_scopes")
match = re.search(r"var mailSenderMethodContracts = \[\]mailSenderMethodContract\{(.*?)\};", contracts, re.S)
contract_block = match.group(1)
items = re.split(r"\},\s*\{", contract_block)
for item in items:
    if "user_mailbox.allow_senders" in item or "user_mailbox.blocked_senders" in item:
        resource = re.search(r"resource:\s*\"([^\"]+)\"", item).group(1)
        method = re.search(r"method:\s*\"([^\"]+)\"", item).group(1)
        scopes = re.search(r"requiredScopes:\s*\[\]string\{(.*)\?}", item, re.S).group(1)
        scopes = re.sub(r"//.*", "", scopes)
        tokens = [tok.strip().strip('"') for tok in scopes.split(",") if tok.strip()]
        print(f"{resource}.{method}: {tokens}")
PY

Repository: larksuite/cli

Length of output: 317


Document both required scopes for sender-list endpoints.

user_mailbox.allow_senders.list and user_mailbox.blocked_senders.list require mail:user_mailbox.message:readonly and mail:user_mailbox.message:modify per the generated contract. Update the permission table rows so users do not fail scope preflight with only modify.

Also applies to: 665-668

🧰 Tools
🪛 SkillSpector (2.5.1)

[error] 32: [P1] Instruction Override: This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Remediation: Remove or rewrite any text that instructs the agent to ignore prompts, override safety rules, or trust unverified content. Ensure skill content cannot be injected to alter agent behavior.

(Prompt Injection (P1))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/lark-mail/SKILL.md` around lines 555 - 561, The permission table
entries for user_mailbox.allow_senders.list and
user_mailbox.blocked_senders.list currently omit a required scope. Update both
rows to document mail:user_mailbox.message:readonly and
mail:user_mailbox.message:modify, matching the generated contract and preserving
the existing endpoint descriptions.

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain/mail PR touches the mail domain size/L Large or sensitive change across domains or core paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants