{"record":{"id":"40cd93b33c15abba","repo":"larksuite/cli","slug":"file-extension-q-is-not-allowed-as-a-mail-attachm","errorCode":null,"errorMessage":"file extension %q is not allowed as a mail attachment","messagePattern":"file extension %q is not allowed as a mail attachment","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/mail/filecheck/filecheck.go","lineNumber":127,"sourceCode":"\t\"vb\":          {},\n\t\"vbe\":         {},\n\t\"vbs\":         {},\n\t\"vbscript\":    {},\n\t\"ws\":          {},\n\t\"wsc\":         {},\n\t\"wsf\":         {},\n\t\"wsh\":         {},\n\t\"zsh\":         {},\n}\n\n// CheckBlockedExtension returns an error if the filename has a blocked extension.\nfunc CheckBlockedExtension(filename string) error {\n\text := strings.ToLower(strings.TrimPrefix(filepath.Ext(filename), \".\"))\n\tif ext == \"\" {\n\t\treturn nil\n\t}\n\tif _, ok := blockedExtensions[ext]; ok {\n\t\treturn fmt.Errorf(\"file extension %q is not allowed as a mail attachment\", \".\"+ext) //nolint:forbidigo // intermediate mail file-format check; mail command layer wraps into typed ValidationError.\n\t}\n\treturn nil\n}\n\n// allowedInlineExtensions is the whitelist of file extensions allowed for\n// inline images. Only well-supported image formats are included.\nvar allowedInlineExtensions = map[string]struct{}{\n\t\"jpg\":  {},\n\t\"jpeg\": {},\n\t\"png\":  {},\n\t\"gif\":  {},\n\t\"webp\": {},\n}\n\n// allowedInlineMIMETypes is the whitelist of MIME types allowed for inline\n// images, checked via content sniffing (http.DetectContentType).\nvar allowedInlineMIMETypes = map[string]struct{}{\n\t\"image/jpeg\": {},","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/mail/filecheck/filecheck.go#L109-L145","documentation":"CheckBlockedExtension rejects attachment filenames whose extension appears in the mail blocked-extension blacklist (e.g. executable/script types that mail systems refuse). The check is case-insensitive on the lowercased extension; an empty extension is allowed. Wrapped into a typed ValidationError by the mail command layer.","triggerScenarios":"Calling AddFileAttachment (directly or via statAttachmentFiles / uploadToDriveForTemplate) with a filename whose extension is in blockedExtensions — e.g. .exe, .bat, .js, .sh — including uppercase variants like REPORT.EXE.","commonSituations":"Users attaching build artifacts or installers (app.exe, setup.msi); scripts (.sh, .bat, .ps1) shared as attachments; macro-enabled Office files blocked by security policy; archives hiding executables.","solutions":["Choose a different, non-blocked file type (e.g. zip the file only if archives are permitted, or export to PDF).","Share the file via a Drive/cloud link instead of attaching it.","Check the blocked extension list to confirm which extensions are disallowed before attaching.","Rename to an allowed extension only if the content type genuinely changes (never spoof the extension)."],"exampleFix":"// before\nb.AddFileAttachment(\"installer.exe\") // blocked extension\n// after\nb.AddFileAttachment(\"installer.pdf\") // or share a download link","handlingStrategy":"validation","validationCode":"if err := filecheck.CheckBlockedExtension(filename); err != nil {\n    return fmt.Errorf(\"cannot attach %s: %w\", filename, err)\n}\nb.AddFileAttachment(filename)","typeGuard":null,"tryCatchPattern":"if err := b.AddFileAttachment(path); err != nil {\n    var verr *ValidationError\n    if errors.As(err, &verr) && strings.Contains(err.Error(), \"not allowed as a mail attachment\") {\n        return fmt.Errorf(\"use a Drive link for %s\", path)\n    }\n    return err\n}","preventionTips":["Pre-screen attachment lists against the blocked extension list before adding them.","Offer a Drive-link fallback flow for executables and scripts.","Never bypass the check by renaming files to a fake extension."],"tags":["email","attachments","security","file-validation"],"backgroundTag":"blocked-file-extension","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}