diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3349fb447..0ffa82c37 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,7 +63,7 @@ jobs: - name: Fetch meta data run: python3 scripts/fetch_meta.py - name: Run tests - run: go test -v -race -count=1 -timeout=5m ./cmd/... ./internal/... ./shortcuts/... ./extension/... + run: go test -v -race -count=1 -timeout=5m ./cmd/... ./internal/... ./shortcuts/... lint: needs: fast-gate @@ -82,8 +82,6 @@ jobs: run: python3 scripts/fetch_meta.py - name: Run golangci-lint run: go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.1.6 run --new-from-rev=origin/main - - name: Run errs/ lint guards (lintcheck) - run: go run -C lint . .. coverage: needs: fast-gate diff --git a/shortcuts/mail/mail_draft_create.go b/shortcuts/mail/mail_draft_create.go index 8f4875c8b..4b27a6ef3 100644 --- a/shortcuts/mail/mail_draft_create.go +++ b/shortcuts/mail/mail_draft_create.go @@ -13,6 +13,7 @@ import ( draftpkg "github.com/larksuite/cli/shortcuts/mail/draft" "github.com/larksuite/cli/shortcuts/mail/emlbuilder" "github.com/larksuite/cli/shortcuts/mail/lint" + "github.com/larksuite/cli/shortcuts/mail/signature" ) // draftCreateInput bundles all +draft-create user flags into a single @@ -56,6 +57,7 @@ var MailDraftCreate = common.Shortcut{ {Name: "request-receipt", Type: "bool", Desc: "Request a read receipt (Message Disposition Notification, RFC 3798) addressed to the sender. Recipient mail clients may prompt the user, send automatically, or silently ignore — delivery of a receipt is not guaranteed."}, {Name: "template-id", Desc: "Optional. Apply a saved template by ID (decimal integer string) before composing. The template's subject/body/to/cc/bcc/attachments are merged with user-supplied flags (user flags win). Requires --as user."}, signatureFlag, + noSignatureFlag, priorityFlag, eventSummaryFlag, eventStartFlag, eventEndFlag, eventLocationFlag, showLintDetailsFlag, @@ -180,7 +182,24 @@ var MailDraftCreate = common.Shortcut{ if strings.TrimSpace(input.Body) == "" { return mailValidationParamError("--body", "effective body is empty after applying template; pass --body explicitly") } - sigResult, err := resolveSignature(ctx, runtime, mailboxID, runtime.Str("signature-id"), runtime.Str("from")) + signatureID := runtime.Str("signature-id") + senderEmail := runtime.Str("from") + noSignature := runtime.Bool("no-signature") + if noSignature { + if signatureID != "" { + fmt.Fprintf(runtime.IO().ErrOut, + "warning: --signature-id ignored because --no-signature is set\n") + } + signatureID = "" + } else if signatureID == "" && !input.PlainText { + if resp, lErr := signature.ListAll(runtime, mailboxID); lErr == nil { + signatureID = signature.DefaultSendID(resp.Usages, senderEmail) + } else { + fmt.Fprintf(runtime.IO().ErrOut, + "warning: failed to fetch default signature: %v\n", lErr) + } + } + sigResult, err := resolveSignature(ctx, runtime, mailboxID, signatureID, senderEmail) if err != nil { return err } diff --git a/shortcuts/mail/mail_forward.go b/shortcuts/mail/mail_forward.go index 25a0ff0ad..1a6e75c9f 100644 --- a/shortcuts/mail/mail_forward.go +++ b/shortcuts/mail/mail_forward.go @@ -14,6 +14,7 @@ import ( "github.com/larksuite/cli/shortcuts/common" draftpkg "github.com/larksuite/cli/shortcuts/mail/draft" "github.com/larksuite/cli/shortcuts/mail/emlbuilder" + "github.com/larksuite/cli/shortcuts/mail/signature" ) // MailForward is the `+forward` shortcut: forward an existing message to @@ -45,6 +46,7 @@ var MailForward = common.Shortcut{ {Name: "subject", Desc: "Optional. Override the auto-generated Fw: subject. When set, the shortcut uses this value verbatim instead of prefixing the original subject."}, {Name: "template-id", Desc: "Optional. Apply a saved template by ID (decimal integer string) before composing. The template's body/to/cc/bcc/attachments are merged into the forward draft (template values appended to user flags / forward-derived values; no de-duplication)."}, signatureFlag, + noSignatureFlag, priorityFlag, eventSummaryFlag, eventStartFlag, eventEndFlag, eventLocationFlag, showLintDetailsFlag}, @@ -129,6 +131,21 @@ var MailForward = common.Shortcut{ signatureID := runtime.Str("signature-id") mailboxID := resolveComposeMailboxID(runtime) + noSignature := runtime.Bool("no-signature") + if noSignature { + if signatureID != "" { + fmt.Fprintf(runtime.IO().ErrOut, + "warning: --signature-id ignored because --no-signature is set\n") + } + signatureID = "" + } else if signatureID == "" && !plainText { + if resp, lErr := signature.ListAll(runtime, mailboxID); lErr == nil { + signatureID = signature.DefaultReplyID(resp.Usages, runtime.Str("from")) + } else { + fmt.Fprintf(runtime.IO().ErrOut, + "warning: failed to fetch default signature: %v\n", lErr) + } + } sigResult, sigErr := resolveSignature(ctx, runtime, mailboxID, signatureID, runtime.Str("from")) if sigErr != nil { return sigErr diff --git a/shortcuts/mail/mail_reply.go b/shortcuts/mail/mail_reply.go index d4f190894..161380ecd 100644 --- a/shortcuts/mail/mail_reply.go +++ b/shortcuts/mail/mail_reply.go @@ -11,6 +11,7 @@ import ( "github.com/larksuite/cli/shortcuts/common" draftpkg "github.com/larksuite/cli/shortcuts/mail/draft" "github.com/larksuite/cli/shortcuts/mail/emlbuilder" + "github.com/larksuite/cli/shortcuts/mail/signature" ) // MailReply is the `+reply` shortcut: reply to the sender of a message, @@ -42,6 +43,7 @@ var MailReply = common.Shortcut{ {Name: "subject", Desc: "Optional. Override the auto-generated Re: subject. When set, the shortcut uses this value verbatim instead of prefixing the original subject."}, {Name: "template-id", Desc: "Optional. Apply a saved template by ID (decimal integer string) before composing. The template's body/to/cc/bcc/attachments are appended to the reply-derived values (no de-duplication; see warning in Execute output)."}, signatureFlag, + noSignatureFlag, priorityFlag, eventSummaryFlag, eventStartFlag, eventEndFlag, eventLocationFlag, showLintDetailsFlag}, @@ -131,6 +133,21 @@ var MailReply = common.Shortcut{ signatureID := runtime.Str("signature-id") mailboxID := resolveComposeMailboxID(runtime) + noSignature := runtime.Bool("no-signature") + if noSignature { + if signatureID != "" { + fmt.Fprintf(runtime.IO().ErrOut, + "warning: --signature-id ignored because --no-signature is set\n") + } + signatureID = "" + } else if signatureID == "" && !plainText { + if resp, lErr := signature.ListAll(runtime, mailboxID); lErr == nil { + signatureID = signature.DefaultReplyID(resp.Usages, runtime.Str("from")) + } else { + fmt.Fprintf(runtime.IO().ErrOut, + "warning: failed to fetch default signature: %v\n", lErr) + } + } sigResult, sigErr := resolveSignature(ctx, runtime, mailboxID, signatureID, runtime.Str("from")) if sigErr != nil { return sigErr diff --git a/shortcuts/mail/mail_reply_all.go b/shortcuts/mail/mail_reply_all.go index 66f584e1f..9a1039cf9 100644 --- a/shortcuts/mail/mail_reply_all.go +++ b/shortcuts/mail/mail_reply_all.go @@ -11,6 +11,7 @@ import ( "github.com/larksuite/cli/shortcuts/common" draftpkg "github.com/larksuite/cli/shortcuts/mail/draft" "github.com/larksuite/cli/shortcuts/mail/emlbuilder" + "github.com/larksuite/cli/shortcuts/mail/signature" ) // MailReplyAll is the `+reply-all` shortcut: reply to the sender plus all @@ -43,6 +44,7 @@ var MailReplyAll = common.Shortcut{ {Name: "subject", Desc: "Optional. Override the auto-generated Re: subject. When set, the shortcut uses this value verbatim instead of prefixing the original subject."}, {Name: "template-id", Desc: "Optional. Apply a saved template by ID (decimal integer string) before composing. The template's body/to/cc/bcc/attachments are appended to the reply-derived values (no de-duplication; see warning in Execute output)."}, signatureFlag, + noSignatureFlag, priorityFlag, eventSummaryFlag, eventStartFlag, eventEndFlag, eventLocationFlag, showLintDetailsFlag}, @@ -133,6 +135,21 @@ var MailReplyAll = common.Shortcut{ signatureID := runtime.Str("signature-id") mailboxID := resolveComposeMailboxID(runtime) + noSignature := runtime.Bool("no-signature") + if noSignature { + if signatureID != "" { + fmt.Fprintf(runtime.IO().ErrOut, + "warning: --signature-id ignored because --no-signature is set\n") + } + signatureID = "" + } else if signatureID == "" && !plainText { + if resp, lErr := signature.ListAll(runtime, mailboxID); lErr == nil { + signatureID = signature.DefaultReplyID(resp.Usages, runtime.Str("from")) + } else { + fmt.Fprintf(runtime.IO().ErrOut, + "warning: failed to fetch default signature: %v\n", lErr) + } + } sigResult, sigErr := resolveSignature(ctx, runtime, mailboxID, signatureID, runtime.Str("from")) if sigErr != nil { return sigErr diff --git a/shortcuts/mail/mail_send.go b/shortcuts/mail/mail_send.go index b536aa827..0f8586600 100644 --- a/shortcuts/mail/mail_send.go +++ b/shortcuts/mail/mail_send.go @@ -11,6 +11,7 @@ import ( "github.com/larksuite/cli/shortcuts/common" draftpkg "github.com/larksuite/cli/shortcuts/mail/draft" "github.com/larksuite/cli/shortcuts/mail/emlbuilder" + "github.com/larksuite/cli/shortcuts/mail/signature" ) // MailSend is the `+send` shortcut: compose a new email and save it as a @@ -40,6 +41,7 @@ var MailSend = common.Shortcut{ {Name: "request-receipt", Type: "bool", Desc: "Request a read receipt (Message Disposition Notification, RFC 3798) addressed to the sender. Recipient mail clients may prompt the user, send automatically, or silently ignore — delivery of a receipt is not guaranteed."}, {Name: "template-id", Desc: "Optional. Apply a saved template by ID (decimal integer string) before composing. The template's subject/body/to/cc/bcc/attachments are merged with user-supplied flags (user flags win). Requires --as user."}, signatureFlag, + noSignatureFlag, priorityFlag, eventSummaryFlag, eventStartFlag, eventEndFlag, eventLocationFlag, showLintDetailsFlag}, @@ -195,6 +197,21 @@ var MailSend = common.Shortcut{ } } + noSignature := runtime.Bool("no-signature") + if noSignature { + if signatureID != "" { + fmt.Fprintf(runtime.IO().ErrOut, + "warning: --signature-id ignored because --no-signature is set\n") + } + signatureID = "" + } else if signatureID == "" && !plainText { + if resp, lErr := signature.ListAll(runtime, mailboxID); lErr == nil { + signatureID = signature.DefaultSendID(resp.Usages, senderEmail) + } else { + fmt.Fprintf(runtime.IO().ErrOut, + "warning: failed to fetch default signature: %v\n", lErr) + } + } sigResult, err := resolveSignature(ctx, runtime, mailboxID, signatureID, senderEmail) if err != nil { return err diff --git a/shortcuts/mail/signature/provider.go b/shortcuts/mail/signature/provider.go index b5a807cc2..98685e431 100644 --- a/shortcuts/mail/signature/provider.go +++ b/shortcuts/mail/signature/provider.go @@ -6,6 +6,7 @@ package signature import ( "encoding/json" "net/url" + "strings" "github.com/larksuite/cli/errs" "github.com/larksuite/cli/shortcuts/common" @@ -68,3 +69,39 @@ func Get(runtime *common.RuntimeContext, mailboxID, signatureID string) (*Signat } return nil, errs.NewValidationError(errs.SubtypeInvalidArgument, "signature not found: %s", signatureID) } + +// DefaultSendID returns the send_mail_signature_id for the given addr. +// Falls back to usages[0] if no entry matches, but returns "" when +// no default is configured (id empty or "0"). +// Returns "" if usages is empty. +func DefaultSendID(usages []SignatureUsage, addr string) string { + return pickSignatureID(usages, addr, func(u SignatureUsage) string { + return u.SendMailSignatureID + }) +} + +// DefaultReplyID returns the reply_signature_id for the given addr. +// Used by reply/reply-all/forward shortcuts. +// Returns "" if usages is empty or no default is configured. +func DefaultReplyID(usages []SignatureUsage, addr string) string { + return pickSignatureID(usages, addr, func(u SignatureUsage) string { + return u.ReplySignatureID + }) +} + +func pickSignatureID(usages []SignatureUsage, addr string, pick func(SignatureUsage) string) string { + if len(usages) == 0 { + return "" + } + laddr := strings.ToLower(strings.TrimSpace(addr)) + for _, u := range usages { + if strings.ToLower(strings.TrimSpace(u.EmailAddress)) == laddr { + id := pick(u) + if id == "" || id == "0" { + return "" + } + return id + } + } + return "" +} diff --git a/shortcuts/mail/signature_compose.go b/shortcuts/mail/signature_compose.go index ac7f13cde..c367b98b0 100644 --- a/shortcuts/mail/signature_compose.go +++ b/shortcuts/mail/signature_compose.go @@ -25,6 +25,13 @@ var signatureFlag = common.Flag{ Desc: "Optional. Signature ID to append after body content. Run `mail +signature` to list available signatures.", } +// noSignatureFlag is the common flag for --no-signature, shared by all compose shortcuts. +var noSignatureFlag = common.Flag{ + Name: "no-signature", + Type: "bool", + Desc: "Do not append any signature to the email body (overrides automatic default signature).", +} + // signatureResult holds the pre-processed signature data ready for HTML injection. type signatureResult struct { ID string diff --git a/skills/lark-mail/references/lark-mail-draft-create.md b/skills/lark-mail/references/lark-mail-draft-create.md index 36b6682dd..52cdb1e46 100644 --- a/skills/lark-mail/references/lark-mail-draft-create.md +++ b/skills/lark-mail/references/lark-mail-draft-create.md @@ -56,6 +56,7 @@ lark-cli mail +draft-create --to alice@example.com --subject '测试' --body 'te | `--attach ` | 否 | 附件文件路径,多个用逗号分隔。相对路径。当附件导致 EML 总大小超过 25 MB 时,超出部分自动上传为超大附件(HTML 邮件插入下载卡片,纯文本邮件追加下载链接),单个文件上限 3 GB | | `--inline ` | 否 | 高级用法:手动指定内嵌图片 CID 映射。推荐直接在 `--body` 中使用 ``(自动解析)。仅在需要精确控制 CID 命名时使用此参数。格式:`'[{"cid":"mycid","file_path":"./logo.png"}]'`,在 body 中用 `` 引用。不可与 `--plain-text` 同时使用 | | `--signature-id ` | 否 | 签名 ID。附加邮箱签名到正文末尾。运行 `mail +signature` 查看可用签名。不可与 `--plain-text` 同时使用 | +| `--no-signature` | 否 | Do not append any signature to the email body (overrides automatic default signature). | | `--priority ` | 否 | 邮件优先级:`high`、`normal`、`low`。省略或 `normal` 时不设置优先级 | | `--request-receipt` | 否 | 请求已读回执(RFC 3798 Message Disposition Notification)。在草稿 EML 里写 `Disposition-Notification-To: ` 头,发送时生效。收件人的邮件客户端可能弹出提示、自动发送或忽略——送达不保证 | | `--event-summary ` | 否 | 日程标题。设置此参数即在邮件中嵌入日程邀请。需同时设置 `--event-start` 和 `--event-end` | diff --git a/skills/lark-mail/references/lark-mail-forward.md b/skills/lark-mail/references/lark-mail-forward.md index 9545161cd..f36e7928a 100644 --- a/skills/lark-mail/references/lark-mail-forward.md +++ b/skills/lark-mail/references/lark-mail-forward.md @@ -72,6 +72,7 @@ lark-cli mail +forward --message-id <邮件ID> --to alice@example.com --dry-run | `--attach ` | 否 | 附件文件路径,多个用逗号分隔,追加在原邮件附件之后。相对路径。当附件导致 EML 总大小超过 25 MB 时,超出部分自动上传为超大附件(HTML 邮件插入下载卡片,纯文本邮件追加下载链接),单个文件上限 3 GB | | `--inline ` | 否 | 高级用法:手动指定内嵌图片 CID 映射。推荐直接在 `--body` 中使用 ``(自动解析)。仅在需要精确控制 CID 命名时使用此参数。格式:`'[{"cid":"mycid","file_path":"./logo.png"}]'`,在 body 中用 `` 引用。不可与 `--plain-text` 同时使用 | | `--signature-id ` | 否 | 签名 ID。附加邮箱签名到转发正文与引用块之间。运行 `mail +signature` 查看可用签名。不可与 `--plain-text` 同时使用 | +| `--no-signature` | 否 | Do not append any signature to the email body (overrides automatic default signature). | | `--priority ` | 否 | 邮件优先级:`high`、`normal`、`low`。省略或 `normal` 时不设置优先级 | | `--event-summary ` | 否 | 日程标题。设置此参数即在邮件中嵌入日程邀请。需同时设置 `--event-start` 和 `--event-end` | | `--event-start