smtp

package
v1.118.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 1, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package smtp is the admin-configured mail server layer of the notification substrate: the stored connection settings, the admin API's write/read shapes with their validation, and the store that persists them with the password encrypted at rest.

It knows nothing about queues, preferences, or rendering. The send path (internal/notification/notifysend) takes a Settings value per call, so an admin change applies to the next send without a restart.

Index

Constants

View Source
const (
	// TLSModeStartTLS negotiates STARTTLS on a plaintext connection (port 587).
	TLSModeStartTLS = "starttls"
	// TLSModeImplicit opens a TLS connection directly (port 465).
	TLSModeImplicit = "implicit"
	// TLSModeNone sends in plaintext. Only for closed-network relays.
	TLSModeNone = "none"
)

SMTP TLS modes.

View Source
const PlaintextAuthWarning = "TLS is disabled (tls_mode: none) while SMTP credentials are configured; " +
	"the username and password are sent in cleartext. Use starttls or implicit unless the relay is on a closed network."

PlaintextAuthWarning is reported when SMTP credentials are configured alongside TLSModeNone: go-mail then authenticates over an unencrypted connection, putting the username and password on the wire in the clear.

View Source
const SettingsSection = "smtp"

SettingsSection is the platform_settings section key for SMTP.

Variables

View Source
var (
	// ErrNotFound is returned by the store when SMTP has never been configured.
	ErrNotFound = errors.New("notification: smtp settings not found")
	// ErrNotConfigured is returned by delivery actions when SMTP is absent,
	// disabled, or missing a host; the caller should surface it as a
	// configuration conflict, not a delivery failure.
	ErrNotConfigured = errors.New("notification: smtp is disabled or not configured")
)

Sentinel errors returned by this package.

Functions

This section is empty.

Types

type PostgresStore

type PostgresStore struct {
	// contains filtered or unexported fields
}

PostgresStore implements SettingsStore backed by the platform_settings table. Secrets inside a section value are encrypted with the injected StringEncryptor before they reach the database.

func NewPostgresStore

func NewPostgresStore(db *sql.DB, enc StringEncryptor) *PostgresStore

NewPostgresStore creates a PostgreSQL-backed settings store. The encryptor may be nil-safe (encryption disabled) but must not be nil.

func (*PostgresStore) Get

func (s *PostgresStore) Get(ctx context.Context) (*Settings, error)

Get returns the stored SMTP settings with the password decrypted.

func (*PostgresStore) Set

func (s *PostgresStore) Set(ctx context.Context, in Settings, author string) error

Set upserts the SMTP settings. An empty incoming password keeps the previously stored (still encrypted) one so the admin UI never round-trips the secret.

type Settings

type Settings struct {
	Enabled  bool   `json:"enabled"`
	Host     string `json:"host"`
	Port     int    `json:"port"`
	Username string `json:"username"`
	Password string `json:"password,omitempty"`
	// From is the sender address, e.g. "platform@example.com".
	From string `json:"from"`
	// FromName is the optional display name for the From address.
	FromName string `json:"from_name"`
	// TLSMode is one of the TLSMode* constants.
	TLSMode string `json:"tls_mode"`
	// UpdatedBy and UpdatedAt describe the last admin write.
	UpdatedBy string    `json:"updated_by,omitempty"`
	UpdatedAt time.Time `json:"updated_at"`
}

Settings is the admin-configured mail server connection. The password is encrypted at rest and never returned by the admin API.

func (*Settings) View

func (s *Settings) View() SettingsView

View maps stored settings to the password-free read shape.

type SettingsInput

type SettingsInput struct {
	Enabled  bool   `json:"enabled" example:"true"`
	Host     string `json:"host" example:"smtp.example.com"`
	Port     int    `json:"port" example:"587"`
	Username string `json:"username,omitempty" example:"mailer@example.com"`
	Password string `json:"password,omitempty" example:"app-password"`
	From     string `json:"from" example:"platform@example.com"`
	FromName string `json:"from_name,omitempty" example:"Data Platform"`
	TLSMode  string `json:"tls_mode,omitempty" example:"starttls"`
}

SettingsInput is the write shape for the admin SMTP configuration. An empty password keeps the currently stored one.

func (*SettingsInput) Settings

func (in *SettingsInput) Settings() Settings

Settings maps the validated input to store settings.

func (*SettingsInput) Validate

func (in *SettingsInput) Validate() string

Validate normalizes defaults in place and returns a non-empty message when the input is invalid. Omitted fields take defaults (port 587, STARTTLS) so a minimal `{"enabled": false}` disable call works.

type SettingsStore

type SettingsStore interface {
	// Get returns the stored SMTP settings with the password decrypted,
	// or ErrNotFound when SMTP has never been configured.
	Get(ctx context.Context) (*Settings, error)
	// Set upserts the SMTP settings, encrypting the password at rest.
	// An empty incoming password preserves the previously stored one so the
	// admin UI can stay write-only without re-sending the secret.
	Set(ctx context.Context, s Settings, author string) error
}

SettingsStore persists the admin's SMTP configuration. It is the SMTP section of the platform_settings table; another global setting would add its own contract over the same table rather than widen this one.

type SettingsView

type SettingsView struct {
	Enabled     bool      `json:"enabled" example:"true"`
	Host        string    `json:"host" example:"smtp.example.com"`
	Port        int       `json:"port" example:"587"`
	Username    string    `json:"username" example:"mailer@example.com"`
	PasswordSet bool      `json:"password_set" example:"true"`
	From        string    `json:"from" example:"platform@example.com"`
	FromName    string    `json:"from_name" example:"Data Platform"`
	TLSMode     string    `json:"tls_mode" example:"starttls"`
	UpdatedBy   string    `json:"updated_by,omitempty" example:"admin@example.com"`
	UpdatedAt   time.Time `json:"updated_at"`
	// Warnings describes accepted-but-hazardous combinations in the stored
	// configuration. They never block a save; they exist so the operator sees
	// the hazard at the surface where the setting was chosen.
	Warnings []string `json:"warnings,omitempty"`
}

SettingsView is the read shape for the admin SMTP configuration. The password is write-only: the view reports only whether one is stored.

func UnconfiguredView

func UnconfiguredView() SettingsView

UnconfiguredView is the read shape served before SMTP has ever been configured: disabled, with the transport defaults prefilled.

type StringEncryptor

type StringEncryptor interface {
	Encrypt(plaintext string) (string, error)
	Decrypt(ciphertext string) (string, error)
}

StringEncryptor encrypts and decrypts a single string secret. Satisfied by fieldcrypt.RestFieldEncryptor; a nil-safe passthrough is acceptable when encryption is disabled.

type TestEmailRequest

type TestEmailRequest struct {
	To string `json:"to" example:"admin@example.com"`
}

TestEmailRequest is the body for the admin send-test-email action.

func (*TestEmailRequest) Validate

func (r *TestEmailRequest) Validate() string

Validate returns a non-empty message when the recipient is invalid.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL