Kai Ole Hartwig
Go · Apache-2.0 · macOS, Linux, Windows, iOS

s3mail — deine Post liegt in deinem Bucket.

Amazon SES schreibt eingehende Mail als rohes MIME in einen S3-Bucket. Was fehlte, war ein Programm, das sie von dort liest. s3mail ist eine einzelne Datei ohne Laufzeitumgebung: es startet einen Webserver auf 127.0.0.1 und zeigt das Postfach im Browser. Dazu eine iOS-App, die denselben Bucket direkt liest — mit einem eigenen Schlüssel.

Dazwischen steht kein Server. Keiner, der ausfällt, keiner, den jemand betreibt, keiner, der mitliest.

  • Geschrieben in: Go — Standardbibliothek plus AWS-SDK, sonst fast nichts
  • Läuft auf: macOS, Linux, Windows · iOS
  • Lizenz: Apache-2.0

SES legt die Mail in den Bucket. Und dann?

Mit s3mail

Ein Postfach im Browser: Ordner, Suche, Regeln, Anhänge, HTML in einer abgeschotteten Ansicht. Antworten geht über SES. Und auf dem Telefon dasselbe Postfach, direkt aus demselben Bucket.

Bisher

aws s3 cp, ein MIME-Parser von Hand und ein Terminal. Anhänge kommen base64-kodiert, Betreffs in kodierten Wörtern, HTML als Quelltext. Antworten geht gar nicht.

Was s3mail ausmacht

Für ein Modell erreichbar — ohne Senden

Über MCP kann ein Sprachmodell lesen, suchen, verschlagworten, verschieben und Entwürfe schreiben. Senden nicht. Eine eingehende Mail ist fremder Text im Kontext des Modells; der Entwurfsordner ist die Stelle, an der ein Mensch hinsieht.

Das Telefon bekommt einen eigenen Schlüssel

Koppeln heißt: Namen eintippen, QR-Code scannen, sechs Ziffern bestätigen. Dahinter entsteht ein eigener IAM-Benutzer mit einer Rechtegrenze — ein verlorenes Telefon ist eine einzelne Sperrung und kein Wechsel überall.

Geteilter Zustand ohne Sperre

Gelesen, Stern, Schlagworte und Regeln liegen im Bucket als Vorgangsprotokoll: jeder Schreibvorgang bekommt seinen eigenen Schlüssel. Es gibt also nichts aufzulösen und kein Vergleiche-und-Tausche, das schiefgehen kann. Der Preis: jeder Vorgang muss wiederholbar sein.

Ordner sind echte S3-Prefixe

Kein Index, der die Wahrheit über den Bucket behauptet. Ein Ordner ist ein Prefix, und die Nachrichtenkennung ist der Dateiname darin — deshalb überlebt alles, was du über eine Mail wusstest, das Verschieben.

Die Policy ist die Konfiguration

Bucket, Prefix und Absenderadresse liest s3mail aus der IAM-Policy des Schlüssels, mit dem es läuft. Es fragt also nach genau einem Ding — dem Schlüssel — und leitet den Rest ab. Nichts zu tippen heißt nichts falsch zu tippen.

Der Bucket gehört dir

Die Post liegt in deinem AWS-Konto, geschrieben von SES. s3mail liest sie mit einem Zugangsschlüssel, den du angelegt hast. Nichts läuft über einen fremden Rechner — und das ist keine Absichtserklärung, sondern das, was das Programm kann: es kennt keine andere Adresse als die von AWS.

Loslegen

Zwei Dinge braucht es: eine Domain, für die SES empfängt, und einen Bucket mit einem IAM-Benutzer, der eng genug ist, um das Einzige zu sein, das ihn liest. Das Zweite legt eine CloudFormation-Vorlage an.

 

aws cloudformation create-stack \
  --stack-name s3mail \
  --template-body file://go/deploy/s3mail.json \
  --capabilities CAPABILITY_NAMED_IAM \
  --parameters \
      ParameterKey=MailDomain,ParameterValue=example.org \
      ParameterKey=MailboxLocalPart,ParameterValue=du \
      ParameterKey=MailBucket,ParameterValue=dein-eindeutiger-bucket

 

Zwei Schritte kann eine Vorlage nicht abschließen, und beide sind ein Befehl: das Regelwerk aktivieren, weil es dafür keine Ressource gibt, und einen Zugangsschlüssel erzeugen. Den legt die Vorlage bewusst nicht an — ein Schlüssel in einer Stack-Ausgabe ist für jeden lesbar, der den Stack lesen darf, und zwar dauerhaft.

Danach s3mail starten und den Schlüssel eintragen. Alles Weitere findet es selbst heraus.

Die Dokumentation

Einrichtung

Was der Rechner braucht (nichts), was das AWS-Konto braucht, CloudFormation oder von Hand, die IAM-Policy, der erste Start.

Lesen →
Einrichtung

Funktionen

Ordner als S3-Prefixe, Lesen, Schreiben ohne Doppelversand, Regeln mit Vorschlägen, Suche, mehrere Postfächer.

Lesen →
Funktionen

Zugang, Verschlüsselung, Zustand

Die drei Prüfungen bei jeder Anfrage, verschlüsselte Buckets, der Cache auf der Platte, geteilter Zustand ohne Sperre.

Lesen →
Zugang, Verschlüsselung, Zustand

MCP, iPhone, Grenzen

Für ein Modell erreichbar, ohne Senden; die iOS-App mit eigenem Schlüssel; was s3mail nicht tut.

Lesen →
MCP, iPhone, Grenzen

Wie es gebaut ist

Von unten nach oben, und nichts unten kennt etwas von oben.

mimeparse macht aus MIME Kopfzeilen und Teile. Für den Index liest es nur den Kopf, beim Öffnen die ganze Mail.

core ist die Logik ohne Seiteneffekte: Zustandsdaten, Ordnernamen, Regel-Engine, Suche. Kein S3, kein HTTP, keine Datei — und keine Uhr im Innern: die Zeit wird hineingereicht, sonst ist die Entscheidung nicht prüfbar.

store legt S3 hinter eine Schnittstelle aus sechs Methoden. Beim Auflisten holt es pro neuer Mail nur den Kopf mit einer Bereichsanfrage und vergleicht über ETags.

web ist die Oberfläche: drei HTML-Seiten, Vanilla JavaScript, kein Bauschritt. HTML-Mail rendert in einem abgeschotteten Rahmen mit Inhaltsrichtlinie, entfernte Bilder bleiben blockiert, bis jemand sie anfordert — ein Mailprogramm, das sie lädt, gibt jedem Absender eine Lesebestätigung.

Drei Prüfungen schützen den lokalen Server: die Host-Kopfzeile gegen DNS-Rebinding, die Origin-Kopfzeile gegen fremde Seiten, und ein Token gegen alle anderen auf demselben Rechner.