Clojure API for easy access to Microsoft Exchange services based on on EWS Java API. This API also supports streaming notifications provided by EWS API in order to receive Exchange events.
API can read configuration (such as credentials) from environment variables. Supported configration options are
EXCHANGE_USER
- username for loginEXCHANGE_PASS
- password for loginEXCHANGE_URL
- URL to authenticate toEXCHANGE_VERSION
- version of Exchange to which API is connecting. Defaults to 2010-SP2 (newest one in EWS)
Documentation is available under Github pages.
You can connect either via provided URL or with Exchange autodiscover feature. Credentials will be read from environment
if you don't provide any parameters. See corresponding functions in exchange.ews.authentication
namespace. Exchange
service object is than stored in an atom and used for all subsequent API calls.
You can impersonate user who will be used for all subsequent calls to the API with
(exchange.ews.authentication/impersonate-user "user@domain.com")
(exchange.ews.emails/send-email "to@email.com" "Subject" "Body as a string")
Folders can be found via their known name (value from enum WellKnownFolderName
) or id provided as a string. Same
applies for creating new folder where parent folder can also be specified as a known name or id.
(exchange.ews.folders/get-inbox)
Get folder by name (exchange.ews.folders/get-folder WellKnownFolderName/Inbox)
(exchange.ews.folders/create-folder "New folder" "parent-folder-id-in-string")
You can set item importance and add or remove categories.
(in-ins 'exchange.ews.items)
(set-item-importance "string-id" :high)
(add-category "string-id" "category1")
(add-categories "string-id" ["cat1" "cat2"])
(remove-category "string-id" "category1")
There are various options for searching but most importantly you create your own collections of filters and feed them to
the API. Fields available for filtering are specified in various enums in packagemicrosoft.exchange.webservices.data.core.service.schema
.
Some fields will accept only enum values for filtering, such as importance
.
(in-ins 'exchange.ews.search)
(let [filter1 (create-search-filter :contains-substring EmailMessageSchema/From "george")
filter2 (create-search-filter :is-greater-than ItemSchema/DateTimeSent (java.util.Date.))
collection (create-filter-collection :or [filter1 filter2])]
(-> (get-items-with-filter collection) ; optionally specify parent folder or limit
(transform-search-result))) ; Transforms result from Java objects to Clojure map
You can both search and create appointments via Exchange API.
(in-ins 'exchange.ews.calendar)
(create-appointment "Meeting" (java.util.Date.) (java.util.Date.) :location "London" :body
"Invitation")
Searching defaults to beginning and end of the current month (but you can of course specify both parameters).
(in-ins 'exchange.ews.calendar)
(transform-appointments (get-all-appointments))
There are two functions to start notification listener, one listen to changes on all folders, the other takes list of folders on which will listen to events.
First you need to implement your notification handler function which will receive an event. You can also implememnt disconnect function (default one just connects back to the API). Also check on-notification-event
and on-disconnect
functions defined in namespace.
(def my-notification-event
(reify StreamingSubscriptionConnection$INotificationEventDelegate ; you have implement the EWS interface
(notificationEventDelegate [_ sender event-args]
(run! (fn [event]
(log/info "Event type" (.name (.getEventType event))) ; Check for EventType (enum)
(log/info "Item id" (.getUniqueId (.getItemId event))) ; Check for Exchange ItemId which have changed
) (.getEvents event-args)))))
Then call function with following args
(let [events #{:created :deleted} ; Events to listen to
folders [(FolderId. (WellKnownFolderName/Calendar))]] ; Vector of folders
(create-streaming-notification events folders my-notification-event))