Ztrash - Disposable Email

ztrash.com is a disposable email inbox paid for with shielded ZEC

I built a disposable-email service where the only way to activate an inbox is a shielded Zcash payment. No accounts, no signup, no email-for-an-email nonsense. Plus no ads or trackers paying the bills, because you do ($1 for 24 hours, $4 for a week, and $12 for the month [30 days]).

How it works (screenshots below)

  1. Hit Generate. You get two credentials, mirrored from Zcash itself: a public address (xyz@ztrash.com receives, safe to share) and a secret viewing key (zvk1... reads, never share). Shown exactly once.
  2. Send exactly the amount for the chosen tier in (this is converted automatically for you based on a price oracle), shielded ZEC, to the unified address on screen.
  3. The payment shows up as “detected in mempool” within seconds, counts down confirmations live, and the inbox goes active in ~5 minutes.
  4. Mail arrives in real time. Verification codes get auto-extracted with a copy button. After 24 hours, the inbox and every message in it are permanently deleted.

Why I hope the community likes this:

  • Shielded-only payments. Transparent or deshielded sends don’t activate anything. Each inbox is a fresh diversified address (Sapling + Orchard receivers in a ZIP-316 unified address) of a single ZIP-32 account. Payment detection is server-side trial decryption of compact blocks with the account IVKs (e.g. the same way your wallet finds its own notes).
  • The server cannot spend. It holds only a unified full viewing key. The spending seed was generated offline and has never touched the box.
  • Viewing keys for email. The address/viewing-key split you know from Zcash, applied to an inbox: knowing the address lets the world send you mail; only the viewing key reads it. The server stores a hash of the key so it can’t recover, reset, or email it to you. Your private link keeps the key in the URL fragment, which never leaves your browser in a request.
  • No third-party mail pipeline. Inbound SMTP is built into the same Rust binary and is receive-only. There is no Mailgun/SES/relay seeing your mail, and nothing to abuse for sending spam.
  • Hosted in Iceland on a privacy-focused provider (1984.hosting), paid for like everything else here. DNS is plain grey-cloud records and traffic does not transit a CDN.
  • Nothing to subpoena. No accounts, no access logs, no archives. Expiry is a hard delete, and it runs on schedule whether anyone asks or not.

Real limitations

  • Receive-only. You can’t send from a ztrash address (that’s what keeps it spam-proof).
  • 24-hour lifetime, 1-hour payment window. Burn after reading is the product, not a bug.
  • Lose the viewing key, lose the inbox. That’s the point.

Stack, for the curious: Rust + Axum, compact-block scanner and mempool watcher over lightwalletd gRPC, Postgres, React. Self-hosting a Zebra/Zaino node is on the roadmap once volume justifies it.

Would love feedback from this community especially on the payment UX and anything you’d want hardened further or new ideas that you might have!

EDIT: a few things have shipped since I posted this.

Mail is encrypted at rest now. Each inbox has an X25519 keypair derived from its viewing key. The server only holds the public half, so it seals incoming mail and can’t open what it just wrote. Sender, subject, body, and attachment filenames are all ciphertext. Decryption happens in your browser. A seized disk or me running SELECT * FROM emails gets you sealed boxes, and backups are payment records only, no mail in them at all.

The viewing key never reaches the server. Stronger than what I wrote above. The zvk1... key is generated in your browser now. Only a hash and a derived public key get sent at creation, and reads authenticate with a derived token (zvt1...) instead of the key itself. I’m not storing a hash of something I received. I never receive it.

STARTTLS on inbound SMTP, plus MTA-STS. Senders that support it now deliver over an encrypted hop instead of cleartext. I don’t reject plaintext senders at the server, since that would bounce older mail servers and lose you mail. The MTA-STS policy at mta-sts.ztrash.com is the right way to get enforcement: senders that implement it (Gmail, Outlook) refuse to deliver in the clear, and senders that don’t are unaffected, so nothing gets dropped. It’s in testing mode while TLS reports come in, then it goes to enforce.

Sender authentication. SPF, DKIM, and DMARC get checked on arrival and the verdict is sealed with the message. A sender only shows as “verified” on a DMARC pass. An SPF pass authenticates the SMTP envelope, not the From: you actually see, and treating it as verification is how a forged sender ends up looking legitimate. Anything I couldn’t check reads as unverified, not as fine.

To be clear: this is encryption at rest, not end-to-end. Mail arrives over SMTP in the clear, so the server sees plaintext for the moment it takes to parse and seal it, and I’m the one serving you the web client. It covers disk seizure, stolen backups, a compromised database, or an operator reading the tables. It doesn’t cover a hostile operator.

14 Likes

Is it possible to make this end-to-end so even the server owners cant read the emails?

5 Likes

Love the suggestion and it’s (obviously) a great follow-up.

4 Likes

Well this stinks! (pun intended) Thanks for sharing :slight_smile: :smiling_face_with_three_hearts:

2 Likes

Would be great if this was made available on Tor!

2 Likes

Another great suggestion. I’ll think about this one a bit more.

2 Likes

I’ll be trying this soon.

1 Like

