usememos/memos · error

SMTP port must be between 1 and 65535

Error message

SMTP port must be between 1 and 65535

What it means

Returned by Config.Validate() when SMTPPort is <= 0 or > 65535. The port is later formatted into "host:port" by GetServerAddress(), and an out-of-range value would produce an invalid dial target, so validation rejects it up front. Note the zero value (unset port) fails this check — there is no default.

Source

Thrown at internal/email/config.go:36

	// SMTPPassword is the SMTP authentication password or app-specific password
	SMTPPassword string
	// FromEmail is the email address that will appear in the "From" field
	FromEmail string
	// FromName is the display name that will appear in the "From" field
	FromName string
	// UseTLS enables STARTTLS encryption (recommended for port 587)
	UseTLS bool
	// UseSSL enables SSL/TLS encryption (for port 465)
	UseSSL bool
}

// Validate checks if the configuration is valid.
func (c *Config) Validate() error {
	if c.SMTPHost == "" {
		return errors.New("SMTP host is required")
	}
	if c.SMTPPort <= 0 || c.SMTPPort > 65535 {
		return errors.New("SMTP port must be between 1 and 65535")
	}
	if c.FromEmail == "" {
		return errors.New("from email is required")
	}
	return nil
}

// GetServerAddress returns the SMTP server address in the format "host:port".
func (c *Config) GetServerAddress() string {
	return fmt.Sprintf("%s:%d", c.SMTPHost, c.SMTPPort)
}

View on GitHub (pinned to 14d757ce1f)

Solutions

  1. Set SMTPPort to a valid port (587 for STARTTLS, 465 for SSL, or your relay's port).
  2. Verify the config loader actually assigns an int to SMTPPort — an unparseable string often decodes to the zero value.
  3. Default the port sensibly when the field is optional in your wiring (e.g., 587) before calling Validate().

Example fix

// before
cfg := email.Config{SMTPHost: "smtp.example.com", FromEmail: "noreply@example.com"} // SMTPPort == 0

// after
cfg := email.Config{SMTPHost: "smtp.example.com", SMTPPort: 587, FromEmail: "noreply@example.com"}
Defensive patterns

Strategy: validation

Validate before calling

// Go
if cfg.SMTPPort == 0 {
  cfg.SMTPPort = 587 // apply an explicit default before validating
}
if err := cfg.Validate(); err != nil {
  return err
}

Try / catch

if err := cfg.Validate(); err != nil {
  return errors.Wrap(err, "invalid SMTP config")
}

Prevention

When it happens

Trigger: Config built with SMTPPort unset (0) because the config loader did not parse the port field; port supplied as a string and never converted; negative or >65535 value from user input or env parsing.

Common situations: Port left blank in the admin SMTP form; port passed as "587" in YAML where an int is expected and decoding silently yields 0; copying a mailto-style URL (smtp://host:587) into a field that expects a bare port number.

Related errors


AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15). Data as JSON: /api/errors/b67b72559223104f. Report an issue: GitHub.