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.

10 thoughts on “Exchange Server 2016 REST Api”

  1. Hallo, Vielen Dank für diesen Artikel.

    Hast du/Ihr evtl. Erfahrungen wenn man Kalender abfragen macht und bei 98% funktioniert es und bei anderen erscheint eine nicht aussagekräftige Fehlermeldung.
    Abfrage: https://mail.domäne.com/api/v2.0/users/Hans.Muster@Domäne.com/calendarview?StartDateTime=2020-07-06T00:00:00&EndDateTime=2020-08-16T23:59:59&$top=1000&$select=Subject,Location,IsAllDay,Start,End,IsCancelled,Sensitivity

    Fehlermeldung:
    {„error“:{„code“:“ErrorItemNotFound“,“message“:“The specified object was not found in the store. REST APIs for this mailbox are currently in preview. You can find more information about the preview REST APIs at https://dev.outlook.com/.“}}

    Gruss und Danke

    Reply
  2. In Deinem Fazit, schreibst Du, dass Dir nicht bekannt ist wesshalb die Rest API in Exchange on Premis nicht bekannt gemacht worden ist. Das geht zwar aus dem Exchange Blog von Ross S. auch nicht hervor aber er schreibt, das es nur Hybriddeployments vorbehalten sein soll – in den Kommentaren schreibt er auch, das nicht geplant ist Onpremis-only Installationen zu unterstützen:

    https://blogs.technet.microsoft.com/exchange/2016/09/26/on-premises-architectural-requirements-for-the-rest-api/

    Reply
  3. Hallo vielen Dank für den „fast“ einzigen Artikel zu dieser Thematik.
    Ich entwickle gerade eine APP auf einen Raspberry Pi die Kalendereinträge des lokalen Exchange servers auslesen soll.
    Könntest du evtl. ein Beispiel mit dem Zugriffsverfahren mit Python zeigen? Damit wäre glaube ich vielen geholfen.

    Danke

    Reply
  4. Hallo Frank,
    vielen Dank für den wie gewohnt hervorragenden Artikel. Beim Herumprobieren ist mir folgendes aufgefallen: die meisten meiner Postfächer haben einen Kalenderordner mit dem Namen „:\Kalender“, bei ein paar Postfächern heißt er aber – scheinbar völlig wahllos – plötzlich „:\calendar“. Ich habe dazu nirgends eine Dokumentation finden können, hast Du eine Erklärung, was es damit auf sich haben könnte?
    Viele Grüße,
    Michael

    Reply
  5. 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

    Reply
  6. 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

    Reply
  7. 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

    Reply
  8. 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

    Reply

Leave a Comment