
Wer heute automatisierte E-Mails versenden will, die nicht unbedingt in jedem Spam-Filter hängen bleiben sollen, der kommt kaum an DKIM vorbei.
DKIM - DomainKeys Identified Mail - ist ein Mechanismus zur Validierung von E-Mail-Absendern; primär über DNS Einträge.
Mit Hilfe eine DNS-TXT Eintrags wird vereinfacht gesagt ein Public-Key bekannt gegeben, den der E-Mail-Empfänger verwenden kann, um den Ursprung einer E-Mail validieren zu können - wozu die E-Mail Nachricht mit Hilfe eines Private Keys eine Signatur erhält.
Mehr über die prinzipelle Funktionsweise auf Wikipedia .
Generierung der Keys
Für DKIM können selbst erstellte Schlüsselpaare verwendet werden; dazu ist kein gekauftes Zertifikat notwendig.
Dank des OpenSSL-Tools ist dies mit zwei einfachen Befehlen umsetzbar:
Erstellung des privaten Schlüssels für das Signieren der E-Mail:
1openssl genrsa -out beispiel.dkim.private 1024
Mit Hilfe des privaten Schlüssels kann nun ein öffentlicher Schlüssel erzeugt werden, der im DNS bekannt gegeben wird:
1openssl rsa -in beispiel.dkim.private -out beispiel.dkim.public -pubout -outform PEM
Setzen des DNS Eintrags
Mit Hilfe des DNS-Eintrags validiert der E-Mail Empfänger die Signatur.
Der Inhalte des öffentlichen Schlüssels - ohne den Header, Footer oder Leerzeichen - kommt nun in folgendes DNS-Format:
v=DKIM1;k=rsa;t=y;p=Undzwn/n2ndsk……UZnbhudnz=;
Der Inhalt de p-Parameters muss der Inhalt aus dem öffentlichen Schlüssel entsprechen.
Der Name des TXT-Eintrags lautet beispielselektor2021._domainkey wobei beispielselektor2021 ein Platzhalter ist, denn einer Domain können prinzipiell viele Domain Keys hinterlegt werden, sodass man jeden E-Mail Ausgang mit eigenen Schlüsseln konfigurieren kann.
Der Selektor wird dabei beim Erstellen der Signatur mit in die E-Mail gepackt, sodass der E-Mail Empfänger weiß, welcher der zugehörige Eintrag ist.
Da jeder Domain-Anbieter eine andere Oberfläche mit sich bringt, wie ein TXT-Eintrag zu setzen ist, überspringe ich diesen Part.
Signieren der E-Mail mit MimeKit
Anders als mit .NET Boardmitteln, die keine direkte Möglichkeit bieten E-Mails mit DKIM zu signrieren, bietet das MimeKit entsprechende Unterstützung an.
Hierzu erzeugen wir mit der Partnerbibliothek MimeKit entsprechend eine E-Mail, setzen Absender und Empfänger sowie den Inhalt - und signieren am Schluss die E-Mail.
1MimeMessage emailMessage = new(.....);
2{
3 // set from
4 // set to
5 // set body
6 // set attachments
7}
8string pk = $"-----BEGIN RSA PRIVATE KEY-----\r\n{PrivateKeyString}\r\n-----END RSA PRIVATE KEY-----";
9MemoryStream stream = new(Encoding.UTF8.GetBytes(pk));
10{
11 stream.Position = 0;
12}
13
14// Erzeugung des Signers mit dem privaten Schlüssel; auch das Lesen einer Datei selbst ist als Übergabeparameter möglich!
15DkimSigner dkimSigner = new DkimSigner(stream, "meinedomain.de", "beispielselektor2021");
16
17// Welche Elemente der Mail sollen mit signiert werden?
18HeaderId[] dkimSignHeaders = { HeaderId.From, HeaderId.To, HeaderId.Subject, HeaderId.Date, HeaderId.MessageId };
19
20// Signieren der Mails
21emailMessage.Body.Prepare(EncodingConstraint.SevenBit);
22dkimSigner.Sign(FormatOptions.Default, emailMessage, dkimSignHeaders);
23
24// Versenden
25smtpClient.SendAsync(emailMessage....);
Das Signieren muss unbedingt am Schluss passieren, da ansonsten entsprechend sich die Inhalte nach der Signatur verändern und die Signatur ungültig wird.
Ebenso ist notwendig, dass der Inhalte der Mail - also der Body - durch Prepare() das entsprechende Encoding erhält; fehlt das, ist auch hier die Signatur am Ende ungültig.
Testen und Validieren der Signatur
Es gibt viele verschiedene Tools, die eine DKIM-Validierung anbieten; wirklich empfehlen kann ich aber im Endeffekt nur zwei Tools:
- Microsoft Outlook kann mit Hilfe des MHA-Addins entsprechende Informationen zu E-Mail Headern anzeigen.
- Mit Hilfe des Services https://dkimvalidator.com/ kann eine Test-E-Mail versendet werden, die entsprechend analyisiert wird
Outlook MHA:
Der Message Header Inilizer sollte - bei einer korrekten Implementierung von DKIM - folgenden Header-Ausschnitt anzeigen
1DKIM-Signature: v=1; a=rsa-sha256; d=meinedomain.de; s=1und1; c=simple/simple;
2 t=1610929057; h=from:to:subject:date:message-id;
3 bh=IR0r/61rl3Xcv7EAYlNJVNAgqOpheEklTFjbFnFyGIU=;
4 b=OXRyC6ZwDAWTVhKzmHiI0gURspIbw5xNCyzYo5D45iqcy1F5l9UljlGMU38lt4Sy3JLlAn5k2PX
5 /DIFDnmRDaBnw+hVHdlwDBC9FWJawZyyVaYzyIpQ3AG+52g8LuQ+SCqIHogFW/IkYnsNajOSVhbRZ
6 G/qQ2wnZoM0tWpDu2RA=
71705
Dies bestägtigt, dass Signatur über das MimeKit erfolgt ist.
Ein weitrer Header-Eintrag bestätigt darüber hinaus, ob die Signatur selbst gültig ist. Dies ist der Authentication-Results Header, in dem allgemeine Validierungen erfolgen; darunter auch entsprechend der DKIM-Eintrag dkim=test (signature was verified) was uns die Information gibt, dass die Validierung erfolgt und gültig ist.
1Authentication-Results: spf=pass (sender IP is xxx)
2 smtp.mailfrom=meinedomain.de; meinedomain.com; dkim=test (signature was
3 verified) header.d=meinedomain.de;zieldomain.com; dmarc=pass action=none
4 header.from=meinedomain.de;compauth=pass reason=100
Fehlersuche
Sollte die die Validierung nicht erfolgreich sein, so ist eine Validierung gar nicht so einfach.
Zunächst muss natürlich nachgeschaut werden, ob der entsprechende Header teil der E-Mail ist; wenn nicht, dann liegt der Fehler auf der Code-Seite. Ansonsten, sollte die Validierung vorhanden aber ungültig sein, liegt es meist am Key-Pair.
Lohnt sich DKIM?
Ganz klar: Ja.
DKIM ist relevant für das Spam-Scoring; und entsprechend sollten automatisierte E-Mails - zB. von Plattformen und Webseiten - ein entsprechend hohes Scoring haben, sodass eben solche Mails nicht im Spam-Filter landen und die Kommunikation mit dem Anwender erschweren.
Dank dem MimeKit und dem MailKit ist das - zumindest aus .NET sicht für SMTP - jedoch kein Problem mehr.

Comments