cf_mail

package module
v0.0.2 Latest Latest
Warning

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

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

README

caerus-framework-mail

CI codecov License

Caerus Framework Mail Component. One chassis for transactional email: apps call Send(ctx, Mail) and never import a provider SDK. The active backend is a config setting (provider), not a second component type.

Supported providers:

provider What it is What it is not
resend Resend transactional API
ses Amazon SES v2 SendEmail SNS, SESv1, campaign tools
unisender_go Unisender Go email/send Unisender.com campaign API (provider: unisender is rejected)

This module replaces caerus-framework-resend for new products. The old resend repo stays tagged for existing binaries until they bump.

flowchart TD
  A[App Send Mail] --> B[CFMail]
  B --> C{provider}
  C -->|resend| D[resend-go]
  C -->|ses| E[AWS SES v2]
  C -->|unisender_go| F[Unisender Go HTTP email/send]

Wiring

Two wiring shapes are supported. Prefer the app-owned shape (demoapp golden path): main declares only the chassis (mail alongside postgres / valkey) and the app class; product machinery that sends email lives under the app and resolves mail as a peer at Init. Use the simple main-level shape for one-off binaries.

App-owned consumer (golden — demoapp pattern)

main declares mail as chassis and runs the app class; it never touches mail itself:

fw := cf.New(&cf.FrameworkOptions{
	Logs: &cf.LogsSettings{Format: "json", Level: "info", ConfigSource: "logs"},
	Observability: &cf.ObservabilitySettings{Bind: ":9090", ConfigSource: "observability"},
	Components: []cf.CaerusComponent{
		cf_postgres.New(cf_postgres.WithConfigSource("postgresql", "config/postgresql.json")),
		cf_mail.New(cf_mail.WithConfigSource("mail", "config/mail.json")),
		app.New(app.Options{}),
	},
})
if err := fw.RunWithSignals(context.Background()); err != nil {
	log.Fatal(err)
}

The app resolves the mail component pointer once at Init (never a client snapshot), declares it in GetDependencies, and calls Send per use:

type App struct {
	email *cf_mail.CFMail
}

func (a *App) GetDependencies() []string {
	return []string{cf_mail.ComponentName} // + logs, chassis peers
}

func (a *App) Init(ctx context.Context, fw *cf.CaerusFramework) error {
	email, ok := cf.Get[*cf_mail.CFMail](fw)
	if !ok {
		return errors.New("app: mail component missing")
	}
	a.email = email
	return nil
}
Simple main-level wiring
fw := cf.New()
logs := cf_logs.New(cf_logs.WithWriter(os.Stdout))
mailer := cf_mail.New(cf_mail.WithConfigSource("mail", "config/mail.json"))
fw.AddComponent(logs)
fw.AddComponent(mailer) // GetDependencies() -> [logs configuration]

In both shapes the component is cf.ConfigSourceRegistrar-self-sufficient: WithConfigSource registers Source[MailConfig]. main never touches os.Getenv / ParseFlags. The --mail path flag comes from the source name.

Sending

Send takes a Caerus Mail value (SES-simple: From, To, Subject, HTML/Text, ReplyTo, Tags, optional IdempotencyKey). One extra attempt runs on HTTP 429 or 5xx (honor Retry-After, wait capped at 1s, stop if ctx is done). 422 and network errors are not retried.

From: when the component uses WithConfigSource, a resolvable soft default From is required on the source (startup and reload validation): top-level from_address, or Resend default_profile / profiles (see below). Soft default: empty Mail.From uses it; non-empty Mail.From overrides that send only. Without a config source, WithFromAddress or Mail.From per send still apply. If both defaults are empty, or the resolved address or any To does not parse as an email (net/mail.ParseAddress), Send fails. At least one of HTML or Text is required.

IdempotencyKey is sent to Resend and Unisender Go. SES v2 SendEmail has no matching field — it is ignored there.

Attachments, Cc/Bcc, and scheduled send stay on the provider escape hatches (ResendClient(), SESClient()). Those return nil when the active provider is a different backend. Unisender Go has no SDK accessor; extra fields stay off Send on purpose (transactional body only).

a.email, _ = cf.Get[*cf_mail.CFMail](fw)

id, err := a.email.Send(ctx, cf_mail.Mail{
	To:      []string{"user@example.com"},
	Subject: "Welcome",
	HTML:    "<p>Hi!</p>",
})
if err != nil {
	if cf_mail.HTTPStatus(err) == 429 {
		// rate limited
	}
	return err
}

