package mail import ( "strings" "github.com/ultisuite/ulti-backend/internal/api/apivalidate" ) const ( maxFoldersRequestBody = 32 << 10 // 32 KiB maxLabelsRequestBody = 8 << 10 // 8 KiB maxFolderName = 256 maxRemoteName = 512 maxLabelName = 128 maxLabelColor = 32 ) var allowedFolderTypes = map[string]struct{}{ "inbox": {}, "sent": {}, "drafts": {}, "trash": {}, "archive": {}, "spam": {}, "custom": {}, } type createFolderRequest struct { AccountID string `json:"account_id"` Name string `json:"name"` RemoteName string `json:"remote_name"` FolderType string `json:"folder_type"` } type updateFolderRequest struct { Name string `json:"name"` RemoteName string `json:"remote_name"` FolderType string `json:"folder_type"` } type createUserLabelRequest struct { Name string `json:"name"` Color string `json:"color"` } type updateUserLabelRequest struct { Name string `json:"name"` Color string `json:"color"` } func validateFolderType(field, folderType string) *apivalidate.FieldDetail { folderType = strings.TrimSpace(strings.ToLower(folderType)) if folderType == "" { return nil } if _, ok := allowedFolderTypes[folderType]; !ok { return &apivalidate.FieldDetail{Field: field, Message: "invalid"} } return nil } func normalizeFolderType(folderType string) string { folderType = strings.TrimSpace(strings.ToLower(folderType)) if folderType == "" { return "custom" } return folderType } func validateFolderName(field, name string, required bool) *apivalidate.FieldDetail { name = strings.TrimSpace(name) if name == "" { if required { return &apivalidate.FieldDetail{Field: field, Message: "required"} } return nil } if len(name) > maxFolderName || containsNewline(name) { return &apivalidate.FieldDetail{Field: field, Message: "invalid"} } return nil } func validateRemoteName(field, remoteName string, required bool) *apivalidate.FieldDetail { remoteName = strings.TrimSpace(remoteName) if remoteName == "" { if required { return &apivalidate.FieldDetail{Field: field, Message: "required"} } return nil } if len(remoteName) > maxRemoteName || containsNewline(remoteName) { return &apivalidate.FieldDetail{Field: field, Message: "invalid"} } return nil } func validateCreateFolder(req *createFolderRequest) *apivalidate.ValidationError { var details []apivalidate.FieldDetail if strings.TrimSpace(req.AccountID) == "" { details = append(details, apivalidate.FieldDetail{Field: "account_id", Message: "required"}) } if d := validateFolderName("name", req.Name, true); d != nil { details = append(details, *d) } if d := validateRemoteName("remote_name", req.RemoteName, false); d != nil { details = append(details, *d) } if d := validateFolderType("folder_type", req.FolderType); d != nil { details = append(details, *d) } if len(details) == 0 { return nil } return apivalidate.NewValidationError(details...) } func validateUpdateFolder(req *updateFolderRequest) *apivalidate.ValidationError { var details []apivalidate.FieldDetail if d := validateFolderName("name", req.Name, true); d != nil { details = append(details, *d) } if d := validateRemoteName("remote_name", req.RemoteName, true); d != nil { details = append(details, *d) } if d := validateFolderType("folder_type", req.FolderType); d != nil { details = append(details, *d) } if len(details) == 0 { return nil } return apivalidate.NewValidationError(details...) } func validateLabelName(field, name string, required bool) *apivalidate.FieldDetail { name = strings.TrimSpace(name) if name == "" { if required { return &apivalidate.FieldDetail{Field: field, Message: "required"} } return nil } if len(name) > maxLabelName || containsNewline(name) { return &apivalidate.FieldDetail{Field: field, Message: "invalid"} } return nil } func validateLabelColor(color string) *apivalidate.FieldDetail { color = strings.TrimSpace(color) if len(color) > maxLabelColor || containsNewline(color) { return &apivalidate.FieldDetail{Field: "color", Message: "invalid"} } return nil } func validateCreateUserLabel(req *createUserLabelRequest) *apivalidate.ValidationError { var details []apivalidate.FieldDetail if d := validateLabelName("name", req.Name, true); d != nil { details = append(details, *d) } if d := validateLabelColor(req.Color); d != nil { details = append(details, *d) } if len(details) == 0 { return nil } return apivalidate.NewValidationError(details...) } func validateUpdateUserLabel(req *updateUserLabelRequest) *apivalidate.ValidationError { var details []apivalidate.FieldDetail if d := validateLabelName("name", req.Name, true); d != nil { details = append(details, *d) } if d := validateLabelColor(req.Color); d != nil { details = append(details, *d) } if len(details) == 0 { return nil } return apivalidate.NewValidationError(details...) } func validateListFoldersAccountID(accountID string) *apivalidate.ValidationError { if strings.TrimSpace(accountID) == "" { return apivalidate.NewValidationError(apivalidate.FieldDetail{ Field: "account_id", Message: "required", }) } return nil }