Sie haben Post!

Veröffentlicht: 05. Aug 2003 | Aktualisiert: 11. Nov 2004

Von Christian Wenz

dot.net magazin - Partner von MSDN Online

Diesen Artikel können Sie dank freundlicher Unterstützung von dot.net magazin auf MSDN Online lesen. dot.net magazin ist ein Partner von MSDN Online.

Partner von MSDN Online

Auf dieser Seite

 Mail-Quickie
 Mailfeatures
 Dateianhang
 HTML-Mails
 Fazit

Auf die Frage nach den größten Mängeln von ASP ist eine der ersten Antworten der Mailversand. Von sich aus ist dieser zunächst nicht möglich. Wird der Microsoft SMTP Service installiert, kann man zumindest darauf zugreifen. Zur Verwendung von externen Mailservern oder für diffizilere Anforderungen waren jedoch stets externe, oftmals kostenpflichtige Komponenten notwendig. In ASP.NET ist dies Vergangenheit - zumindest größtenteils.

Eines vorweg - um den Mailversand von ASP.NET einsetzen zu können, benötigen Sie auf jeden Fall einen SMTP-Server. Einer der häufigsten Fehler ist es, dass dieser Server nicht vorhanden oder nicht korrekt installiert ist. Bei Windows 2000, XP und 2003 ist bereits ein SMTP-Server von Microsoft mit dabei. In der Systemsteuerung, Rubrik Software, können Sie weitere Windows-Komponenten hinzufügen. Die SMTP-Funktionalität verbirgt sich hier als Teilkomponente des IIS-Webservers, der hier Internet-Informationsdienste (IIS) genannt ist. Klicken Sie auf Details und wählen Sie den Eintrag SMTP-Dienst.

Außerdem sollten Sie den Dienst entsprechend konfigurieren. In der IIS-Konsole befindet sich ein Eintrag Virtueller Standardserver für SMTP. Bei dessen Eigenschaften können Sie beispielsweise den anonymen Zugriff aktivieren und die Weitergabe von eMails auf Ihre lokale IP beschränken.

Wenn Sie einen externen Mailserver verwenden, können Sie diesen ebenfalls mit ASP.NET verwenden. Achten Sie aber auf eventuelle Zugriffsvoraussetzungen. Viele Anbieter erlauben beispielsweise nur dann den Zugriff auf den SMTP-Server, wenn der Benutzer sich zuvor beim POP3-Server (für eingehende eMails) angemeldet hat. Dies wird SMTP-after-POP genannt. Andere Mailserver setzen auf SMTP-Auth, das heißt, dass auch für den Mailversand Benutzername und Passwort notwendig sind. Wiederum andere eMail-Server sind so konfiguriert, dass nur bestimmte Absenderadressen akzeptiert werden - das SMTP-Protokoll an sich lässt ja jeden Absender zu.

Alles weitere spielt sich in der Klasse System.Web.Mail ab, in der die gesamte Funktionalität für den ASP.NET-Mailversand zur Verfügung steht.

wenz_mail_1.gif

Abb. 1: Der Klassenbrowser von ASP.NET Web Matrix bietet eine gute Übersicht über die Mail-Klassen von ASP.NET

Mail-Quickie

Wie bei vielen Dingen in der Programmierung gibt es auch für die Aufgabe des Mailversands einen einfachen und einen schwierigeren Weg. Der einfache Weg geht sehr schnell vonstatten, ist aber nicht sehr flexibel. Verwenden Sie die Unterklasse SmtpMail von System.Web.Mail und dort die Methode Send(). Diese erwartet als Parameter den Absender, Empfänger, Betreff und den eigentlichen Mailtext - in genau dieser Reihenfolge. Der Dokumentation zufolge genügt dies, wenn Ihr Mailserver auf dem lokalen Rechner liegt. Dem ist aber nicht so: Sie erhalten eine Fehlermeldung, wenn Sie die Send()-Funktion ohne vorbereitende Initialisierung verwenden. Zunächst müssen Sie explizit den Mailserver angeben. Dazu setzen Sie die Eigenschaft SmtpServer der Klasse SmtpMail. Hier ein komplettes Skript:

