Nostr Mail Protocol

An email is an RFC 2822 message. Nostr Mail keeps the message and replaces the transport: instead of travelling between SMTP servers, the message travels inside a kind 1301 event, gift wrapped to its recipient.


Specifications

Spec Covers
Nostr Mail Core The kind 1301 event, sending, bridging, signed rumors, public emails
Nostr Mail Labels Folders, read state, stars, custom tags
Nostr Mail Settings Public and private settings synced across devices
Mail Contacts A portable address book shared between mail clients
Alias protocol Claiming and releasing a name@domain on a NIP-05 domain
Bridges and DSN Routing tags and delivery status notifications, below
Large MIME Emails above the NIP-44 limit, stored on Blossom, below

Kind 1301: Email

{
  "kind": 1301,
  "pubkey": "<sender_pubkey>",
  "tags": [
    ["email-id", "<unique_id>"]
  ],
  "content": "<rfc_2822_email>"
}

The content is a standard email. Nostr is only the delivery mechanism.

Tags

Tag When Description
email-id Recommended always Unique random id generated by the sender, stable across edits of the event
mail-from Bridged email SMTP envelope sender
rcpt-to Outbound bridging SMTP envelope recipient, repeatable for Cc and Bcc
public-ref Bcc of a public email Id of the public event, followed by relay hints

The email-id is what a bridge quotes in a delivery status notification, what a client uses to thread replies, and what lets the same email be recognised across devices and across relays.


Sending

  1. Build the kind 1301 rumor.
  2. Gift wrap it (NIP-59).
  3. Publish the wrap to the recipient's DM relays (kind 10050, NIP-17).

Relays only ever see a kind 1059 wrap addressed to a pubkey. The sender, the subject, the recipients and the body are all inside the encrypted payload.

To a Nostr recipient

{
  "kind": 1301,
  "pubkey": "<alice_pubkey>",
  "tags": [["email-id", "550e8400-e29b-41d4-a716-446655440000"]],
  "content": "From: npub1alice...@nostr\nTo: npub1bob...@nostr\nSubject: Hello\nDate: Sat, 28 Dec 2024 12:00:00 +0000\n\nHey Bob, how are you?"
}

To a legacy recipient

A recipient who is not on Nostr is reached through a bridge. The wrap goes to the bridge, and the envelope lives in the tags.

{
  "kind": 1301,
  "pubkey": "<alice_pubkey>",
  "tags": [
    ["email-id", "550e8400-e29b-41d4-a716-446655440000"],
    ["mail-from", "npub1alice...@bridge.com"],
    ["rcpt-to", "bob@example.com"]
  ],
  "content": "<rfc_2822_email>"
}

Resolve the bridge pubkey with NIP-05 on _smtp@bridge_domain.

From a legacy sender

When a bridge receives inbound SMTP for a Nostr user, it builds the rumor on the sender's behalf and sets mail-from so the recipient's client can tell a bridged email from a native one. There is no rcpt-to inbound: the recipient is already the p tag of the gift wrap.

{
  "kind": 1301,
  "pubkey": "<bridge_pubkey>",
  "tags": [["mail-from", "alice@example.com"]],
  "content": "<rfc_2822_email>"
}

Choosing the transport

An address of the form name@domain may belong to either world. The sender decides, and never guesses:

  1. Resolve name@domain through NIP-05. No pubkey means SMTP.
  2. Read that pubkey's public settings from its NIP-65 write relays.
  3. prefer_nostr: true means deliver over Nostr, anything else means SMTP.

A failed lookup counts as false. A transient NIP-05 error must never silently route a Nostr recipient through a bridge.


Authentication

The rumor is unsigned by default, which is what gives the sender deniability: the recipient knows who wrote it, nobody else can prove it.

A sender who wants to prove authorship MAY sign the rumor. A signed rumor is a complete Nostr event, so anyone can verify it, and it can be republished by anyone without the recipient's cooperation. That is the useful property in a professional or legal context.


Public emails

An email to a public entity MAY skip the gift wrap and be published as a plain, signed kind 1301 event. It is then a public and verifiable record that the sender wrote it.

Bcc recipients of a public email are notified with a gift wrap whose rumor carries a public-ref tag:

["public-ref", "<public_event_id>", "wss://relay1.com", "wss://relay2.com"]

The client learns that the email is public and where to fetch the signed event.


Large emails

NIP-44 caps a plaintext at 65535 bytes, and NIP-59 encrypts twice, so the usable inline budget is smaller than it looks. Implementations keep MIME inline below a safe threshold (the Dart SDK uses 32 KB) and move anything larger to a Blossom server, encrypted with AES-GCM. The kind 1301 event then carries the blob reference and its decryption key instead of the message.

This is what lets Nostr Mail carry attachments of any size.


Delivery status notifications

A bridge reports the fate of an email it was asked to send with a kind 7679 event referencing the email-id of the original. Delivered, delayed, failed, queued: the sender's client learns what an SMTP user would read in a bounce message.

The event carries no p tag, so the relays never learn who sent the original. Its content is NIP-44 encrypted to the sender with an ephemeral key the bridge destroys immediately, so the bridge cannot read its own archived notifications either. The bridge's permanent key signs it, which is what makes it verifiable.

{
  "kind": 7679,
  "pubkey": "<bridge_permanent_pubkey>",
  "tags": [
    ["r", "<email_id>"],
    ["ephemeral-pubkey", "<temp_pubkey>"]
  ],
  "content": "<nip44_encrypted_status>"
}

See Delivery Status for the full shape.


Everything else a mailbox needs

Folders, read state and stars are labels: signed kind 1985 events, each wrapped in its own gift wrap so the metadata stays private, removed by deleting that wrap.

Signature, bridges and From identities are private settings: a NIP-78 event encrypted to self. dm_copy and prefer_nostr are public, because a bridge has to read them.

Contacts are an append-only list named mail/contacts, private by default, shared by every client that speaks the same list.

An address like alice@example.com is claimed and released through the alias protocol, a small NIP-98 authenticated REST API served by the NIP-05 domain itself.


NIPs used

NIP Usage
NIP-01 Event structure
NIP-05 user@domain resolution, bridge discovery
NIP-09 Deleting an email or a label
NIP-17 DM relays (kind 10050)
NIP-32 Labels (kind 1985)
NIP-44 Encryption
NIP-59 Gift wrap (kind 1059)
NIP-65 Relay discovery
NIP-78 Settings (kind 30078)
NIP-98 Auth for the alias API