Billionmail/BillionMail · error

at least one recipient is required

Error message

at least one recipient is required

What it means

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.

Source

Thrown at core/internal/controller/settings/settings_v1_set_blacklist_alert_settings.go:88

	if !strings.Contains(settings.SenderEmail, "@") {
		return fmt.Errorf("invalid sender email format")
	}

	if settings.SMTPServer == "" {
		return fmt.Errorf("SMTP server is required")
	}

	if settings.SMTPPort < 1 || settings.SMTPPort > 65535 {
		return fmt.Errorf("SMTP port must be between 1 and 65535")
	}

	if settings.SMTPPassword == "" {
		return fmt.Errorf("SMTP password is required")
	}

	if len(settings.RecipientList) == 0 {
		return fmt.Errorf("at least one recipient is required")
	}

	for _, recipient := range settings.RecipientList {
		if !strings.Contains(recipient, "@") {
			return fmt.Errorf("invalid recipient email format: %s", recipient)
		}
	}

	return nil
}

func testSMTPConnectionWithRelay(ctx context.Context, settings *v1.SetBlacklistAlertSettingsReq) error {
	//g.Log().Infof(ctx, "Testing SMTP connection to %s:%d", settings.SMTPServer, settings.SMTPPort)

	result := relay.TestSmtpConnection(
		settings.SMTPServer,
		fmt.Sprintf("%d", settings.SMTPPort),
		settings.SenderEmail,

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Include at least one email address in the recipientList array.
  2. Verify the JSON field name matches the struct binding tag so the list is not silently empty.
  3. In the UI, disable the save button until at least one validated recipient exists.

Example fix

// before
{"recipientList":[]}
// after
{"recipientList":["admin@example.com"]}
Defensive patterns

Strategy: validation

Validate before calling

const recipients = Array.isArray(payload.recipientList) ? payload.recipientList : []
if (recipients.length === 0) {
  throw new Error('Add at least one alert recipient')
}

Type guard

function hasRecipients(s: { recipientList?: string[] }): s is { recipientList: string[] } {
  return Array.isArray(s.recipientList) && s.recipientList.length > 0
}

Try / catch

try {
  await api.setBlacklistAlertSettings(payload)
} catch (e) {
  if (String(e).includes('at least one recipient')) {
    showFormError('recipients', 'At least one recipient email is required')
  }
}

Prevention

When it happens

Trigger: Calling SetBlacklistAlertSettings with recipientList an empty array, null, or omitted from the request.

Common situations: 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.

Related errors


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/beb5be96751ab82f. Report an issue: GitHub.