# Privacy Policy

*Last updated: July 13, 2026*

## For Users

Mail-to-Nostr stores **no email content, no plaintext public keys, no IP addresses, and no plaintext delivery metadata.** Everything is hashed, encrypted, or ephemeral.

### Summary

- **Email content** is never stored. It is parsed in RAM, forwarded as an encrypted Nostr message, then discarded.
- **IP addresses** are never logged. All log sinks are disabled.
- **Public keys** are stored only as memory-hard scrypt hashes — never in plaintext.
- **No cookies, no analytics, no tracking.** The website sets no tracking cookies and runs no analytics.
- **No user accounts.** Your Nostr keypair is your identity. There are no passwords to leak.
- **No data sale.** We do not sell, share, or transfer personal data to third parties.

### What We Collect

| Category | What | How long | Why |
|----------|------|----------|-----|
| Email content | Not stored — processed in RAM and discarded immediately | 0 seconds | Message delivery |
| Sender IP | Not stored — all access logs disabled | 0 seconds | — |
| Public key hash | scrypt hash (memory-hard, not reversible) | Until feature expiry (30 days) | Feature lookup |
| Feature config | Encrypted (NIP-44), decryptable only at processing time | Until expiry (30 days) | Feature activation |
| Payment metadata | Invoice, preimage — sanitized after 1h, deleted after 7 days | 7 days | Payment audit |
| Purchase nonce | Random token (no personal data) | Permanent | Replay protection |
| Rate limit counter | Salted hash, RAM only | Until process restart | Abuse prevention |

### Your Rights

- **Access:** Since we store no plaintext personal data, there is nothing to provide in a data subject access request. Your public key hash is not personal data under most definitions — it cannot be reversed to identify you.
- **Deletion:** Feature data is automatically deleted after 30 days. Payment records after 7 days. You can request early deletion by contacting postmaster@mail-to-nostr.com.
- **Opt-out:** The free tier requires no registration and stores no personal data. Simply stop using the service.
- **NIP-05:** Username-to-pubkey mapping is **off by default**. You must explicitly opt in via DM. See the technical section below for details.

### Children's Privacy

The Service is not directed at children under 13 (or the minimum age in your jurisdiction). We do not knowingly collect data from children. If you believe a child has used paid features, contact us for a refund and data deletion.

### Data Breach

In the event of a data breach, we will notify affected users via the Service's Nostr account and update this page. Note: because we store no plaintext personal data, the impact of any breach is limited to encrypted blobs and unreversible hashes.

### International Users

This Service is operated from outside the United States and is not subject to U.S. data protection regulations. The Service is not directed at EU residents for paid features. If you are in a jurisdiction with specific data protection requirements, please evaluate whether the Service meets your needs.

### Security Practices

- All sensitive data at rest is either **hashed** (scrypt, memory-hard) or **encrypted** (NIP-44)
- Three independent domain-separation salts prevent cross-attack vectors
- Greylist data is **RAM-only** — a process restart wipes all state
- Email processing is **stateless** — no content is ever written to disk
- See the technical documentation below for cryptographic details

### Changes to This Policy

We may update this Privacy Policy at any time. The "Last updated" date reflects the most recent revision. Significant changes will be announced via our Nostr account.

### Contact

Privacy questions: **postmaster@mail-to-nostr.com**

---

## For Developers & Technical Review

The remainder of this document provides detailed technical specifications for privacy-conscious users, security researchers, and developers reviewing the Service.

This page documents exactly what is stored, in what form, and for how long.


## What We Store

| Data | Form | Location | Retention |
|------|------|----------|-----------|
| Email content | — | **Not stored.** Parsed in RAM, forwarded as Nostr DM, discarded | 0 seconds |
| Sender IP | — | **Not stored.** Postfix logs to `/dev/null`, nginx access log disabled | 0 seconds |
| SMTP envelope (sender, recipient) | SHA-256 hash (salted) | Greylist process, RAM only | Until process restart (max 24h) |
| Customer pubkey | scrypt hash (N=16384, memory-hard) | Gateway database | Until feature expiry (30 days), then deleted |
| Feature configuration | NIP-44 encrypted blob | Gateway database | Until expiry (30 days), then deleted |
| Purchase nonce | Random token (plaintext) | Gateway database | Permanent (replay protection) |
| Commitment hash | SHA-256 | Gateway database | Permanent (no personal data) |
| Username → Pubkey mapping | scrypt(username) as key, target NIP-44 encrypted | Gateway database | Permanent |
| NIP-05 identifier | Username → pubkey mapping served via `/.well-known/nostr.json` (only if opt-in via DM) | Gateway database (same as username binding) | Permanent |
| Lightning payment hash | Sanitized after 1h, hard-deleted after 7 days | PP database | 7 days (retention for audit) |
| Lightning invoice | Sanitized after 1h (field cleared), row deleted after 7 days | PP database | 7 days |
| Lightning preimage | Sanitized after 1h, row deleted after 7 days | PP database | 7 days |
| Checkout request (pf, ef, epf, hp) | NIP-44 encrypted / hashed at rest; sensitive fields sanitized 1h after terminal status; row hard-deleted after 7 days | PP database | 7 days |
| Checkout metadata (status, amount, timestamps, nonce) | Non-personal — retained for 7 days for audit, then deleted | PP database | 7 days |
| Beta discount tracker | scrypt hash of pubkey | PP database | Until beta ends |
| Rate limit counter | Salted hash, RAM only | Gateway process memory | Until process restart |
| Feature cache | In-memory, 5min TTL | PP process memory | 5 minutes |