Since detection is local trial decryption over a hosted lightwalletd, does that provider learn which inboxes are active from your query pattern, or does moving to your own Zebra and Zaino node mainly help availability rather than privacy?

1 Like

No. The scanner is only calling 3 RPCs: get_latest_block get_block_range and get_mempool_tx.

The inbox per-inbox diversified addresses never leave the box.

And you’re correct in that Zebra or Zaino would give more availability and trust along with slightly more privacy by not revealing our IP.

1 Like

The name is a bit harsh, but aside that, this is a wonderful project :+1:

2 Likes

I like the project, I worked on something similar a PoC of sort, as I suggestion offering end to end encryption for emails content would be great, and maybe going for a decentralized store of emails(it’s more complex but worth exploring, e.g using IPFS to store encrypted emails, where only the receipients and sender can decrypt) for the encryption scheme anything might work from RSA to shared AES(protected with RSA), those are simple exploring forward secrecy would be great too
they may be better schemes to use from, those I just listed are the ones I explored myself

It’s exciting seeing someone working on such project, didn’t put effort into my PoC but I’m glad someone though of it too

2 Likes

Alright, there are real limits on making this completely e2e, but here’s what I’ve shipped since launch that gets us closer.

The hard part first: with PGP the sender encrypts before anything leaves their machine. Here, the sender is some signup confirmation bot that’s never heard of you and isn’t encrypting anything, so mail hits my SMTP listener as plaintext no matter what I do.

What I did ship:

  • Your key is generated in your browser and never transmitted. The server gets a hash and a public key derived from it.
  • Mail is sealed to that public key as soon as it arrives, and only ciphertext is stored. Sender, subject, body, attachment names, all of it.
  • Decryption happens in your browser.
  • On the way in, STARTTLS, so senders that support it encrypt the hop instead of handing it to me in the clear. An MTA-STS policy is published too, (note: currently in testing mode while reports come in, then I will switch to enforce it).

So if my disks get seized, my backups get stolen, or I want to snoop, what’s there is sealed boxes, and the key isn’t on the machine.

The two gaps I can’t close:

  1. That moment of plaintext at ingest.
  2. I’m the one serving you the JS, so theoretically, I could ship code that leaks your key.
2 Likes

On the encryption itself, that’s shipped. See the EDIT on the original post. Mail is sealed to a per-inbox X25519 key derived in your browser, and only ciphertext reaches the database. The catch is in my reply to @dismad above: inbound mail can’t be truly end to end, because the sender is a signup bot that isn’t encrypting to you, so there’s always a moment of plaintext at ingest. Encrypted at rest is more accurate.

I’m using libsodium sealed boxes which is more or less AES under RSA with modern primitives.

Re: IPFS, the main sales pitch here is the deletion aspect, and because it has a content identifier, Someone watching the DHT could log “ztrash’s node just published a 4KB blob at 14:32” over and over and build a traffic pattern of when mail arrives and how much. Right now that’s invisible, since it’s one Postgres box and nothing gets announced anywhere.

If you ever dust off that PoC I’d be curious what you did differently.

1 Like

Two new updates just landed:

  1. You can now pick how long an inbox lives instead of always getting 24 hours. Prices are pegged in USD. A background task polls ZEC/USD from Kraken, Coinbase, and CoinGecko:

  1. Inboxes are able to be destroyed on demand instead of the TTL for the tier for which it was purchased:

This is a really interesting use case for shielded Zcash

One suggestion could be letting users choose different inbox lifetimes like 24 hours 3 days or 7 days with different pricing

That would make the service more flexible while keeping privacy at the center

Nice work

1 Like

Oh, I understand now, true with IPFS some metadata can lead up to pattern, but I think they might be ways to reduce them even partially, like for example, adding random delays before publishing to IPFS, that’s just a thought of mine, also regarding the variable size of blob, setting all blobs to a max fixed size would help a lot(though it’ll cost storage, when splitting blobs that can’t fit into the fixed size).

For my PoC I’ve essentially opted for end to end encryption although I didn’t take much consideration regarding patterns with the use of IPFS. A good thing is the encryption at rest with it mails can only be read by intended recipient.

The plaintext on reception doesn’t seem like it can’t be solve,atleast not easily , unless the sender encrypts it.
Although my PoC was mostly centered around end to end decentralized mailing, not everything I did could be applied there, for instance, I required users to encrypt the emails themselves(with a client to handle it offline/locally, or they could have done it manually, with custom codes).
My PoC make end to end encryption possible but, at the cost of user experience, while ztrash actually make user experience smooth and simpler.
Ultimately it’ll be up to the user to ensure that nothing links back to them, the service can help, but if users fail that, the app can’t do anything about that(Just talking about like sharing the generate address on forums or socials medias)

3 Likes

This pattern is common in many areas! Neat insight :+1:

1 Like

Thanks for the suggestion :slight_smile: I actually added this exact request last night.

1 Like

Two additional features just dropped:

Aliases: To track specific services (e.g. Netflix)

Extensions: Increase the length of your current inbox by topping off

If every inbox calls the same three RPCs regardless of which one is active, does running thousands of inboxes on one node ever show up as a distinctive request volume to whoever is watching, or does that pattern stay invisible either way?