Billionmail/BillionMail · error
no recipients specified
Error message
no recipients specified
What it means
Send() validates its input before any network work: if recipients is empty or nil it returns this error immediately. It guards against attempting an SMTP transaction with no RCPT TO, which would fail downstream anyway. This is purely a caller-input problem, not a server issue.
Source
Thrown at core/internal/service/mail_service/sending.go:309
// GenerateMessageID generates a unique Message-ID for email
func (e *EmailSender) GenerateMessageID() string {
randomBytes := grand.B(16)
randomID := hex.EncodeToString(randomBytes)
timestampMillis := time.Now().UnixMilli()
domain := strings.SplitN(e.Email, "@", 2)
domainPart := "billionmail"
if len(domain) > 1 {
domainPart = domain[1]
}
return fmt.Sprintf("<%d.%s@%s>", timestampMillis, randomID, domainPart)
}
// Send sends an email to specified recipients
func (e *EmailSender) Send(message Message, recipients []string) error {
if len(recipients) == 0 {
return fmt.Errorf("no recipients specified")
}
e.mutex.Lock()
defer e.mutex.Unlock()
// Make sure we have a connection
if !e.connected || e.client == nil {
e.mutex.Unlock()
if err := e.Connect(); err != nil {
e.mutex.Lock()
return fmt.Errorf("failed to connect: %w", err)
}
e.mutex.Lock()
}
// Try to send the message, with reconnect on failure
err := e.doSend(message, recipients)
if err != nil {View on GitHub (pinned to fc36c76c05)
Solutions
- Fix the caller (sendApiMailWithSender) to ensure recipients is populated before invoking Send, failing fast with a clearer upstream message.
- If sending to zero contacts is expected/legitimate, skip the Send call instead of invoking it.
- Validate and dedupe recipient addresses upstream so a partially valid list still sends to valid entries.
- Log the campaign/message context when this triggers to identify which upstream step dropped the recipients.
Example fix
// before
err := sender.Send(message, recipients)
// after
if len(recipients) == 0 {
return fmt.Errorf("send skipped: no recipients resolved for this message")
}
err := sender.Send(message, recipients) Defensive patterns
Strategy: validation
Validate before calling
func send(sender *EmailSender, msg Message, recipients []string) error {
if len(recipients) == 0 {
return fmt.Errorf("send skipped: no recipients resolved")
}
filtered := make([]string, 0, len(recipients))
for _, r := range recipients {
if addr, err := mail.ParseAddress(r); err == nil {
filtered = append(filtered, addr.Address)
}
}
if len(filtered) == 0 {
return fmt.Errorf("send skipped: no valid recipient addresses")
}
return sender.Send(msg, filtered)
} Type guard
func hasRecipients(recipients []string) bool {
return len(recipients) > 0
} Try / catch
if err := sender.Send(msg, recipients); err != nil {
if err.Error() == "no recipients specified" {
// caller bug, not a mail-server problem: log campaign context and skip
log.Printf("skipped send: empty recipient list")
return nil
}
return err
} Prevention
- Validate recipients upstream of Send; fail fast with context about which step emptied the list.
- Deduplicate and syntax-check addresses with net/mail.ParseAddress before sending.
- Treat zero resolved contacts as a business-level skip, not a Send() call.
When it happens
Trigger: Calling EmailSender.Send(message, recipients) with an empty slice — e.g. a campaign resolved to zero contacts, or a nil recipients value passed through sendApiMailWithSender.
Common situations: A campaign/contact query filtered everyone out before sending; an API caller sent an empty recipients array; a code path forgot to append CC/BCC into the recipients list; a bug mapping contact list to []string produced an empty result.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- SMTP server is required
- SMTP port must be between 1 and 65535
- SMTP password is required
- at least one recipient is required
- supplier name, base URL, and API key are required
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/5ab0a40175fff7f1.
Report an issue: GitHub.