Azure Functions eignen sich hervorragend, um eine ausgelagerte Routine zum Versand von Email im Web zu erstellen. Die Funktion selbst kann, universell anlegt, in diversen eigenen Applikationen verwendet werden.
Der zentrale Ansatz sorgt dabei dafür, dass die Funktion einfach skalierbar bleibt und notwendige Stammdaten wie z.B. Zugangsdaten und Serveradressen leicht und zentral ausgetauscht werden können.
Im Folgenden beschrieben wir, wie eine derartige Funktion mit Microsoft Azure Functions-App angelegt werden kann.
Erstellung der Functions-App
Zunächst erstellen wir eine neue Functions-App.
Diese finden wir unter Neu -> Compute -> Functions-App
Als nächstes müssen die notwendigen Grunddaten für die Erstellung angegeben bzw. ausgewählt werden:
Die verschiedenen Einstellungen wie Name, Abonnement/Subscription und Standort können dabei entsprechend den individuellen Anforderungen ausgewählt werden.
Nach einem Klick auf „Erstellen“ wird die Functions-App entsprechend den eingestellten Daten erzeugt. Die Erstellung dauert im Normalfall nur wenige Sekunden, dann steht die App in der ausgewählten Ressourcengruppe zur Verfügung.
Code zur App hinzufügen
Im nächsten Schritt bringen wir den Inhalt in die Functions-App. Auf der Startseite der App werden hierbei verschiedene Möglichkeiten angeboten, auf denen die Funktion aufbauen kann. Im Wesentlichen geht es dabei um den Auslösemechanismus (Trigger), der die App startet. Azure unterstützt dabei verschiedene Trigger:
- Timer, ähnlich einem CRON-Job
- Änderungen in einem Speicherkonto (BLOB-Container)
- Azure Queues
- Service-Bus-Nachrichten
- HTTP-Trigger
In diesem Beispiel verwenden wir „eigene benutzerdefinierte Funktion erstellen“, was sich auf der Startseite ganz unten findet, damit unsere Funktion über HTTP aufgerufen werden kann. Hierfür stehen uns die Programmiersprachen C# und NodeJS zur Verfügung.
Azure unterstützt folgende Programmiersprachen:
- C# .NET
- NodeJS
- Python
- PHP
Für dieses Beispiel verwenden wir als HTTP-Trigger in Verbindung mit C#.NET den „GenericWebHook-CSharp“ als Ausgangsvorlage.
Anschließend wird unten noch ein Name für die Funktion vergeben. Hiermit ist die Funktion mit einem Grundgerüst auch schon erstellt.
Einige Anmerkungen zur Code-Ansicht:
- Funktions-URL: Über diesen URL wird die Funktion später aufgerufen
- Code: der eigentliche Code der Funktion
- Logs: Ausgaben und Rückmeldungen der Funktion
- Ausführen: manueller Start der Funktion mit der Möglichkeit, manuelle Testdaten an den Funktionsaufruf zu senden
Beim Code selbst handelt es sich um Standard-C#-ASP-.NET-Code, der selbstverständlich modifiziert werden kann.
Emails senden
In unserem Fall möchten wir, dass die Funktion Emails sendet. Hierfür werden einige dynamische Parameter benötigt:
- from-Email: Emailadresse des Absenders
- to-Email: Emailadresse des Empfängers
- subjekt: Betreffzeile
- message: Inhalt der Email
- is-important: Priorität „hoch“ ja/nein
Da die Funktion diese Parameter im JSON-Format erwartet, hier ein Beispiel für einige Muster-Parameter:
{ "fromEmail": "muster@absender.com", "toEmail": "max.mustermann@empfaenger.com", "subject": "Beispiel-Email", "message": "Hallo Welt, das ist eine Test-Email.", "isImportant": true }
Diese Parameter sind natürlich nur Beispiele – sie können Sie für Ihre Tests jederzeit anpassen.
Der eigentliche Programmcode, den Sie hier kopieren können, sieht folgendermaßen aus:
#r "Newtonsoft.Json" using System; using System.Net; using Newtonsoft.Json; using System.Net.Mail; public static async Task<object> Run(HttpRequestMessage req, TraceWriter log) { log.Verbose($"Webhook was triggered!"); string jsonContent = await req.Content.ReadAsStringAsync(); dynamic data = JsonConvert.DeserializeObject(jsonContent); // do some data validation... skipped this for demo purpose only. // if validation failes -> HttpStatusCode.BadRequest should be returned as HTTP Status bool isImportantEmail = bool.Parse(data.isImportant.ToString()); string fromEmail = data.fromEmail; string toEmail = data.toEmail; int smtpPort = 587; bool smtpEnableSsl = true; string smtpHost = ""; // your smtp host string smtpUser = ""; // your smtp user string smtpPass = ""; // your smtp password string subject = data.subject; string message = data.message; MailMessage mail = new MailMessage(fromEmail, toEmail); SmtpClient client = new SmtpClient(); client.Port = smtpPort; client.EnableSsl = smtpEnableSsl; client.DeliveryMethod = SmtpDeliveryMethod.Network; client.UseDefaultCredentials = false; client.Host = smtpHost; client.Credentials = new System.Net.NetworkCredential(smtpUser, smtpPass); mail.Subject = message; if (isImportantEmail) { mail.Priority = MailPriority.High; } mail.Body = message; try { client.Send(mail); log.Verbose("Email sent."); return req.CreateResponse(HttpStatusCode.OK, new { status = true, message = string.Empty }); } catch (Exception ex) { log.Verbose(ex.ToString()); return req.CreateResponse(HttpStatusCode.InternalServerError, new { status = false, message = "Message has not been sent. Check Azure Function Logs for more information." }); } }
In den Zeilen 23-25 müssen Sie selbstverständlich Ihre eigenen Daten für SMTP-Server und Authentifizierung eintragen. Wenn Sie danach auf „Speichern“ klicken, wird der Code automatisch in Microsoft Azure gespeichert und kompiliert. Im Log-Bereich erscheinen entsprechende Informationen, ob das Kompilieren erfolgreich war.
Anschließend können Sie einen Testlauf machen, indem Sie Muster-Parameter an die Funktion übergeben und diese ausführen.
Wenn alles geklappt hat, erhalten Sie nach wenigen Sekunden eine Email im angegebenen Empfänger-Postfach.
Zusammenfassung
Functions-Apps sind eine praktische Bereicherung des Azure Portfolios. Zu akzeptablen Preisen können Sie hier einfach Code „in die Cloud“ auslagern und wiederverwendbaren Code für Ihre Applikationen bilden.
Wie man ein HTML-Formular als JSON an die Azure-Functions-App sendet, erfahren Sie im nächsten Beitrag.