usememos/memos · error
SMTP host is required
Error message
SMTP host is required
What it means
Returned by Config.Validate() in internal/email/config.go when SMTPHost is the empty string. The SMTP client cannot dial GetServerAddress() ("host:port") without a host, so validation fails fast before any connection attempt. It is a pure configuration error: the mailer was constructed without a host.
Source
Thrown at internal/email/config.go:33
SMTPPort int
// SMTPUsername is the SMTP authentication username (usually the email address)
SMTPUsername string
// 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
- Set the SMTP host in Settings > SMTP (e.g., smtp.example.com) or the equivalent config source, then re-validate.
- Check that the config key actually maps to Config.SMTPHost (typo/case mismatch in env or YAML keys).
- Call Validate() early at startup or after config load so this surfaces before the first send attempt.
- Confirm the rest of the config passes too (port 1-65535, FromEmail non-empty) since Validate checks all three.
Example fix
// before
cfg := email.Config{SMTPPort: 587, FromEmail: "noreply@example.com"}
// after
cfg := email.Config{SMTPHost: "smtp.example.com", SMTPPort: 587, FromEmail: "noreply@example.com"}
if err := cfg.Validate(); err != nil {
return err
} Defensive patterns
Strategy: validation
Validate before calling
// Go — validate before constructing the mailer
if strings.TrimSpace(cfg.SMTPHost) == "" {
return errors.New("SMTP host missing: set it in settings or config before enabling mail")
}
if err := cfg.Validate(); err != nil {
return err
} Try / catch
if err := cfg.Validate(); err != nil {
if errors.Is(err, email.ErrHostRequired) { /* if sentinel introduced */ }
return errors.Wrap(err, "invalid SMTP config")
} Prevention
- Run Config.Validate() at startup or settings-save time, not only on first send.
- Fail the admin form when host is blank instead of persisting an unusable config.
- Integration-test config loading with the exact env/YAML keys you deploy.
When it happens
Trigger: Instantiating email.NewClient / sending mail with a Config whose SMTPHost was never set — e.g., SMTP system setting empty in the Memos admin UI, or an environment/config loader defaulting host to "". First surfaces on the first email send (e.g., a memo notification or test email) or at config validation time.
Common situations: Fresh install where the SMTP settings were never filled; deployment where the SMTP_HOST env var name differs from what the loader expects; adding email notifications to a stack/compose file but leaving host blank; YAML/JSON config with a typo'd key so the field stays zero-valued.
Related errors
- SMTP port must be between 1 and 65535
- from email is required
- SMTP server does not support STARTTLS
- enabled notification email requires smtpHost, a positive smt
- notification email cannot enable both useTls and useSsl
AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15).
Data as JSON: /api/errors/4c0786934bcbfffc.
Report an issue: GitHub.