4

CODE-C# 程式讀取 Exchange 共用行事曆

 2 years ago
source link: https://blog.darkthread.net/blog/ews-read-shared-calendar/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
CODE-C# 程式讀取 Exchange 共用行事曆-黑暗執行緒

工作遇到新需求:辦公室自動化服務希望讀取使用者行事曆,整合顯示於個人資訊頁。

EWS Managed API 封裝了複雜又囉嗦的 Exchange Web Service SOAP 細節,改以 .NET 程式庫形式提供電子郵件、連絡人、行事曆、公用資料夾的存取管道,是 C# 開發 Exchange 相關程式的首選。(意外發現 EWS Managed API 從 2014 起轉為 Github 開源專案,有原始碼在手,搞不懂走不通都有救,用起來格外讓人放心,微軟真的愈來愈開放)

官方文件有篇詳細介紹文,示範如何使用 EWS Mananged API 查詢行事曆取得個人約會資訊。基本原理是利用 CalendarFolder.Bind() 連上個人行事曆,接著建立一個 CalendarView 指定查詢期間、取回筆數,CalendarView.PropertySet 則傳入要讀取的欄位(主旨、開始/結束時間… 等),接著呼叫 CalendarFolder.FindAppointments() 就取得 Appointment 的集合,很簡單,這部分可直接參考官方範例。好消息是 EWS Managed API 用 NuGet 就可以下載:

4329-dc94-o.gif

不過我的需求多了一些變化,系統會使用統一中間程式查詢不同使用者的行事曆,而我們不可能為此要使用者交出 AD 帳號密碼。因此,透過行事曆共用是較可行做法。

行事曆共用可使用 Outlook 操作, 找到自己的行事曆(一般會有兩份,要選名稱有個人郵件地址位於 Exchange Server 的那一份),右鍵選單開啟內容:

4330-54b0-o.gif

程式使用 EWS Managed API 會以特定 AD 帳號執行(測試時可用開發者自己的帳號,正式營運則會申請專用帳號),要開放行事曆供程式存取,使用者必須授與該帳號讀取權限,授權完成可使用 Outlook 檢查是否看到測試對象的約會做為驗證。但有一點要留意,除了授權讀取空閒/忙碌時間、主旨、地點外,其他區域有個「可看到資料夾」一定要勾選。未勾選時 Oulook 可查看共享行事曆,但 EWS Managed API 不行,我花了不少時間才發現這個眉角。

若要求省事,也可請共用行事曆的使用者直接選取「權限等級:檢閱者」;若使用者很介意約會細節外流,只想透露主旨、地點,甚至只打算開放/空閒忙碌資訊,只勾選自己想開放範圍也成,但記得一定要勾選「可看到資料夾」,不然程式沒戲唱:

4331-cb39-o.gif

程式範例如下。查詢他人行事曆時,有個關鍵是使用 new FolderId(WellKnownFloderName.Calendar, "對方的Email") 取得資料夾代號,若對方未授與「可看到資料夾」權限,程式會在 FindAppointments 時噴出找不到資料夾的錯誤。

排版顯示純文字
private static void QuerySharedCalender()
{
    var ewsUrl = "https://the-exchange-server/ews/Exchange.asmx";
    ExchangeService ews = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
    ews.Credentials = new WebCredentials(userId, pwd, domainName);
    ews.Url = new Uri(ewsUrl);
    FolderId folderToAccess = 
            new FolderId(WellKnownFolderName.Calendar, "[email protected]");
    //指定日期區間與資料筆數
    var view = new CalendarView(
        new DateTime(2017, 12, 10),
        new DateTime(2017, 12, 17), 
        1024);
    view.PropertySet = new PropertySet(
                AppointmentSchema.Subject, 
                AppointmentSchema.Start, 
                AppointmentSchema.End);
    FindItemsResults<Appointment> apps = ews.FindAppointments(folderToAccess, view);
    foreach (var app in apps)
    {
        Console.WriteLine(
            $"{app.Start:MM-dd HH:mm} - {app.End:MM-dd HH:mm} {app.Subject}");
    }
}

假設行事曆如下:

4332-2aaa-o.gif

測試成功!

4333-3354-o.gif

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK