knadh/listmonk · error

campaigns.fieldInvalidFromEmail

Error message

campaigns.fieldInvalidFromEmail

What it means

validateCampaignFields in cmd/campaigns.go rejects a campaign request whose FromEmail is neither empty nor empty-defaulted from config, when it fails both the reFromAddress regex and importer.SanitizeEmail(). It means the supplied sender address is not a parseable/valid e-mail the outgoing mail system can use.

Source

Thrown at cmd/campaigns.go:685

	}

	// Create a sample campaign message.
	msg, err := a.manager.NewCampaignMessage(camp, sub)
	if err != nil {
		a.log.Printf("error rendering message: %v", err)
		return echo.NewHTTPError(http.StatusNotFound, a.i18n.Ts("templates.errorRendering", "error", err.Error()))
	}

	return a.manager.PushCampaignMessage(msg)
}

// validateCampaignFields validates incoming campaign field values.
func (a *App) validateCampaignFields(c campReq) (campReq, error) {
	if c.FromEmail == "" {
		c.FromEmail = a.cfg.FromEmail
	} else if !reFromAddress.Match([]byte(c.FromEmail)) {
		if _, err := a.importer.SanitizeEmail(c.FromEmail); err != nil {
			return c, errors.New(a.i18n.T("campaigns.fieldInvalidFromEmail"))
		}
	}

	if !strHasLen(c.Name, 1, stdInputMaxLen) {
		return c, errors.New(a.i18n.T("campaigns.fieldInvalidName"))
	}

	// Larger char limit for subject as it can contain {{ go templating }} logic.
	if !strHasLen(c.Subject, 1, 5000) {
		return c, errors.New(a.i18n.T("campaigns.fieldInvalidSubject"))
	}

	// If no content-type is specified, default to richtext.
	if c.ContentType != models.CampaignContentTypeRichtext &&
		c.ContentType != models.CampaignContentTypeHTML &&
		c.ContentType != models.CampaignContentTypePlain &&
		c.ContentType != models.CampaignContentTypeVisual &&
		c.ContentType != models.CampaignContentTypeMarkdown {

View on GitHub (pinned to 670c01717d)

Solutions

  1. Send a plain valid e-mail address (e.g. 'sender@domain.com') in the from_email field.
  2. Omit from_email entirely to inherit the default a.cfg.FromEmail configured in the app config.
  3. Strip whitespace/display-name wrappers before sending; use net/mail.ParseAddress client-side to pre-validate.
  4. If a display name is needed, configure the sender name field separately rather than embedding '<>' in the address.

Example fix

// before
{"from_email": "Marketing <marketing@example.com>"}
// after
{"from_email": "marketing@example.com", "from_name": "Marketing"}
Defensive patterns

Strategy: validation

Validate before calling

// validate from_email before calling the campaign API
function isValidFromEmail(v) {
  return /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(String(v || '').trim());
}
// or, omit the field to inherit the server default:
const payload = { name, subject, lists };
if (fromEmail) payload.from_email = fromEmail;

Type guard

function isPlainEmail(v: unknown): v is string {
  return typeof v === 'string' && /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(v.trim());
}

Try / catch

try {
  await api.createCampaign(payload);
} catch (e) {
  if (e.message.includes('fieldInvalidFromEmail')) {
    throw new Error(`from_email "${payload.from_email}" is not a valid address`);
  }
  throw e;
}

Prevention

When it happens

Trigger: POST/PUT campaign endpoints (CreateCampaign, UpdateCampaign) or TestCampaign with a from_email value like 'not-an-email', 'John <john>' (malformed), or containing stray whitespace/characters that fail both the regex and sanitization.

Common situations: Typing a display name into the from_email field instead of an address, pasting 'Name <addr@x.com>' when the API expects just the address, or copying an address with hidden unicode/whitespace from a document.

Related errors


AI-assisted analysis of knadh/listmonk@670c01717d (2026-09-01). Data as JSON: /api/errors/d6590b844ca9cb0c. Report an issue: GitHub.