Skip to content

Releases: luongnv89/cmail

v0.4.0

Choose a tag to compare

@github-actions github-actions released this 13 Oct 14:14

What's Changed

  • feat(cli): add forward command to change an address destination (#31) by @luongnv89 in #32

Full Changelog: v0.3.0...v0.4.0

v0.3.0

Choose a tag to compare

@luongnv89 luongnv89 released this 11 Oct 05:53

v0.3.0 — 2026-10-11

  • Move the installer's default pinned runtime from the v0.1.0 release commit to
    the v0.2.0 release commit (21b3a08), so unflagged bash install.sh installs
    the 0.2.0 CLI. Docs, skill guidance and offline regressions now describe the
    new pin.
  • Rewrite the documentation site for the 0.2.0 CLI: a concise 8-step setup
    guide with a sticky progress stepper, an illustrative replay of a cmail setup
    session built from real CLI output, a token-permission mock, a nameserver swap
    diagram and per-step "Done when" checks. Add CLI docs, changelog and privacy
    pages. Checklist progress moves to the cmail:setup-progress:v2 key (older
    14-step progress is not carried over). The site no longer documents the old
    pinned source snapshot; the README keeps that history.
  • Setup guide: move "add your domain to Cloudflare" before cmail setup (now
    step 4, setup is step 5) and mark it as needed only when the domain is not on
    Cloudflare yet. The step now points to Cloudflare's own "Add a domain" flow
    and nameserver instructions. Saved checklist progress is keyed by step ID, so
    existing ticks still load (#26).
  • Setup guide: show a congratulations card asking for a GitHub star once all 8
    steps are checked. It hides again when a step is unchecked or progress is
    reset, and its state is restored on reload (#27).
  • Install with one command, without cloning:
    curl -fsSL https://raw.githubusercontent.com/luongnv89/cmail/main/install.sh | bash.
    The installer no longer fails when piped (it previously stopped with
    BASH_SOURCE[0]: unbound variable), runs nothing if the download is cut
    short, and says whether ~/.local/bin is already on PATH or prints the
    export PATH line to add. It still downloads the pinned v0.2.0 runtime;
    bash install.sh and bash install.sh --local from a checkout keep working.
    The README, setup guide and CLI docs now lead with the one-line command (#25).

Full Changelog: v0.2.0...v0.3.0

v0.2.0

Choose a tag to compare

@luongnv89 luongnv89 released this 10 Oct 20:54

cmail v0.2.0 makes receiving the default: cmail setup forwards mail for a domain at any registrar to any inbox you own, with no Google or GoDaddy account required, while Gmail "Send mail as" and GoDaddy automation become opt-in. It also adds the read-only cmail list command, a reworked CLI with full setup previews, cmail config commands, JSON output, shell completions and elapsed setup timing, an autonomous cmail-setup agent skill, a user-local installer, and a landing page with checkable setup guides.

Upgrading from v0.1.0

  • Installing 0.2.0. The installer's default still pins the v0.1.0 runtime, so a plain bash install.sh installs v0.1.0. To install 0.2.0, check out this release (git clone --branch v0.2.0 https://github.com/luongnv89/cmail.git && cd cmail) and run bash install.sh --local there.
  • GoDaddy automation is opt-in. cmail setup now defaults to REGISTRAR=manual: it works with a domain at any registrar and never runs gddy, changes nameservers or offers a purchase. Domains whose Cloudflare zone is already active need no change. To keep the v0.1.0 GoDaddy flow (domain picker, nameserver replacement, purchase), run cmail config set REGISTRAR godaddy once or use cmail setup --registrar godaddy.
  • Setup ends once receiving works. The Gmail "Send mail as" guide moved from cmail setup to the optional cmail send-as command; run it after setup only if you want to send from your custom address.
  • cmail no longer installs tools for you. Setup checks for curl and jq (plus gddy only with REGISTRAR=godaddy) and stops with installation instructions when one is missing. cmail doctor and cmail status are read-only and no longer create or repair the config file; cmail setup or cmail config init creates it.
  • Guided commands need an interactive terminal. cmail setup and cmail send-as stop before making changes when stdin is closed or piped, so automation must use a pseudo-terminal. A domain purchase can only be approved by typing the exact domain at an interactive terminal.
  • Stricter arguments and configuration. Unknown flags and extra arguments are errors. The config file must be a user-owned regular file (not a symlink) with mode 600 containing only literal KEY=value lines for known keys; shell commands, expansions, export prefixes, duplicate keys and unquoted spaces (including inline comments) are rejected. Files written by v0.1.0 setup load unchanged. Environment variables now take precedence over the config file.
  • DRY_RUN=1 previews the whole setup. Like cmail setup --dry-run, it makes no provider changes, purchases, configuration writes or installations and needs valid Cloudflare credentials; v0.1.0 previewed only the nameserver change.

Features

  • Receiving no longer requires Gmail or a Google account. cmail setup now forwards to any inbox you own and ends after the forwarding rules with a Receiving is set up summary (exit 0, no final Enter prompt). Gmail "Send mail as" moved to the optional cmail send-as command, which is not run by default. The DEST_EMAIL prompt, .env.example, destination-verification hints, README, site guides and the cmail-setup skill (2.1.0) now describe receiving as the default and sending as opt-in. The skill's pass 2 pipes only y, and it runs send-as only when the user asks to send. (Superseded in #18: guided setup now requires terminal stdin, and the skill no longer pipes answers to the 0.2.0 CLI.) The README, landing page and setup guides lead with "custom-domain email in a few simple steps" (review source, ./cmail setup, send a test), and the CLI help and setup banner state that sending is optional and only on request. The landing page adds a "Do I need Gmail or a Google account?" FAQ. (#16) @luongnv89
  • Make GoDaddy automation optional (#20). Behavior change: setup now defaults to REGISTRAR=manual and no longer requires gddy or GoDaddy authentication. It accepts an existing domain at any registrar. An already-active Cloudflare zone skips nameserver steps; a pending zone gets the exact assigned nameservers, DNS-record/DNSSEC migration warnings, and bounded activation polling. cmail never changes delegation in this mode. GoDaddy automation (domain picker, nameserver replacement, and the only path to a domain purchase) now requires REGISTRAR=godaddy or cmail setup --registrar godaddy. doctor checks gddy and GoDaddy authentication only in that mode, and setup --dry-run reports registrar and skips GoDaddy reads and blockers in manual mode. New REGISTRAR config key, --registrar option, completions, recovery guidance, and offline regressions. (#18) @luongnv89
  • Add read-only cmail list [--domain DOMAIN]: every address on a domain, sorted, with its forward destinations (marked verified, unverified or unregistered), drop/worker actions, disabled rules, and the catch-all rule. Text and --format json output, completions, and offline regressions. --domain is now accepted by setup and list only. (#21) @luongnv89
  • Add the 0.2.0 CLI: strict arguments, command-level help/version, text/JSON reports, read-only doctor/status, full setup previews, literal configuration with environment precedence, private atomic config commands, secret stdin input, bash/zsh/fish completions, and complete local-checkout installation. (#18) @luongnv89
  • Show actual elapsed setup time on success/failure and in preview JSON; include user input and provider verification waits. Bound provider requests/polling, require terminal stdin for guided commands, preserve provider confirmations, paginate rule inspection/reuse, and use GoDaddy's quote-token purchase flow with displayed prices, fees, and agreement titles/links before confirmation. Any charge requires the domain typed at an interactive terminal; piped input, flags, and environment variables can never approve a purchase. (#18) @luongnv89
  • Add a user-local one-command installer for the complete pinned runtime with a generated launcher, private external config, staged validation and offline installer regressions. Installation does not run setup/doctor or provider calls. (#7) @luongnv89
  • Add a portable cmail-setup agent skill with fail-closed verification gates, local-only credential guidance, consented staged provider setup and targeted failure/recheck instructions. Include a non-executing private config checker, offline tests and realistic evaluation cases; no live setup or skill publication. (#8) @luongnv89
  • cmail-setup skill 1.1.0 opens with read-only context discovery (OS, source checkout, installed launcher, config presence, tools, request cues) instead of asking about setup mode, OS/access or installation status. Undetectable facts, such as browser access, stay unknown until a gate needs them. Discovery never executes cmail, reads .env or changes anything; consent and secret rules are unchanged. (#13) @luongnv89
  • cmail-setup skill 2.0.0 runs setup autonomously. The agent installs cmail and missing tools, writes non-secret config with a new set_config.py helper, reads config through check_config.py --summary (non-secret values only), runs a read-only preflight and then executes cmail setup itself with stdin closed. Stops are classified from setup's Setup stopped at: line and repaired from a step-keyed troubleshooting table. The agent asks only for missing values, hands-on steps (token entry, browser approvals, Gmail), nameserver replacement, existing MX/DNSSEC records, purchases, sudo or repeated failure; approval input is piped only for the nameserver confirmation after a closed-stdin pass. (Superseded in #18: guided setup now requires terminal stdin, and the skill no longer pipes answers to the 0.2.0 CLI.) (#14) @luongnv89
  • Add a framework-free cmail landing page and ordered first-time setup guides, with enabled native checkboxes, boolean-only browser progress, reset and resilient storage/no-JS handling. Document actual installer/skill paths, Cloudflare scopes, GoDaddy authentication/environment behavior, DNS safeguards, Gmail restrictions/confirmation and independent inbound/outbound checks. Flag Google's announced January 2027 third-party Send as removal. Include offline checklist/docs tests and optional real-browser regressions; no hosting, provider writes or live delivery verification is claimed. (#9) @luongnv89

Bug Fixes

  • Fix plain-text cmail status failing with "could not format routing state" when a rule has no forward destinations (drop, worker, catch-all, or no action). Rules now show drop, worker NAME, no action, and catch-all; JSON output is unchanged. Adds an offline regression. (#23) @luongnv89
  • Fix the runtime mismatch in receive-only/optional-send quickstarts (#17). README, landing page and both setup guides now select the immutable reviewed development source snapshot cda65f0554a870ed8079e93741a331918118acec, check ./cmail help for send-as before setup, and consistently use source ./cmail and checkout .env. The unchanged installer still pins legacy v0.1.0, whose setup includes the Gmail guide and has no send-as. The mirrored setup skill accepts either current receiving summary + exit 0 or the trusted legacy post-receiving Gmail pause at gate 8; both require every requested rule enabled exactly once to the intended destination. Add offline prose-contract regressions; no new release, installer pin change or live verification is claimed. ([#16](https://github.com/luongnv89/cmail/p...
Read more

v0.1.0

Choose a tag to compare

@luongnv89 luongnv89 released this 07 Oct 08:31

cmail v0.1.0

The first release of cmail, a Bash CLI for custom-domain email using Cloudflare Email Routing to receive mail in Gmail and guided Gmail “Send mail as” configuration for outbound mail. No additional hosted mailbox subscription is needed; domain registration still costs money.

Included in this release

  • ./cmail setup — guided dependency installation, GoDaddy authentication and domain selection, Cloudflare zone and Email Routing configuration, destination verification, forwarding rules, and manual Gmail send-as instructions.
  • ./cmail status — report zone, routing, destination verification, and forwarding-rule state.
  • ./cmail doctor — check dependencies and authentication. It may install missing dependencies; both status and doctor can create or secure local configuration.
  • Safer re-runs and recovery — skip equivalent nameservers, enabled routing, and existing destinations; reject conflicting rules; use correct account-scoped APIs; validate provider responses and configuration; provide step-specific recovery guidance (PR #1, closing issue #2).
  • Documentation and tests — token permissions, DNS migration, account selection, recovery guidance, and six offline regression suites with mocked provider calls.

Getting started

Requires Bash on Linux or macOS and GoDaddy, Cloudflare, and Gmail accounts. Setup can install missing dependencies.

git clone --branch v0.1.0 --depth 1 https://github.com/luongnv89/cmail
cd cmail
./cmail setup

Before running setup

  • Nameserver replacement can disrupt existing websites and mail. Migrate DNS records first; interrupted setup does not automatically roll back delegation.
  • DRY_RUN=1 previews only the nameserver change, not the entire setup. Other steps may still change local or provider state.
  • Keep .env, tokens, PATs, and Gmail App Passwords private.
  • Cloudflare provides forwarding, not a mailbox. Gmail send-as remains manual; verify inbound and outbound delivery separately. Gmail SMTP does not DKIM-sign outbound mail with your custom domain.

Thanks to @luongnv89 for the initial implementation and fixes.

Changelog · First-release history