// Resend multi-domain: pick a named profile (api_key + from).
id, err = a.email.SendWithProfile(ctx, "kronos", cf_mail.Mail{
	To:      []string{"user@example.com"},
	Subject: "Welcome",
	HTML:    "<p>Hi!</p>",
})

Peers resolve the component once at Init (declare cf_mail.ComponentName in GetDependencies) and call Send / SendWithProfile per use — never snapshot a provider client, since config reload swaps it.

Configuration

Shared settings sit at the top of the file. Each provider has a nested object. Only the nested blob for the active provider is required.

The configuration env overlay does not walk nested structs, so local go run uses flat MAIL_* aliases (same idea as valkey-state RATE_LIMIT_*). In Kubernetes the nested JSON/YAML file is canonical.

{
  "provider": "resend",
  "from_address": "noreply@example.com",
  "timeout_sec": 10,
  "resend": {
    "api_key": "re_…",
    "base_url": "",
    "default_profile": "",
    "profiles": {}
  },
  "ses": {
    "region": "eu-central-1",
    "access_key_id": "",
    "secret_access_key": "",
    "endpoint": ""
  },
  "unisender_go": {
    "api_key": "",
    "base_url": "https://goapi.unisender.ru/en/transactional/api/v1",
    "skip_unsubscribe": true
  }
}

Default EnvPrefix is MAIL_ (from the source name mail).

Setting File Env (prefix MAIL_)
Provider provider MAIL_PROVIDER
Soft-default From from_address MAIL_FROM_ADDRESS
HTTP timeout seconds timeout_sec MAIL_TIMEOUT_SEC
Resend API key resend.api_key MAIL_RESEND_API_KEY
Resend base URL resend.base_url MAIL_RESEND_BASE_URL
Resend default profile resend.default_profile — (file only)
Resend named profiles resend.profiles.<name>.* — (file only)
SES region ses.region MAIL_SES_REGION
SES access key ses.access_key_id MAIL_SES_ACCESS_KEY_ID
SES secret ses.secret_access_key MAIL_SES_SECRET_ACCESS_KEY
SES endpoint (LocalStack) ses.endpoint MAIL_SES_ENDPOINT
Unisender Go API key unisender_go.api_key MAIL_UNISENDER_GO_API_KEY
Unisender Go base URL unisender_go.base_url MAIL_UNISENDER_GO_BASE_URL
Skip unsubscribe block unisender_go.skip_unsubscribe MAIL_UNISENDER_GO_SKIP_UNSUBSCRIBE

Wrong vs right:

Wrong: provider "unisender"  → campaign Unisender.com API (not implemented)
Right: provider "unisender_go" → transactional email/send on goapi.unisender.ru
Resend named profiles (multi-domain / multi-key)

Resend API keys are often bound to one verified domain. One Auth process that sends as several apps therefore needs several keys. Put them under resend.profiles (Path A — one mail component, not several WithName instances).

{
  "provider": "resend",
  "resend": {
    "default_profile": "kronos",
    "profiles": {
      "kronos": {
        "api_key": "re_kronos_…",
        "from_address": "noreply@kronos.example"
      },
      "stock-market": {
        "api_key": "re_sm_…",
        "from_address": "hello@stock.example"
      }
    }
  }
}
Call Which key / From
Send default_profile when set; else legacy resend.api_key + top-level from_address
SendWithProfile(name, …) resend.profiles[name]

Rules juniors trip on:

  • Each profile needs both api_key and from_address.
  • default_profile must name an entry in profiles (or be omitted).
  • Profiles-only (no top-level from_address, no default_profile) is valid: SendWithProfile works; plain Send fails until you set a default.
  • SES and Unisender Go do not use profiles — one credential can send from many verified domains; set Mail.From per send instead.
  • Flat MAIL_RESEND_API_KEY only fills the legacy single key, not profiles. In Kubernetes, put profile keys in the mounted mail.json (ESO template).

You can still keep a legacy resend.api_key + top-level from_address and add profiles; Send stays on the legacy pair unless default_profile is set.

SES credentials (two exclusive paths)

Path A — file keys (local / explicit): set both access_key_id and secret_access_key in the nested ses object (or the matching MAIL_SES_* env aliases). One without the other is an Init error.

Path B — default AWS chain (recommended in cluster): leave both keys empty. The AWS SDK uses IRSA / instance role / shared config. region is still required.

Unisender Go

