config

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Oct 13, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package config defines the mailctl YAML schema and loads it into a desired-state tree.

Index

Constants

View Source
const (
	DefaultCloudflareBaseURL = "https://api.cloudflare.com/client/v4"
	DefaultPurelymailBaseURL = "https://purelymail.com"
	DefaultTTL               = 1
	// DefaultDMARCPct is applied when dmarc is configured but pct is omitted,
	// so pct is not a required key.
	DefaultDMARCPct = 100
)
View Source
const SchemaVersion = 1

SchemaVersion is the only config schema version this build understands.

Variables

View Source
var InboundProviders = []string{"purelymail", "cfrouting", "ms365"}

InboundProviders accept inbound mail: each publishes MX records and creates its own alias routing rules. A domain may name at most one; cfsending is outbound-only and may pair with either.

View Source
var KnownProviders = []string{"purelymail", "cfrouting", "cfsending", "ms365"}

KnownProviders is every mail provider name the config accepts. Providers are registered at init time in internal/mail, but config must be able to reject a typo without importing that package, so the list is duplicated here deliberately and kept in sync by TestKnownProvidersMatchRegistry.

View Source
var MailboxlessProviders = []string{"cfrouting", "cfsending"}

MailboxlessProviders route mail but do not host it. A domain using only these providers may not declare mailboxes.

Functions

func BoolOr

func BoolOr(value *bool, fallback bool) bool

BoolOr resolves an optional YAML bool against a default.

Types

type Alias

type Alias struct {
	Match string   `yaml:"match"`
	To    []string `yaml:"to"`
}

func (Alias) MatchUser

func (a Alias) MatchUser() string

MatchUser returns the alias local part with any trailing * removed.

func (Alias) Prefix

func (a Alias) Prefix() bool

Prefix reports whether the alias match is a prefix match (trailing *).

type BIMI

type BIMI struct {
	VMC  string `yaml:"vmc"`
}

type CatchAll

type CatchAll struct {
	To []string `yaml:"to"`
}

type CloudflareConfig

type CloudflareConfig struct {
	AccountID string `yaml:"accountId"`
	BaseURL   string `yaml:"baseUrl"`
	TTL       int    `yaml:"ttl"`
}

type Config

type Config struct {
	Version    int              `yaml:"version"`
	Cloudflare CloudflareConfig `yaml:"cloudflare"`
	Purelymail PurelymailConfig `yaml:"purelymail"`
	Domains    []Domain         `yaml:"domains"`
}

func Load

func Load(path string, getenv func(string) string) (Config, error)

Load reads path, expands ${VAR} references using getenv, applies defaults, and validates the result. getenv may be nil, in which case os.Getenv is used.

func (*Config) ApplyDefaults

func (c *Config) ApplyDefaults()

ApplyDefaults sets default values for configuration fields that are not explicitly set.

func (Config) Domain

func (c Config) Domain(name string) (Domain, bool)

Domain returns the domain with the given name, and whether it was found.

func (Config) Validate

func (c Config) Validate() error

type DMARC

type DMARC struct {
	Policy          string `yaml:"policy"`
	SubdomainPolicy string `yaml:"subdomainPolicy"`
	Pct             int    `yaml:"pct"`
	RUA             string `yaml:"rua"`
	RUF             string `yaml:"ruf"`
}

type Deliverability

type Deliverability struct {
	SPFIncludes []string `yaml:"spfIncludes"`
	DMARC       *DMARC   `yaml:"dmarc"`
	MTASts      *MTASts  `yaml:"mtaSts"`
	TLSRpt      string   `yaml:"tlsRpt"`
	BIMI        *BIMI    `yaml:"bimi"`
}

Deliverability configures the SPF, DMARC, MTA-STS, TLS-RPT, and BIMI records mailctl publishes alongside whatever a mail provider asks for.

type Domain

type Domain struct {
	Name           string         `yaml:"name"`
	ZoneName       string         `yaml:"zoneName"`
	Mail           Mail           `yaml:"mail"`
	Mailboxes      []Mailbox      `yaml:"mailboxes"`
	Aliases        []Alias        `yaml:"aliases"`
	CatchAll       *CatchAll      `yaml:"catchAll"`
	Deliverability Deliverability `yaml:"deliverability"`
}

func (Domain) AllTargets

func (d Domain) AllTargets() []string

AllTargets returns every address this domain forwards to, deduplicated. Cloudflare Email Routing requires each of them to be a verified destination.

type DomainSettings

type DomainSettings struct {
	AllowAccountReset     *bool `yaml:"allowAccountReset"`
	SymbolicSubaddressing *bool `yaml:"symbolicSubaddressing"`
}

type MS365

type MS365 struct {
	// License is a skuPartNumber such as BUSINESS_BASIC, not a skuId GUID.
	// It is the domain-level default; a mailbox's own Mailbox.License
	// overrides it for that mailbox only.
	License string `yaml:"license"`
	// UsageLocation is an ISO 3166-1 alpha-2 code. Graph requires it on a user
	// before a licence can be assigned.
	UsageLocation string `yaml:"usageLocation"`
	// DKIMCnames are the two targets copied from the Defender portal, for
	// selector1 and selector2 in that order. Graph cannot supply them.
	DKIMCnames []string `yaml:"dkimCnames"`
}

MS365 holds the Microsoft 365 settings for a domain. Fields Graph cannot change are absent by design; see the ms365 design doc.

type MTASts

type MTASts struct {
	Mode   string `yaml:"mode"`
	MaxAge int    `yaml:"maxAge"`
	Deploy bool   `yaml:"deploy"`
}

type Mail

type Mail struct {
	Providers []string
	Settings  DomainSettings
	MS365     *MS365
}

Mail holds the provider selection and provider-level domain settings. provider accepts either a scalar name or a list of names.

func (*Mail) UnmarshalYAML

func (m *Mail) UnmarshalYAML(node *yaml.Node) error

UnmarshalYAML decodes the mail: mapping by hand rather than via node.Decode(&raw): that call starts a fresh decode that does not inherit the top-level decoder's KnownFields(true), so a typo'd key would load silently. Walking Content in pairs keeps strictness for mail.provider, mail.settings, and the two settings keys, which are the domain-level security settings.

type Mailbox

type Mailbox struct {
	Address                        string     `yaml:"address"`
	PasswordEnv                    string     `yaml:"passwordEnv"`
	EnablePasswordReset            *bool      `yaml:"enablePasswordReset"`
	EnableSearchIndexing           *bool      `yaml:"enableSearchIndexing"`
	RequireTwoFactorAuthentication *bool      `yaml:"requireTwoFactorAuthentication"`
	SendWelcomeEmail               *bool      `yaml:"sendWelcomeEmail"`
	Recovery                       []Recovery `yaml:"recovery"`
	// DisplayName and License are ms365 fields. Validation rejects them on a
	// domain using any other provider. License, when set, overrides
	// MS365.License's domain-level default for this mailbox only.
	DisplayName string `yaml:"displayName"`
	License     string `yaml:"license"`
}

func (Mailbox) LocalPart

func (m Mailbox) LocalPart() string

LocalPart returns the portion of the address before the @.

type PurelymailConfig

type PurelymailConfig struct {
	BaseURL string `yaml:"baseUrl"`
}

type Recovery

type Recovery struct {
	Type          string `yaml:"type"` // email | phone
	Target        string `yaml:"target"`
	Description   string `yaml:"description"`
	AllowMfaReset bool   `yaml:"allowMfaReset"`
}

Recovery is one password-reset method attached to a mailbox.

Jump to

Keyboard shortcuts

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