knadh/listmonk · error
subscribers.invalidEmail
Error message
subscribers.invalidEmail
What it means
Importer.SanitizeEmail wraps utils.SanitizeEmail; when bare-address validation fails (malformed email), it replaces the low-level error with the i18n message 'subscribers.invalidEmail' so import errors are localized. It is thrown per-row during subscriber import when the email value cannot be parsed as a valid address.
Source
Thrown at internal/subimporter/importer.go:614
im.Unlock()
return
}
select {
case im.stop <- true:
im.setStatus(StatusStopping)
default:
}
}
// SanitizeEmail validates and sanitizes an e-mail string and returns the
// canonical (lowercased, trimmed) address. Domain allowlist/blocklist rules
// are enforced on top of the bare-address validation in utils.SanitizeEmail.
func (im *Importer) SanitizeEmail(email string) (string, error) {
addr, err := utils.SanitizeEmail(email)
if err != nil {
return "", errors.New(im.i18n.T("subscribers.invalidEmail"))
}
// Check if the e-mail's domain is blocklisted. The e-mail domain and blocklist config
// are always lowercase.
if im.hasAllowlist || im.hasBlocklist {
d := strings.Split(addr, "@")
if len(d) != 2 {
return addr, nil
}
domain := d[1]
// If there's an allowlist, check if the domain is in it. Checking blocklist after that is moot.
if im.hasAllowlist {
if !im.checkInList(domain, im.hasAllowlistWildcards, im.domainAllowlist) {
return "", errors.New(im.i18n.T("subscribers.domainBlocklisted"))
}
} else if im.hasBlocklist {View on GitHub (pinned to 670c01717d)
Solutions
- Correct or remove rows with malformed email values in the CSV before importing.
- Pre-validate the file with a script using the same address syntax check (e.g. Go net/mail ParseAddress).
- Trim whitespace and strip stray characters (commas, quotes) from the email column.
- If valid emails are rejected, verify the input encoding (BOM, smart quotes) isn't corrupting values.
Example fix
// before email john acme.com // after email john@acme.com
Defensive patterns
Strategy: validation
Validate before calling
email := strings.TrimSpace(row.Email)
if email == "" || len(email) > 1000 {
return fmt.Errorf("row %d: empty or oversized email", i)
}
if _, err := mail.ParseAddress(email); err != nil {
return fmt.Errorf("row %d: malformed email %q", i, email)
} Type guard
func isValidEmail(s string) bool {
_, err := mail.ParseAddress(strings.TrimSpace(s))
return err == nil && !strings.Contains(s, " ")
} Try / catch
em, err := importer.SanitizeEmail(email)
if err != nil {
log.Printf("skipping row: %v", err) // localized 'subscribers.invalidEmail'
continue
} Prevention
- Trim and normalize the email column before import.
- Reject display-name forms ('Name <a@b.c>') at data entry.
- Deduplicate and syntax-check lists from third parties before import.
- Use ValidateEmail for pre-screening files client-side.
When it happens
Trigger: ValidateFields calls SanitizeEmail on each imported row and the email string fails utils.SanitizeEmail — empty string, missing '@', invalid characters, unbalanced quotes, or invalid domain format.
Common situations: Dirty third-party lists with values like 'john(at)acme.com', trailing spaces/commas, concatenated fields, or Excel-mangled emails; also rows where column shift put a name in the email cell.
Related errors
- globals.messages.invalidFields
- campaigns.fieldInvalidFromEmail
- 'email' column not found
- subscribers.domainBlocklisted
- invalid e-mail address
AI-assisted analysis of knadh/listmonk@670c01717d (2026-09-01).
Data as JSON: /api/errors/de2c32aab82ecb7e.
Report an issue: GitHub.