Default base URL is https://goapi.unisender.ru/en/transactional/api/v1. Override base_url for the go1/go2 datacenter your account is on. Auth is the X-API-KEY header. skip_unsubscribe defaults on (value 1) so transactional mail does not get a campaign unsubscribe footer; set skip_unsubscribe: false only if Unisender support enabled that for you.

Send returns the Unisender Go job_id. If every To address is in failed_emails, Send fails.

Files are canonical in Kubernetes, including API keys — mount a Secret/ConfigMap and let fsnotify + OnConfigReload rotate the sender without a restart. Nested api_key / secret_access_key are tagged secret:"redact". On reload failure the previous sender stays live (last-good).

Health reports initialized/uninitialized (no provider liveness probe; send failures surface per call). Metrics emits the following while initialized, nil before Init/after Shutdown:

Metric Type Labels
mail_info gauge 1 component, provider, from
mail_config_reloads_total counter component
mail_emails_sent_total counter component, from
mail_send_retries_total counter component, from
mail_send_duration_seconds_sum counter component, from
mail_send_duration_seconds_count counter component, from
mail_emails_failed_total counter component, from, error_code

The from label on traffic counters is the actual sender of each email. error_code is the HTTP status or network.

Options

Option Description
WithConfig(MailConfig) static snapshot; non-zero fields override option-set defaults
WithConfigSource(name, path, …) bind a configuration source for Init + OnConfigReload
WithProvider(name) resend, ses, or unisender_go
WithFromAddress(from) soft-default sender
WithTimeout(d) per-send HTTP timeout (default 10s)
WithHTTPClient(*http.Client) stub RoundTripper in tests; used by every provider
WithResendAPIKey / WithResendBaseURL Resend construct-time
WithResendProfiles / WithResendDefaultProfile Resend named profiles (tests / embedded)
WithSESRegion / WithSESCredentials / WithSESEndpoint SES construct-time
WithUnisenderGoAPIKey / WithUnisenderGoBaseURL Unisender Go construct-time
WithName(name) custom component name (default "mail")
WithLogger(*slog.Logger) explicit logger override

Tests

Unit tests cover config layering, the Init contract, all three providers (stub http.RoundTripper), reload last-good, and health/metrics — no external service.

License

Apache License 2.0 — see LICENSE.

Documentation

Index

Constants

View Source
const (
	// ProviderResend is the Resend transactional API (resend.com).
	ProviderResend = "resend"
	// ProviderSES is Amazon SES v2 SendEmail (transactional).
	ProviderSES = "ses"
	// ProviderUnisenderGo is Unisender Go transactional email/send
	// (goapi.unisender.ru). It is not the Unisender.com campaign API.
	ProviderUnisenderGo = "unisender_go"
)
View Source
const (
	// ComponentName is the framework component name for the mail component.
	ComponentName = "mail"

	// ComponentStage is the stage data-layer components initialize in.
	ComponentStage = cf.Stage("data")
)

Variables

This section is empty.

Functions

func HTTPStatus

func HTTPStatus(err error) int

HTTPStatus returns the provider HTTP status from err when err is (or wraps) a SendError. It returns 0 for nil, validation errors, network failures, and SDK errors that did not go through Send.

Types

type CFMail

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

CFMail is the caerus-framework-mail component. Apps hold this pointer and call Send per use. The active provider is a config setting, not a second component type.

func New

func New(opts ...Option) *CFMail

New creates a mail component. The provider client is built at Init, not here.

func (*CFMail) From

func (c *CFMail) From() string

From returns the configured soft-default sender. When Resend default_profile is active, that is the profile's from_address.

func (*CFMail) GetDependencies

func (c *CFMail) GetDependencies() []string

GetDependencies implements cf.Dependencies.

func (*CFMail) GetInitOrderStage

func (c *CFMail) GetInitOrderStage() cf.Stage

GetInitOrderStage implements cf.CaerusComponent.

func (*CFMail) Health

func (c *CFMail) Health(ctx context.Context) error

Health implements cf.HealthProvider. Providers expose no liveness endpoint; health reflects that a sender is initialized.

func (*CFMail) Init

func (c *CFMail) Init(ctx context.Context, fw *cf.CaerusFramework) error

Init implements cf.CaerusComponent.

func (*CFMail) Metrics

func (c *CFMail) Metrics() []cf_observability.Metric

Metrics implements cf_observability.MetricsProvider.

func (*CFMail) Name

func (c *CFMail) Name() string

Name implements cf.CaerusComponent.

func (*CFMail) OnConfigReload

