Repository navigation
Releases: luongnv89/cmail
Release list
v0.4.0
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
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 unflaggedbash install.shinstalls
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 acmail 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 thecmail:setup-progress:v2key (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/binis already on PATH or prints the
export PATHline to add. It still downloads the pinned v0.2.0 runtime;
bash install.shandbash install.sh --localfrom 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
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.shinstalls 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 runbash install.sh --localthere. - GoDaddy automation is opt-in.
cmail setupnow defaults toREGISTRAR=manual: it works with a domain at any registrar and never runsgddy, 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), runcmail config set REGISTRAR godaddyonce or usecmail setup --registrar godaddy. - Setup ends once receiving works. The Gmail "Send mail as" guide moved from
cmail setupto the optionalcmail send-ascommand; run it after setup only if you want to send from your custom address. - cmail no longer installs tools for you. Setup checks for
curlandjq(plusgddyonly withREGISTRAR=godaddy) and stops with installation instructions when one is missing.cmail doctorandcmail statusare read-only and no longer create or repair the config file;cmail setuporcmail config initcreates it. - Guided commands need an interactive terminal.
cmail setupandcmail send-asstop 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=valuelines for known keys; shell commands, expansions,exportprefixes, 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=1previews the whole setup. Likecmail 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 setupnow forwards to any inbox you own and ends after the forwarding rules with aReceiving is set upsummary (exit 0, no final Enter prompt). Gmail "Send mail as" moved to the optionalcmail send-ascommand, 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 onlyy, and it runssend-asonly 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=manualand no longer requiresgddyor 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 requiresREGISTRAR=godaddyorcmail setup --registrar godaddy.doctorchecks gddy and GoDaddy authentication only in that mode, andsetup --dry-runreportsregistrarand skips GoDaddy reads and blockers in manual mode. NewREGISTRARconfig key,--registraroption, 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 jsonoutput, completions, and offline regressions.--domainis now accepted bysetupandlistonly. (#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
.envor 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.pyhelper, reads config throughcheck_config.py --summary(non-secret values only), runs a read-only preflight and then executescmail setupitself with stdin closed. Stops are classified from setup'sSetup 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 statusfailing with "could not format routing state" when a rule has no forward destinations (drop, worker, catch-all, or no action). Rules now showdrop,worker NAME,no action, andcatch-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 helpforsend-asbefore setup, and consistently use source./cmailand checkout.env. The unchanged installer still pins legacy v0.1.0, whose setup includes the Gmail guide and has nosend-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...
v0.1.0
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; bothstatusanddoctorcan 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 setupBefore running setup
- Nameserver replacement can disrupt existing websites and mail. Migrate DNS records first; interrupted setup does not automatically roll back delegation.
DRY_RUN=1previews 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.