<script runat="server"> 
Sub Page_Load 
  System.Web.Mail.SmtpMail.SmtpServer = "localhost" 
  System.Web.Mail.SmtpMail.Send( _ 
 "<A href="mailto:von_mir@xy.de">von_mir@xy.de</A>", _ 
 "<A href="mailto:an_dich@yz.de">an_dich@yz.de</A>", _ 
 "Erstellt von ASP.NET", _ 
 "Ging das nicht unglaublich einfach?!") 
  Label1.Text = "Mail wurde versandt!" 
End Sub 
</script> 
<asp:Label id="Label1" runat="server" />

Das geht schnell und zuverlässig, ist allerdings wenig flexibel.

 

Mailfeatures

Diffizilere Mailfeatures wie beispielsweise Kopie- und Blindkopieempfänger können bei der Send()-Methode nicht mit angegeben werden, hier müssen Sie explizit bestimmte Eigenschaften setzen. Instanziieren Sie dazu die Klasse MailMessage:

Dim mail As System.Web.Mail.MailMessage = New System.Web.Mail.MailMessage

Dieses Objekt hat nun ebenfalls eine Reihe von Eigenschaften und Methoden (die wesentlichen Eigenschaften des Objekts werden im Verlauf dieses Artikels behandelt). Das entsprechend konfigurierte MailMessage-Objekt übergeben Sie dann als Parameter an die bereits bekannte Send()-Methode:

System.Web.Mail.SmtpMail.Send(mail)

Als Beispiel hierfür sehen Sie in Listing 1 einen Teil einer fiktiven Webmail-Anwendung. Der Benutzer kann in Formularelemente den oder die Empfänger, einen Betreff und den Mailtext eintragen. Außerdem kann die Mailpriorität angegeben werden:

Listing 1

Von: <asp:TextBox id="MailFrom" runat="server" /><br /> 
An: <asp:TextBox id="MailTo" runat="server" /><br /> 
Kopie: <asp:TextBox id="MailCc" runat="server" /><br /> 
Blindkopie: <asp:TextBox id="MailBcc" runat="server" /><br /> 
Betreff: <asp:TextBox id="MailSubject" runat="server" /> 
Priorität:  
<asp:DropDownList id="MailPrio" runat="server"> 
<asp:ListItem Text="normal" Value="Normal" Selected="True" />  
<asp:ListItem Text="niedrig" Value="Low" /> 
<asp:ListItem Text="hoch" Value="High" /> 
</asp:DropDownList><br /> 
<asp:TextBox id="MailBody" TextMode="MultiLine" Columns="70" Rows="10" runat="server" />

Sobald das Formular verschickt wird, sorgt eine serverseitige Methode dafür, dass ein entsprechendes Mailobjekt erzeugt wird. Zunächst werden die entsprechenden Eigenschaften für die Empfänger, Mailtext und Betreff gesetzt:

Dim mail As System.Web.Mail.MailMessage = New System.Web.Mail.MailMessage 
mail.From = MailFrom.Text 
mail.To = MailTo.Text 
mail.Cc = MailCc.Text 
mail.Bcc = MailBcc.Text 
mail.Subject = MailSubject.Text 
mail.Body = MailBody.Text

Dann wird die Mailpriorität gesetzt. Eine einfache Fallunterscheidung würde hier bereits ausreichen; beim Einsatz von Visual Basic .NET geht es allerdings besonders elegant durch eine Umwandlung des Textes aus dem Formular mittels CType():

mail.Priority = CType(MailPrio.SelectedIndex, System.Web.Mail.MailPriority)

Der Clou: Mail.MailPriority ist ein Integerwert - 0 bedeutet niedrig, 1 normal und 2 hoch. Dies entspricht genau dem Index der entsprechenden Listenelemente in der Dropdown-Liste für die Mailpriorität. Also ist eine solche Umwandlung leicht möglich. Allerdings setzen dies nicht alle Mailserver korrekt um. Der Microsoft SMTP Service beispielsweise setzt nicht den Priority-Header in der generierten eMail, sondern den Importance-Header. Aus diesem Grund wird ein entsprechender Header-Eintrag von Hand gesetzt:

mail.Headers.Add("X-Priority", MailPrio.SelectedItem.Value)