func (c *CFMail) OnConfigReload(source string, cfg any)

OnConfigReload implements cf.ConfigReloader. On failure the previous sender is kept (last-good).

func (*CFMail) Provider

func (c *CFMail) Provider() string

Provider returns the normalized provider name after Init (empty before).

func (*CFMail) RegisterConfigSources

func (c *CFMail) RegisterConfigSources(conf any) error

RegisterConfigSources implements cf.ConfigSourceRegistrar.

func (*CFMail) ResendClient

func (c *CFMail) ResendClient() *resend.Client

ResendClient returns the live Resend SDK client for the default sender, or nil when the active provider is not resend (or before Init / after Shutdown). With named profiles this is the legacy api_key client, or the default_profile client when that setting is set — not a profile picked via SendWithProfile.

func (*CFMail) ResendProfiles added in v0.0.2

func (c *CFMail) ResendProfiles() []string

ResendProfiles returns the sorted names of configured Resend profiles (empty when the provider is not resend or no profiles are set).

func (*CFMail) SESClient

func (c *CFMail) SESClient() *sesv2.Client

SESClient returns the live SES v2 client, or nil when the active provider is not ses (or before Init / after Shutdown).

func (*CFMail) Send

func (c *CFMail) Send(ctx context.Context, m Mail) (string, error)

Send sends m through the configured provider and returns the provider message id (Resend id, SES MessageId, Unisender Go job_id).

From: from_address / WithFromAddress is a soft default when Mail.From is empty. When Resend default_profile is set, that profile's from_address is the soft default instead. If both are empty, or the resolved From or any To address does not parse (`net/mail.ParseAddress`), Send fails. HTML and Text may both be set; at least one must be non-empty.

For a named Resend API key / From pair, use SendWithProfile.

If the first HTTP status is 429 or 5xx, Send waits (Retry-After, capped at 1s) and tries once more while ctx is live. 4xx other than 429 and network errors are not retried.

func (*CFMail) SendWithProfile added in v0.0.2

func (c *CFMail) SendWithProfile(ctx context.Context, profile string, m Mail) (string, error)

SendWithProfile sends m with a named Resend profile (resend.profiles[name]). Soft-default From is that profile's from_address; Mail.From still overrides. SES and Unisender Go have no profiles — use Send and set Mail.From instead.

func (*CFMail) Shutdown

func (c *CFMail) Shutdown(ctx context.Context) error

Shutdown implements cf.CaerusComponent.

type Mail

type Mail struct {
	// From overrides from_address when non-empty. Empty (or whitespace)
	// uses the configured soft default. The resolved value must parse as
	// an RFC 5322 address (`net/mail.ParseAddress`).
	From    string
	To      []string
	Subject string
	HTML    string
	Text    string
	ReplyTo string
	// Tags are provider metadata (name → value). Empty names are skipped.
	// Resend and SES send name/value pairs. Unisender Go uses the names as
	// its string tags (max 4) and the pairs as global_metadata (max 10).
	Tags map[string]string
	// IdempotencyKey is forwarded when the provider supports it (Resend
	// Idempotency-Key header; Unisender Go idempotence_key). SES v2 SendEmail
	// has no matching field; it is ignored there.
	IdempotencyKey string
}

Mail is the Caerus send DTO (SES-simple shape). Apps pass this to Send without importing a provider SDK. Attachments, Cc/Bcc, headers, and scheduled send stay on the provider escape hatches (ResendClient / SESClient) for callers that opt into an SDK.

type MailConfig

