Billionmail/BillionMail · error
failed to send alert email to %d recipient(s): %v
Error message
failed to send alert email to %d recipient(s): %v
What it means
sendAlertEmail iterates settings.RecipientList, sending to each recipient and recording addresses whose Send() call fails. If any recipient failed, it returns 'failed to send alert email to %d recipient(s): %v' listing the count and the failed addresses. Note the connection already succeeded — this is a per-recipient delivery failure, and the successful recipients still got the alert.
Source
Thrown at core/internal/service/domains/blacklist.go:507
var failedRecipients []string
for _, recipient := range settings.RecipientList {
message := mail_service.NewMessage(subject, body)
message.SetRealName(settings.Name)
messageId := sender.GenerateMessageID()
message.SetMessageID(messageId)
err = sender.Send(message, []string{recipient})
if err != nil {
g.Log().Errorf(ctx, "Failed to send alert email to %s: %v", recipient, err)
failedRecipients = append(failedRecipients, recipient)
} else {
g.Log().Infof(ctx, "Alert email sent successfully to %s", recipient)
}
}
if len(failedRecipients) > 0 {
return fmt.Errorf("failed to send alert email to %d recipient(s): %v", len(failedRecipients), failedRecipients)
}
return nil
}
func buildBlacklistAlertEmailHTML(ip, domain string, result *model.BlacklistCheckResult) string {
var blacklistItems string
for i, bl := range result.BlackList {
blacklistItems += fmt.Sprintf(" <li><strong>%d. %s</strong> (Response: %s)</li>\n",
i+1, bl.Blacklist, bl.Response)
}
return fmt.Sprintf(`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />View on GitHub (pinned to fc36c76c05)
Solutions
- Review the failedRecipients list in the wrapped error and correct or remove invalid addresses from alert settings
- Check the SMTP server logs for the exact rejection codes (550/551/554) per failed address
- Ensure the sender domain has valid SPF/DKIM/DMARC so recipient servers accept the mail
- Resend the alert to only the failed recipients after fixing the cause
Example fix
// before
if len(failedRecipients) > 0 {
return fmt.Errorf("failed to send alert email to %d recipient(s): %v", len(failedRecipients), failedRecipients)
}
// after
if len(failedRecipients) > 0 {
return fmt.Errorf("failed to send alert email to %d/%d recipient(s): %v (subject=%q)", len(failedRecipients), len(settings.RecipientList), failedRecipients, subject)
} Defensive patterns
Strategy: fallback
Validate before calling
// validate recipient addresses before sending
for _, r := range settings.RecipientList {
if _, err := mail.ParseAddress(r); err != nil {
return fmt.Errorf("invalid alert recipient %q: %w", r, err)
}
} Type guard
func validRecipients(rs []string) bool {
for _, r := range rs {
if _, err := mail.ParseAddress(r); err != nil {
return false
}
}
return len(rs) > 0
} Try / catch
err := sendAlertEmail(ctx, settings, subject, body)
if err != nil && strings.Contains(err.Error(), "failed to send alert email to") {
// partial failure: alert still reached some recipients;
// parse failedRecipients from the message and retry only those
} Prevention
- Prune stale/typo addresses from RecipientList regularly
- Verify recipient mail servers accept the sender (SPF/DKIM/DMARC aligned)
- Keep recipient lists short to avoid relay rate limits
- On partial failure, resend only to the failed addresses rather than everyone
When it happens
Trigger: Called from sendBlacklistAlert when one or more recipient addresses are rejected by the SMTP server (550 no such user, 554 relay denied, greylisting, invalid address format, mailbox full) during the per-recipient Send loop.
Common situations: Typo'd or departed employee addresses in RecipientList; recipients on domains with strict SPF/DMARC rejecting the sender; SMTP relay refusing to relay for external domains; rate limiting after many alert recipients; alias addresses that no longer exist in the alias table.
Related errors
- failed to connect to SMTP server: %v
- unexpected server response
- Email Sender not configured
- No SPF record found
- sender email is required
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/6027cabcab6d95c1.
Report an issue: GitHub.