{"record":{"id":"beb5be96751ab82f","repo":"Billionmail/BillionMail","slug":"at-least-one-recipient-is-required","errorCode":null,"errorMessage":"at least one recipient is required","messagePattern":"at least one recipient is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/controller/settings/settings_v1_set_blacklist_alert_settings.go","lineNumber":88,"sourceCode":"\n\tif !strings.Contains(settings.SenderEmail, \"@\") {\n\t\treturn fmt.Errorf(\"invalid sender email format\")\n\t}\n\n\tif settings.SMTPServer == \"\" {\n\t\treturn fmt.Errorf(\"SMTP server is required\")\n\t}\n\n\tif settings.SMTPPort < 1 || settings.SMTPPort > 65535 {\n\t\treturn fmt.Errorf(\"SMTP port must be between 1 and 65535\")\n\t}\n\n\tif settings.SMTPPassword == \"\" {\n\t\treturn fmt.Errorf(\"SMTP password is required\")\n\t}\n\n\tif len(settings.RecipientList) == 0 {\n\t\treturn fmt.Errorf(\"at least one recipient is required\")\n\t}\n\n\tfor _, recipient := range settings.RecipientList {\n\t\tif !strings.Contains(recipient, \"@\") {\n\t\t\treturn fmt.Errorf(\"invalid recipient email format: %s\", recipient)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc testSMTPConnectionWithRelay(ctx context.Context, settings *v1.SetBlacklistAlertSettingsReq) error {\n\t//g.Log().Infof(ctx, \"Testing SMTP connection to %s:%d\", settings.SMTPServer, settings.SMTPPort)\n\n\tresult := relay.TestSmtpConnection(\n\t\tsettings.SMTPServer,\n\t\tfmt.Sprintf(\"%d\", settings.SMTPPort),\n\t\tsettings.SenderEmail,","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/controller/settings/settings_v1_set_blacklist_alert_settings.go#L70-L106","documentation":"Validation guard inside validateAlertSettings: RecipientList on the blacklist alert settings request is empty, meaning there is no destination address to notify when a blacklisting is detected. The request is rejected before persistence.","triggerScenarios":"Calling SetBlacklistAlertSettings with recipientList an empty array, null, or omitted from the request.","commonSituations":"UI allows saving the form with no recipients added; a bulk-import of recipient emails failed silently leaving the array empty; JSON field name mismatch (recipients vs recipientList) so the list deserializes empty.","solutions":["Include at least one email address in the recipientList array.","Verify the JSON field name matches the struct binding tag so the list is not silently empty.","In the UI, disable the save button until at least one validated recipient exists."],"exampleFix":"// before\n{\"recipientList\":[]}\n// after\n{\"recipientList\":[\"admin@example.com\"]}","handlingStrategy":"validation","validationCode":"const recipients = Array.isArray(payload.recipientList) ? payload.recipientList : []\nif (recipients.length === 0) {\n  throw new Error('Add at least one alert recipient')\n}","typeGuard":"function hasRecipients(s: { recipientList?: string[] }): s is { recipientList: string[] } {\n  return Array.isArray(s.recipientList) && s.recipientList.length > 0\n}","tryCatchPattern":"try {\n  await api.setBlacklistAlertSettings(payload)\n} catch (e) {\n  if (String(e).includes('at least one recipient')) {\n    showFormError('recipients', 'At least one recipient email is required')\n  }\n}","preventionTips":["Require at least one recipient in the UI before enabling save","Check JSON field names match server binding tags so arrays aren't silently empty","Validate arrays are non-empty after any transform/import step"],"tags":["validation","smtp","config"],"backgroundTag":"empty-recipient-list","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}