type MailConfig struct {
	// Provider selects the sender: resend, ses, or unisender_go.
	Provider string `json:"provider" yaml:"provider" env:"PROVIDER"`
	// FromAddress is the soft-default sender. Send uses it when Mail.From is empty.
	FromAddress string `json:"from_address" yaml:"from_address" env:"FROM_ADDRESS"`
	// TimeoutSec bounds each provider HTTP call (default 10s).
	TimeoutSec float64 `json:"timeout_sec,omitempty" yaml:"timeout_sec,omitempty" env:"TIMEOUT_SEC"`

	Resend      ResendSettings      `json:"resend,omitempty" yaml:"resend,omitempty" env:"-"`
	SES         SESSettings         `json:"ses,omitempty" yaml:"ses,omitempty" env:"-"`
	UnisenderGo UnisenderGoSettings `json:"unisender_go,omitempty" yaml:"unisender_go,omitempty" env:"-"`

	// Flat env aliases (nested JSON/YAML still wins when both are set after
	// merge: env overlay fills these, applyConfig copies them into the nested
	// structs when the nested field is still empty).
	ResendAPIKey         string `json:"-" yaml:"-" env:"RESEND_API_KEY" secret:"redact"`
	ResendBaseURL        string `json:"-" yaml:"-" env:"RESEND_BASE_URL"`
	SESRegion            string `json:"-" yaml:"-" env:"SES_REGION"`
	SESAccessKeyID       string `json:"-" yaml:"-" env:"SES_ACCESS_KEY_ID"`
	SESSecretAccessKey   string `json:"-" yaml:"-" env:"SES_SECRET_ACCESS_KEY" secret:"redact"`
	SESEndpoint          string `json:"-" yaml:"-" env:"SES_ENDPOINT"`
	UnisenderGoAPIKey    string `json:"-" yaml:"-" env:"UNISENDER_GO_API_KEY" secret:"redact"`
	UnisenderGoBaseURL   string `json:"-" yaml:"-" env:"UNISENDER_GO_BASE_URL"`
	UnisenderGoSkipUnsub *bool  `json:"-" yaml:"-" env:"UNISENDER_GO_SKIP_UNSUBSCRIBE"`
}

MailConfig is the file/env-drivable configuration. Shared settings sit at the top; each provider has a nested object. The configuration overlay does not walk nested structs for env, so the flat MAIL_* aliases below exist for local/`go run` (same pattern as valkey-state RATE_LIMIT_*).

type Option

type Option func(*options)

Option configures the mail component at construction time.

func WithConfig

func WithConfig(cfg MailConfig) Option

WithConfig sets a static configuration snapshot. Non-zero fields of cfg override the values set by the convenience options. Prefer WithConfigSource when using caerus-framework-configuration with hot-reload.

func WithConfigSource

func WithConfigSource(name, path string, opts ...SourceOption) Option

