Create FastMail Masked Email Addresses with maskedemail-cli

I’m a happy FastMail user.

If you want to be a happy, too, use my referral code for 10% off of your first year (and I’ll get a discount, too!) →

I never used their Masked Email feature, though, because it’s so cumbersome to create these addresses from the web UI. I all but forgot about this feature until today, when I looked for something else in my settings.

A quick research then produced a CLI application to manage Masked Emails:

Here’s how to set this up to make creating generated email addresses as easy as mm create!

Create a FastMail API Token

First, create an API token for the CLI app:

Heads up: the FastMail settings have changed recently and API Tokens aren’t where the docs say they are. Go to Settings > Privacy & Security and pick the Integrations tab. API tokens are at the bottom.

Update 2023-04-18: FastMail support reacted fast and updated their docs to better reflect the new location.

I called my token “dvcrn/maskedemail-cli”. Grant it read-write access to “Masked Email”. (Read-write is the default.)

Now install the CLI tool.

Install maskedmail-cli

It requires Go:

$ brew install golang  # if you need Go
$ go install

Go, by, default installs these binaries to ~/go/bin. I needed to add this to my path in my ~/.zshrc:

export PATH=$PATH:$HOME/go/bin

You can check that maskedemail-cli works by experimenting with examples from its README. I’m going ahead with the setup instead.

Store your FastMail API Token in Keychain

Add a password for maskedemail-cli to your Keychain like so:

$ security add-generic-password -a $USER -s "maskedemail-cli" -w "<<API TOKEN HERE>>"

Verify the password is readable:

$ security find-generic-password -ws "maskedemail-cli"

I asked for ideas on Mastodon and got the excellent advice not to pass the token (or any password for that matter) as a parameter, ever. Instead, favor the environment variables offered by maskedemail-cli.

$ maskedemail-cli
Usage of maskedemail-cli:
Global Flags:
  -accountid string
    	fastmail account id (or MASKEDEMAIL_ACCOUNTID env)
  -appname string
    	the appname to identify the creator (or MASKEDEMAIL_APPNAME env) (default: maskedemail-cli)
  -token string
    	the token to authenticate with (or MASKEDEMAIL_TOKEN env)

So we’ll be using MASKEDEMAIL_TOKEN.

Access the Keychain to populate the environment variable just before calling the actual command:

$ MASKEDEMAIL_TOKEN=$(security find-generic-password -ws "maskedmail-cli") maskedemail-cli session [deadbeef] (primary: true, enabled: true)

If everything worked, this should show details about your account session.

For brevity, you could reach for an alias:

# ⚠️ Don't do this!
$ alias mm="MASKEDEMAIL_TOKEN=$(security find-generic-password -ws "maskedmail-cli") maskedemail-cli"
$ mm list

But the alias evaluates the expression first, then stores the resulting string, including the plain text token. which mm would then print the token for everyone! Not good.

Use a function instead and forward parameters via $@:

mm() {
    MASKEDEMAIL_TOKEN=$(security find-generic-password -ws "maskedemail-cli")\
        maskedemail-cli "$@"

Update 2023-04-21: Added missing quotes around $@, which makes passing whitespace in quoted parameters possible instead of flattening everything. Thanks!

With that, you can use the shorthand mm session or mm list just like you could with an alias, but the function will evaluate the sub-expression every time – like it should!

Getting a Masked Email is as simple as: mm create

To put the email onto your clipboard on macOS:

$ mm create | pbcopy

Nice! That’s already great for automation.

For fine-grained control, the create command also accepts

  • -domain "<domain>", e.g. “”
  • a human-readabable -desc "<description>"

To have an overview in the onslaught of newly generated email addresses, supplying these parameters is likely a good idea!

Now I’ll experiment with creating some Keyboard Maestro macros or Siri Shortcuts to make Masked Email creation simpler.

Join FastMail using my referral code for 10% off of your first year →