In this article I had already written that the new REST Api already works with local Exchange 2016 from CU3. The REST Api is a fairly new interface that was initially only available in Office 365 or Exchange Online. As of today (20.12.2016), I could not find any precise information as to whether this interface is supported for local installations. However, REST with exclusively local Exchange 2016 installations already works surprisingly well. Read more in this article.
Why REST rather than EWS?
There are now primarily two interfaces available for connecting tools and programs to Exchange Server:
Exchange Web Services (EWS) and REST Api
Both interfaces are provided via the IIS web server on the Exchange servers:
Both interfaces also use the HTTP (or HTTPS) protocol for communication. The two interfaces are therefore similar, but the REST Api has a decisive advantage:
The REST Api is complete Platform-independent. In contrast to EWS, no library needs to be installed for REST. To use EWS, the "Echange Web Services Managed API", the EWS Api requires .NET Framework and is only supported for Windows operating systems.
These dependencies do not exist with REST, as it uses simple HTTP requests that can be triggered by almost any device or program. The response to a request via REST Api is delivered in JSON format and is therefore easy to reuse. Access to Exchange data (mailboxes, calendars, tasks, etc.) is therefore possible via REST from almost any device, program or operating system. This is the big advantage over EWS.
Here you can find more information about REST and JSON:
- https://de.wikipedia.org/wiki/Representational_State_Transfer
- https://de.wikipedia.org/wiki/JavaScript_Object_Notation
Examples for accessing the REST Api
As already mentioned, accessing the REST Api is quite easy, so here are a few small examples:
PowerShell (Windows)
I have started my first attempts with PowerShell. The following one-liner is enough to retrieve the mails via REST Api:
$restdata = Invoke-RestMethod -Uri "https://mail.frankysweb.de/api/v2.0/me/messages" -Credential (Get-Credential)
The variable $restdata now contains the data supplied by the Api.
The data in the $restdata object can now be easily accessed, here for example the recipients:
Or, for example, the time of receipt:
Curl (Linux)
Here is a small example using Curl on a Linux computer. In order for the authentication to work, I had to activate the "Standard authentication" on the "API" directory in the IIS:
I had to encode the user name and password as a Base64 string, which I could then use for authentication:
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
Of course, Curl initially only returns the "raw data" in JSON format. With the help of Python, the raw data can be formatted in a more readable way and saved as a file, for example:
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
This makes it easier to understand the content:
How the REST Api works
The examples above are very simple, but the REST Api is much more powerful. For example, you can specify in the request which data you want to receive. This means you don't have to retrieve a lot of data in order to filter it again later.
For example, the following example only provides the sender and subject of sent mails:
$restdata = Invoke-RestMethod -Uri "https://mail.frankysweb.de/api/v2.0/me/MailFolders/sentitems/messages/?`$select=Sender,Subject" -Credential (get-credential)
The REST Api also allows data to be sent, for example an email:
$mail = ' { "Message": { "Subject": "Test via REST", "Body": { "ContentType": "Text", "Content": "This is a 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)
The same naturally also applies to other data types, such as calendar entries, tasks and contacts. To get an insight into the REST Api, simply take a look at the documentation.
Documentation for the REST Api
The documentation of the REST Api can be found here:
- Mail API Reference
- Calendar API Reference
- Contacts API Reference
- Notifications API Reference
- User Photo API Reference
- Groups API Reference
- Office 365 Data Extensions (Office 365)
- Outlook Extended Properties
- Synchronize Messages
- Synchronize Folder Hierarchy
Some functions (e.g. Office 365 Groups / Office 365 Dataextensions) are only possible in conjunction with Office 365.
Customizations Sophos UTM Web Application Firewall for REST Api
In this article I described the configuration of the Sophos UTM Web Application Firewall (WAF) in conjunction with Exchange 2016. When the article was written, the REST Api did not yet exist in Exchange 2016 on-premises. Based on the article mentioned, only two small adjustments to the configuration are necessary for the REST Api to work with Sophos UTM Web Server Protection.
In the firewall profile, the following paths are added for the "Exchange Webservices" profile:
- /api
- /API
In addition, the following paths must be defined as exceptions for the "Webservices Hardening" rule:
- /api/*
- /API/*
No further adjustments are necessary.
Conclusion
The REST Api already works amazingly well. Unfortunately, I do not yet know why this interface has not yet been officially announced for local Exchange installations. There will probably still be changes to the interface, so it is better not to adapt any productive applications for the REST interface yet. However, it is very suitable for testing in the test environment.
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
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/
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
Ohh, ja, ein Python Beispiel wäre toll.
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
Hallo Michael,
ich nehme an, die Postfächer haben unterschiedliche Sprachen, den Namen der Ordner kannst du via OWA prüfen und ggf. ändern.
Gruß,
Frank
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
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
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
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