Sovite.Core.Config (sovite v0.2.0)

Copy Markdown View Source

Loads, validates, and stores the Sovite configuration file.

The file is TOML. Every key is checked against a schema: unknown keys, wrong types, and invalid values are all reported together, each with the path of the bad key. See docs/configuration.md for the reference.

The running configuration is kept in :persistent_term. Read it with get/0.

Summary

Functions

Returns whether any listener offers AUTH.

The SASL mechanisms to offer: auth.mechanisms, or by default those the backend supports.

Returns the config file path: $SOVITE_CONFIG if set, otherwise /etc/sovite/sovite.toml.

Returns the running configuration. Raises if none has been stored.

Reads, parses, and validates the config file at path.

Parses and validates TOML config contents.

Stores config as the running configuration.

Returns whether TLS certificates are configured (files or ACME).

Validates a decoded config map (string keys, as produced by a TOML decoder), fills in defaults, and returns the config struct.

Types

t()

@type t() :: %Sovite.Core.Config{
  auth: map(),
  bounce: %{double_bounce_recipient: String.t() | nil},
  database: %{
    adapter: :sqlite | :postgres | :mysql,
    path: Path.t(),
    url: String.t() | nil,
    pool_size: pos_integer(),
    ssl: boolean()
  },
  delivery: %{
    relayhost:
      %{host: String.t(), port: :inet.port_number(), mx: boolean()} | nil,
    max_deliveries: pos_integer(),
    destination_concurrency: pos_integer(),
    destination_rate_delay: pos_integer() | nil,
    max_recipients: pos_integer(),
    max_addresses: pos_integer(),
    ip_versions: [:ipv6 | :ipv4, ...],
    connect_timeout: pos_integer(),
    tls: tls_level(),
    tls_policy: %{required(String.t()) => tls_level()},
    tls_ca_file: Path.t() | nil,
    relayhost_username: String.t() | nil,
    relayhost_password: String.t() | nil,
    source_address: [:inet.ip_address()]
  },
  domains: %{
    local: [String.t()],
    relay: [String.t()],
    local_recipients: [String.t()] | nil,
    aliased: [String.t()],
    hosted: [String.t()]
  },
  listener: [
    %{
      address: :inet.ip_address(),
      port: :inet.port_number(),
      mode: :smtp | :submission | :submissions | :lmtp,
      auth: boolean(),
      require_tls: boolean(),
      require_auth: boolean(),
      tls_min_version: :"tlsv1.2" | :"tlsv1.3" | nil,
      tls_ciphers: [String.t()] | nil
    }
  ],
  log: Sovite.Core.Logging.config(),
  maildir: %{local: String.t() | nil, mailbox: String.t() | nil},
  pipe: %{
    required(String.t()) => %{
      command: [String.t(), ...],
      sandbox: [String.t(), ...] | nil,
      timeout: pos_integer(),
      directory: Path.t(),
      env: %{required(String.t()) => String.t()},
      trace_headers: boolean()
    }
  },
  queue: %{
    directory: Path.t(),
    max_lifetime: pos_integer(),
    min_backoff: pos_integer(),
    max_backoff: pos_integer(),
    delay_warning: pos_integer() | nil
  },
  restrictions: %{required(atom()) => [String.t()]},
  routing: map(),
  server: %{hostname: String.t()},
  smtp: %{
    max_message_size: pos_integer(),
    max_recipients: pos_integer(),
    max_connections: pos_integer(),
    max_connections_per_ip: pos_integer(),
    max_errors: pos_integer(),
    command_timeout: pos_integer(),
    data_timeout: pos_integer(),
    bare_line_endings: :reject | :normalize,
    vrfy: boolean(),
    trusted_networks: [Sovite.Net.network()],
    max_hops: pos_integer()
  },
  submission: %{strip_headers: [String.t()]},
  tls: %{
    certificate: [%{cert_file: Path.t(), key_file: Path.t()}],
    min_version: :"tlsv1.2" | :"tlsv1.3",
    ciphers: [String.t()] | nil,
    reload_interval: pos_integer(),
    acme: map()
  }
}

tls_level()

@type tls_level() :: :none | :may | :encrypt | :verify | :dane

Functions

auth_enabled?(config)

@spec auth_enabled?(t() | map()) :: boolean()

Returns whether any listener offers AUTH.

auth_mechanisms(map)

@spec auth_mechanisms(t() | map()) :: [String.t()]

The SASL mechanisms to offer: auth.mechanisms, or by default those the backend supports.

default_path()

@spec default_path() :: Path.t()

Returns the config file path: $SOVITE_CONFIG if set, otherwise /etc/sovite/sovite.toml.

get()

@spec get() :: t()

Returns the running configuration. Raises if none has been stored.

load(path)

@spec load(Path.t()) :: {:ok, t()} | {:error, [Sovite.Core.Config.Error.t()]}

Reads, parses, and validates the config file at path.

parse(contents)

@spec parse(String.t()) :: {:ok, t()} | {:error, [Sovite.Core.Config.Error.t()]}

Parses and validates TOML config contents.

put(config)

@spec put(t()) :: :ok

Stores config as the running configuration.

tls_enabled?(config)

@spec tls_enabled?(t() | map()) :: boolean()

Returns whether TLS certificates are configured (files or ACME).

validate(map)

@spec validate(map()) :: {:ok, t()} | {:error, [Sovite.Core.Config.Error.t()]}

Validates a decoded config map (string keys, as produced by a TOML decoder), fills in defaults, and returns the config struct.