Einrichtung
Auf dem Rechner, der s3mail startet: nichts. Kein Webserver, keine Datenbank, kein Docker, keine Laufzeitumgebung. s3mail ist ein einzelnes Programm, bringt seinen eigenen Server mit und bindet ihn an 127.0.0.1. Nach außen gehen nur HTTPS-Verbindungen zu s3.<region>.amazonaws.com, email.<region>.amazonaws.com und, falls verschlüsselt, kms.<region>.amazonaws.com.
- Paket: macOS (Apple Silicon und Intel, signiert und notarisiert), Linux und Windows, jeweils amd64/arm64, aus den Releases
- Start:
unzip s3mail-macos-arm64.zip && open s3mail.app, unter Linux und Windows./s3mailoder Doppelklick - Selbst bauen: Go 1.27 oder neuer, CGO aus
Im AWS-Konto
| Was | Wofür | Fehlt es, dann … |
|---|---|---|
| In SES verifizierte Domain | Empfang überhaupt | kommt keine Mail an |
| MX-Record auf SES | leitet die Mail zu AWS | Mail geht an den alten Server |
| S3-Bucket in derselben Region | die Mails liegen dort | – |
| Bucket-Policy für SES | SES darf hineinschreiben | Mails werden verworfen |
| Aktives Receipt-Rule-Set mit S3-Aktion | schreibt die Mail in den Bucket | Mail wird angenommen und weggeworfen |
| IAM-Identität mit der Policy unten | s3mail liest und sortiert | s3mail kommt nicht an den Bucket |
| Verifizierte Absenderadresse | Schreiben, Antworten, Weiterleiten | Lesen geht, Senden nicht (--no-send) |
| KMS-Schlüssel (optional) | nur bei Verschlüsselung | siehe Verschlüsselte Buckets |
Nicht gebraucht werden Lambda, EC2, VPC oder eine WorkMail-Organisation.
Der kurze Weg: CloudFormation
Bucket, Bucket-Policy, IAM-Benutzer samt Policy, die Geräte-Boundary und die SES-Empfangsregel legt eine Vorlage an (deploy/README.md im Repository sagt, wofür jede Ressource da ist):
aws cloudformation create-stack \
--stack-name s3mail \
--template-body file://deploy/s3mail.json \
--capabilities CAPABILITY_NAMED_IAM \
--parameters \
ParameterKey=MailDomain,ParameterValue=firma.de \
ParameterKey=MailboxLocalPart,ParameterValue=info \
ParameterKey=MailBucket,ParameterValue=mein-eindeutiger-bucket
Die Domain muss vorher in SES verifiziert sein; dafür braucht es DNS-Einträge, die nur du setzen kannst. Zwei Schritte kann die Vorlage nicht abschließen, und beide sind ein Befehl: das Rule-Set aktivieren (dafür gibt es keine CloudFormation-Ressource) und einen Zugangsschlüssel erzeugen. Die Vorlage legt bewusst keinen an: ein Schlüssel in einem Stack-Output ist für jeden lesbar, der den Stack lesen kann, und bleibt es.
aws ses set-active-receipt-rule-set --rule-set-name s3mail-info
aws iam create-access-key --user-name s3mail-infoVon Hand, der Reihe nach
Region wählen
SES nimmt Mail nur in bestimmten Regionen entgegen; Bucket und SES gehören in dieselbe.
Domain in SES verifizieren
Und die DKIM-CNAMEs im DNS setzen.
MX-Record
Der Domain auf inbound-smtp.<region>.amazonaws.com, Priorität 10.
S3-Bucket anlegen
Darin ein Prefix als Wurzel, üblicherweise mail/.
Bucket-Policy
Damit SES schreiben darf; die SES-Konsole bietet sie beim Anlegen der Regel an.
Receipt-Rule-Set anlegen und aktivieren
Darin eine Regel mit der Aktion S3 → Bucket und Prefix mail/. Danach das Rule-Set aktivieren. Ein angelegtes, aber inaktives Rule-Set ist der häufigste Grund dafür, dass nichts ankommt.
Zugang für s3mail
Ein IAM-Benutzer mit Access Key (empfohlen), ein vorhandenes Profil mit Schlüsseln, oder AWS SSO / IAM Identity Center nach aws sso login. Der Assistent schreibt eingetippte Schlüssel als eigenes, zusätzliches Profil nach ~/.aws/credentials (chmod 600); vorhandene Profile bleiben unangetastet.
Absenderadresse verifizieren
Wenn gesendet werden soll. Solange das SES-Konto in der Sandbox steckt, kann es nur an verifizierte Adressen senden; Empfang funktioniert dort uneingeschränkt.
Testmail schicken
Dann in s3mail „Neu laden“. Ob alles sitzt, musst du nicht raten: Schritt 3 des Assistenten prüft der Reihe nach Bucket lesen, Mail lesen, Schreiben, Löschen, Zustand von mehreren Rechnern, Verschlüsselung und SES-Absender, und schreibt zu jedem fehlenden Punkt die IAM-Aktion dazu, die dafür nötig wäre.
IAM-Policy
{
"Version": "2012-10-17",
"Statement": [
{ "Effect": "Allow", "Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::MEIN-BUCKET",
"Condition": {"StringLike": {"s3:prefix": ["mail/*"]}} },
{ "Effect": "Allow", "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::MEIN-BUCKET/mail/*" },
{ "Effect": "Allow", "Action": "ses:SendRawEmail", "Resource": "*" },
{ "Effect": "Allow", "Action": ["sqs:ReceiveMessage", "sqs:DeleteMessage"],
"Resource": "arn:aws:sqs:REGION:KONTO:MEINE-QUEUE" },
{ "Effect": "Allow", "Action": ["kms:Decrypt", "kms:GenerateDataKey"],
"Resource": "arn:aws:kms:REGION:KONTO:key/DEIN-SCHLUESSEL" }
]
}
Der KMS-Teil entfällt, wenn weder der Bucket noch die SES-Regel verschlüsselt. Der SQS-Teil entfällt, wenn es keine Klingel gibt; dann läuft der Abgleich im Takt. sqs:GetQueueUrl steht bewusst nicht dabei: s3mail baut die URL aus dem ARN, den es ohnehin in der Policy liest.
Bucket, Ordner, Absenderadresse und Queue stehen bereits in der Policy, als genau die Angabe, an der AWS den Zugriff später misst. Darf der Zugang seine eigene Policy lesen (iam:ListUserPolicies, iam:GetUserPolicy auf user/${aws:username}), holt s3mail sie sich von dort, statt danach zu fragen: eintragen musst du dann nur noch Access Key und Secret. Gelesen werden nur eingebettete Policies. Die Region nennt S3 selbst im Kopf seiner Antwort.
Optional, nur für die Bequemlichkeit des Assistenten: s3:ListAllMyBuckets (Bucket-Auswahlliste; bewusst nicht in der Policy oben, weil es jeden Bucket des Kontos zeigt), ses:ListIdentities und ses:GetIdentityVerificationAttributes (Absender-Auswahl), s3:GetLifecycleConfiguration und s3:PutLifecycleConfiguration (Papierkorb-Automatik).
Erster Start
./s3mail
Beim Start schreibt s3mail eine Adresse ins Terminal, die ein Token enthält: s3mail laeuft auf 127.0.0.1.. Der Browser öffnet sich damit von selbst. Ohne dieses Token antwortet der Server nicht.
Beim ersten Mal öffnet sich der Einrichtungs-Assistent statt des Postfachs, in drei Schritten: AWS-Zugang (Profil wählen oder Access Key ID + Secret eintragen, dazu die Region), Postfach (Bucket, Prefix aus der SES-Regel, Absenderadresse für Antworten, optional Signatur und ein Name für den Umschalter), Prüfen (legt kurz ein Testobjekt an und löscht es wieder; Ergebnis ist eine Checkliste, und was fehlt, steht im Klartext dabei). Danach lässt sich optional eine Lifecycle-Regel setzen, die den Papierkorb nach 7/30/90 Tagen leert.
„Speichern und starten“ schreibt ~/.config/s3mail/config.json (chmod 600) und lädt direkt das Postfach. Ab dann genügt ./s3mail. Über Einstellungen oben rechts kommst du jederzeit zurück in den Assistenten, auch für ein zweites Postfach.
Optionen
| Option | Bedeutung |
|---|---|
--setup | Assistent öffnen, auch wenn schon konfiguriert |
--bucket, --prefix, --region, --profile, --from | Bucket, Wurzel-Prefix, Region, Profil, Absender; bei mehreren Postfächern wirken sie auf das erste |
--no-send | SES-Versand deaktivieren (reiner Lesemodus) |
--no-delete | Endgültiges Löschen sperren; dann geht nur Papierkorb |
--port / --host | Standard 127.0.0.1:8765 |
--no-browser | Browser nicht automatisch öffnen |
--no-cache | Nichts auf Platte zwischenspeichern |
--cache-plaintext | Cache unverschlüsselt schreiben, wenn kein Schlüsselbund da ist |
--debug | Aufrufe an S3 und SES protokollieren: Schlüssel, Größen, Dauer, keine Mailinhalte |
--refresh | Sekunden zwischen automatischen Abgleichen, 0 schaltet ab (Standard 60) |
--mcp, --mcp-readonly | als MCP-Server über stdin/stdout laufen; readonly ohne Verschieben, Verschlagworten, Entwerfen |
--version | Version ausgeben und beenden |