惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 【当耐特】
Stack Overflow Blog
Stack Overflow Blog
V
Visual Studio Blog
小众软件
小众软件
The Cloudflare Blog
T
Tailwind CSS Blog
Apple Machine Learning Research
Apple Machine Learning Research
爱范儿
爱范儿
美团技术团队
WordPress大学
WordPress大学
罗磊的独立博客
Microsoft Azure Blog
Microsoft Azure Blog
A
About on SuperTechFans
Last Week in AI
Last Week in AI
月光博客
月光博客
博客园 - Franky
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
G
Google Developers Blog
GbyAI
GbyAI
B
Blog
大猫的无限游戏
大猫的无限游戏
博客园 - 聂微东
Hugging Face - Blog
Hugging Face - Blog
博客园 - 叶小钗

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Build a disposable email alias CLI in 50 lines of Bash
anon.li · 2026-04-26 · via DEV Community

I have a rule I keep breaking: never give a website my real email if I'm not sure I want a relationship with them. Five minutes later I'm on some forum, signup form open, and I'm typing me@gmail.com again because firing up a password manager, generating an alias, copying it, pasting it - it's just enough friction that I default to the lazy thing.

So this weekend I built alias - a single shell command that spits out a fresh forwarding address I can paste anywhere. Took about an hour. The whole thing is curl, jq, and one POST request.

I'm using anon.li as the backend because (a) it has a clean REST API, (b) it's open source, and (c) the free tier covers personal use. But the structure here works against any forwarding service that exposes an API - Addy, SimpleLogin, your own self-hosted thing.

The endpoint

The Alias API has a Bitwarden-compatible "just generate me one" endpoint. From the docs:

POST https://anon.li/api/v1/alias?generate=true
Authorization: Bearer ak_...

Enter fullscreen mode Exit fullscreen mode

You can pass an optional domain in the body if you've added a custom one. With no body, it returns a random alias on anon.li. The response is the canonical alias object - id, email, timestamps, the works.

That's literally the entire API surface for what I want. One call, one address.

Step 1: get a key

Sign up, go to Dashboard → API Keys, generate one. It'll look like ak_ followed by 32 hex characters. Copy it once, because anon.li only shows the SHA-256 hash on their side after that - if you lose it, you rotate.

I stash mine in ~/.config/anon/key:

mkdir -p ~/.config/anon
echo "ak_yourkeyhere" > ~/.config/anon/key
chmod 600 ~/.config/anon/key

Enter fullscreen mode Exit fullscreen mode

If you're on a multi-user machine or just paranoid, swap this for pass, 1Password CLI, gpg --decrypt, whatever. Don't put it in .bashrc in plaintext.

Step 2: the function

Drop this into ~/.bashrc (or ~/.zshrc):

alias() {
  local key
  key=$(cat ~/.config/anon/key 2>/dev/null) || {
    echo "no api key at ~/.config/anon/key" >&2
    return 1
  }

  local domain="${1:-anon.li}"
  local response
  response=$(curl -sS -X POST \
    "https://anon.li/api/v1/alias?generate=true" \
    -H "Authorization: Bearer $key" \
    -H "Content-Type: application/json" \
    -d "{\"domain\":\"$domain\"}")

  local email
  email=$(echo "$response" | jq -r '.data.email // empty')

  if [[ -z "$email" ]]; then
    echo "alias creation failed:" >&2
    echo "$response" >&2
    return 1
  fi

  echo -n "$email" | (command -v pbcopy >/dev/null && pbcopy \
                  || command -v wl-copy >/dev/null && wl-copy \
                  || command -v xclip >/dev/null && xclip -selection clipboard)
  echo "$email (copied)"
}

Enter fullscreen mode Exit fullscreen mode

Reload your shell. Now:

$ alias
x7k9m2@anon.li (copied)

Enter fullscreen mode Exit fullscreen mode

That's it. Forty-something lines of Bash, one network call, address on my clipboard. I haven't typed gmail.com into a signup form in six weeks.

Heads up: alias is a Bash builtin (the thing you use for alias ll='ls -la'). Defining a function with the same name shadows it inside your own shell, which is fine for personal use, but if you script anything that depends on alias the builtin, name yours aka or alli or whatever. I personally don't care.

Why not just use the dashboard?

I do, for ones I want to label and track. But for a throwaway - "I just want to read this gated article" - I don't need to think about what to call it. I want it on my clipboard before I've finished alt-tabbing back to the browser. The CLI wins on that exact use case.

The dashboard is also where I go later to disable the alias when the site inevitably starts spamming me. Toggling active: false is one PATCH request, but I rarely bother scripting that part - I'm already in the dashboard reading the spam.

Bonus: domain switcher

If you've added a custom domain (say, mail.example.dev), you can pass it as an argument:

$ alias mail.example.dev
random-suffix@mail.example.dev (copied)

Enter fullscreen mode Exit fullscreen mode

I use this for my "real but disposable" identity - the one I give to recruiters and conference signups. Random-looking but on a domain I own, so it doesn't trip the "is this a burner?" filters that some sites run against known alias domains.

Bonus 2: skip the CLI, use Bitwarden

If you live in Bitwarden anyway, anon.li implements the Addy.io-compatible flow. In Settings → Options → Username Generator, pick Forwarded Email Alias → addy.io, paste your API key, and set the URL to https://anon.li/api/v1. Now the username field on every "create new login" sheet has a generate button that talks to the same endpoint. That's the fully no-friction version.

The CLI still wins for terminal flows - quick test signups, registering API sandboxes, anywhere I'm not in the password manager UI.

What's actually happening behind the curtain

The Alias backend isn't a hosted mailbox. There's no inbox. anon.li's mail server takes the inbound message, optionally encrypts the forwarded copy with your recipient's PGP key, signs it with DKIM, rewrites the envelope sender (SRS) so SPF still aligns, and ships it to your real address. The only state stored per alias is aggregate counters: received, blocked, last-seen-at.

That trust model is what makes me comfortable using disposable aliases for anything moderately sensitive - receipts, account confirmations, the dentist. Even if anon.li got fully owned tomorrow, there's no historical archive of my mail to leak. Just the routing config.

It's not a replacement for E2EE messaging. SMTP is what it is. But it raises the floor by a meaningful amount, and the API makes it easy enough that I actually use it instead of giving up and pasting my real address.

The whole script

For copy-paste convenience:

# ~/.bashrc
alias() {
  local key
  key=$(cat ~/.config/anon/key 2>/dev/null) || {
    echo "no api key at ~/.config/anon/key" >&2
    return 1
  }
  local domain="${1:-anon.li}"
  local response
  response=$(curl -sS -X POST \
    "https://anon.li/api/v1/alias?generate=true" \
    -H "Authorization: Bearer $key" \
    -H "Content-Type: application/json" \
    -d "{\"domain\":\"$domain\"}")
  local email
  email=$(echo "$response" | jq -r '.data.email // empty')
  if [[ -z "$email" ]]; then
    echo "alias creation failed:" >&2
    echo "$response" >&2
    return 1
  fi
  echo -n "$email" | (command -v pbcopy >/dev/null && pbcopy \
                  || command -v wl-copy >/dev/null && wl-copy \
                  || command -v xclip >/dev/null && xclip -selection clipboard)
  echo "$email (copied)"
}

Enter fullscreen mode Exit fullscreen mode

Friction is the enemy of good security habits. The smaller you can make the gap between "I want to do the right thing" and "the right thing is done," the more often you'll do it. A single shell function won me back the habit. Try it.