Status: design discussion, NOT yet scheduled. Ship gate is a yes/no from the threat-model team on the BRIDGED trust tier.
Filed as: issue #16.
The least-bad first product is one-way outbound + magic-address
reply-only inbound, scoped to wireup.net handles. Wireup.net runs as
a constrained MTA-of-record (DKIM-signed, SPF-aligned,
DMARC p=quarantine) under a dedicated subdomain (mail.wireup.net)
so the apex isn't poisoned. From: is operator-owned —
<wire-handle>@mail.wireup.net, not spoofed as the user's real email.
Wire's Ed25519 DID stays the cryptographic root; the SMTP envelope is a lossy projection of it. Two-way "wire user ↔ arbitrary email user" as an equal peer is a v0.2+ thing and probably never the right shape — it inverts the bilateral consent gate (T11) and exposes wire's slot to the global spam universe.
A wire send-email <addr> "<body>" CLI + MCP tool that POSTs to a new
relay endpoint /v1/email/send, which DKIM-signs and submits via a
single outbound SMTP provider (Postmark / Resend / SES — pick one,
treat as replaceable).
- From:
<sender-handle>@mail.wireup.net - Reply-To: same.
- Relay maintains
(from_did, to_email, message_id) → wire event_idmapping for thread reconciliation. - Inbound MX on
mail.wireup.netaccepts replies only if theIn-Reply-To/Referencesheader threads against a known mapping; everything else is dropped at SMTP550. - Reply MIME parsed (text/plain preferred, HTML stripped), wrapped
as a new
kind=1event signed by a relay-held bridge keypair (DIDdid:wire:bridge:<message-id-hash>), deposited in the original sender's slot.
Cost: ~600 LOC, one new module (email_bridge.rs), one new relay
route pair, zero changes to the wire protocol envelope.
Demo: "wire user texts their non-wire friend's gmail; friend replies
in gmail; reply lands in wire tail."
-
MTA posture: own or rent. Run our own SMTP on
mail.wireup.net(full control, slow IP warmup, RBL surface) vs proxy through Postmark / Resend / SES (fast, $0–50/mo, vendor lock, ToS limits agents). Recommend rent for v0.2.0, own for v0.3; document the swap point. -
Identity mapping for inbound senders. When
paul@gmail.comreplies, what DID do we synthesize? Options:- (a) deterministic
did:wire:email:sha256(addr)(stable, leaks address-as-identifier) - (b) per-thread ephemeral DID (no cross-thread linkability, breaks "block this sender")
- (c) no DID, surface as
from: email:paul@gmail.comliteral
Recommend (a) with an
email:prefix subnamespace so it cannot be confused with native DIDs. - (a) deterministic
-
Threading model. Email's
Message-Id/In-Reply-Tovs wire's signed event chain. Pick one canonical thread root; the other side is denormalized. Recommend: wireevent_idis canonical; outbound mail carriesMessage-Id: <event_id>@mail.wireup.netso reply headers round-trip losslessly. -
Bridge-key trust tier. Email-derived events are signed by the relay's bridge key, not by the email sender. They MUST surface in
wire tailat a distinct tier (BRIDGED, belowVERIFIED) and the CLI MUST render them asbridge:paul@gmail.comnotpaul@gmail.com— otherwise an email forger can impersonate any pinned peer. This is a new tier intrust.rs; not a Cargo-only change. -
Consent gate equivalent. Bilateral pair (#7–#9) was the whole T11 mitigation. Email has no SPAKE2. Replacement: explicit per-recipient outbound enable (
wire email enable <addr>) creates the(from_did, to_email)mapping; inbound that doesn't match a mapping is hard-dropped. No global "open my inbox to email" switch.
-
IP / domain reputation. Apex
wireup.netalready serves the landing + relay. One spam complaint onmail.wireup.netwith bad alignment and Gmail/Outlook silently SPAM-folder the whole apex. Must run mail on a subdomain with separate DKIM selector, separate SPF, and DMARCruareports going to a real human. -
Spam/abuse asymmetry. Wire's current threat model assumes bilateral consent. An open inbound MX is the exact opposite. Without the per-mapping allowlist (decision 5), any wire user becomes spam-reachable the moment they send one email.
-
Forged-From-line impersonation. SMTP From: is not authenticated below DKIM. Without SPF+DKIM+DMARC alignment checks at MX ingress, an attacker sends
From: paul@gmail.comwith no DKIM and the bridge happily signs a wire event purporting to be from paul. Inbound MUST require DKIM-pass + DMARC-aligned-pass; fail → 550, no event emitted. -
SMTP injection in body concatenation. If
wire send-emailever templates user-supplied subject / from into header lines, CRLF injection writes new headers (Bcc:, Reply-To:). Use a real MIME builder (lettre), neverformat!. -
Plaintext-by-default mismatch with wire's signing story. Wire promises operators "every event is Ed25519-signed by the pinned peer." Email-bridged events break that and there is no way around it without PGP / S/MIME. Documentation must be loud: bridged events are attested by the relay, not by the sender. Hiding this loses the audit-log integrity property that's wire's main differentiator.
Carries over cleanly:
- The signed-event envelope — bridged events are still canonical
JSON + Ed25519, just signed by the bridge key.
relays,wire tail,wire verifywork unchanged. - The dual-slot routing — the bridge is a third slot type
(
email_bridgeslot) alongside local / federation, samerelay_clientplumbing. - The
.well-knowndiscovery hook — an email recipient becomes a synthesized agent-card with the bridge DID, sowire whois email:paul@gmail.comreturns a real card. - The trust-tier state machine — add
BRIDGEDas a new tier strictly belowVERIFIED.
Needs new shape:
- A real MTA module (no SMTP code exists today).
- An address-mapping store (new
~/.config/wire/email-bridge.json, structurally distinct frompetnames.jsonbecause it's relay-side state not operator-side). - A consent primitive that is not SAS-based — the bilateral SPAKE2 handshake assumes both endpoints run wire and that assumption is exactly what email breaks.
Matrix's bridge model is mautrix-email: per-user double-puppeted
bridge running in the user's homeserver. The analogous wire shape is
"the bridge runs on the user's own relay, not on wireup.net,"
which is the right v0.3 posture and the one ANTI_FEATURES.md #1
("no SaaS dependency") implicitly demands. The MVP can centralize on
wireup.net; v0.3 must let operators run their own bridge against
their own MX.
Ship the outbound-only wire send-email first (one week, low risk,
demonstrates intent). Gate inbound on the explicit per-mapping
allowlist (decision 5). Treat anything beyond "reply to a thread I
started" as out of scope until v0.3.
If the threat-model team won't sign off on a relay-held bridge key
with a new BRIDGED tier, don't ship. Outbound-only with no reply
path is still a useful product and doesn't compromise the integrity
story.