Das Versenden von Emails selbst programmieren
Geschrieben von: Christoph Wille Emailkomponenten gibt es (beinahe) soviele wie Sand am Meer, und viele davon sind sogar gratis. Verwendet hat sie bestimmt schon (beinahe) jeder, sei es jetzt AspMail, CDONTS, SA-SmtpMail oder eine der vielen anderen. Etwas, das aber bestimmt (beinahe) keiner bis jetzt gemacht hat, ist sich eine Emailkomponente selbst zu programmieren. Im heutigen Artikel befassen wir uns mit den Grundlagen, und werden nur eine sehr einfache Email versenden. Spätere Artikel werden auf dem heute vorgestellten Sourcecode aufbauen, und am Ende werden wir eine voll funktionstüchtige Komponente für HTML Emails und Attachments haben. Voraussetzung um den Sourcecode dieses Artikels verwenden zu können ist eine Installation des Microsoft .NET Framework SDK's auf einem Webserver. Weiters setze ich voraus, daß der Leser die Programmiersprache C# zu einem gewissen Grad beherrscht - es finden sich etliche Artikel auf diesem Server, um das notwendige Wissen zu erlernen Eine minimale EmailAls erstes müssen wir abklären, wie das SMTP (Simple Mail Transport Protocol) Protokoll funktioniert - weil dieses die Grundlage für den Versand von Emails darstellt. Das schöne ist, daß alle Befehle und Antworten vom SMTP Server in Klartext verschickt werden (was man allerdings wiederum auch als Sicherheitsproblem auslegen kann...). Das folgende "Script" zeigt die grundsätzliche Reihenfolge der SMTP Befehle um eine Mail zu verschicken: HELO local computername MAIL FROM: sender's address RCPT TO: recipient's address DATA mail header and body text . Um nun tatsächlich eine Email zu verschicken, verbindet man sich mittels Telnet mit Port 25 (der SMTP Port, telnet servername 25) am Emailserver und tippt eine Beispielemail ein: HELO SHAGPAD MAIL FROM: christophw@alphasierrapapa.com RCPT TO: christophw@dev.alfasierrapapa.com DATA Subject: Hi Chris This is a part of the body text . Die Parameter HELO, MAIL FROM und RCPT TO sind unspektakulär und waren "vorhersehbar". Der DATA Parameter ist hingegen interessant: die Header (Subject) und der Body Text sind durch eine Leerzeile voneinander getrennt. Dieses Beispiel zeigt nur einen Header (Subject), folgende Beispiele werden die fehlenden Header einfügen. Der Punkt schließt die Email ab, und der Server meldet den Status der Operation. Apropos Statusmeldungen: jedes der gezeigten Kommandos liefert eine Statusmeldung des Servers - diese können sehr nützlich sein! Implementierung der minimalen Email in C#Wir werden diesen Prozess jetzt 1:1 in C# umsetzen, und zwar mit Hilfe der Net Klassen des .NET Frameworks. Grundsätzlich dreht sich alles um eine Instanz der TcpClient Klasse und dessen Stream - für die Verbindung zum SMTP Server, und zum Austausch von Befehlen und Statusmeldungen. Die Datei email-simple.aspx ist im Download des heutigen Artikels enthalten. <% @Page Language="C#" %> <% @Import Namespace="System.IO" %> <% @Import Namespace="System.Net" %> <% @Import Namespace="System.Net.Sockets" %> <% @Import Namespace="System.Text" %> <script language="C#" runat="server"> bool WriteToStream(ref NetworkStream nwstream, string strLine) { string strString2Send = strLine + "\r\n"; Byte[] arr2Send = Encoding.ASCII.GetBytes(strString2Send.ToCharArray()); try { nwstream.Write(arr2Send, 0, arr2Send.Length); } catch { return false; } return true; } bool ReadFromStream(ref NetworkStream nwstream, out string strMessage) { byte[] readBuffer = new byte[255]; int nLength = nwstream.Read(readBuffer, 0, readBuffer.Length); strMessage = Encoding.ASCII.GetString(readBuffer, 0, nLength); return (3 <= readBuffer[0]); // 2 success, 3 informational } </script> <% Response.Buffer = false; string strEmailServer = "fx2.dev.alfasierrapapa.com"; string strSendTo = "christophw@fx2.dev.alfasierrapapa.com"; string strMailFrom = "christophw@alphasierrapapa.com"; string strSubject = "My Email Test"; TcpClient tcpc = new TcpClient(); try { tcpc.Connect(strEmailServer, 25); } catch (SocketException socketEx) { Response.Write("Connection Error: " + socketEx.ToString()); Response.End(); } string strResponse; NetworkStream nwstream = tcpc.GetStream(); ReadFromStream(ref nwstream, out strResponse); Response.Write(strResponse + "<br>"); WriteToStream(ref nwstream, "HELO myhost"); ReadFromStream(ref nwstream, out strResponse); Response.Write(strResponse + "<br>"); WriteToStream(ref nwstream, "MAIL FROM: " + strMailFrom); ReadFromStream(ref nwstream, out strResponse); Response.Write(strResponse + "<br>"); WriteToStream(ref nwstream, "RCPT TO: " + strSendTo); ReadFromStream(ref nwstream, out strResponse); Response.Write(strResponse + "<br>"); WriteToStream(ref nwstream, "DATA"); ReadFromStream(ref nwstream, out strResponse); Response.Write(strResponse + "<br>"); WriteToStream(ref nwstream, "Subject: " + strSubject); WriteToStream(ref nwstream, "."); ReadFromStream(ref nwstream, out strResponse); Response.Write(strResponse + "<br>"); %> Wenn wir uns nur auf den unteren Teil des Listings konzentrieren (die Dreier-Codeblöcke), dann sieht dies wirklich nicht anders aus als wenn man händisch per Telnet eine Email erstellen würde. Die Funktionalität für das Senden der Befehle und Abfragen der Statusmeldungen ist in den Funktionen WriteToStream bzw ReadFromStream versteckt. Die WriteToStream Methode ist für das Versenden der Befehle verantwortlich. Dies geschieht durch Anhängen eines CR/LF Paares an den String, sowie dessen Konvertierung in ein Byte-Array und das darauffolgende Verschicken an den SMTP Server durch die Write Methode des NetworkStream Objektes. Der Rückgabewert ist true/false, abhängig davon ob der Befehl erfolgreich gesendet werden konnte: bool WriteToStream(ref NetworkStream nwstream, string strLine) { string strString2Send = strLine + "\r\n"; Byte[] arr2Send = Encoding.ASCII.GetBytes(strString2Send.ToCharArray()); try { nwstream.Write(arr2Send, 0, arr2Send.Length); } catch { return false; } return true; } Die ReadFromStream Methode funktioniert im Grunde sehr ähnlich, nur daß sie ein Byte-Array ausliest, und dann als String an den Aufrufer zurückliefert. Da jede Statusmeldung des SMTP Servers mit einem dreistelligen Statuscode beginnt, verwende ich diesen, um true/false zu berechnen: 2xx sind Erfolgsmeldungen, 3xx sind Erfolge mit Zusatzinformation: bool ReadFromStream(ref NetworkStream nwstream, out string strMessage) { byte[] readBuffer = new byte[255]; int nLength = nwstream.Read(readBuffer, 0, readBuffer.Length); strMessage = Encoding.ASCII.GetString(readBuffer, 0, nLength); return (3 <= readBuffer[0]); // 2 success, 3 informational } Obwohl beide Methoden boolsche Resultate liefern, ignoriere ich diese aus Einfachheitsgründen im heutigen Beispiel. Dafür gebe ich die Statusmeldungen des SMTP Servers aus - etwas, das man in einer Produktionsumgebung nicht machen würde: Laut Statuscode war der Emailversand erfolgreich - auch Outlook Express ist dieser Meinung: Allerdings sieht das Ergebnis nicht ansprechend aus, weil Outlook spezielle Header für Absender und Empfänger erwartet - Eudora ist hier nicht so kleinlich, aber eben nicht so weit verbreitet. Daher müssen wir noch eine Kleinigkeit hinzuprogrammieren, um die Outlookianer gewogen zu stimmen. Optischer Aufputz für OutlookDiese Kleinigkeit sind die Header To und From. Diese werden einfach im Headerteil mit angeführt (email-better.aspx): WriteToStream(ref nwstream, "DATA"); ReadFromStream(ref nwstream, out strResponse); Response.Write(strResponse + "<br>"); WriteToStream(ref nwstream, "From: " + strMailFrom); WriteToStream(ref nwstream, "Subject: " + strSubject); WriteToStream(ref nwstream, "To: " + strSendTo); WriteToStream(ref nwstream, ""); WriteToStream(ref nwstream, "Hello Christoph!"); WriteToStream(ref nwstream, "\r\n."); ReadFromStream(ref nwstream, out strResponse); Response.Write(strResponse + "<br>"); Dieses Mal ist auch Outlook Express so "freundlich" und zeigt alle gewünschten Informationen an: SchlußbemerkungHeute haben wir nur eine simple Email verschickt, allerdings dabei alle wichtigen SMTP Kommandos kennengelernt. Was wir in den nächsten Artikeln einfügen werden sind Kopie- und Blindkopieempfänger, Content-Type, zusätzliche Header, HTML Emails und Attachments. Stay tuned! Download des CodesKlicken Sie hier, um den Download zu starten. Verwandte Artikel
ACT MetaMailer - Mails verschicken leicht gemacht Wenn Sie jetzt Fragen haben...Wenn Sie Fragen rund um die in diesem Artikel vorgestellte Technologie haben, dann schauen Sie einfach bei uns in den Community Foren der deutschen .NET Community vorbei. Die Teilnehmer helfen Ihnen gerne, wenn Sie sich zur im Artikel vorgestellten Technologie weiterbilden möchten. Eine weitere sehr hilfreiche Resource ist das deutsche ASP.NET Wiki, das als zentrale Anlaufstelle für Tips, Tricks, Know How und alles Nützliche was man in seinem Alltag als (ASP).NET-Entwickler so braucht und entdeckt gedacht ist. Haben Sie Fragen die sich direkt auf den Inhalt des Artikels beziehen, dann schreiben Sie dem Autor! Unsere Autoren freuen sich über Feedback zu ihren Artikeln. Ein einfacher Klick auf die Autor kontaktieren Schaltfläche (weiter unten) und schon haben Sie ein für diesen Artikel personalisiertes Anfrageformular.
Und zu guter Letzt möchten wir Sie bitten, den Artikel zu bewerten. Damit helfen Sie uns, die Qualität der Artikel zu verbessern - und anderen Lesern bei der Auswahl der Artikel, die sie lesen sollten.
©2000-2006 AspHeute.com |