Am Ende wird die eMail dann wie gezeigt verschickt und eine entsprechende Meldung ausgegeben:

System.Web.Mail.SmtpMail.SmtpServer = "localhost" 
System.Web.Mail.SmtpMail.Send(mail) 
Label1.Text = "Mail verschickt!"

Mehrere Mailempfänger
Wer viel mit Microsoft-Mailprogrammen arbeitet, ist es gewohnt, mehrere Mailempfänger durch ein Semikolon (;) voneinander zu trennen. Dies ist allerdings eine Microsoft-Erfindung; Standard im Mailverkehr ist ein Komma als Trennzeichen. Für Kompatibilität mit allen Mailservern sollten Sie Ihre Webmail-Nutzer dazu anhalten, mehrere Empfänger mit Kommata voneinander zu trennen, nicht mit Strichpunkten.

In HTML-Mails verlinken
Wenn HTML-Mails mit ASP.NET erzeugt werden sollen, enthält dies sicherlich Links und Verweise auf eingebundene Grafiken. Es ist eine Menge unnötiger Overhead, wenn für jeden Link und für jede Grafik der komplette Servername angegeben werden muss. Die Eigenschaft UrlContentBase der MailMessage-Klasse ermöglicht es, die URL-Basis zu setzen. Das entspricht <base href="xxx" /> im HTML-Code.

 

Dateianhang

Im nächsten Schritt soll der Benutzer noch eine Datei an die eMail anhängen können. Dazu wird zunächst ein HTML-Control zum Datei-Upload eingefügt:

<input type="file" id="MailFile" runat="server" />

Die Datei wird dann serverseitig an die eMail angefügt. Dazu erzeugen Sie zunächst ein MailAttachment-Objekt. Beim Konstruktor geben Sie als ersten Parameter den Dateinamen an, als zweiten den Kodierungstyp für den Dateianhang. Dieser ist vom Typ MailEncoding mit den Optionen Base64 und UUEncode. Base64 ist empfehlenswerter, weil performanter - und auch der Standard: Wenn Sie keinen Kodierungstypen angeben, wird Base64 verwendet.

MailFile.PostedFile.SaveAs("javascript:void(null);" + _ 
  System.IO.Path.GetFileName(MailFile.PostedFile.FileName)) 
Dim anhang As System.Web.Mail.MailAttachment = _ 
  new System.Web.Mail.MailAttachment( _ 
 "javascript:void(null);" + System.IO.Path.GetFileName( _ 
   MailFile.PostedFile.FileName) _ 
  )

Der Anhang wird dann mit der Add()-Methode an die eMail angefügt:

mail.Attachments.Add(anhang)

Nun müssen Sie noch das HTML-Formular anpassen, indem Sie das Attribut enctype="multipart/form-data" einfügen - nur dann nämlich können Datei-Uploads verarbeitet werden. Außerdem sollten Sie eine Abfrage einbauen, ob überhaupt eine Datei übertragen worden ist, bevor Sie der eMail einen Anhang geben. Die übertragene Datei sollte nach dem Mailversand auch noch gelöscht werden. Das komplette Listing finden Sie ebenfalls auf der Heft-CD.

wenz_mail_2.gif

Abb. 2: Die Webmail-Anwendung im Browser

wenz_mail_3.gif

Abb. 3: ... und die daraus erzeugte eMail

 

HTML-Mails

Der Einsatz von HTML-Code in eMails ist umstritten und wird von den meisten Spamfiltern mit "Punktabzug" bestraft. Es mag aber dennoch sinnvolle Einsatzgebiete geben. Die Klasse System.Web.Mail bietet hierfür eine Unterstützung an. Die Eigenschaft BodyFormat von MailMessage kann entweder auf MailFormat.Text (Standard) oder MailFormat.Html (HTML-Mail) gesetzt werden. Damit der Benutzer hier eine Wahlmöglichkeit hat, wird das Webmail-Formular um eine Checkbox erweitert, bei der zwischen HTML und Text hin- und hergeschaltet werden kann:

<asp:CheckBox id="MailForm" Text="HTML verwenden" runat="server" />

Im Quellcode wird der Zustand dieser Checkbox einfach abgefragt