WithConfigSource binds this component to a named configuration source and registers that source with the configuration component (via the framework's ConfigSourceRegistrar pass during argv absorption).

cf_mail.New(cf_mail.WithConfigSource("mail", "config/mail.json"))

A path of "" registers an env-only (fileless) source when the EnvPrefix is non-empty. The path CLI override stays --<source-name> (ParseFlags). Declares a dependency on "configuration".

func WithFromAddress

func WithFromAddress(from string) Option

WithFromAddress sets the soft-default sender. Send uses it when Mail.From is empty. A non-empty Mail.From overrides this call only.

func WithHTTPClient

func WithHTTPClient(hc *http.Client) Option

WithHTTPClient overrides the HTTP client used by every provider. Useful for tests (a stub RoundTripper). The component does not close a client it did not create.

func WithLogger

func WithLogger(logger *slog.Logger) Option

WithLogger overrides the logger used for component diagnostics. By default the component logs through the framework logs component.

func WithName

func WithName(name string) Option

WithName sets a custom component name, allowing multiple mail instances in the same process. The default name is "mail" (ComponentName).

func WithProvider

func WithProvider(provider string) Option

WithProvider selects the sender (resend, ses, unisender_go). Required unless the bound config file sets provider.

func WithResendAPIKey

func WithResendAPIKey(apiKey string) Option

WithResendAPIKey sets the Resend API key (tests, embedded use).

func WithResendBaseURL

func WithResendBaseURL(baseURL string) Option

WithResendBaseURL overrides the Resend API endpoint.

func WithResendDefaultProfile added in v0.0.2

func WithResendDefaultProfile(name string) Option

WithResendDefaultProfile names the profiles entry Send uses by default.

func WithResendProfiles added in v0.0.2

func WithResendProfiles(profiles map[string]ResendProfile) Option

WithResendProfiles sets named Resend senders (api_key + from per name). Prefer the config file's resend.profiles in production.

func WithSESCredentials

func WithSESCredentials(accessKeyID, secretAccessKey string) Option

WithSESCredentials sets static AWS keys. Leave unset to use the default credential chain (IRSA / shared config).

func WithSESEndpoint

func WithSESEndpoint(endpoint string) Option

WithSESEndpoint overrides the SES v2 endpoint (LocalStack / tests).

func WithSESRegion

func WithSESRegion(region string) Option

WithSESRegion sets the AWS region for SES v2.

func WithTimeout

func WithTimeout(d time.Duration) Option

WithTimeout sets the per-send HTTP timeout (default 10s).

func WithUnisenderGoAPIKey

func WithUnisenderGoAPIKey(apiKey string) Option

WithUnisenderGoAPIKey sets the Unisender Go API key.

func WithUnisenderGoBaseURL

func WithUnisenderGoBaseURL(baseURL string) Option

WithUnisenderGoBaseURL overrides the Unisender Go transactional base URL.

type ResendProfile added in v0.0.2

type ResendProfile struct {
	APIKey      string `json:"api_key" yaml:"api_key" secret:"redact"`
	FromAddress string `json:"from_address" yaml:"from_address"`
	// BaseURL overrides ResendSettings.BaseURL for this profile only.
	BaseURL string `json:"base_url,omitempty" yaml:"base_url,omitempty"`
}

ResendProfile is one named Resend API key + From pair.

type ResendSettings

type ResendSettings struct {
	APIKey  string `json:"api_key" yaml:"api_key" env:"-" secret:"redact"`
	BaseURL string `json:"base_url,omitempty" yaml:"base_url,omitempty" env:"-"`
	// DefaultProfile names the profiles entry Send uses when set. Empty
	// keeps Send on the legacy api_key + top-level from_address.
	DefaultProfile string `json:"default_profile,omitempty" yaml:"default_profile,omitempty" env:"-"`
	// Profiles are named Resend senders (one API key + From per name).
	Profiles map[string]ResendProfile `json:"profiles,omitempty" yaml:"profiles,omitempty" env:"-"`
}

ResendSettings is the nested Resend blob.

Two shapes are supported (they may be combined):

  1. Legacy single key — api_key + top-level from_address. Send uses that pair. Flat MAIL_RESEND_API_KEY still fills api_key.
  2. Named profiles — profiles map (each api_key + from_address). Use SendWithProfile to pick one. Optional default_profile makes Send use that profile when set.

Profiles exist because Resend API keys are often bound to one domain.

type SESSettings

type SESSettings struct {
	Region          string `json:"region" yaml:"region" env:"-"`
	AccessKeyID     string `json:"access_key_id,omitempty" yaml:"access_key_id,omitempty" env:"-"`
	SecretAccessKey string `json:"secret_access_key,omitempty" yaml:"secret_access_key,omitempty" env:"-" secret:"redact"`
	Endpoint        string `json:"endpoint,omitempty" yaml:"endpoint,omitempty" env:"-"`
}

SESSettings is the nested Amazon SES v2 blob.

Credentials: set both AccessKeyID and SecretAccessKey in the file (K8s Secret mount). Leave both empty to use the default AWS chain (IRSA in cluster, shared config on a laptop). Setting only one is an Init error.

type SendError

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

SendError is returned by Send when the provider HTTP call failed. HTTPStatus is filled from the component transport (the same source as mail_emails_failed_total).

Status 0 means a transport/network failure or an unknown status.

func (*SendError) Error

func (e *SendError) Error() string

func (*SendError) HTTPStatus

func (e *SendError) HTTPStatus() int

HTTPStatus is the provider API status for this send, or 0 if the request never got an HTTP response.

func (*SendError) Unwrap

func (e *SendError) Unwrap() error

Unwrap returns the SDK (or transport) error so errors.Is / errors.As keep working on the inner value.

type SourceOption

type SourceOption func(*sourceOptions)

SourceOption configures the self-registered configuration source created by WithConfigSource.

func WithSourceEnvPrefix

func WithSourceEnvPrefix(prefix string) SourceOption

WithSourceEnvPrefix sets the environment overlay prefix for the source (default: the uppercase source name with "-" replaced by "_", plus "_"). An empty prefix disables env overlay.

func WithSourceFormat

func WithSourceFormat(f cf_configuration.Format) SourceOption

WithSourceFormat forces the file format instead of inferring it from the path extension (".yaml"/".yml" → YAML; anything else JSON).

type UnisenderGoSettings

type UnisenderGoSettings struct {
	APIKey          string `json:"api_key" yaml:"api_key" env:"-" secret:"redact"`
	BaseURL         string `json:"base_url,omitempty" yaml:"base_url,omitempty" env:"-"`
	SkipUnsubscribe *bool  `json:"skip_unsubscribe,omitempty" yaml:"skip_unsubscribe,omitempty" env:"-"`
}

UnisenderGoSettings is the nested Unisender Go transactional blob. Default BaseURL is https://goapi.unisender.ru/en/transactional/api/v1 (override for go1/go2 datacenters). This is not api.unisender.com.

Jump to

Keyboard shortcuts

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