Skip to main content
Every setting resolves from four places, in this order:
mailkube config list prints the effective value of every setting together with which of the four supplied it, which is how you answer “why is it using that base URL” without guessing:
An environment variable set to the empty string counts as unset.

Settings

smtp_tls accepts starttls, which is the only value: the connection is always encrypted. The trailing slash on base_url is load-bearing. Paths resolve by RFC 3986 reference resolution, where the last segment of the base is replaced rather than appended to, so a base ending /mta/v1 would resolve emails to /mta/emails and return a 404 with nothing to explain it. The CLI appends the slash for you if you set a value without one.
api_key is a secret and is never printed in full, by config get or anything else.
smtp_password cannot be set as an argument. An argument is visible in your shell history and in the process list, so the command refuses it. Use mailkube auth login --smtp, or the MAILKUBE_SMTP_PASSWORD environment variable.

Environment variables

--timeout has no environment variable, by design: a timeout is a property of the call you are making rather than of the machine you are on. MAILKUBE_WEBHOOK_SECRET is deliberately never stored in the config file. A signing secret belongs to an endpoint, not to a profile.

Profiles

A profile holds an API key, a base URL, and one SMTP credential. The active one comes from --profile, then MAILKUBE_PROFILE, then active_profile in the file, defaulting to default.
Deleting a profile deletes the credentials in it, and asks first unless you pass -y. One SMTP credential per profile is a hard limit, because a credential is bound to one sending domain. More than one sending domain means more than one profile:

The config file

TOML, in your platform’s own configuration directory: mailkube config path prints the real one. --config and MAILKUBE_CONFIG point somewhere else entirely.
The file is created readable only by you, mode 0600 inside a 0700 directory, and every write is atomic and serialized under a lock. It is a plain file rather than an entry in the OS keychain, which is a deliberate trade: it works the same on a server, in a container and on a laptop.
A file that cannot be parsed is never rewritten or repaired. It may hold the only copy of a credential, so the CLI reports the problem and leaves the file exactly as it found it.

Reading values from files

Any flag that could take either literal content or a filename follows one rule: It applies to --html, --text, --json, --vars and --body, with at most one @- per invocation. Flags whose value is only ever a path take it bare: --attach, --record, --config.