If MailForm.Checked Then 
  mail.BodyFormat = System.Web.Mail.MailFormat.Html 
End If

 

Fazit

Insbesondere im Vergleich zu ASP gilt: Ein Mailversand mit ASP.NET ist sehr einfach zu bewerkstelligen. Bestimmte Funktionalität, wie beispielsweise das Anhängen von Dateien (z.B. Grafiken), die dann innerhalb der eMail verwendet werden, ist jedoch weiterhin nicht trivial möglich. Hierfür sind dann doch wieder externe Komponenten notwendig.

Listing 2

<script runat="server"> 
Sub Versenden(o As Object, e As EventArgs) 
  Dim mail As System.Web.Mail.MailMessage = New System.Web.Mail.MailMessage 
  mail.From = MailFrom.Text 
  mail.To = MailTo.Text 
  mail.Cc = MailCc.Text 
  mail.Bcc = MailBcc.Text 
  mail.Subject = MailSubject.Text 
  mail.Body = MailBody.Text 
  mail.Priority = CType(MailPrio.SelectedIndex, System.Web.Mail.MailPriority) 
  mail.Headers.Add("X-Priority", MailPrio.SelectedItem.Value) 
  If Not MailFile.PostedFile Is Nothing Then 
 MailFile.PostedFile.SaveAs("javascript:void(null);" + _ 
   System.IO.Path.GetFileName(MailFile.PostedFile.FileName)) 
 Dim anhang As System.Web.Mail.MailAttachment = _ 
   new System.Web.Mail.MailAttachment( _ 
  "javascript:void(null);" + System.IO.Path.GetFileName( _ 
 MailFile.PostedFile.FileName) _ 
   ) 
 mail.Attachments.Add(anhang) 
  End If 
  System.Web.Mail.SmtpMail.SmtpServer = "localhost" 
  System.Web.Mail.SmtpMail.Send(mail) 
  If Not MailFile.PostedFile Is Nothing Then 
 System.IO.File.Delete("javascript:void(null);" + _ 
   System.IO.Path.GetFileName(MailFile.PostedFile.FileName)) 
  End If 
  If MailForm.Checked Then 
 mail.BodyFormat = System.Web.Mail.MailFormat.Html 
  End If 
  Label1.Text = "Mail verschickt!" 
End Sub 
</script> 
<asp:Label id="Label1" runat="server" /> 
<form enctype="multipart/form-data" runat="server"> 
Von: <asp:TextBox id="MailFrom" runat="server" /><br /> 
An: <asp:TextBox id="MailTo" runat="server" /><br /> 
Kopie: <asp:TextBox id="MailCc" runat="server" /><br /> 
Blindkopie: <asp:TextBox id="MailBcc" runat="server" /><br /> 
Betreff: <asp:TextBox id="MailSubject" runat="server" /> 
Priorität:  
<asp:DropDownList id="MailPrio" runat="server"> 
<asp:ListItem Text="normal" Value="Normal" Selected="True" /> 
<asp:ListItem Text="niedrig" Value="Low" /> 
<asp:ListItem Text="hoch" Value="High" /> 
</asp:DropDownList> 
<asp:CheckBox id="MailForm" Text="HTML verwenden" runat="server" /><br /> 
<asp:TextBox id="MailBody" TextMode="MultiLine" Columns="70" Rows="10" runat="server" /><br /> 
Anhang: <input type="file" id="MailFile" runat="server" /><br /> 
<asp:Button Text="Mail versenden" OnClick="Versenden" runat="server" /> 
</form>

Das vollständige Webmail-Listing, inklusive kleinerer kosmetischer Erweiterungen, finden Sie zur Übersicht in Listing 2. Zum Abschluss seien noch einige Ideen für Erweiterungsmöglichkeiten angeführt:

  • Mehr Sicherheitschecks.

  • Deaktivierung von Viewstate, damit das Mailformular nach dem Versand wieder leer ist.

  • Integration eines Rich-Text-Feldes zur vereinfachten Erstellung von HTML-Mails (z.B. sourceforge.net/projects/freetextbox/).

  • Beschränkung der Absender-eMail-Adresse auf einen oder wenige, feste, Werte

Viel Spaß beim Erweitern!