Exchange Server 2016 REST Api

In diesem Artikel hatte ich bereits geschrieben, dass die neue REST Api auch bereits mit lokalen Exchange 2016 ab CU3 funktioniert. Die REST Api ist eine recht neue Schnittstelle, die zunächst nur in Office 365 bzw. Exchange Online verfügbar war. Stand heute (20.12.2016), konnte ich keine genauen Informationen finden, ob diese Schnittstelle für lokale Installationen supported wird. REST mit ausschließlich lokalen Exchange 2016 Installationen funktioniert aber bereits erstaunlich gut. Mehr dazu in diesem Artikel.

Warum lieber REST als EWS?

Jetzt gibt es also primär zwei Schnittstellen, die für die Anbindung von Tools und Programmen an Exchange Server zur Verfügung stehen:

Exchange Web Services (EWS) und REST Api

Beide Schnittstellen werden über den IIS Webserver auf den Exchange Servern bereit gestellt:

image

Ebenfalls nutzen beide Schnittstellen das HTTP (bzw HTTPS) Protokoll für die Kommunikation. Die beiden Schnittstellen sind sich also ähnlich, jedoch hat die REST Api einen ganz entscheidenden Vorteil:

Die REST Api ist komplett Plattformunabhängig. Im Gegensatz zu EWS muss für REST keine Bibliothek installiert werden. Um EWS zu nutzen, muss auf dem entsprechenden Rechner die “Echange Web Services Managed API” installiert werden, die EWS Api setzt wiederum .NET Framework voraus und wird nur für Windows Betriebssysteme unterstützt.

Diese Abhängigkeiten gibt es bei REST nicht, denn hier werden einfache HTTP Requests verwendet, die nahezu von jedem beliebigen Gerät oder Programm ausgelöst werden können. Die Antwort auf eine Anfrage via REST Api wird im JSON Format ausgeliefert und ist somit auch für leicht weiterzuverwenden. Der Zugriff auf Exchange Daten (Postfächer, Kalender, Aufgaben, etc) ist via REST also von nahezu jedem Gerät, Programm oder Betriebssystem möglich. Hier liegt der große Vorteil gegenüber EWS.

Hier gibt es nähere Informationen zu REST und JSON:

 

Beispiele für den Zugriff auf REST Api

Wie schon erwähnt, ist ein Zugriff auf die REST Api ziemlich einfach möglich, daher gibt es hier ein paar kleine Beispiele:

PowerShell (Windows)

Mit der PowerShell habe ich meine ersten Versuche gestartet. Der folgende Einzeiler genügt um die Mails via REST Api abzurufen:

$restdata = Invoke-RestMethod -Uri "https://mail.frankysweb.de/api/v2.0/me/messages" -Credential (Get-Credential)

REST Api

Die Variable $restdata enthält nun die Daten die von der Api geliefert wurden.

Auf die Daten im Objekt $restdata lässt sich jetzt einfach zugreifen, hier zum Beispiel die Empfänger:

image

Oder beispielsweise auch der Zeitpunkt des Empfangs:

image

Curl (Linux)

Hier mal ein kleines Beispiel mittels Curl auf einem Linux Rechner. Damit die Authentifizierung klappt, musste ich die “Standard Authentifizierung” auf dem “API” Verzeichnis im IIS aktivieren:

image

Benutzername und Passwort musste ich als Base64 String codieren, den String konnte ich dann zur Authentifizierung nutzen:

echo -n 'user@frankysweb.de:meinPassWort' | base64 
curl -X GET -H "Authorization: Basic dXNlckBmcmFua3lzd2ViLmRlOm1laW5QYXNzV29ydA==" -H "Content-Type: application/json" https://mail.frankysweb.de/api/v2.0/me/messages

SNAGHTML88b7e0

SNAGHTML95e078

Curl liefert natürlich erst einmal nur die “Rohdaten” im JSON Format zurück. Mit der Hilfe von Python lassen sich die Rohdaten lesbarer formatieren und beispielsweise als Datei speichern:

curl -X GET -H "Authorization: Basic dXNlckBmcmFua3lzd2ViLmRlOm1laW5QYXNzV29ydA==" -H "Content-Type: application/json" https://mail.frankysweb.de/api/v2.0/me/messages | python3 -m json.tool >> /tmp/rest

SNAGHTML9eac1e

So lässt sich der Inhalt schon besser verstehen:

image

Funktionsweise der REST Api

Die oben genannten Beispiele sind sehr einfach, jedoch ist die REST Api deutlich mächtiger. Zum Beispiel lässt sich schon im Request bestimmen, welche Daten man erhalten möchte. So muss man erst gar nicht viele Daten abrufen, um diese später wieder zu filtern.

Das folgende Beispiel liefert zum Beispiel nur Absender und Betreff von Gesendeten Mails:

$restdata = Invoke-RestMethod -Uri "https://mail.frankysweb.de/api/v2.0/me/MailFolders/sentitems/messages/?`$select=Sender,Subject" -Credential (get-credential)