## Encryption & Hashing

**Two layers protect data at rest:**

1. **scrypt hashing** (N=16384, r=6, p=1) — memory-hard, ~57ms + 12MB RAM per attempt. Used for all pubkey lookups. Impossible to reverse to the original pubkey without brute-forcing 12MB of memory per guess.

2. **NIP-44 encryption** — Feature configurations are encrypted with a key derived from the customer's Nostr keypair. The Gateway can only decrypt at email processing time, when the plaintext pubkey is available in RAM. The decrypted feature config is never written to disk.

**Domain separation:** Three independent salts ensure that compromising one does not weaken the others:
- Pubkey hashing salt
- Username derivation salt
- Greylisting salt


## Greylisting

Mail-to-Nostr replaces Postgrey (which stores plaintext sender/recipient/IP triplets on disk) with a custom hash-based greylisting server.

- All envelope data (IP, sender, recipient) is **salted SHA-256 hashed** before storage
- Storage is **in-memory only** — nothing is written to disk
- Process restart wipes all greylist state


## Logging

| Component | Configuration |
|-----------|--------------|
| Postfix | `maillog_file = /dev/null` |
| nginx | `access_log off; error_log /dev/null;` |
| Payment Processor | `access_log = False` (uvicorn) |
| Application logs | WARNING/INFO level, sensitive fields truncated or omitted |


## Email Processing

Emails are parsed in RAM. Content is extracted and converted to a text format for Nostr DM delivery. Attachments are always discarded — never stored, never forwarded.

**Content extraction priority:**
1. `text/plain` — used directly when it contains real content
2. `text/html` → Markdown — used when text/plain is missing, or when it's a stub (e.g. "view in browser")
3. Otherwise — a "no content" notice is sent

**Privacy protections during HTML processing:**
- Tracking pixels (`<img>` tags, including 1×1 invisible images) are stripped
- Inline images, CSS (`<style>`), and scripts (`<script>`) are removed
- No external resources are fetched during conversion
- The converted Markdown is processed in RAM only — never written to disk

No email content (plain text, HTML, or converted Markdown) is persisted. Everything is discarded after the Nostr DM is sent.


## What We Don't Store

- Email bodies, subjects, or attachments
- HTML content or converted Markdown
- Plaintext public keys (only scrypt hashes)
- IP addresses (all log sinks disabled)
- Delivery metadata (no record of "email X sent to Y at time Z")
- SMTP envelope in plaintext (greylist stores salted hashes, RAM only)
- Cookies, tracking pixels, or analytics
- User accounts or passwords (stateless — your Nostr keypair is your identity)


## Username & NIP-05 Correlation

When you register an email username (e.g. `user@mail-to-nostr.com`), NIP-05 is **off by default**. Your username works for email delivery without any public pubkey mapping.

To enable NIP-05 (so Nostr clients show a ✅ checkmark for your address), you must explicitly opt in:

1. Send a NIP-04 encrypted DM to the gateway pubkey containing your username
2. The gateway verifies you are the registered owner and enables NIP-05

Once activated, `/.well-known/nostr.json?name=user` publicly resolves your username to your Nostr pubkey. This means:

- **Anyone can look up your pubkey from your username.** The NIP-05 endpoint is public. This is by design — it's how NIP-05 verification works.
- **Your username is not anonymous while NIP-05 is on.** If you share your email address, anyone can resolve it to your Nostr pubkey.
- **Burner and Shadow Pubkey features do not help here.** They protect the *delivery* path, not the *registration*. The NIP-05 mapping always points to the pubkey you registered with.
- **Ownership transfer disables NIP-05 automatically.** If the username is re-registered with a different pubkey, NIP-05 goes offline until the new owner sends a DM.

**If you need anonymity, do not activate NIP-05.** Email delivery works without it. Your username stays private — the gateway resolves it internally via scrypt hashing, never publishing the mapping.


## Automatic Cleanup

| Mechanism | What it does | Frequency |
|-----------|-------------|-----------|
| TTL expiry | Deletes expired feature bindings | Every email (lazy) + hourly systemd timer |
| Checkout sanitize | Clears all sensitive fields (pf, ef, epf, hp, invoice, preimage) from completed/failed checkouts | 1h after terminal status (lazy + hourly timer) |
| Checkout hard-delete | Deletes entire checkout row after retention period | 7 days after `created_at` (hourly timer) |
| Transient field clearing | Empties payment hash, payer note, preimage from payments table | 1h after processing (lazy + hourly timer) |
| Greylist RAM wipe | All greylist data lost on restart | Process restart |