image

Die REST Api erlaubt es aber auch Daten zu senden, hier wird zum Beispiel eine Mail gesendet:

$mail = '
{
  "Message": {
    "Subject": "Test via REST",
    "Body": {
      "ContentType": "Text",
      "Content": "Dies ist ein Test"
    },
    "ToRecipients": [
      {
        "EmailAddress": {
          "Address": "frank@frankysweb.de"
        }
      }
    ]
  },
  "SaveToSentItems": "true"
}
'

invoke-RestMethod -Uri "https://mail.frankysweb.de/api/v2.0/me/sendmail" -Method Post -Body $mail -ContentType "application/json" -Credential (get-credential)

image

Gleiches gilt natürlich auch für andere Datentypen, wie zum Beispiel Kalendereinträge, Aufgaben und Kontakte. Um einen Einblick in die REST Api zu bekommen, einfach mal in die Dokumentation schauen.

Dokumentation für die REST Api

Die Dokumentation der REST Api findet sich hier:

Einige Funktionen (zum Beispiel Office 365 Groups / Office 365 Dataextensions) sind nur in Verbindung mit Office 365 möglich.

Anpassungen Sophos UTM Web Application Firewall für REST Api

In diesem Artikel hatte ich die Konfiguration der Sophos UTM Web Application Firewall (WAF) in Verbindung mit Exchange 2016 beschrieben. Als der Artikel entstanden ist, gab es die REST Api in Exchange 2016 on-Premises noch nicht. Basierend auf den genannten Artikel sind nur zwei kleine Anpassungen an der Konfiguration nötig, damit die REST Api auch mit der Sophos UTM Webserver Protection funktioniert.

Im Firewall Profil, werden die folgenden Pfade für das “Exchange Webservices” Profil hinzugefügt:

  • /api
  • /API

 

image

Zusätzlich müssen die folgenden Pfade als Ausnahme für die Regel “Webservices Hardening” definiert werden:

  • /api/*
  • /API/*

image

Weitere Anpassungen sind nicht nötig.

Fazit

Die REST Api funktioniert schon erstaunlich gut. Leider kenne ich bisher nicht den Hintergrund, warum diese Schnittstelle bisher nicht für lokale Exchange Installationen offiziell bekannt gemacht wurde. Wahrscheinlich wird es noch Änderungen an der Schnittstelle geben, daher sollten besser noch keine produktiven Anwendungen für die REST Schnittstelle angepasst werden. Zum Ausprobieren in der Testumgebung ist es aber sehr gut geeignet.

4 Replies to “Exchange Server 2016 REST Api”

  1. Hi,

    hast du schon getestet ob du ein Attachment herunterladen kannst? Ich bekomme das aktuell nicht hin bzw. finde auch keine Doku dazu. Die Attachment-ID kann man sich noch bequem anzeigen lassen; der Download ist mir noch nicht klar.

    Ich habe das hier gefunden, was sich aber auf Version 1.0 der API zu beziehen scheint und in Version 2.0, zumindest in meinen Tests noch nicht funktioniert:
    http://stackoverflow.com/questions/32749496/how-to-retrieve-itemattachment-contents-from-office-365-rest-api

    Grüße,
    Norbert

  2. Hi Frank,
    danke für den tollen Artikel :-)
    Wenn du einen POST-Request ohne Daten sendest, bekommst du einen kleinen Hinweis, dass die REST API noch Beta-Charakter hat:

    REST APIs for this mailbox are currently in preview. You can find more information about the preview REST APIs at https://dev.outlook.com/.

    Gruß,
    Markus

  3. Hallo Norbert,
    das Attachment steht in ContentBytes des Reponse als Base64 String codiert. Diesen musst du decodiert in eine Datei schreiben mit korrektem ContentType (ebenfalls im Response zu finden). Ein PS-Script dafür habe ich nicht, aber ich habe es mit PHP gelöst.
    Gruß,
    Markus

  4. Hi Markus,

    vielen Dank für den Hinweis mit dem Decodieren. Da stand ich völlig auf dem Schlauch bzw. fühlte mich gezwungen das komplett über die REST-API zu lösen.

    Hier meine Lösung (ohne PHP) nachdem man sich die Message-ID geholt hat:
    […]
    $urlattachment = „https://$exchangeserver/api/v2.0/me/messages/$messageid/attachments“
    $attachment = invoke-webrequest $urlattachment -credential $creds
    $attachmentanswer = $attachment.content | ConvertFrom-Json
    $attachmentbase64 = $attachmentanswer.value | select -ExpandProperty contentbytes

    $filename = $attachmentanswer.value.Name
    $path = „C:\….“
    $outfile = „$path“+$filename

    $bytes = [Convert]::FromBase64String($attachmentbase64)
    [IO.File]::WriteAllBytes($outfile, $bytes)

    Viele Grüße,
    Norbert

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.